my application needs multiple jars to work. Since it is a desktop application i can not hold the user responsible of installing. So in my build script i unzip the jars content in to my build directory delete manifest files, compile my software and jar it again. Everything works as it should my question is are there any long term side effects to this process?
In the past, there were JARs with weird content (like the DB2 driver which contains com.ibm and com.IBM; after decompressing in a Windows filesystem, those two packages would be merged).
The only issue you need to be aware of are signed jars and other files in META-INF which might have the same name in multiple source JARs.
A simple solution for all these issues is to use One-JAR. It allows to wrap several JARs into one without unpacking them, first. And read this answer: Easiest way to merge a release into one JAR file
A simpler solution (IMO) is using Maven's assembly plugin, which is also described in one of the answers to another question which was linked to in a previous Q&A. This is provided you are using Maven (which is a recommended tool by its own right) as a build tool.
If you want a no fuss way for the end user to kick off a program with multiple jar dependencies you may want to look at Launch4j or Jsmooth (I prefer Launch4j). Both are programs that create executables that wrap jar(s) and the JRE together so that to the end user it appears no different then any other executable.
Another great option is ProGuard, which can also shrink and/or obfuscate the code too.
If your primary target platform is Windows desktop, then you could also consider generating an Windows native exe from the jars of your application
If some of the jars are signed you lose the signature by unpacking/repacking it.
Well you're throwing away the MANIFEST of your third party jars, so that could cause you problems. For example you could be causing security issues by throwing away the "Sealed" attribute.
Why not just create a simple installer and a script to launch your application which sets the CLASSPATH correctly?
One-JAR will do the job, and has a new release (0.97) which supports frameworks like Spring and Guice, which users are now packing into One-JAR archives. http://one-jar.sourceforge.net
Ference Hechler also did some great work inside Eclipse with the Eclipse export wizard: we worked together on FatJar/One-JAR from which the Eclipse work grew, and I can recommend that as an approach, though I don't know how well it handles the frameworks.
Related
I need to package a java program (with a bundle jre) into a single exe file. Until now I always used Launch4J. Launch4j only accepts one single jar though, so I always packed all external libraries into one single jar before calling launch4j.
This doesn't work with the bouncycastle libraries, since they are signed and extracting and re-packing them into the single jar damages the signature.
Signing the resulting "onejar" doesn't help, because the bouncycastle libraries expect a trusted sign authority.
I didn't find any other recent exe wrapper besides Launch4j which accepts external jars.
Any ideas?
Another solution is the oracle java (fx) packager tool. It took a bit to work for me, but at the end I think it is the best solution to this problem right now (2016) since it is quite new and gets updated from release to release. It's called javafxpackager, but it works for non-fx-applications as well. It can produce applications for Win, Mac and Linux.
See here for more details on the java(fx)packager:
http://docs.oracle.com/javafx/2/deployment/jfxpub-deployment.htm
A good overview over all the existing tools do deploy java applications can be found here:
http://www.excelsior-usa.com/articles/java-to-exe.html
I found a solution to my problem and want to explain here briefly, maybe somebody is interested:
You can instruct Launch4j not to wrap the jars into the exe, but access them in an outside folder. To do so, set <dontWrapJar>true</dontWrapJar>
and provide the runtime path to the main class jar via
<jar>myfolder/myjar.jar</jar>
All other external libraries can be put in a separate library folder. (via <classPath><cp>mylibraries</cp></classPath>)
Let's imagine, I created a bunch of command line utilities, written in Scala and/or Java, and I'm using SBT to build them. They all use a couple of libraries, some of them pretty big, and in case of Scala, also the (not so small) Scala standard library.
I want to have these utilities in completely built form (runnable .jar files) to be able to instantly launch any of them and, if needed, also easily distribute them. But what I don't want is to include their dependencies in all of them, because they will be taking disk space. Instead I want them to get dependencies from a shared folder at runtime, and the application jar should contain only "my" classes.
The question is, is there a standard way to accomplish this? If so, where must be shared .jars located? Otherwise, what would you recommend to do?
You can set the CLASSPATH for this.
The JRE searched for classes in the .jar files named in the CLASSPATH.
Additionally all .jar files in the directory jre/lib/ext are used.
To find the complete serching in classpathes please consult the official documentation from Oracle.
Something you might like to consider (although it will require slightly changing what you plan to do) is to have a local Maven repository.
You could have SBT publish libraries to it when they're built. Instead of building runnable JARs, you could run your applications via SBT, which would pull libraries from the local repository as/when required.
The benefit of this is that all the plumbing to do this is built into SBT, and it would make distribution trivial.
The downside is that you would have to run your apps via SBT instead of building runnable JARs. Whether that will work for you, I don't know.
I was wondering how to include Java itself with a jar file so that people don't have to have Java installed already. Is it possible and if so, how do you do it?
To execute the jar in the first place you'd need to have java installed. So it would be best to include a JRE installer in a separate file if you'r including one. Also, you'd have to have a different installer for each target platform so this would be somewhat impractical for general distribution because of the inflated file size.
This is like asking "Can we include the chicken that lays the egg, in the egg?". Answer, no.
As to solving the bigger problem though, there is at least one strategy that might work well for applets, JWS apps. and (possibly) single Jars of desktop apps. that are launched from a link (I've never tried that, though). This approach uses JS to check for the right JRE before providing a link to the Jar.
In order to get a computer to do something, you need to have code that the operating system knows how to handle. Most modern operating systems do not know how to handle Java code unless you install a Java Runtime Engine - to them JAR files are just ZIP files.
Hence you need some code which can be executed directly (without Java) and the simplest is just to use a Java launcher. Many exist - see Java packaging tools - alternatives for jsmooth, launch4j, onejar - but e.g. launch4j is maintained and supports the <path> tag to specify a relative path to an included JRE. Those are unfortunately rather large, but you could provide two versions. One with the JRE, and one without (which then prompts the user to install a JRE).
i am setting up a java project now. in the past, we always included everything (unzipped) from the 3rdparty, such as ant, junit, jfreechart, and others, inside our release. I am wondering is it possible just take those related .jar files but not everything with our software release? then we can get a smaller and neat release. Those 3rdparty library licenses don't allow us to do that way? what's your way? thanks,
You really want to retain the separate jars, if possible. Check out the maven appassembler plugin. It does a nice job of putting together an "unzippable" installation for you, in a controlled way. In the result you'll have a very straightforward "repo" directory filled with all of your dependencies.
I use the maven-assembly-plugin to build a single jar for each application. The plugin quickly handles the fuss of unzipping all the library jars and putting the whole lot back together as a single jar. It also supports writing a manifest with a main class specified which makes running the application simple from a command line (much simpler than specifying a classpath argument as long as your arm anyway).
If their licenses say that you should distribute derivatives with sources, then you are obliged to do that by law.
Another question is if they really force that. As far as I remember GPL, you shall distribute the sources if you want, but there is another way - you must make sources easily availiable to users. So you can drop sources in your distributables.
Any way, you should look at the licenses.
EDIT:
If you will decide to pack the whole program into single jar, I recommend Proguard. It is java optimiser, shrinker, and much more - all in one! To pack everything into one jar, just specify all your jars - program and libraries - as program jars, and specify only one jar as output. Usually it works just fine.
The external jar files are placed under /Library/Java/Extensions on Mac OS X, i have multiple applications that depend on a group of jars such as JavaMail Api, if i dump all the jars in the folder java picks them up, but what i want to do is group them together such as all mail api jars go to the mail folder. But if group them under folders they are not picked up by java. Do i have to just dump them in to Extensions folder? It would make my life a lot easier when updating to group them.
No, they should resize directly under /Library/Java/Extensions/.
However, you can always pass -Djava.ext.dirs=... as an additional argument when you invoke Java programs.
As a sidenote: If you're about to manage dependencies for your projects, try look into build tools, which declaratively resolve dependencies, such as ant.apache.org/ivy or maven.apache.org.
You should not use the global extensions library unless you really, really have to.
Basically your programs should be self contained units with library code on top of a stock JVM, this will allow different programs to have different requirements regardring library code versions, and it will also work when used on other machines.
Pick a good IDE (Eclipse, NetBeans, perhaps Xcode but I have not used it) and learn to add jar files to your projects. It will make you a more attractive programmer to a future employer.
I do find this behaviour annoying myself, that you have to have a flat folder structure when referencing external jars (if you don't add the jars individually).
However, if you don't mind grouping them into jar files instead of grouping them into folders, I would recommend One-Jar.
Quoting: "One-JAR uses a classloader which knows how to load classes and resources from Jar files inside a Jar file. "