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).
Related
I have created a jar with the .class files and the dependency libraries which are required for executing the class files using the below jar code
<target name="jar" depends="clean">
<jar destfile="${basedir}/lib/HelloWorld.jar">
<zipgroupfileset dir="${basedir}/lib" includes="*.jar" />
<fileset dir="${basedir}" includes="/com/temp/**" />
<fileset dir="${basedir}" includes="build.properties"/>
<manifest>
<attribute name="Class-Path" value="./HelloWorld.jar"/>
</manifest>
</jar>
</target>
Now i have written other build.xml to run taskdef actions using this jar but the following error occurs when i try to invoke the class files using the taskdef actions even though the class files and their dependencies are present in the same jar.
BUILD FAILED
C:\Users\kh2139\Desktop\New folder\build.xml:4: taskdef class com.temp.install.common.action.UserInstallDirRule cannot be found
using the classloader AntClassLoader[C:\Users\kh2139\Desktop\New folder\HelloWorld.jar]
Attaching my build.xml code below which is used to run taskdef actions on the HelloWorld.jar
<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="MyTask" basedir="." default="use">
<target name="use" description="Use the Task" >
<taskdef name="helloworld1" classname="com.temp.install.common.action.UserInstallDirRule" classpath="HelloWorld.jar"/>
<helloworld1/>
<taskdef name="helloworld" classname="com.temp.install.common.action.EncryptionGUID" classpath="HelloWorld.jar"/>
<helloworld/>
</target>
</project>
PS: I could able to run the build.xml file successfully without errors when i specify the lib folder in the location where i place HelloWorld.jar and give the classpath to the lib folder in the taskdef actions.
But my issue is i want to use the same jar to contain the dependencies that are used while executing the classes.
The error indicates that Java cannot find UserInstallDirRule.class in HelloWorld.jar. To determine if HelloWorld.jar contains the class, try running the jar.exe program included with the JDK.
Here's an example of running jar.exe in a Windows Command Prompt:
C:\>jar.exe tf "C:\Users\kh2139\Desktop\New folder\HelloWorld.jar"
The output will show whether UserInstallDirRule.class is in the JAR file.
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}:\
Since the latest java release (7u45), I'm getting tons of errors on third part jar libraries that my webstart application uses, due to newly required manifest attributes being missing:
Missing Application-Name: manifest attribute for: http://site/lib/jh.jar
Missing Permissions manifest attribute for: http://site/lib/jh.jar
Missing Codebase manifest attribute for: http://lib/jh.jar
So, I need to run a batch ant task to update the manifest files in each of the 30 or so required libraries before I can use them for distribution.
How can I do this in ant? (preferably without ant-contrib)
PS: I've already fixed all the other 7u45 update crap (code signing, JNLP attribs, etc).
Try something like this.
<for param="jarFile">
<fileset dir="${webapp.dir}">
<include name="*.jar"/>
</fileset>
<sequential>
<jar update="true" file="#{jarFile}">
<manifest>
<attribute name="Application-Name" value="ABCDEF"/>
<attribute name="Codebase" value="*"/>
<attribute name="Permissions" value="all-permissions"/>
</manifest>
</jar>
</sequential>
</for>
I am trying to build a project using Ant Build and i have referenced several jars to make it work. Now When i put the jar created by Ant build in some other machine and run it.
I am getting the error saying NoClassDefFoundError org/apache... Not found.
Is there anyway to put all the referenced jars in the classpath of the project or in the manifest file?
Or is there anyway to repackage all the jar in a project?
I know there is one method using jarjar but I don't have any idea of how to use it.
Please suggest me some ideas, I've been stuck with this small problem for a long time.
When building with ANT the external jars you need are being added to the classpath by the ANT tool. Look in your build script, you most likely have an entry either in the javac task or in a setup task that defines your classpath.
After you build your code, your jar file only has your classes in it, the classes in the 3rd party jar files (like Apache) are not added to your jar file by default.
What you need to decide is do you want a single jar file with all needed classes or are you willing to deploy multiple jar files? If you're comfortable delivering your application as multiple jar files, you will want to provide a batch file or shell script to launch the application for the user that builds the classpath to include the deployed jars.
If you want one jar file, you can do something like below. Assume that all the 3rd party jars you have are in a directory identified by the ANT property lib.dir:
<jar destfile='${build.dir}/lib-jars.jar'>
<zipgroupfileset dir="${lib.dir}">
<include name="**/*.jar" />
</zipgroupfileset>
</jar>
<sleep seconds='1'/> <!-- avoid timestamp warnings -->
what this will do is create in your build.dir directory a single jar file named lib-jars.jar that contains all the classes from all of the 3rd party jars. Understand that this will result in equivalent files (like MANIFEST.MF files) being overwritten if they exist in multiple jars and only the last one will be present.
Once you have this new all-libs jar, you can then jar up your application classes and the contents of this all-libs jar into one jar:
<jar destfile='${jar.file}' basedir='${classes.dir}'>
<!-- using zipfileset we can filter on entries in the one file -->
<zipfileset src='${build.dir}/lib-jars.jar'>
<exclude name="META-INF/MANIFEST.MF"/>
</zipfileset>
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Main-Class" value="${main.class}"/>
<section name="common">
<attribute name="Specification-Title" value="${project.title}"/>
<attribute name="Specification-Version" value="${release.version}"/>
<attribute name="Specification-Vendor" value="${vendor}"/>
<attribute name="Implementation-Title" value="${project.title}"/>
<attribute name="Implementation-Version" value="${release.version}"/>
<attribute name="Implementation-Vendor" value="${vendor}"/>
</section>
</manifest>
</jar>
notice that I exclude the MANIFEST.MF file from the all-libs jar and create my own. Then end result of this is a single jar file that includes all of the classes/property files/resources from all of the library jar files and your classes.
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.