I just whipped up a medium-sized utilities JAR to be used by many other Eclipse projects. I spent a good deal of time writing tedious javadocs so that it would be pretty obvious how to use the API.
I used Ant to throw everything in a JAR, and I am now adding that JAR to the build path of a new project. But low and behold...when I mouseover any of my utility classes/methods, the tool tip that pops up says:
Note: this element neither has attached source nor attached Javadoc
and hence no Javadoc can be found.
What is going on here? What's the solution? Here is the dist Ant target that JARs up my utilities project:
<target name="dist" depends="compile">
<jar jarfile="dist/testing-utils.jar">
<fileset dir="bin/main" />
<fileset dir="src/main/config" />
</jar>
</target>
What else do I need to configure?!? Thanks in advance!
The java compile task, which I assume you're using in the "compile" target, generates bytecode from your Java source. This bytecode will not include comments by design and thus your distribution jar will not include comments.
What you are probably looking for is to attach the source in Eclipse to get access to the Javadocs. You can attach source to your library jars by right clicking on the target jar, selecting properties, select Java Source Attachment and provide the location of the source jar. You can also provide a folder location, if you want to reference your project directly.
To generate a Jar that includes javadocs and source, you may use the following in ant:
<target description="bundle sources in a jar" name="package-sources">
<jar basedir="src" destfile="build/release/${ant.project.name}-${project.version}-sources.jar"/>
</target>
Reference
If you do want to ship sources then johncarl's answer is probably correct; it is the first of the two options offered by eclipse -- attached sources. If you don't want to ship sources then you need to generate javadocs, see the ant javadoc task. With that approach, you would have two jars, one containing the compiled classes and another containing documentation. In eclipse, your users will add the class jar to project and then attach to it the javadoc jar.
Related
I have a Netbeans project where I am letting Netbeans handle the packaging; its using Netbean's build-impl.xml Ant script to package it. There are certain packages that I do not want ending up in the final jar that Netbeans creates. Is there a way to exclude those packages from ending up in the final jar?
In the build-impl.xml file I think this is where the Jar command is called, or at least defined.
<target name="-init-presetdef-jar">
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
<jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">
<j2seproject1:fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes},**/editor/**"/>
</jar>
</presetdef>
</target>
One of the packages that I want to exclude is called "editor". I added it in the copy above in effort to try to get it to be excluded but that didn't work, the "editor" package and all its classes still show up in the final jar.
Any ideas how I can get that package excluded from the jar? I would rather not touch the build-impl.xml file and instead accomplish this by messing with the build.xml file which Netbeans sets aside for us to mess with... so bonus points if the solution only touches that file.
thanks
OK I found two ways to do this (each with their own drawbacks), both from the Sources section of the Properties window.
1) Move the packages you do not want to one of your test package folders. In Properties -> Sources you can add or edit your test Package Folders. The drawback here is that you can only use the package as a test. This worked fine for me because the only time I had to use that code was when I was on my IDE. It might become an issue if I ever need to add this package to a jar.
2) In Properties -> Sources at the lower right hand there is a button labeled Includes/Excludes that you can use to add files or packages to exclude for the final jar. The drawback here is that the code is completely unusable if it relies on the other packages. Netbeans essentially ostracizes it. This didn't work for me.
An ideal solution would be a way to design which packages make it to the final jar then have various profiles for building these jars. That is to say I can build Jar-A or Jar-B, each with their own packages. I will wait for that solution before marking this question answered.
2) You can directly define all of the *.class files that has to be excluded rather than defining the whole package from the Final jar. Go to the tag in your build-imple.xml file
<target name="-init-presetdef-jar">
<presetdef name="jar" uri="http://www.netbeans.org/ns/j2se-project/1">
<jar compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}">
<j2seproject1:fileset dir="${build.classes.dir}" excludes="${dist.archive.excludes},**/editor/**"/>
</jar>
</presetdef>
</target>
which generates jar file. Now find the attribute excludes="${dist.archive.excludes} And EDIT this.
Example: excludes="**/X*.class,**/Y*.class,**/FullClassName.class"
You don't need to move your packages anywhere. You can still exclude all of the *.class files that you don't want to include in your final JAR.
Open your nbproject/project.properties file and find dist.archive.excludes then give all of the *.class file name (to be excluded) as a comma-separated value to that key dist.archive.excludes.
Example:
dist.archive.excludes=`**/X*.class,**/Y*.class,**/FullClassName.class`
**/X*.class, **/Y*.class, X and Y are prefixes of the class, You can give the full class name as shown above
The syntax is **/X*.class where X is the prefix of the class name.
In one of my projects the build time is too long. I was able to locate the dependencies, but every time I'm executing a build I have to perform a clean, which deletes all the java files and after that the javac recompiles everything. This consumes a lot of time.
I'm using ANT for build and I was thinking; is it possible to perform a clean (which deletes files) on demand? For the better understanding I made up an example:
target top: builds the top.jar
target first: builds the first.jar
target second: builds the second.jar
top.jar depends on first.jar and second.jar. If I change any files associated to second.jar, ANT will run the second target, and when this affects the top.jar, then ANT will run the top target. So far so good.
But, it can happen that I rename a class in second.jar - with eclipse for example -, and I end up with two classes: the old class and the new class. Different names, but same content. This can be a problem, that's why I have to run the clean target all over the time.
In the example above, I have no problem with running the clean only for the target, which has changed.
So my question: is it possible to determine that the content of a specific folder has changed, and when it happens, run an ANT task on demand?
I looked around and there is an ANT task with almost the same functionality I need. It is called depend. Unfortunately it doesn't perform a full delete.
Might libnotify bindings for java be helpful? If you don't need to run this within java, check out inotify, Kqueue, or the like.
Another possibility would be to switch to an IDE that automatically compiles everything for you in an intelligent way. For example Eclipse compiles every class when it is saved in the editor.
Additionally it is possible to define custom builders (e.g. an ant task) that are executed before or afterwards. That would allow you to automatically update your JAR files using the class files generated by Eclipse from the project's bin directory.
There is the <depend> task in Ant which may do what you want.
I might have found a solution to my problem. I'm going to use the outofdate task of ant contrib:
<outofdate>
<sourcefiles path="src3"/>
<targetfiles path="target/second.jar"/>
<sequential>
<delete includeemptydirs="true">
<fileset dir="bin3" includes="**/*"/>
</delete>
<delete file="target/second.jar"/>
</sequential>
</outofdate>
<javac .../>
a question on building executable jar files. Suppose we have a jar file a.jar that contains UI.class. I have used a metafile in archiving a.jar that says
Main-Class: UI
Class-Path: . b.jar c.jar
Now, if I want to ship this executable a.jar to somebody, I have to ship 3 files - a.jar, b.jar and c.jar. The user has to put all 3 in the same folder, and then double clicking on a.jar would work. It would be simpler if I could ship a single file (a.jar), and the JVM could figure out to extract b.jar and c.jar from in there to use the classes. These 2 are external libraries and I dont want to expand them and re-jar the class files in a.jar.
Can this be done? If so, what is the jar command and what should go in the metafile? Currently the command is
jar cmf metafile a.jar UI.class
Thank you.
Have you looked at this tool OneJar? Also this is a good article to read on OneJar.
If you decide to not use an external tool then your alternative is to put the library/helper jars in the classpath in the manifest, and then copy the jars themselves in a directory path relative to your main jar.
EDIT: OP asked for an example MANIFEST.MF. I coped this from the example One-Jar example jar file.
Manifest-Version: 1.0
Main-Class: com.simontuffs.onejar.Boot
One-Jar-Expand: expand,doc
There is OneJar as people have mentioned but also (especially if you are using eclipse) you can consider fatjar.
ALternatively, you can also achieve this by using an ANT Task here's an example:
<target name="dist" depends="compile,static" description="Compiles and builds jar files">
<mkdir dir="${dist}"/>
<jar destfile="${dist}/MYAPP.jar">
<zipfileset src="${dist}/MY_OTHER_APP.jar"/>
<zipfileset src="${lib}/commons-io-1.4/commons-io-1.4.jar"/>
<zipfileset src="${lib}/commons-math-2.1/commons-math-2.1.jar"/>
<fileset dir="${res}" includes="*"/>
<manifest>
<attribute name="Main-Class" value=<where your main class is>/>
</manifest>
</jar>
</target>
OneJar is good for just bundling a few things together, but it's generally quite slow and inflexible. This isn't a dig at OneJar, it's great for what it does but unless I wanted a quick and easy distributable for a tiny program I wouldn't use it.
I did use it for a while but then switched to izpack. It provides an installer as a single jar which I've found to generally work very well, and supports things such as windows specific shortcuts as well. It's also really easy to integrate it with ant.
Another way can be use one of several available tools to create a setup deliverable and your setup pack will unpack your application when installed.
Maven users can also use the assembly plugin for this:
http://maven.apache.org/plugins/maven-assembly-plugin/usage.html
When receiving a bug report or an it-doesnt-work message one of my initials questions is always what version? With a different builds being at many stages of testing, planning and deploying this is often a non-trivial question.
I the case of releasing Java JAR (ear, jar, rar, war) files I would like to be able to look in/at the JAR and switch to the same branch, version or tag that was the source of the released JAR.
How can I best adjust the ant build process so that the version information in the svn checkout remains in the created build?
I was thinking along the lines of:
adding a VERSION file, but with what content?
storing information in the META-INF file, but under what property with which content?
copying sources into the result archive
added svn:properties to all sources with keywords in places the compiler leaves them be
I ended up using the svnversion approach (the accepted anwser), because it scans the entire subtree as opposed to svn info which just looks at the current file / directory. For this I defined the SVN task in the ant file to make it more portable.
<taskdef name="svn" classname="org.tigris.subversion.svnant.SvnTask">
<classpath>
<pathelement location="${dir.lib}/ant/svnant.jar"/>
<pathelement location="${dir.lib}/ant/svnClientAdapter.jar"/>
<pathelement location="${dir.lib}/ant/svnkit.jar"/>
<pathelement location="${dir.lib}/ant/svnjavahl.jar"/>
</classpath>
</taskdef>
Not all builds result in webservices. The ear file before deployment must remain the same name because of updating in the application server. Making the file executable is still an option, but until then I just include a version information file.
<target name="version">
<svn><wcVersion path="${dir.source}"/></svn>
<echo file="${dir.build}/VERSION">${revision.range}</echo>
</target>
Refs:
svnrevision: http://svnbook.red-bean.com/en/1.1/re57.html
svn info http://svnbook.red-bean.com/en/1.1/re13.html
subclipse svn task: http://subclipse.tigris.org/svnant/svn.html
svn client: http://svnkit.com/
Use the svnversion command in your Ant script to get the revision number:
<exec executable="svnversion" outputproperty="svnversion" failonerror="true">
<env key="path" value="/usr/bin"/>
<arg value="--no-newline" />
</exec>
Then use the ${svnversion} property somewhere in your EAR. We put it in the EAR file name, but you could also put it in a readme or version file inside the EAR, or specify the version in the EAR's META-INF/manifest.mf:
<!-- myapp-r1234.ear -->
<property name="ear" value="myapp-r${svnrevision}.ear" />
You'd want to provide the Subversion branch and repository number. As discussed in How to access the current Subversion build number?, the svn info command will give you this information, which you can then use to build a VERSION file or place in any of the other files that you're building into your *AR files. If you've nothing else in mind, you could consider using the XmlProperty Ant task to extract the relevant information from the output of your
svn info --xml command
Check out the jreleaseinfo project. Contains a ANT task that can generate a java class that can be called at runtime to display the release info for your project.
I like its simplicity.
See also this question: Build and Version Numbering for Java Projects (ant, cvs, hudson)
It includes several helpful code snippets.
From the top of my mind. A tag for each jar build?
We have the first part of our build create a version.txt file in the root of the package and dump the tag used to check the code out from (in our case) CVS... Additionally, the final part of our build process checks the fully built EAR back into CVS for future reference.
That way, if we have an issue with a webapp - it's just a case of asking the reporter to hit /app/version.txt - from there we can drill down the particular build history in CVS to locate the relevant components (handles different versions of libraries in apps) to locate the error.
Not sure how much help this is to our support folk - but it's definitely something they complain about not being there!
Do automatic builds, and place a tag (with a date stamp) on the codebase when the build is succesful (with unittest ofcourse).
In your delivery process, only deliver tagged builds to the customer. This way you are in control, and can place the tag name in a readme.txt somewhere, or have the filename of the ear file reflect the tagname.
I personally switched back to CVS, and this is one of the reasons. In CVS, I can have a class report it's tag. All my jar files contain a "main" which makes them runnable. With support questions, I ask the customer to do a "java -jar somejar.jar" and send the output to me alongside the question.
This way I'm sure of the build they-re using, and I can even have information like java version, OS type and version. Without the customer having to answer strange questions.
It's simple but very effective.
Why not put the build number into a properties file... this can then be easily read by the java and output to a Help | About dialog (applet/application), web-page footer or whatever other GUI you might have.
(See the footer on every SOF page.... has the SVN version number there.)
Seems a load easier than looking in the WAR/EAR/JAR etc easy time?
I store the absolute repository revision as a part of my full version number. This gives people a quick glance to see if a given change is in a given version or not.
We also store the version number / build date / etc in the manifest file of the ear as custom properties, these are mostly informational only. We also store it in a properties file that is built into our jar, so the application can read it.
Is it possible to specify a Java classpath that includes a JAR file contained within another JAR file?
If you're trying to create a single jar that contains your application and its required libraries, there are two ways (that I know of) to do that. The first is One-Jar, which uses a special classloader to allow the nesting of jars. The second is UberJar, (or Shade), which explodes the included libraries and puts all the classes in the top-level jar.
I should also mention that UberJar and Shade are plugins for Maven1 and Maven2 respectively. As mentioned below, you can also use the assembly plugin (which in reality is much more powerful, but much harder to properly configure).
You do NOT want to use those "explode JAR contents" solutions. They definitely make it harder to see stuff (since everything is exploded at the same level). Furthermore, there could be naming conflicts (should not happen if people use proper packages, but you cannot always control this).
The feature that you want is one of the top 25 Sun RFEs: RFE 4648386, which Sun, in their infinite wisdom, has designated as being of low priority. We can only hope that Sun wakes up...
In the meanwhile, the best solution that I have come across (which I wish that Sun would copy in the JDK) is to use the custom class loader JarClassLoader.
After some research I have found method that doesn't require maven or any 3rd party extension/program.
You can use "Class-Path" in your manifest file.
For example:
Create manifest file MANIFEST.MF
Manifest-Version: 1.0
Created-By: Bundle
Class-Path: ./custom_lib.jar
Main-Class: YourMainClass
Compile all your classes and run jar cfm Testing.jar MANIFEST.MF *.class custom_lib.jar
c stands for create archive
f indicates that you want to specify file
v is for verbose input
m means that we will pass custom manifest file
Be sure that you included lib in jar package. You should be able to run jar in the normal way.
based on: http://www.ibm.com/developerworks/library/j-5things6/
all other information you need about the class-path do you find here
Use the zipgroupfileset tag (uses same attributes as a fileset tag); it will unzip all files in the directory and add to your new archive file.
More information: http://ant.apache.org/manual/Tasks/zip.html
This is a very useful way to get around the jar-in-a-jar problem -- I know because I have googled this exact StackOverflow question while trying to figure out what to do. If you want to package a jar or a folder of jars into your one built jar with Ant, then forget about all this classpath or third-party plugin stuff, all you gotta do is this (in Ant):
<jar destfile="your.jar" basedir="java/dir">
...
<zipgroupfileset dir="dir/of/jars" />
</jar>
If you are building with ant (I am using ant from eclipse), you can just add the extra jar files
by saying to ant to add them...
Not necessarily the best method if you have a project maintained by multiple people but it works for one person project and is easy.
for example my target that was building the .jar file was:
<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}">
<manifest>
<attribute name="Author" value="ntg"/>
................................
<attribute name="Plugin-Version" value="${version.entry.commit.revision}"/>
</manifest>
</jar>
I just added one line to make it:
<jar ....">
<zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
<manifest>
................................
</manifest>
</jar>
where
<property name="external-lib-dir"
value="C:\...\eclipseWorkspace\Filter\external\...\lib" />
was the dir with the external jars.
And that's it...
Not without writing your own class loader. You can add jars to the jar's classpath, but they must be co-located, not contained in the main jar.
You need to build a custom class-loader to do this or a third-party library that supports this. Your best bet is to extract the jar from the runtime and add them to the classpath (or have them already added to the classpath).
I use maven for my java builds which has a plugin called the maven assembly plugin.
It does what your asking, but like some of the other suggestions describe - essentially exploding all the dependent jars and recombining them into a single jar
If you have eclpise IDE, you just need to export your JAR and choose "Package Required libraries into generated JAR". eclipse will automatically add the required dependant JARs into the generated JAR as well as generated some eclipse custom class loader that load these JARs automatically.
I was about to advise to extract all the files at the same level, then to make a jar out of the result, since the package system should keep them neatly separated.
That would be the manual way, I suppose the tools indicated by Steve will do that nicely.
Winstone is pretty good http://blog.jayway.com/2008/11/28/executable-war-with-winstone-maven-plugin/. But not for complex sites. And that's a shame because all it takes is to include the plugin.
Well, there is a very easy way if you're using Eclipse.
Export your project as a "Runnable" Jar file (right-click project folder from within Eclipse, select "Export..."). When you configure the export settings, be sure to select "Extract required libraries into generated Jar." Keep in mind, select "Extract..." and not "Package required libraries...".
Additionally: You must select a run-configuration in your export settings. So, you could always create an empty main( ) in some class and use it for your run configuration.
Anyway, it isn't guaranteed to work 100% of the time - as you will notice a pop-up message telling you to make sure you check the licenses of the Jar files you're including and something about not copying signature files. However, I have been doing this for years and have never encountered a problem.
Extracting into an Uber-dir works for me as we s should all be using root:\java and have outlets code in packages with versioning. Ie ca.tecreations-1.0.0. Signing is okay because the jars are intact from their downloaded location. 3rd party signatures intact, extract to c:\java. There’s my project dir. run from launcher so java -cp c:\java Launcher
In case you are using Spring Boot, you may want to have a look at this documentation: The Executable Jar Format
Java does not provide any standard way to load nested jar files (that
is, jar files that are themselves contained within a jar). This can be
problematic if you need to distribute a self-contained application
that can be run from the command line without unpacking.
To solve this problem, many developers use “shaded” jars. A shaded jar
packages all classes, from all jars, into a single “uber jar”. The
problem with shaded jars is that it becomes hard to see which
libraries are actually in your application. It can also be problematic
if the same filename is used (but with different content) in multiple
jars. Spring Boot takes a different approach and lets you actually
nest jars directly.
The Spring documentation also lists some alternative single Jar solutions:
Apache Maven Shade Plugin
JDotSoft JarClassLoader
One-JAR
Shadow Plugin (Gradle)
I would advise to use one jar and many libraries in separate jars, not in a single jar. Use separate jar from jar libraries.
Suppose you have such a folder structure:
path/yourApp/yourApp.jar
path/yourApp/lib/lib1.jar
path/yourApp/lib/megalib1.jar
path/yourApp/lib/supermegalib1.jar
All you have to do, add in MANIFEST.MF each of used jar.
Manifest-Version: 1.0
Main-Class: com.company.MyProgram
Class-Path: ./lib/lib1.jar ./lib/megalib1.jar ./lib/supermegalib1.jar
From within the manifest, you grant usage to each library.
Single all in one jar file might be easier to share and distribute, but in fact this doesn't give significant advantages over distributing as an archive and unpack it in some folder where you want to deploy. This will not make your program easier to maintain, faster. It will not make significant hdd usage difference.