• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Compiling outside Netbeans

 
Ranch Hand
Posts: 146
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a lot of projects, many of which depend on one library. When I change that library I have to re-compile and release all of the projects.
I created a batch file which deleted the existing .jar files, rebuilt them and copied the jar files to the run directory. It worked perfectly for several years.

Following an upgrade to Netbeans I find that the script no longer works, I get:

call ant -S  -buildfile F:\Javadev\house\BrierCalc\build.xml

Buildfile: F:\Javadev\house\BrierCalc\build.xml
module-info.java doesn't exist
module-info.java doesn't exist
Trying to override old definition of task http://www.netbeans.org/ns/j2se-project/3:javac
Trying to override old definition of task http://www.netbeans.org/ns/j2se-project/3:depend
Trying to override old definition of task http://www.netbeans.org/ns/j2se-project/3:junit-prototype
Trying to override old definition of task http://www.netbeans.org/ns/j2se-project/1:nbjpdastart
Trying to override old definition of task http://www.netbeans.org/ns/j2se-project/3:debug
Trying to override old definition of task http://www.netbeans.org/ns/j2se-project/1:java
javac: invalid target release: 20
Usage: javac <options> <source files>
use -help for a list of possible options

BUILD FAILED
F:\Javadev\house\BrierCalc\nbproject\build-impl.xml:1105: The following error occurred while executing this line:
F:\Javadev\house\BrierCalc\nbproject\build-impl.xml:346: Compile failed; see the compiler error output for details.

Total time: 0 seconds

It seems to suggest that it is using a different javac version to that used by Netbeans. I would have thought that it would leave it to ANT to work out, I finally got both to use the same version of ANT but now I've hit this I can't get any further. Netbeans says it is using JDK20 so I cannot see why this is an issue.
 
Saloon Keeper
Posts: 15630
366
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Honestly, with Ant the causes can be so diverse that I'm not even going to venture a guess.

You will save yourself a LOT of pain, effort and time if you invest a little bit in converting your projects to Maven. Benefits of Maven include:

  • Configuration is really quite simple.
  • The build will be the reproducible, regardless of your environment.
  • Dependencies are downloaded and gathered for you.
  • You can easily declare dependencies on other home grown libraries.
  • If you want to clean up build artifacts (JARs), you can run a command that will do it all for you.
  • It's quite easy to copy an application with all its dependencies into a single directory.

  • And all of the above without the use of batch scripts.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks Stephan,
    It seems to me a bit sad that the solution to a simple compilation problem is: port all your apps to a new IDE, rebuild the whole thing, learn the IDE, then find out how to do the simple thing you started with.

    Still, I have felt pressure to move to Maven before (I resisted because I don't like building on multiple things, now I'm going to be dependent on Netbeans and Maven), I think I have to give in and do it.
    So I downloaded Maven, installed it, set my JAVA_HOME and it all seems to work. I went into NB and created a new Maven project, copied my code over and it fails because the dependencies are wrong. How do you add a dependency? It's easy... you just add the Group ID (don't know what that  is), add the Artifact ID (that neither), Version (don't care), Type (?).
    It has a search button down the bottom so I entered Hikari (because that's the jar file I want to add). It's still searching several hours later.

    Do you know where I can find a simple intro to Maven which will tell me something simple like that?
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Maven is not an IDE. It's a build tool. You'd still use NetBeans as your IDE. The bonus is that NetBeans and Maven work very well together, as NetBeans natively understand Maven.

    The culprit in this story is Ant. Ant builds can become terribly complex, to the point that it's almost impossible to diagnose a "simple compilation problem".

    The Maven site itself has very good guides. Read these in order:

    https://maven.apache.org/guides/getting-started/maven-in-five-minutes.html
    https://maven.apache.org/guides/getting-started/index.html

    Then when you get more familiar with Maven, read this:

    https://maven.apache.org/pom.html

    As for your current problem: I can give you an example, but you need to tell us what library your project depends on.

    Finally, a bit of explanation of coordinates and scopes:

  • groupId is the identifier of the organization that created the library.
  • artifactId is the identifier of the library itself.
  • version should be self-explanatory. I don't know why you don't care about the version.
  • type is what the library is packaged as, for instance, jar, war, zip, pom, etc. Usually you can leave this empty, as the default is what you want.
  • Then there's scope, which determines at what point the dependency is used:


  • compile (default) means it's used for compilation and runtime.
  • test means it's used to compile and run your tests only.
  • runtime means your project doesn't rely on the library for compilation, but the library must be available at runtime.
  • provided means the library is used for compilation, but unlike compile, it doesn't get bundled with your application for runtime.
  •  
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks Stephan,
    I'll go off & read those tutorials. Hopefully that'll get me through it!
    Regards,
    Neil
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:I entered Hikari (because that's the jar file I want to add).


    Sorry, I missed this. This is likely what you need:

    I left out type, because typically you want the default (which for most libraries is jar).

    I left out scope, because typically you want the default compile scope.

    Note though that in general for connection pools in web applications, you don't want to bundle a connection pool with your application, but rather depend on DataSource and have your application container provide a connection pool.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks again Stephan,
    I can't immediately make that work, I think it goes in the POM somewhere but wherever I put it it seems to fail to compile. Not to worry, I'm sure everything will become clear when I do the tutorials.
    Meanwhile can you just answer the million dollar question... when I've got everything working in Maven how do I call it from a batch file to do the compilations and copy across the executables? I don't need detailled instructions I just want to be sure that after all of this extra stuff I will be able to do what I want!

    Thanks Again,
    Neil
     
    Saloon Keeper
    Posts: 27884
    198
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I resisted moving from Ant to Maven for a long time myself. With Ant, I knew exactly what was going on. Maven did a lot of its work by "magic". Plus Maven forced me to use a standardized project directory structure foreign to how I'd traditionally laid out my projects.

    But now that it has been mentioned, Maven support in modern IDEs is probably far superior to Ant's. Some IDEs also support gradle, but gradle is sort of a "super-Maven", so many of the same rules apply there as well.

    The heart of an Ant project is its build.xml file(s). The heart of a Maven project is its pom.xml file, which is always located in the project root directory.

    The full structure of a POM file is documented at the maven.apache.org website, but two of its most important components are the project descriptor and the dependencies list.

    The project descriptor names the project by vendor-id and project name (more or less) as well as provides a specific version ID. Maven makes projects maintainable over time by building discrete immutable versions that can be cataloged in a Maven repository, which can either be local, site-wide or on the master Maven repository, depending on how widely you want to share them. The project descriptor also indicates what type of standardized assembly you are building, be it JAR, WAR, EAR, or whatever. Unlike Ant, a Maven project primarily only produces one component. You can inter-link Maven projects if, for example you are building an EAR containing multiple WARs and other components, with each component being a separate Maven project.

    The dependencies part is convenient because rather than having to keep - and maintain - a complete collection of libraries used by the project, you can pull them in by their Maven repository IDs. You can also define the scope of the dependencies. For example, some dependencies are required only to compile a project because when the project assembly is deployed into production, the referenced classes are already built into the server. Most JEE classes are like that, especially for full-stack JEE servers.

    Maven works using goals and one of the "magic" bits comes from the fact that there's no way to actually list all possible goals. Fortunately there are primary goals which are documented (you can also make your own goals, but that's an advanced topic). So for example the following command:

    This invokes 3 goals:

    1. clean, which deletes everything under the project's target directory, where both intermediate work and the final product are built.
    2. compile, which runs the source file compilations, and places the compiled classes under the target directory for later use
    3. jar:jar, which takes the compiled classes, combines them with files under the project's /src/main/resources directory and builds a JAR file from them under the target diretory.

    Note that "jar:jar" invokes a specific sub-goal of the "jar" goal. There are others documented for doing stuff like building an "exploded" (unzipped) version of the JAR.

    In many cases, a goal can implicitly run predecessor goals. Something like "mvn assembly" might run both the compile and jar:jar goals automatically to produce the final assembled JAR.

    There are support goals, as well, such as the "deploy" goal, and diagnostic goals such as the dependency-charting goals. Maven is very powerful.

    Maven is a 100% Java application, and IDEs typically run it as just another Java application. Except that in this case, the application is building your application!
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:Meanwhile can you just answer the million dollar question... when I've got everything working in Maven how do I call it from a batch file to do the compilations and copy across the executables?


    To run Maven from a command line interface, you call "mvn" with a list of "phases" and "goals".

    A phase is a part of a build lifecycle. The default lifecycle consists of the following phases:

  • validate
  • initialize
  • generate-sources
  • process-sources
  • generate-resources
  • process-resources
  • compile
  • process-classes
  • generate-test-sources
  • process-test-sources
  • generate-test-resources
  • process-test-resources
  • test-compile
  • process-test-classes
  • test
  • prepare-package
  • package
  • pre-integration-test
  • integration-test
  • post-integration-test
  • verify
  • install
  • deploy

  • If you run a phase, it automatically runs all phases before it, so you don't need to list all phases you want to run, just the last one.

    It's typical to run one of the following commands:
    or
    depending on whether you want to install your build artifact into the local repository after building it.

    By the way, the clean phase is not part of the default lifecycle, but rather of the clean lifecycle. That's why you list it in addition to the verify or install phases.

    A phase by itself doesn't really do anything. However, every phase is associated with one or more "goals". A goal is like a small command that does the actual work. Besides listing phases to run with the mvn command, you can also list individual goals. Tim gave an example that included the jar:jar goal.

    Goals are provided by build plugins. A plugin is like a dependency that is used by Maven during the build. You can use custom plugins to modify how your project is built. So instead of running a batch file with multiple commands, you just add plugins to your Maven build, and then build the whole thing by running "mvn clean verify".

    We can propose what plugins to add to your build, but you have to tell us what you expect the final result to look like. Just a folder that contains your application and all its dependency JARs?
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks Stephan (and others),
    I'm frantically reading up but I'm keen not to make a fundamental error.
    I want to carry on using Netbeans (it seems OK).
    I have a number of NB Projects that all use one key Project.
    What I want to do is be able to test it in isolation (& make a mess of it) and then (when I've fixed it & tested it) do a release which copies the executables (jar) files across to the 'run' directory and put the central JAR into the lib directory.

    Is it as simple as it sounds?
    I got the central library to compile but I'm currently stuck trying to work out how to tell NB to add the central project to this one as a dependency. It was easy in the old world but I'm about 15 pages in and yet to work out how to do this.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Doh! I hadn't tried it since getting the central lib to compile. Yes it is easy, same as before!
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    OK, it compiled. That bit was successful, this is the build:
    cd F:\Javadev\Maven\Slicer; "JAVA_HOME=C:\\Program Files\\Java\\jdk-20.0.1" cmd /c "\"C:\\Program Files (x86)\\NetBeans-17\\netbeans\\java\\maven\\bin\\mvn.cmd\" \"-Dmaven.ext.class.path=C:\\Program Files (x86)\\NetBeans-17\\netbeans\\java\\maven-nblib\\netbeans-eventspy.jar\" clean install"
    Scanning for projects...

    ------------------------< com.mycompany:Slicer >------------------------
    Building Slicer 1.0-SNAPSHOT
    --------------------------------[ jar ]---------------------------------

    --- maven-clean-plugin:2.5:clean (default-clean) @ Slicer ---
    Deleting F:\Javadev\Maven\Slicer\target

    --- maven-resources-plugin:2.6:resources (default-resources) @ Slicer ---
    Using 'UTF-8' encoding to copy filtered resources.
    skip non existing resourceDirectory F:\Javadev\Maven\Slicer\src\main\resources

    --- maven-compiler-plugin:3.1:compile (default-compile) @ Slicer ---
    Changes detected - recompiling the module!
    Compiling 4 source files to F:\Javadev\Maven\Slicer\target\classes

    --- maven-resources-plugin:2.6:testResources (default-testResources) @ Slicer ---
    Using 'UTF-8' encoding to copy filtered resources.
    skip non existing resourceDirectory F:\Javadev\Maven\Slicer\src\test\resources

    --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ Slicer ---
    Nothing to compile - all classes are up to date

    --- maven-surefire-plugin:2.12.4:test (default-test) @ Slicer ---
    No tests to run.

    --- maven-jar-plugin:2.4:jar (default-jar) @ Slicer ---
    Building jar: F:\Javadev\Maven\Slicer\target\Slicer-1.0-SNAPSHOT.jar

    --- maven-install-plugin:2.4:install (default-install) @ Slicer ---
    Installing F:\Javadev\Maven\Slicer\target\Slicer-1.0-SNAPSHOT.jar to C:\Users\NeilB\.m2\repository\com\mycompany\Slicer\1.0-SNAPSHOT\Slicer-1.0-SNAPSHOT.jar
    Installing F:\Javadev\Maven\Slicer\pom.xml to C:\Users\NeilB\.m2\repository\com\mycompany\Slicer\1.0-SNAPSHOT\Slicer-1.0-SNAPSHOT.pom
    ------------------------------------------------------------------------
    BUILD SUCCESS
    ------------------------------------------------------------------------
    Total time:  2.093 s
    Finished at: 2023-09-12T17:47:43+01:00
    ------------------------------------------------------------------------

    But then when I try to run it it says:
    cd F:\Javadev\Maven\Slicer; "JAVA_HOME=C:\\Program Files\\Java\\jdk-20.0.1" cmd /c "\"C:\\Program Files (x86)\\NetBeans-17\\netbeans\\java\\maven\\bin\\mvn.cmd\" -Dexec.vmArgs= \"-Dexec.args=${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}\" -Dexec.appArgs= -Dexec.mainClass=com.mycompany.slicer.Slicer \"-Dexec.executable=C:\\Program Files\\Java\\jdk-20.0.1\\bin\\java.exe\" \"-Dmaven.ext.class.path=C:\\Program Files (x86)\\NetBeans-17\\netbeans\\java\\maven-nblib\\netbeans-eventspy.jar;C:\\Program Files (x86)\\NetBeans-17\\netbeans\\java\\maven-nblib\\netbeans-cos.jar\" org.codehaus.mojo:exec-maven-plugin:3.1.0:exec"
    Running NetBeans Compile On Save execution. Phase execution is skipped and output directories of dependency projects (with Compile on Save turned on) will be used instead of their jar artifacts.
    Scanning for projects...

    ------------------------< com.mycompany:Slicer >------------------------
    Building Slicer 1.0-SNAPSHOT
    --------------------------------[ jar ]---------------------------------

    --- exec-maven-plugin:3.1.0:exec (default-cli) @ Slicer ---
    Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.net.URL.toExternalForm()" because "location" is null
    at java.desktop/javax.swing.ImageIcon.<init>(ImageIcon.java:232)
    at com.mycompany.slicer.SlicerFE.initComponents(SlicerFE.java:813)
    at com.mycompany.slicer.SlicerFE.<init>(SlicerFE.java:41)
    at com.mycompany.slicer.Slicer.main(Slicer.java:15)
    Command execution failed.
    org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
       at org.apache.commons.exec.DefaultExecutor.executeInternal (DefaultExecutor.java:404)
       at org.apache.commons.exec.DefaultExecutor.execute (DefaultExecutor.java:166)
       at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:1000)
       at org.codehaus.mojo.exec.ExecMojo.executeCommandLine (ExecMojo.java:947)
       at org.codehaus.mojo.exec.ExecMojo.execute (ExecMojo.java:471)
       at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
       at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute2 (MojoExecutor.java:370)
       at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:351)
       at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
       at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:171)
       at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:163)
       at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
       at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
       at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
       at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
       at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:298)
       at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
       at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
       at org.apache.maven.cli.MavenCli.execute (MavenCli.java:960)
       at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:293)
       at org.apache.maven.cli.MavenCli.main (MavenCli.java:196)
       at jdk.internal.reflect.DirectMethodHandleAccessor.invoke (DirectMethodHandleAccessor.java:104)
       at java.lang.reflect.Method.invoke (Method.java:578)
       at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
       at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
       at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
       at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
    ------------------------------------------------------------------------
    BUILD FAILURE
    ------------------------------------------------------------------------
    Total time:  1.953 s
    Finished at: 2023-09-12T17:45:54+01:00
    ------------------------------------------------------------------------
    Failed to execute goal org.codehaus.mojo:exec-maven-plugin:3.1.0:exec (default-cli) on project Slicer: Command execution failed.: Process exited with an error: 1 (Exit value: 1) -> [Help 1]

    To see the full stack trace of the errors, re-run Maven with the -e switch.
    Re-run Maven using the -X switch to enable full debug logging.

    For more information about the errors and possible solutions, please read the following articles:
    [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

    I looked up the error which says it's something to do with a plugin but gives no indication which one. It says I can run maven with -e to get more info but how you do that from within NetBeans is unclear to me. There is no variable called location so I'm not sure what it's on about. This project does use an icon which is in slicer.resources, I can't think what else might have caused this.
    Sorry to be a pain, any help greatly appreciated, I'm sure if I can get this working the others will be a breeze!

     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Oh, that's really annoying. I went into NB and refreshed the icon. It all works now!
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:I have a number of NB Projects that all use one key Project.


    Yeah, that's fine. You'd just list that project as a dependency of your other projects.

    What I want to do is be able to test it in isolation (& make a mess of it) and then (when I've fixed it & tested it) do a release which copies the executables (jar) files across to the 'run' directory and put the central JAR into the lib directory.


    Run "mvn clean verify" to compile and test your library. If you're happy, run "mvn clean install" to do the same thing (compiling and testing), but additionally to install it in Maven's local repository on your system. Your other projects will be able to find the shared library in your local repository.

    You can have multiple versions of your library (or ANY library, really) in your local repository. You just gotta bump the version number.

    Note that you don't really need to copy any libraries to some sort of "run" directory. When you use the maven-exec-plugin to run an application, Maven will automatically put all of the application's required dependencies on the class path. This is also the plugin that NetBeans uses to run a Maven application. To run the application from a command line interface manually, you could use the following command:

    It means: run the exec goal of the exec-maven-plugin artifact by the org.codehaus.mojo group.

    There is an easier way to run this particular goal though:

    It works because the org.codehaus.mojo and the org.apache.maven group IDs are special: you don't need to explicitly specify them when calling or configuring a plugin.

    Furthermore, if a plugin has an artifact ID that has the format maven-<name>-plugin or <name>-maven-plugin, you can call it by just specifying the <name> part.

    Now, I understand that this is nice and all for when you're developing locally, but if you want to release an application to your clients, you might want to gather all of the application's dependencies into a folder. I'll show you how to do this in a later post.

    I got the central library to compile but I'm currently stuck trying to work out how to tell NB to add the central project to this one as a dependency.


    Your shared library has a groupId, artifactId and version that you assigned to it in your POM. You must use these coordinates to list this library as a dependency in your other projects. You do this in the <dependencies> section of your POM.

    I looked up the error which says it's something to do with a plugin but gives no indication which one.


    It's a bit hard to see, but the exec-maven-plugin is just forwarding a runtime exception:

    It's likely that you initialized location with a value returned from Class.getResource(), but the icon that you're trying to load isn't in the correct location.

    It says I can run maven with -e to get more info but how you do that from within NetBeans is unclear to me.


    Usually the error message that Maven spits out should give you enough information to be able to figure out where the issue is. You just need a little bit of practice in reading the error messages.

    Sometimes you really do need to run Maven with the -e or -X switches though. I find it easiest to just do this from the command line, so I don't get WAY too much information whenever I'm building in NetBeans. If you really want all the verbose debugging information in NetBeans though, you can right-click your project and go to Actions. Here you can configure what commands NetBeans should execute when performing actions such as "Debug Project". Just add the switch to this command.

    Oh, that's really annoying. I went into NB and refreshed the icon. It all works now!


    Please share the pom.xml of your shared library with us, and the pom.xml from your dependent project. Even if it works currently, it's likely that we can suggest some things for you to tweak.
     
    Tim Holloway
    Saloon Keeper
    Posts: 27884
    198
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    What I want to do is be able to test it in isolation (& make a mess of it) and then (when I've fixed it & tested it) do a release which copies the executables (jar) files across to the 'run' directory and put the central JAR into the lib directory.



    Stephan has already said this, but I'm going to try and say it in a way that's shorter and (I hope) clearer. In a Maven project, you don't have a "lib" directory where you keep external libraries used to build your target. Instead you have a Maven repository. The Maven repository generally resides under the ".m2" subdirectory of your home directory, so a typical JAR might be found like this:

    $HOME/.m2/repos/org/apache/tomcat/catalina/6.0.53/

    Where the "6.0.53" subdirectory contains a "catalina.jar", and various other support files, including a pom.xml that indicates what sub-dependencies that version of catalina.jar requires.

    Maven is very big on versioning. You cannot replace a given version of a product with another one and give it the same version number. The closest exception to that is "snapshot" versions, but that's beyond our scope here.


    Basically, instead of a "lib" directory and a separate copy of the JAR in each project, like Ant does, you do a "mvn install" to install that library in your local Maven repository, and use its name - and version - as a dependency in the POMs of any projects that require it.

    And yes, it's a good idea when building a library JAR to include unit tests. Maven can use the "test" goal to compile and run tests found under the project's /src/test/java directory and using /src/test/resources as part of the test classpath. That keeps your test classes from getting dumped into the library copy that you install once it has passed testing.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks Guys,
    OK, I got my slicer app to compile and run in Netbeans using Maven.

    I currently have a JRun directory where all my active JARs are held. Normally at this point I would copy the JAR file from the DIST directory to the JRun directory where is is called by clicking icons or Task Scheduler.

    Under Maven I don't have a DIST directory and the JAR file does not have a standard name (it has the version number in it). It also doesn't run from the command line (no main manifest attribute, in Slicer-1.0-SNAPSHOT.jar). I tried mvn exec:exec from a command line in the Slicer directory but it failed with 'Build Failure'. I don't want to build it, I want to run it!

    From what Tim says above I'm thinking that I always now have to run my app from mvn (so I have to have that installed on all machines that will run it - a big negative) and then I call mvn install but looking at Netbeans that is what it does, the action says install which means it's always going to run the version I'm working on, not the current release.

    There's clearly something major that I'm missing here, how do I migrate a finished project to a runnable JAR file? Sorry if I'm being a bit thick! It feels like I am!
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:Thanks Guys,I currently have a JRun directory where all my active JARs are held. Normally at this point I would copy the JAR file from the DIST directory to the JRun directory where is is called by clicking icons or Task Scheduler.


    Will the same "JRun" directory also be deployed to other machines, with the same content? If so, then you should probably create an "aggregator" project that lists all modules that need to be included, and then add a module to it whose build artifact will be a "JRun" zip file.

    I will give you an example of how to achieve this later, but you first need to tell me what the contents of this JRun directory are, where the contents (used to) come from, and how you deploy it to other machines.

    Under Maven I don't have a DIST directory and the JAR file does not have a standard name (it has the version number in it). It also doesn't run from the command line (no main manifest attribute, in Slicer-1.0-SNAPSHOT.jar).


    You can modify the name of the final build artifact using <finalName> in the <build> section. I will include this in the example I will give you later, but first you must show us the pom.xml from your shared library, and the pom.xml from one of your projects that depend on the shared library.

    From what Tim says above I'm thinking that I always now have to run my app from mvn (so I have to have that installed on all machines that will run it - a big negative) and then I call mvn install but looking at Netbeans that is what it does, the action says install which means it's always going to run the version I'm working on, not the current release.


    No. While it certainly is an option to bundle Maven with your deployment, you can also easily avoid this by creating executable JARs by just adding some plugins to your builds. But once again, you need to show me your pom.xml files so I can give you a good example on how to do this.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks Stephan,
    I've attached my pom, it's not very exciting. Basically this is the simplest project I have and it includes the main central library. I use it by clicking on an icon which fires F:\JRun\Slicer.jar.
    So the JRun folder just has all of my JAR files in it and a lib directory containing all the JAR files required to run (including the Central.jar file).
    To put this on other machines I just copy the whole JRun directory and everything runs. Simple!

    I'm thinking that just changing the name to remove the snapshot & version number bits will not make it runnable!

    Netbeans (looking at the actions 'clean & build') does an install so I'm not sure why it isn't setting up a directory with a runnable JAR in it, I guess I haven't told it to and I guess you do that in the POM but how and what the syntax is I can't seem to find in the documentation. All they seem to talk about is running it from within Maven, I don't want to put Maven on my other machines. For one they aren't connected to the internet (security!) so this will give me a whole new world of pain when maven tries to download everything (I'm just not going there).

    It doesn't sound like I'm trying to do anything complicated. It seems very difficult!
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    OK, I went to attachments and did upload. Did that work? I don't see the attachment. This is the POM:
     
    Tim Holloway
    Saloon Keeper
    Posts: 27884
    198
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    There's more there than I can easily read, much less address, but as to your JAR collection, The Maven Way involves taking your JARs and installing them as artefacts in your Maven repository. It's a simple Maven command and I use it to manage resources that are not on the universal Maven repository such as IBM's DB2 JDBC driver. At that point, they look just like any other Maven dependency.

    If you want Maven resources shared between many local machines, but not on the general public Maven Repository, you can run a site repository server such as Nexus. Artefacts installed in a Nexus repository will be automatically downloaded to people's local repository caches as needed. Nexus also acts as a proxy to the upstream Maven repositories, so it reduces the burden on the Internet (and global Maven repos) if you have dozens of developers.

    I do not normally install straight from Maven. I may simply copy the target product to wherever I need it. Or, for a lot of stuff, I may have Maven produce an installable OS package and use that. I often package webapps that way, since an RPM package can automatically create files that a webapp might need that are not creatable by the webapp itself, such as a local storage for uploaded files (which should NEVER be uploaded to the WAR directory!!!).

    Maven actually has some powerful deployment plugins that can hook into things like your source code control system, be it local or something like github.

    Another option is to use a full automation server such as Jenkins. Jenkins can do the Maven builds, publish test results, and deploy build products.

    In short, while I use Maven as my build tool, I don't often put it in charge of every stage of my projects.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks Tim,
    Can I focus on " I may simply copy the target product to wherever I need it." How do you do that? It sounds like exactly what I want to do. I guess you change the POM to add something to say where to put it and how to build it. Can I get Netbeans to do that for me or do I have to edit the POM? What do you copy? From where to where. I want to copy it from the Maven equivalent of the old DIST directory to my JRun folder.
    I like having a clearly defined break between my development area (which maybe chaotic) and my run area which will have finished products. I also like having a runnable environment on other machines where I can clearly see the version they are running and can update it from the development machine. It sounds like all of this is acheiveable but how to actually do it seems opaque at the moment :-(
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I've been reading this: https://www.w3docs.com/snippets/java/how-can-i-create-an-executable-runnable-jar-with-dependencies-using-maven.html#:~:text=To%20create%20an%20executable%20JAR,into%20a%20single%20JAR%20file.&text=This%20configuration%20creates%20an%20executable%20JAR%20file%20with%20the%20name%20%24%7Bproject.

    Following this I have created 'build' section in my POM. It builds OK and builds a huge JAR file (allegedly including all of it's dependencies). It won't run because there is something wrong with the icon again:
    F:\Javadev\Maven\Slicer>java -jar target\Slicer-1.0-SNAPSHOT-jar-with-dependencies.jar
    Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.net.URL.toExternalForm()" because "location" is null
           at java.desktop/javax.swing.ImageIcon.<init>(ImageIcon.java:232)
           at com.mycompany.slicer.SlicerFE.initComponents(SlicerFE.java:813)
           at com.mycompany.slicer.SlicerFE.<init>(SlicerFE.java:41)
           at com.mycompany.slicer.Slicer.main(Slicer.java:15)

    Also this happens now every time I Clean&Build my Netbeans app, how do I switch between building whilst I'm developing and then later, releasing the current state of everything? Do I have to edit the POM every time?

    New POM:
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    No, you shouldn't have to edit your POM.

    Your problem is caused by your icon being in the wrong location. Show us SlicerFE.initComponents, and tell us where in your project structure the icon is located.

    Anyway, I created an example project for you to take a look at: https://github.com/nibsi/JRun

    After you build the project with Maven, check out the jrun-assembly/target directory.

    I will give a detailed explanation later.
     
    Tim Holloway
    Saloon Keeper
    Posts: 27884
    198
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Maven puts all of its products (including intermediate work files in the project's /target directory. So if you use Maven to build a JAR named "foo", a "mvn clean compile jar:jar" command or one of the more direct goals that I can't recall offhand should have at least 2 items in the /target directory: /target/foo and /target/foo.jar. The /target/foo directory should be what Maven zips up to create the JAR file itself and should contain the compiled classes. Allowing for memory rot on my part.

    You can copy the /target/foo.jar file directly. That's what the maven deployment goals do, for that matter. It's a matter of who does what.

    The /target directory contains all of the files generated by Maven. It is the ONLY part of a Maven project that should change (I'm not counting stuff like source code editing here, just temporary build stuff and the final product). In fact the mvn clean goal simply deletes the /target directory, since everything can be rebuilt.

    This is a tremendous plus for Maven, since it means I can do a "mvn clean", ZIP up the post-cleanup project and ship it to, say Devaka in Sri Lanka and he can completely build an identical version of the project using only the JDK and Maven. Mave's versioning feature means that he will always be getting the right versions of the right libraries.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks Stephan & Tim,
    I do believe I'm getting somewhere! I can compile it in Netbeans and run it. I've put the icon in the lib directory, I would prefer it to be part of the project (it used to live in the resources directory) but Maven seems to have a problem with this and can't find it. However it can find it if it's simply an external file. I can live with that.
    Tim, you say I can copy the jar in the target directory anywhere and that's true but it won't run, it just crashes so there's no point in copying it anywhere.
    Stephan, I copied you files down to my PC and ran it from the command line:
    I:\cak\mvntest\JRun-main\JRun-main>dir /s *.jar
    Volume in drive I is FastSmall
    Volume Serial Number is 590F-513A

    Directory of I:\cak\mvntest\JRun-main\JRun-main\jrun-common\target

    13/09/2023  17:29             2,192 jrun-common-1.0-SNAPSHOT.jar
                  1 File(s)          2,192 bytes

    Directory of I:\cak\mvntest\JRun-main\JRun-main\jrun-slicer\target

    13/09/2023  17:29             2,601 Slicer.jar
                  1 File(s)          2,601 bytes

        Total Files Listed:
                  2 File(s)          4,793 bytes
                  0 Dir(s)  194,043,629,568 bytes free

    I:\cak\mvntest\JRun-main\JRun-main>cd jrun-slicer

    I:\cak\mvntest\JRun-main\JRun-main\jrun-slicer>java -jar target\Slicer.jar
    Exception in thread "main" java.lang.NoClassDefFoundError: com/mycompany/common/Greeter
           at com.mycompany.slicer.Slicer.main(Slicer.java:10)
    Caused by: java.lang.ClassNotFoundException: com.mycompany.common.Greeter
           at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
           at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
           at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
           ... 1 more

    This is familiar as it's what I now get when I try to run the jar file outside of NB.
    This is my Slicer program:
    F:\Javadev\Maven\Slicer>java -jar target\Slicer-1.0-SNAPSHOT.jar
    Exception in thread "main" java.lang.NoClassDefFoundError: com/mycompany/Central/DBHandler
           at com.mycompany.slicer.SlicerFE.<init>(SlicerFE.java:46)
           at com.mycompany.slicer.Slicer.main(Slicer.java:15)
    Caused by: java.lang.ClassNotFoundException: com.mycompany.Central.DBHandler
           at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
           at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
           at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
           ... 2 more
    DBHandler is the interface to the DB and calls the Hikari system. If I go to Dependencies for Slicer I can see the Central project listed and DBHandler is there but for some reason it can't find it! And yet it runs inside NB!
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Incidentally, I've just noticed that my C: drive is about to overflow! It seems that Maven has been putting stuff in a repository over there. Where is this configured? I've tried NB settings and Project Properties but can't see it. Is it a setting within Maven and how do I change it?
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    I put an extra bit in my POM after looking at how to generate an executable :
       <build>  
           <plugins>  
               <plugin>  
                   <!-- Build an executable JAR -->  
                   <groupId>org.apache.maven.plugins</groupId>  
                   <artifactId>maven-jar-plugin</artifactId>  
                   <version>3.1.0</version>  
                   <configuration>  
                       <archive>  
                           <manifest>  
                               <mainClass>com.mycompany.slicer.Slicer</mainClass>  
                           </manifest>  
                       </archive>  
                   </configuration>  
               </plugin>  
           </plugins>  
       </build>
    This means I don't get "no main manifest attribute, in Slicer-1.0-SNAPSHOT.jar" but I still get the error above :-(
     
    Tim Holloway
    Saloon Keeper
    Posts: 27884
    198
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:Incidentally, I've just noticed that my C: drive is about to overflow! It seems that Maven has been putting stuff in a repository over there. Where is this configured? I've tried NB settings and Project Properties but can't see it. Is it a setting within Maven and how do I change it?


    You're quite right. A few projects and before you know it, your local repository cache is easily a gigabyte or 2.

    You can relocate the ".m2" directory by setting a MAVEN_HOME environment variable. You can also relocate just the repository by changing the localRepository attribute in the .m2 comfig file.

    In linux, I think I just allocated a disk logical volume specifically for the repositories and mounted it as $HOME/.m2/repos, but I don't think that's an option for Windows.
     
    Tim Holloway
    Saloon Keeper
    Posts: 27884
    198
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:Thanks Stephan & Tim,
    I do believe I'm getting somewhere! I can compile it in Netbeans and run it. I've put the icon in the lib directory, I would prefer it to be part of the project (it used to live in the resources directory) but Maven seems to have a problem with this and can't find it. However it can find it if it's simply an external file. I can live with that.


    Put the icon in /src/main/resources The app will be able to locate it via getResource(). For a JAR, it will live in the root of the JAR file. If you want it in a class package. create a package path directory structure under /src/main/resources.

    I'm hoping that that stuff I haven't read yet told you why the JAR didn't execute, but the target JAR is the exact same file that the deployer would publish, so there should be no difference in operation.

    Maven does require extra POM specs to build a self-executing JAR, but that's because JAVA doesn't read classes from JARs inside other JARs. A special classpath modifier has to do that and the Maven "executable jar" plugin handles that.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:I've put the icon in the lib directory, I would prefer it to be part of the project (it used to live in the resources directory) but Maven seems to have a problem with this and can't find it.


    Yes, the icon can be part of the project. You just need to put it in the correct location and then retrieve it in the correct manner. I asked you to show us your SlicerFE.initComponents method before. If you show it to us we can help you figure out what was wrong.

    DBHandler is the interface to the DB and calls the Hikari system. If I go to Dependencies for Slicer I can see the Central project listed and DBHandler is there but for some reason it can't find it! And yet it runs inside NB!


    The jrun-slicer/target directory contains only the JAR for the Slicer application. It doesn't contain any of the dependencies, and neither should it. The files you're looking for are in jrun-assembly/target.

    If you go to the jrun-assembly/target directory, it will contain three archives that were assembled from the application and shared libraries in the other projects. If you unpack one of them, you'll find a directory structure that mimics what you originally intended. Inside the unpacked JRun directory, just run the following command:

    You'll find that it prints "Hello World!".


    To see why it works, open Slicer.jar with an archiver and open META-INF/MANIFEST.MF. It contains the following entries:

    As you can see, it requires the shared library to be in the lib folder next to Slicer.jar. These entries were added by the maven-jar-plugin in the jrun-slicer project.

    The jrun-assembly project then builds archives containing the Slicer application and the required dependencies inside a lib folder using the maven-assembly-plugin.

    If you want the jrun-assembly/target folder to contain an unpacked directory containing the distribution, just add <format>dir</format> to the maven-assembly-plugin configuration in the jrun-assembly project.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Wahoo! Some progress! I found the settings.xml file that is in use in:
    C:\Program Files (x86)\NetBeans-17\netbeans\java\maven\conf
    By changing this I managed to move the m2 repository off of the C: drive which is good.

    Stephan, Thanks for the advice on the icon thing, I'll get to that later but first I want to get the thing to run! (It currently will run with the icon defined in a seperate folder). I'll try to attach my SlicerFE init to this but it doesn;t seem to accept any file extension! I followed through your message and everything worked until the last bit: "If you want the jrun-assembly/target folder to contain an unpacked directory containing the distribution, just add <format>dir</format> to the maven-assembly-plugin configuration in the jrun-assembly project." How do I do that within NetBeans? Is it in the POM (presumably the one for Slicer) or somewhere else?

    So now I'm trying to build a runnable jar file in my repository. It builds and runs within Netbeans so it should be ready to go. I found the resulting jar file and this is what happens when I run it...

    E:\MavenHome\repo\com\mycompany\Slicer\1.0-SNAPSHOT>java -jar Slicer-1.0-SNAPSHOT.jar
    Exception in thread "main" java.lang.NoClassDefFoundError: com/mycompany/horsey/DBHandler
           at com.mycompany.slicer.SlicerFE.<init>(SlicerFE.java:46)
           at com.mycompany.slicer.Slicer.main(Slicer.java:15)
    Caused by: java.lang.ClassNotFoundException: com.mycompany.central.DBHandler
           at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
           at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
           at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
           ... 2 more

    So it can't find the DBHandler class which is in the Central Jar file. I'm just trying to think this through, is there something I need to do with any sort of CLASSPATH variable? I don't have any such variable declared, is it needed? Should it be set to the repository? Is this documented anywhere? I went through the documentation you sent me at teh start and can't see anything about setting it up.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Stephan asked for my initcomponents from slicerFE. I cannot upload it as a file (it seems they only allow images) so here it is, it's a bit long!

    I've removed everything that isn't relevant as it doesn't fit otherwise :-)
     
    Tim Holloway
    Saloon Keeper
    Posts: 27884
    198
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:
    So it can't find the DBHandler class which is in the Central Jar file. I'm just trying to think this through, is there something I need to do with any sort of CLASSPATH variable? I don't have any such variable declared, is it needed? Should it be set to the repository? Is this documented anywhere? I went through the documentation you sent me at teh start and can't see anything about setting it up.


    Yes, it looks like you need to catalog "Central.jar" into your Maven repository and make it a dependency of your project. You could even mavenize the building of "Central.jar" and use "mvn install" to do that.

    You may notice that when Maven builds an executable JAR that there will be 2 jar files in the /target directory. One will be the basic (non-executable) JAR and the other will be that JAR with the extra hooks installed that makes the second JAR executable.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Neil Barton wrote:I followed through your message and everything worked until the last bit: "If you want the jrun-assembly/target folder to contain an unpacked directory containing the distribution, just add <format>dir</format> to the maven-assembly-plugin configuration in the jrun-assembly project." How do I do that within NetBeans? Is it in the POM (presumably the one for Slicer) or somewhere else?


    It's in the POM for jrun-assembly. Again, the jrun-slicer project ONLY builds the Slicer JAR, it doesn't bundle it with any dependencies. The jrun-assembly project takes jrun-slicer as a dependency, and builds the final distribution by making an archive containing your application and its dependencies that you can ship to your clients.

    Have you already looked in the jrun-assembly/target directory? Have you already inspected the example POMs I gave you, and compared them to the build results?

    So now I'm trying to build a runnable jar file in my repository. It builds and runs within Netbeans so it should be ready to go.


    NetBeans doesn't use the JAR. It tells the exec-maven-plugin where the compiled classes are and how to run them. You wanted to build a release that doesn't require Maven to run it.

    To make NetBeans actually use the JAR, you have to do some extra configuration. But setting it up is not really worth it.

    So it can't find the DBHandler class which is in the Central Jar file. I'm just trying to think this through, is there something I need to do with any sort of CLASSPATH variable? I don't have any such variable declared, is it needed? Should it be set to the repository? Is this documented anywhere? I went through the documentation you sent me at teh start and can't see anything about setting it up.


    Read my previous post carefully. It explains how the classpath is set in the Slicer JAR itself.

    But first, all you need to do is take a look at the jrun-assembly/target folder, and see if you can unpack and run the application that was built there.

    Report whether you managed. Then we can help you adapt the example into your own project.

    Neil Barton wrote:


    Here is your problem. You shouldn't treat application icons as files on disk. Instead, you should bake them into your JAR and treat them as embedded resources.

    Put slicer.png in the following location, relative to the root of your Slicer project:

    Load your icon like this:
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Tim Holloway wrote:Yes, it looks like you need to catalog "Central.jar" into your Maven repository and make it a dependency of your project. You could even mavenize the building of "Central.jar" and use "mvn install" to do that.


    I believe the shared library is already Mavenized. The problem is getting the application to find the library at runtime, without using exec:exec.

    You may notice that when Maven builds an executable JAR that there will be 2 jar files in the /target directory. One will be the basic (non-executable) JAR and the other will be that JAR with the extra hooks installed that makes the second JAR executable.


    I think this only happens if you configure the project to build a fat JAR with the shade-maven-plugin, or similar. That's not what Neil is trying to achieve. We're trying to generate a "thin" executable JAR that refers to its dependencies through the internal Class-Path entry of its JAR Manifest, and then build a directory containing the executable and the dependencies separately.
     
    Tim Holloway
    Saloon Keeper
    Posts: 27884
    198
    Android Eclipse IDE Tomcat Server Redhat Java Linux
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Stephan van Hulst wrote:
    I think this only happens if you configure the project to build a fat JAR with the shade-maven-plugin, or similar. That's not what Neil is trying to achieve. We're trying to generate a "thin" executable JAR that refers to its dependencies through the internal Class-Path entry of its JAR Manifest, and then build a directory containing the executable and the dependencies separately.


    Hmmm. This is a bit of a mixed bag, it sounds like. Normally you wouldn't make 2 jars do the work of one unless you had something like a database explorer (SchemaSpy, for example) plus a JDBC drvier JAR(s), in which case you'd be binding at runtime, not via a Manifest. Although I suppose that if you had several thin-jar apps sharing a common JAR (for example JPA objects), that might be a good use case, though there again, it's more common to simply have multiple main classes in a single main JAR (see Apache OpenJPA's utilities, for example).

    The main thing is that Maven only produces ONE product per POM. So building a JAR and slapping another JAR in next to it isn't a Maven thing. Although it is an Ant thing, since Ant has no such restrictions. Not a good reason to use Ant, however.

    What I myself would be doing is have a super-project whose product was an RPM or whatever package manager the target OS used. An RPM, DEB, or whatever is a single product, and it's particularly well-suited for doing stuff with multiple files and directories, as I alluded when I mentioned it in regard to making deployable webapps. Otherwise, I'd just install stuff manually.

    [edit]
    "Manually" might actually mean via a provisioner such as Jenkins, Ansible, Puppet, or the like.
     
    Stephan van Hulst
    Saloon Keeper
    Posts: 15630
    366
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Tim Holloway wrote:Although I suppose that if you had several thin-jar apps sharing a common JAR (for example JPA objects), that might be a good use case


    That's exactly what OP is trying to achieve. It appears he has multiple "command-like" applications, that all share some common libraries.

    The main thing is that Maven only produces ONE product per POM. So building a JAR and slapping another JAR in next to it isn't a Maven thing.


    I agree, and I don't think the example project I made violates that. It consists of:

    jrun-parent: an aggregator project.
    jrun-common: a shared dependency.
    jrun-slicer: an application that uses the dependency.
    jrun-assembly: a project that assembles the application and its dependencies into a single archive.
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Thanks Tim,

    "Yes, it looks like you need to catalog "Central.jar" into your Maven repository and make it a dependency of your project. You could even mavenize the building of "Central.jar" and use "mvn install" to do that."
    How do I catalog "Central.jar"? It's in Netbeans as a Maven project and declared as a dependency of Slicer.
    How do I mavenise the building of Central.jar? It's in Netbeans as a Maven project. It has been compiled and runs (in as much as it can).

    Thanks Stephan,
    It looks like your JRun app is doing exactly what mine does:

    Mine does exactly the same with one of my classes from Central. There seems to be some confusion about my structure so I'll attach a diagram showing that basically there are lots of projects which all include the central project, this uses mysql, hikari and other libraries. All of these programs are called from the operating system either by clicking on an icon or from the task scheduler. Usually they are kept in a JRun folder which has a Lib folder under it where all the required JAR files are held. So what I need Maven to produce is something that can be called to run from the o/s.
    If I do what you say and unzip the file in JRun-Assembly I can run the file. This is true but doesn't help. For one, I don't know how you produced that assembly folder and two it is still hidden inside a zip. Do I need to write a batch file to extract the files I want from the zip file? Why can't Maven just put it in a folder for me unzipped?
    I did what you suggested and added <format>dir</format> in the maven plugin part of the POM, no change. I'm not sure now (my memory is getting a bit hazy) but I thought when I first started using Maven Netbeans produced a file called "Slicer-with-dependencies". It doesn't seem to do this any more. Or is it putting it somewhere that I don't know about.

    Another weird thing: despite everything else going into my MavenHome folder it still insists on putting some classes on my C: drive. These are the things like Hikari that are JARs that I've pulled in from the net (as opposed to classes that I have written). Can I stop that happening?

    This thread seems to be getting quite complicated so let me summarise my current confusion:
    How do I build a Netbeans project with another Netbeans project as a dependency and run that from the command line? (without getting the classnotfound error)
    Why is it putting jar files in my old .m2 directory on my C: drive when everything else is going to my MavenHome (E:)? How can I change that?
    Structure.jpg
    [Thumbnail for Structure.jpg]
     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    This is my current POM:

     
    Neil Barton
    Ranch Hand
    Posts: 146
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    So I went here: https://medium.com/@skywalkerhunter/make-and-run-a-jar-file-101-maven-guru-cc035f219639
    This has things I can cut & paste. This has now created a jar with dependencies which runs from the command line! Wahoo! It is nearly 6mb in size but disk space is cheap and I'm not sure I have the enthusiasm to keep playing with Maven, it's opaque to say the least. I now have some weird errors relating to slf4j which seems to be the result of using an out of date version of Hikari (which uses slf4j) but I'll get on to that.
    Still can't work out why it still wants to use my C: drive though!!!
     
    Consider Paul's rocket mass heater.
    reply
      Bookmark Topic Watch Topic
    • New Topic