Build the classpath string for an executable Jar with ant

These days i need to deliver a Java program and faced the problem to generate the classpath string for the manifest file. After struggling around i managed to let ant build this string. I wonder why there isn’t an attribute in the manifest task which can deal with an classpath fileset.

OK, here is my solution (i post it mostly for me – to keep it in memory.. ) which uses a filesetpath and the
pathconvert task.

The directory structure should look like this:

dist
|- lib
| |- x.jar
| |- y.jar
| |- z.jar
|- executable.jar
|- start.bat

Where all needed librarys (eg. log4j.jar, spring.jar etc.) are stored in a subdirectory called lib.

In the ant build.xml we define some properties and the classpath:

         
         <property name="src.dir" value="src" />
         <property name="src.lib.dir" value="librarys" />

        <property name="dist.dir" value="dist" />
	<property name="dist.dir.location" location="dist" />
        <property name="dist.lib.dir" value="lib" />

        <path id="compile.classpath">
		<fileset file="${src.lib.dir}/x.jar" />
		<fileset file="${src.lib.dir}/y.jar" />
		<fileset file="${src.lib.dir}/z.jar" />
       </path>

The interesting thing is the dist.dir.location which is defined as location. This enables us to use the given relative path as absolute path in the pathconvert task.

Before we build the manifest we need to copy the librarys to the lib folder and build the classpath string out of the classpath fileset. This String will passed to the manifest task an specify the classpath relative to our executable jar.

        <!-- copy all needed librarys into the lib folder -->
	<copy todir="${dist.dir}/${lib.dir}" flatten="true" verbose="true">
		<path refid="compile.classpath" />
	</copy>

Now we create a new path out of al librarys stored in the lib folder. This path wil be used to build the classpath string for the manifest file. This is necessary to create consistent path information in the
lib.classpath path (maybe some of your librarys in the project a stored in different places). Now they all have a path like c:/project/dist/lib/x.jar; c:/project/dist/lib/y.jar …

	
	<path id="lib.classpath">
		<fileset dir="${dist.dir}/${lib.dir}">
			<include name="*.*" />
		</fileset>
	</path>
       

After this we convert the path information into a string which is java classpath conform:
./lib/x.jar ./lib/y.jar ….

      <!-- convert lib folder to string property for use in manifest classpath-->
	<pathconvert property="string.classpath" pathsep=" ">
		<path refid="lib.classpath" />
		<map from="${dist.dir.location}\" to=".\" />
	</pathconvert>

Now we can use ${string.classpath} to build the manifest:

       <!-- create the manifest file -->
	<manifest file="${src.dir}/MANIFEST.MF">
		<attribute name="Implementation-Title" value="MyProject" />
		<attribute name="Implementation-Version" value="0.0.1" />
		<attribute name="Implementation-Vendor" value="Me" />
		<attribute name="Main-Class" value="de.koelnerwasser.SuperApp" />
		<attribute name="Class-Path" value="${string.classpath}" />
	</manifest>

And jar the mainproject:

        <!-- jar all the stuff -->
	<jar jarfile="${dist.dir}/MyProject.jar" basedir="${src.dir}" 
         manifest="${src.dir}/MANIFEST.MF" />

To start the Application in windows, it’s useful to put a start.bat file in the dist folder. The bat is easy – it only starts the jar..

java -jar MyProject.jar
pause

Spring – BeanId vs. BeanName

Spring supports two ways to adress a Bean, by ID or by Name.
But what happens in the following scenario :

<bean id="test1" name="test" class="java.lang.String"/>
<bean id="test" class="java.lang.Object"/>

If the declaration is made in one spring configuration xml, the spring parser will throw an exception during spring startup. This is expected.

But be careful if the declaration is distributed over two spring configuration files. In this scenario the spring parser will not intervene.
If you try to get the bean via applicationContext.getBean(“test”), the id=test1 bean is delivered. In general it’s better to declare beans by id not by name. This avoids to corrupt beanDefinitions in other spring configuration files.

The name property should only be used for names which datatypes are not xsd:ID conform.