I'm developing a test tool designed for a 3rd party Java application. Now, here's my problem:
The 3rd party application has many nested directories in its layout, with many jars.
It has a plugin framework that allows people to add code referencing whatever libraries they would like to use within their plugins.
When I run the test tool I'm developing, often when I use certain plugins in the 3rd party App, the test tool gives ClassNotFound exception at run time (or whatever it is). So, I can build, but I haven't gotten all the class references I need.
Is there a way I can just add the root of the 3rd part application to my class path so IntelliJ will use all the JARs it finds in that and its sub directories when it executes?
Been open a while and no alternative suggestions have been made, so closing with #CrazyCoder's comment as the answer.
The following link reports this lack of functionality; it may be addressed in newer versions of IDE:
http://youtrack.jetbrains.com/issue/IDEA-40818
Related
I think it goes without saying that I should be able to use Oracle's own JDK with JavaFX (from gluonhq) to build a distributable jar file that users can just USE.
After an exhaustive search, much reading (24 hours or more over the last few months)and finally this Google search query:
how to make a fat jar -maven -gradle -scala -eclipse -ant -docker -hadoop -netbeans -jerkar -phy -mozni -yogurt -pizza - throwing -python -bacon
I'm absolutely at the end of the road. Why on earth is this so much work? How can I build a JavaFX application and give it to people that want to actually use it without knowing anything else except how to use the application itself?
This has been answered a few times already for Maven and Gradle. Build tools make things way easier than doing it on command line, and not only because of the dependency management.
Since you ask specifically about command line, there is already a full set of instructions documented for it here: https://openjfx.io/openjfx-docs/#modular.
Non modular App
The section Non-Modular from CLI covers JavaFX non-modular projects from command line, and gives you the whole set of instructions to create an old classic fat jar, where all the dependencies, including the JavaFX ones, are bundled all together.
There is a note that warns you not to use this procedure:
Warning: This is a discouraged tedious error-prone manual process that should be avoided by using the Maven's shade plugin or the Gradle's jar task, in case jlink is not applicable.
After you get the fat jar (it can be cross-platform), you can distribute it, and your user will need to have Java installed and run:
java -jar myFat.jar
Modular App
The section Modular from CLI covers JavaFX modular projects from command line, and refers to the use of the jlink command, in terms of distribution, as it creates a custom image that you can send to your users. It is not a fat jar, but it will allow you sending a zip to your user that needs only to be unzipped and run like:
hellofx/bin/java -m hellofx/hellofx.HelloFX
In this case your user won't even need to have Java installed.
And with a little bit of extra work you can also create a batch, so you can run:
hellofx
However, if you still want to do a fat jar with a modular app, you can still apply the exact same instructions from the non-modular apps. In this case, you will probably have to remove the module-info.java file, as it doesn't really makes sense at this point.
Other options
You still have a few more options to distribute your application.
Custom Java+JavaFX image
Another option, covered in the same document, section Custom JDK+JavaFX image, explains how to create your own "JDK" that includes JavaFX. Then you will produce your jar as usual in Java 8 and you will be able to run it with:
/path/to/custom/java -jar myFat.jar
Note that there are already some JDK distributions that bundle JavaFX, like this one.
jpackage
jpackage tool is not there yet, but there is an early access: http://jdk.java.net/jpackage/, that is using Java 13-internal. The exiting documentation explains what are the command line options you need to produce a custom image or an installer.
Note that you can still use JavaFX 11 or 12 with this.
Build tools
And finally, you can still decide to use build tools (Maven or Gradle), that will really help you in many ways. See any of the linked questions above.
I have a java project where I use an external jar (not controlled by me).
Until now whenever that a new version of that library is out, I update
my project to use the more recent one, but now is required that the
project uses different versions of that library.
My problem is I don't have any clue how to do that.
How do I tell in java to make the imports according a version of a jar,
What I need to do:
int versionFlag = getVersion2use();
if(verssionFlag = 0){
use imports from last version
}else if(verssionFlag = 1){
use imports from last version 1
} else if(verssionFlag = 2){
use imports from last version 2
}
This is to be used at runtime!
This is usually something that a project will do at build time rather than dynamically at runtime.
That said, here's a good answer on how to add a jar to the system classloader dynamically at runtime, which is something you could work into your general logic above:
How should I load Jars dynamically at runtime?
With respect to imports, there's no way around the fact that you can't dynamically pick your imports. So if you're lucky the two versions have the same basic API. If that holds, add the jar to classloader as early as possible in your app and then develop like normal.
If the two versions have different a different API, however, then you're going to have to write some very convoluted code that tries building objects and almost ubiquitously catches all the many different class load / class incompatibility exceptions (such as ClassNotFoundException). Worse, you'll probably have to do this behind some sort of facade or factory architecture so that you can actually keep running software insulated from all these class loading shenanigans. In short, if the two have different APIs you may actually be better off writing two separate products.
At Runtime
Classes with the same name in the same package follow a first available rule. The first one that is on the classpath is the one that is used.
You can not easily do what you want at runtime without a wrapper program to move the libraries into and out of the system classpath before the Java application is started.
A launcher script/program that dynamically builds the classpath and only includes the version you need of each library and passes it to java -cp is the only way to do what you want at runtime.
At build time
If it is at build time, then just use something like the shade plugin in Maven to build an uberjar with all the required libraries embedded in a single .jar for each of the versions. So 3 versions would be 3 separate uberjar assemblies.
If you can do it at build time, you can use a dependency manager, like Maven.
It provides you with a means to be able to select which versions of which library you use at build-time.
If you need to do this at runtime, you might need to package all libraries in your project. You can use shading (see here) to make sure you don't get import issues, because when importing different versions of libs you end up with similar imports.
Shading can help you make for example:
com.foo.Class in jarv1
com.foo.Class in jarv2
To become
com.foo.v1.Class in jarv1
com.foo.v2.Class in jarv2
This will make sure your code can still use all libs you want.
I am experimenting with my first GWT app that uses GIN. I am essentially mimicking the exact same source code example found in their Getting Started tutorial. At the end of that tutorial, the author mentions that you need to supply the the GWT compiler with a classpath pointing to the compiled Java binaries. The example they use for doing this is done using an Ant target.
Although I will have an automated (Ant-driven) build that also emulates this build task, I want to be able to run/debug my GWT apps from inside of Eclipse without having to kick off an Ant build.
So I ask: when running my GWT app inside Eclipse (Dev Mode), how do I configure the GIN library to point to the compiled classes? Thanks in advance!
All you should need to do is add the gin.jar (and dependencies, probably just guice.jar) to your project's classpath.
It should not be required to copy these to WEB-INF/lib/, though depending on your server setup, you may require guice.jar there, but never gin.jar.
I'm trying to learn project automation and I'm using the book Pragmatic Project Automation as a guide. It's examples are in Java so I find it easier to follow it along in Java. I don't have any experience using Java or any of its IDEs. However, I've learned some C# using Visual Studio (although I'm still a beginner).
I'm having trouble understanding some parts of setting up a Java project. I'm using Netbeans IDE 7.0 on Windows 7. With Visual Studio, I have a solution with projects underneath. With Netbeans, I appear to just have a project with directories determining the rest of the structure (and the IDE to some degree)? The equivalent to Add Reference appears to be adding a source to the Classpath. There also seems to be a degree of separation between the compiler and the IDE. I'm currently in a situation where I can compile my project just fine while the IDE tells me I still have errors (and I assume this is because I have the project set up incorrectly).
I'm basically looking for analogies that will help me better understand Java project structure.
Lots of similarities between the two languages and IDEs. I spent many years in both. For starters the equivalent to 'add reference' in VS is adding a library or jar in netbeans. In respect to a reference - a jar is pretty much the same thing as a module or .dll in VS. A jar is a compiled reference. To add a reference just go to the project menu and then properties then to the libraries menu from there you can add either pre-assembled netbeans libraries, which are collections of .jar's, or a single .jar, or even a project. Once you add a reference you can import them into your class just like you would in C#.
Netbeans doesn't really have a 'solution' as VS does. You deal with individual projects. It does however have the capability to add a project as a reference so you don't have to continually re-build the references when you change something between multiple projects. It also has project groups to group similar projects.
Lastly Apache ANT is responsible for tying everything together in the background. Netbeans creates a build.xml and build-impl.xml file in the background to tell ANT how to assemble the project into a .jar.
There are my other things to cover but I thing this answers most of your questions. Does this help?
I can't speak for NetBeans, as I use Eclipse, but you are on the right track with classpath being roughly equivalent to references in the Visual Studio world. Libraries (usually .jar files) are placed on the classpath and must be there both at compile time and runtime (you specify the classpath to the compiler at compile time, and to the JVM at runtime). The classpath can contain many different entries, and they can be anywhere in the project structure (or outside of it entirely).
Java itself doesn't impose many restrictions on your project structure, although various IDEs and build tools do. The one thing that is a universal restriction in all Java environments is that source files (and class files) are placed in a directory named after the package name. So if your package name is com.test.something, then your source files will be in SRC_DIR/com/test/something, and your class files in OUT_DIR/com/test/something (note: SRC_DIR and OUT_DIR are not special variables; each IDE will have a different way to specify those directories).
Java libraires tend to heavily build-on one-another, so at some point, you'll find that the classpath entries are too many to manage manually. Before you get there, you'll want to take a look at Apache Maven or Apache Ivy which are dependency management tools. You'll need to understand how they work (either one, not both) and how to integrate them with your IDE. If you use Eclipse and Maven, m2eclipse offers fairly complete integration between the IDE and the dependency management tool.
With Netbeans, I appear to just have a
project with directories determining
the rest of the structure (and the IDE
to some degree)?
Visual Studio dictates a particular project layout and since the compiler is so tightly integrated into the IDE there's no real concept of a build script. In contrast, Java has no such structure (although certain 'best practices' have emerged such as having a 'src' directory for source files, 'lib' for libraries, 'test' for test source, etc.) and a build script is usually required to tell the compiler were to find source files and libraries, what artefacts to produce and a miscellany of other chores (running tests, deployment, creating code metrics and so forth).
In simple cases, the IDE will take care of this for you (if you follow the convention for that particular IDE) but ultimately you will probably want to take a look at a build tool to understand what's going on behind the scenes. Apache Ant and Apache Maven are both prominent offerings. Ant is very flexible whereas Maven attempts to dictate a common layout. I suggest you investigate both and see which suits.
There also seems to be a degree of
separation between the compiler and
the IDE. I'm currently in a situation
where I can compile my project just
fine while the IDE tells me I still
have errors
If your code compiles, it is correct. The IDE is simply acting in an advisory capacity (and will highlight issues beyond compiler errors, such as warning you of potential code mistakes or bad practice).
and I assume this is because I have
the project set up incorrectly
This is a possibility although, as stated above, there are many other explanations.
I've trying to use Eclipse JDT AST parsing classes. After including the initial JAR, and sorting out a couple more dependencies, it is with 7+ JARs and I still having NoClassDefFoundError exceptions. This situation arises whenever I'm trying to test libraries with little or no documentation. Trial and error seems a very dumb (and annoying) approach to solve this problem.
Is there a way to automatically sort this out using Eclipse?
Update: Later I found that adding all the JARs you have, and using Ctrl-T (to view/locate types), lets you manually locate the JAR. That was the solution that Google provided so far. Is there a better way?
If you refer to this SO question Finding unused jars used in an eclipse project, you also have:
ClassPathHelper, which can quickly focus on unresolved classes:
It automatically identifies orphan jars, blocked (obscured) classes, and much more.
The only limit is dependencies that are not defined in classes, e.g. in dependency injection framework configuration files.
I have found setting up a workspace exclusively for browsing the eclipse source code incredibly useful. In this manner, you can use PDE tools like the Plug-in Spy, bundle dependency analysis, browsing the documentation, etc much like you would your own plugin projects. I found this article at Vogella a very useful guide.
If you know which bundle your desired class is you can generate the transitive closure of dependencies by creating a new OSGi launch configuration, with just the single bundle selected. By hitting the Add Required button, you can see all bundles necessary to use the one you're interested in.
Edit:
From your question it wasn't clear as to the environment you want to run the compiler in. If you're interested in an embeddable Java compiler to be run outside of an OSGi environment, may I suggest Janino.
You could use a dependency analyzer like:
JarAnalyzer
This will parse a directory full of Jars and give you an XML output dependency map, for which there are several tools for displaying in either graphical or text form.