Java Netbeans, libraries not being packaged into jar file on build - java

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/

Related

Netbeans Create Standalone Jar

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}:\

java.util.logger.Logging: keeping logger.properties file outside the jar file

In my project I have a properties file which I use to set the level of logging. Now when I export my project as a jar and use it to run the project on a remote machine (linux), I cannot set the level. Is there a way to keep the properties file outside the jar file such that I can set the level and make the jar read that properties file. (preferred using environment variable)
There are several ways to achieve this, for example:
Configure your IDE to export resources outside the JAR: usually I don't consider this option since the specific solution depends by the developer's IDE
Use a generic build tool, for example Ant, and specify in the build.xml file which properties files should be packaged outside the jar
Integrate your project with Maven and customize the package goal in order to copy some specific properties file outside jar
From your question I guess you are exporting the JAR from your IDE, but as I stated above the solution depends by the IDE. For this reason, in order to adopt an IDE independent solution, I would suggest to use Ant. This would allow you to solve this and many similar issues that could arise in the future.
You can get Ant here: just download and unpackage it in any folder, it takes a couple of minutes. Then add a reference to Ant bin directory in your PATH variable (not strictly necessary but suggested) and create a sample build.xml file. Here it is a template example:
<project name="template" default="compile" basedir=".">
<description>Build file template</description>
<property name="project.name" value="myProject"/>
<property name="driver.log" value="log4j-1.2.15.jar"/>
<property name="driver.database" value="ojdbc6.jar"/>
<property name="library.home" value="lib"/>
<property name="env.type" value="dev"/>
<property name="src.version" value="Demo" />
<property name="src.folder" value="root/folder/template"/>
<property name="src.package" value="root.folder.template"/>
<property name="src.home" value="${basedir}/src/${src.folder}"/>
<property name="dist.home" value="${basedir}/dist"/>
<property name="build.home" value="${basedir}/build"/>
<property name="docs.home" value="${basedir}/docs"/>
<!-- Setting the classpath necessary to compile -->
<path id="compile.classpath">
<pathelement location="${library.home}/${driver.log}"/>
<pathelement location="${library.home}/${driver.database}"/>
</path>
<!-- DELETE the class files from the ${build.home} directory tree -->
<target name="clean" description="Clean up the build folder">
<delete dir="${build.home}"/>
<delete dir="${dist.home}"/>
</target>
<!-- CREATE the build directory structure used by compile -->
<target name="init" description="Creates the necessary directories">
<mkdir dir="${dist.home}"/>
<mkdir dir="${build.home}"/>
</target>
<!-- COMPILE the project and copy all necessary resources -->
<!-- Options: <compilerarg value="-Xlint"/> -->
<target name="compile" depends="init" description="Compile the sources">
<javac srcdir="${src.home}" destdir="${build.home}" includeantruntime="false">
<classpath refid="compile.classpath"/>
</javac>
<copy todir="${build.home}/${src.folder}/resources">
<fileset dir="${src.home}/resources">
<include name="messages_list.properties"/>
<include name="messages_list_en.properties"/>
</fileset>
</copy>
<copy file="${src.home}/resources/log4j_${env.type}.properties" tofile="${build.home}/${src.folder}/resources/log4j_${project.name}.properties"/>
<copy file="${src.home}/resources/configuration_${env.type}.properties" tofile="${build.home}/${src.folder}/resources/${project.name}_config.properties"/>
</target>
<!-- Creates the DISTRIBUTABLE JAR package and add 3d part libraries -->
<target name="dist" description="Create the distributable JAR archive">
<jar destfile="${dist.home}/${project.name}.jar">
<fileset dir="${build.home}">
<exclude name="place_holder\"/>
</fileset>
<!-- Setting MANIFEST properties -->
<manifest>
<section name="${ant.project.name} - ver. ${src.version}">
<attribute name="Built_By" value="${user.name}"/>
<attribute name="Created" value="${ts}"/>
</section>
<attribute name="Main-Class" value="package.mine.MainClass"/>
<attribute name="Class-Path" value=". lib/${driver.log} lib/${driver.database}"/>
</manifest>
</jar>
<!-- Adding third part libraries -->
<mkdir dir="${dist.home}/lib"/>
<copy file="${library.home}/${driver.database}" todir="${dist.home}/lib"/>
<copy file="${library.home}/${driver.log}" todir="${dist.home}/lib"/>
</target>
<tstamp><format property="ts" pattern="dd/MM/yyyy HH:mm:ss" /></tstamp>
</project>
Remark: in the template above you should replace the sample JARS (log4j and the OJDBC driver) with the actual JARS needed by your project. Then you can customize the copy task in order to place the properties files where you wish. You can copy those file in any directory you like, as long as such path appears in the application's classpath.

Why combine all jars together?

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

How to include the lib folder in the manifest classpath in Netbeans

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.

Ant Script Example

I would like to make a very simple ant script that does 1 thing, which is to bulid a jar file. But when I try to use a very simple example, it fails due to dependancies on jars that my source depends on. So, How you you specify jars that there are jars that need to be in the class path when building an Ant target.
<project name="project" default="default">
<property name="src.dir" value="src"/>
<property name="build.dir" value="build"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="jar.dir" value="${build.dir}/jar"/>
<property name="lib.dir" value="//tomcat/common/lib"/>
<description> description </description>
<!-- =================================
target: default
================================= -->
<target name="default" depends="compile" description="description">
<jar destfile="/path/to/dir/Library.jar">
</jar>
</target>
<target name="compile">
<mkdir dir="${classes.dir}"/>
<javac srcdir="${src.dir}" destdir="${classes.dir}"/>
</target>
</project>
Your question isn't entirely clear - I suspect you mean you want to compile your source (with the javac task) and then build a jar file from the results. If that's not the case, I don't see where your source dependencies come into it. If that is the case, then the jar task is irrelevant.
In the javac task, use the classpath attribute to specify other jar dependencies.
Here's an ANT script generated by using the Eclipse Runnable JAR Export Wizard. This is a project that updates stats on a Google Spreadsheet for a small fantasy baseball league with some friends. It gets the stats by scraping ESPN.com player pages.
Class-Path attribute inside the manifest element is used to set the classpath used by the jar. This defaulted "." but I had to add my src path explicitly so that log4j would pick up log4j.properties.
zipfileset elements are external jars used by my source that I wanted to be included with my jar. I suspect this might be what you're looking for.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project default="create_run_jar" name="Create Runnable Jar for Project cob_fantasy_baseball">
<!--this file was created by Eclipse Runnable JAR Export Wizard-->
<!--ANT 1.7 is required -->
<target name="create_run_jar">
<jar destfile="C:/workspace/cob_fantasy_baseball/cob_fantasy_baseball.jar" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="com.me.cob_fantasy_baseball.UpdateCobStats"/>
<attribute name="Class-Path" value=".;src/com/me/cob_fantasy_baseball"/>
</manifest>
<fileset dir="C:/workspace/cob_fantasy_baseball/classes"/>
<zipfileset excludes="META-INF/*.SF" src="C:/workspace/gdata/java/lib/gdata-core-1.0.jar"/>
<zipfileset excludes="META-INF/*.SF" src="C:/workspace/gdata/java/lib/gdata-spreadsheet-2.0.jar"/>
<zipfileset excludes="META-INF/*.SF" src="C:/workspace/jericho-html-2.6/lib/jericho-html-2.6.jar"/>
<zipfileset excludes="META-INF/*.SF" src="C:/workspace/apache-log4j-1.2.15/log4j-1.2.15.jar"/>
<zipfileset excludes="META-INF/*.SF" src="C:/workspace/jaf-1.1.1/activation.jar"/>
<zipfileset excludes="META-INF/*.SF" src="C:/workspace/javamail-1.4.2/mail.jar"/>
<zipfileset excludes="META-INF/*.SF" src="C:/workspace/javamail-1.4.2/lib/smtp.jar"/>
<fileset dir="C:/workspace/cob_fantasy_baseball/src/com/me/cob_fantasy_baseball"/>
</jar>
</target>
</project>
Also, here's a link to the Ant documentation for the jar task: http://ant.apache.org/manual/Tasks/jar.html
Based on your example you can just put libs inside javac:
<javac srcdir="${src.dir}" destdir="${classes.dir}">
<classpath>
<pathelement location="${lib.dir}/lib1.jar"/>
<pathelement location="${lib.dir}/lib2.jar"/>
</classpath>
</javac>
Here is the ant file we use to build the Timeline opensource project. It is pretty straight forward. It doesn't build a jar, but it does use libraries to minimize JS files.
http://simile-widgets.googlecode.com/svn/timeline/trunk/build.xml
Larry

Categories

Resources