I have an application with two libraries that are being used from the java\extensions folder. I would like this jar file be be runnable from any computer such as a computer without netbeans. What is the best way to create this jar? I have read some tutorials but they don't seem to answer my question.
If it is a standard NetBeans project with build.xml, I usually add a target like this to build.xml:
<target name="-post-jar">
<jar jarfile="${dist.jar}" update="true">
<zipfileset src="${dist.jar}" includes="**/*.class" />
<zipfileset src="${libs.somelibrary.classpath}" includes="**/*.class"/>
</jar>
</target>
Here somelibrary is a third party library that has been added to the project. Add a zipfileset element for each library you want to include in the jar file. You should already have something like this in project.properties for each of the libraries:
javac.classpath=\
${libs.somelibrary.classpath}:\
Related
I am using netbeans and have this in my build.xml file (under Project > Build.xml)
<target name="package-for-store" depends="jar">
<property name="store.jar.name" value="MyProjectName"/>
<property name="store.dir" value="store"/>
<property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/>
<echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/>
<delete dir="${store.dir}"/>
<mkdir dir="${store.dir}"/>
<jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip">
<zipgroupfileset dir="dist" includes="*.jar"/>
<zipgroupfileset dir="dist/lib" includes="*.jar"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
</manifest>
</jar>
<zip destfile="${store.jar}">
<zipfileset src="${store.dir}/temp_final.jar"
excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
</zip>
<delete file="${store.dir}/temp_final.jar"/>
Supposedly what this should do is package the 3 libraries i have into my jar file so that when the jar is run it has its dependencies with it.
My folder system looks like this:
Project / dist / lib /
commons-lang3-3-7.jar
commons-text-1.1.jar
jsoup-1.10.3.jar
But when i click "Clean and Build" in netbeans it does not package the libraries into the jar, instead it seems to be ignoring the code that i have put in the build.xml file.
Is there some button that i need to click in order to get it to use my build configuration?
Finally i found the answer. In Netbeans it is possible to build the dependent libraries within the jar file.
Netbeans features a tool that automatically un-archives the dependent libraries and includes them in the jar (such as MyJar.jar|org\apache\commons...).
And it is actually very easy to do!
First you need to click on the "Files" tab in the top left window which shows your project. Then you should be able to see all your files including the Build.xml (in which you have put your build code, such as that featured in the question above).
Right click on the Build.xml file and select "Run Target"
Then choose "Other Target" in the pop up menu
Then select "package-for-store" in the further pop up menu
This will then build your jar file, with dependencies under /YourProject/store/
I have create RESTful web service based on the JAX-RS and used Jersey embedded web server. My ant script compiles code successfully while it gives me error ClassNotFoundException when I run my main class. So after doing research I came up with solution & here it goes java build ant file with external jar files . What I did was created a bundled jar file try to execute that & it works perfectly fine. I want to know the reason behind :
why this solution works ?
Why I should combine all jar file ?
Is it similar to war file which we create following J2EE architecture otherwise war will not be extracted by server ( say TOMCAT ) & in my case jar file for Jersey embedded HTTP server?
EDIT:
Here is my ant build.xml file
<property name="lib.dir" value="${user.dir}/lib"/>
<property name="build.dir" value="${user.dir}/build"/>
<property name="build.lib.dir" value="${build.dir}/lib"/>
<property name="build.classes.dir" value="${build.dir}/classes"/>
<property name="src.dir" value="${user.dir}/src/main/java"/>
<property name="main.class" value="com.assignment.ConsoleServer"/>
<path id="classpath">
<fileset dir="${lib.dir}" includes="**/*.jar"/>
</path>
<target name="clean">
<delete dir="${build.dir}"/>
</target>
<target name="init" depends="clean">
<!-- Create the build directory structure used by compile -->
<mkdir dir="${build.dir}"/>
<mkdir dir="${build.classes.dir}"/>
</target>
<target name="copy_jars" depends="init" >
<copy todir="${build.lib.dir}" >
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</copy>
</target>
<target name="compile" depends="copy_jars">
<javac srcdir="${src.dir}" destdir="${build.classes.dir}" classpathref="classpath" includeantruntime="false"/>
</target>
<target name="jar" depends="compile">
<jar destfile="${build.dir}/${ant.project.name}.jar" basedir="${build.classes.dir}">
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
</manifest>
<zipgroupfileset dir="${lib.dir}" includes="*.jar"/>
</jar>
</target>
<target name="run" depends="jar">
<java fork="true" classname="${main.class}">
<classpath>
<path refid="classpath"/>
<path location="${build.dir}/${ant.project.name}.jar"/>
</classpath>
</java>
</target>
Here is my folder structure
P.S. I am not java expert so pardon me if this question is stupid.
Why this solution works?
In your particular case, you probably didn't include all of the necessary dependencies in your deployment in your previous. (It is not clear from your question how you were originally doing the deployment.)
Now you have put all of the application and dependent class files, etc into one JAR file, and presumably you are deploying / running that file. It works because now it has everything that it needs to run ... which it didn't before.
Why I should combine all jar file?
In your case I suspect that it was not strictly necessary. There was probably a way to "deploy" all of the dependencies without combining them into a single JAR file.
However, there is one case where a "uber-jar" has advantages. That is when the JAR is intended to be an "executable" JAR, and you want to be able to distribute / install it as a single file. (And executable JAR
file can refer to external JARs, etc, but the way that you have to do
it is "fragile".)
Is it similar to war file ... ?
Sort of, though a WAR file contains JAR files ... and typically other kinds of resources that the web-container understands.
The solution works because you packed all you service classes and depending libraries in one jar. That jar and everything inside will be in the class path and visible to your execution virtual machines class loader.
If you leave your depending libraries out your Jersey Web server needs to have them on it's class path, then you wouldn't get ClassNotFoundExcpetion
You shouldn't pack web application in single jar. You should crate war file where you dependencies will be placed inside WEB-INF/lib. You would easily then deploy that war on any application server. Switching to Maven instead of Ant can help a lot.
EDIT: After you added more details to description and ant
If you don't want to use fat-jar you can either
modify your antjava task to specify classpath that will reference
all external libraries (basically telling ant how to build
-classpath parameter for java -jar command
even better, modify your javac ant task by making complete Manifest file that specifies Class-Path correctly, take a better
look at the solution (at the bottom) of the answer you linked (java build ant file with external jar files)
For completness reference on Manifest here
I have been researching trying to find a way to combine multiple Jar files into on Jar as a deliverable.
In a directory I have an ant file named Jar_gen.xml that consists of the following code in its entirety
<target name="combine-jars">
<jar destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</jar>
</target>
In that same directory I have another directory named lib which contains all of the Jar files I would like to flatten.
I have been running the ant script with
ant -buildfile Jar_gen.xml
making sure that I am running it from the same directory that the Jar_gen.xml file is in.
I am getting no output from my ant script and I have not idea why. Can someone please help me fix my script so I may flatten all of my jars and continue constructing my deliverable package.
NOTE
I have no main class so the Eclipse runnable Jar will not work for me
I have very little experience running Ant scripts so complete answers would be very helpful.
Is your directory structure set up correctly?
I created a quick test using your script and it appears to work, given that you have everything set up in a directory structure as
project_root_dir
- build.xml
- lib
- a.jar
- b.jar
and build.xml looks like:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project name="test">
<target name="combine-jars">
<jar destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</jar>
</target>
</project>
when I go to the project_root_dir and run "ant combine-jars", I get an out.jar that contains the contents of both a.jar and b.jar.
I'm trying to compile a runnable jar-file for a project that makes use of hibernate. I'm trying to construct an ant build.xml file to streamline my build process, but I'm having troubles with the inclusion of the hibernate3.jar inside the final jar-file.
If I run the ant script I manage to include all my library jars, and they are put in the final jar-file's root. When I run the jar-file I get a
java.lang.NoClassDefFoundError: org/hibernate/Session
error. If I make use of the built-in export to jar in Eclipse, it works only if I choose "extract required libraries into jar". But that bloats the jar, and includes too much of my project (i.e. unit tests).
Below is my generated manifest:
Manifest-Version: 1.0
Main-Class: main.ServerImpl
Class-Path: ./ antlr-2.7.6.jar commons-collections-3.1.jar dom4j-1.6.1.jar
hibernate3.jar javassist-3.9.0.GA.jar jta-1.1.jar slf4j-api-1.5.11.jar
slf4j-simple-1.5.11.jar mysql-connector-java-5.1.12-bin.jar rmiio-2.0.2.jar
commons-logging-1.1.1.jar
And the part of the build.xml looks like this:
<target name="dist" depends="compile" description="Generates the Distribution Jar(s)">
<mkdir dir="${dist.dir}" />
<jar destfile="${dist.dir}/${dist.file.name}.jar" basedir="${build.prod.dir}" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="${main.class}" />
<attribute name="Class-Path" value="./ ${manifest.classpath} " />
<attribute name="Implementation-Title" value="${app.name}" />
<attribute name="Implementation-Version" value="${app.version}" />
<attribute name="Implementation-Vendor" value="${app.vendor}" />
</manifest>
<zipfileset refid="hibernatefiles" />
<zipfileset refid="slf4jfiles" />
<zipfileset refid="mysqlfiles" />
<zipfileset refid="commonsloggingfiles" />
<zipfileset refid="rmiiofiles" />
</jar>
</target>
The refids' for the zipfilesets point to the directories in a library directory lib in the root of the project. The manifest.classpath-variable takes the classpath of all those library jar-files, and flattens them with pathconvert and mapper.
I've also tried to set the manifest classpath to ".", "./" and only the library jar, but to no difference at all. I'm hoping there's a simple remedy to my problems...
Since you can't specify jar-inside-jar in your classpath, this way won't work.
You need either to jar only your code and then zip your jar with libs jars and launch script, like
#!/bin/sh
java -cp ./hibernate.jar:./mycode.jar... my.Main
(this what most people do), or you may unpack all your lib jars to the same dir which contains your compiled classes and then jar result dir back to single jar file (this what maven jar-with-dependencies packaging do).
A library that my java application uses needs looks for a file (log4j.xml) in the class path. I use netbeans to manage my project, but I can't find a way to include the lib/ folder.
Netbeans automatically creates a MANIFEST.MF file inside the application jar and also creates a folder called lib/ which includes all dependencies. This manifest specifies a Class-Path attribute that overrides any -cp argument provided on the command line. I can select an arbitrary folder in netbeans' library panel, but it creates a sub folder in the manifest's classpath. I'd like all dependencies and the log4j.xml file inside the lib/ folder.
Hopefully it's possible to do this in the IDE. I include a snippet of the auto-generated build-impl.xml file.
<target depends="init,compile,-pre-pre-jar,-pre-jar" if="manifest.available+main.class+mkdist.available" name="-do-jar-with-libraries">
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
</pathconvert>
<pathconvert pathsep=" " property="jar.classpath">
<path path="${run.classpath.without.build.classes.dir}"/>
<chainedmapper>
<flattenmapper/>
<globmapper from="*" to="lib/*"/>
</chainedmapper>
</pathconvert>
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
<copylibs compress="${jar.compress}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
<attribute name="Class-Path" value="${jar.classpath}"/>
</manifest>
</copylibs>
<echo>To run this application from the command line without Ant, try:</echo>
<property location="${dist.jar}" name="dist.jar.resolved"/>
<echo>java -jar "${dist.jar.resolved}"</echo>
</target>
Thanks.
Instead of editing the build-impl.xml file you should add this entry to the build.xml file. When you modify anything in your project pertaining to the building of that project, it will generate a new build-impl.xml file.
Here is an example of what I put in my build.xml file:
<target depends="init" name="-do-clean">
<delete dir="${build.dir}"/>
<delete file="${dist.jar}"/>
<delete dir="${dist.dir}/lib"/>
<delete dir="${dist.dir}/resources"/>
</target>
Since I put this in the build.xml file, it will override the "-do-clean" section of the build-impl.xml file which contains:
<target depends="init" name="-do-clean">
<delete dir="${build.dir}"/>
<delete dir="${dist.dir}" followsymlinks="false" includeemptydirs="true"/>
</target>
Furthermore, since it is in the build.xml it won't be modified by Netbeans.
I found a way to acheive this modifying the build-impl.xml.
I changed:
<attribute name="Class-Path" value="${jar.classpath}"/>
to:
<attribute name="Class-Path" value="${jar.classpath} /lib"/>
The problem is that netbeans will overwrite it since this file is automatically generated.
You can simply turn off project option Build/Packaging/Copy Dependent Library and manualy edit manifest.mf in root folder of your project (which is a template for manifest in jar file).
It seems that your problem is the "globmapper" that stores your log4j.xml file in /lib - you'd want it on the "/" or the jar.