Including a directory inside web-inf/lib in tomcat classpath - java

In my webapp; WEB-INF/lib is added in classpath by default which is fine.
Now, I want to add spring jar files in my tomcat's classpath. If I put all the jar files inside WEB-INF/lib; it works fine. But if I want to add a directory WEB-INF/lib/spring and put all jar files inside spring directory ; it doesnt work. How can I include WEB-INF/lib/spring in classpath.
I would prefer to make changes in web.xml as that is very localised to my webapp. Surely I will not want to make changes in catalina.properties because there all the jar files are loaded in JVM ( not just added in classpath )

You shouldn't care about how the jar files are segregated into the war file: it's only used by the container. Segregating the jar files could be useful in your source project. But then you just need to have a build process (using ant, gradle, whatever) that copies all the jar files from all the subdirectories into WEB-INF/lib. Using ant:
<copy todir="web/WEB-INF/lib" flatten="true">
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
</copy>

Since things don't care about JAR naming, another alternative is to simply append prefixes to the the JARs (i.e. "spring-OLD JAR NAME.jar") to keep related JARs grouped without folders.

Related

Ant jar task - Include files not underneath basedir

I am trying to write an ant target that will create a jar based on a bunch of java files and some properties files, but am having trouble including the properties files the way the project is set up currently.
These are the ant targets I have:
1 - Compile the java souce files from the "myjar.src" folder and put the resulting classes into a "myjar.classes" folder. Once this is done copy all non .java files from "myjar.src" to "myjar.classes".
2 - Create the jar using the "jar" command using basedir = ${myjar.classes} and tell it to include everything.
These are the ant targets I want:
1 - Compile the java souce files and put the resulting classes into a "myjar.classes" folder. Only .java files are included
2 - Create the jars using the "jar" command using basedir = ${myjar.classes.location} but also include the .properties and .xml files from "myjar.src."
The key difference is I want the properties and xml files from "myjar.src" to be included when I package up the classes in "myjar.classes" using basedir = ${myjar.classes} - How do I include these fies when they are not underneath "myjar.classes"?
This is the ant target I want to modify:
<CreateManifest title="myjar classes etc"/>
<jar
destfile="${myProject.build.jars.dir}\ta_test_driver.jar"
basedir="${myjar.classes}"
manifest="${manifest}">
<include name="**"/>
</jar>
The reason I am not just using a directory one level up for basedir is that none of the other jar creation calls in the project do that, and I am hesitant to change that for just this one. I did try to do that, but had trouble specifying the right directory. (There are other jars that use a similar directory structure, and I don't want to interfere with them either now or in the future.) I was just wondering if these is a better way to do this? Thanks very much.
I managed to figure this out from here: How to include file in Jar through Ant at specific location
This was my modified ant call in the end:
<CreateManifest title="myjar classes etc"/>
<jar
destfile="${myProject.build.jars.dir}\ta_test_driver.jar"
basedir="${myProject.classes}\ta_test_driver"
manifest="${manifest}">
<include name="**"/>
<zipfileset dir="${myjar.src}"
includes="**/*.xml, **/*.properties, **/*.gif"
/>
</jar>
Notice the zipfileset tag.

Generate jar files from required project

I have a Java project composed by many jar files, let's say the application directory is composed by the following jar files:
File_1.jar
File_2.jar
...
File_N.jar
In addition there is a file executable file which makes use of the jar files
For some reason I am responsible of modifying two jar files, les's say File_1.jar and File_2.jar with the particularity that File_2.jar requieres the project associated to File_1.jar in the build path.
I generated the jar files without problems, so rigth now the application has the following jar files:
File_1_modif.jar
File_2_modif.jar
File_1.jar
File_2.jar
...
File_N.jar
Everything went fine, I mean I could execute the application with my modifications but my problem came up when I removed the old jar files(File_1.jar, File_2.jar) from the application directory. Actually I do not get an error message but the application does not behave as it did before removing the old jar files, I was wondering if I should generate the file File_1_modif.jar in an special way due to the fact that this file is requiered to build the file File_2_modif.jar. Could anybody advice my some tries to do in order to fix my problem?
It appears your project is still referencing the File_1.jar and File_2.jar. You may need to locate how the jar files are being loaded into your project, if in eclipse or netbeans, you'll need to add the File_1_modif and file_2_modif files to your build path and remove the file_1.jar and file_2.jar. If you are using ant build, you will have to include the .jar files using directives like this:
<fileset dir="${lib}">
<include name="file_1_modif.jar"/>
<include name="file_1_modif.jar"/>
<exclude name="**/${ant.project.name}.jar"/>
</fileset>

Setting Class-Path in Ant build script

I'm trying to build my console application and I'm using Ant to build it. I can run my application in Eclipse, but when I try to run it from jar that I get - the ClassNotFoundException: is thrown. is in one of jars, that I use for my application. Here is a part of build.xml where I create manifest:
<manifest>
<attribute name="Main-Class" value="com.package.Reporter" />
<attribute name="Class-Path" value="lib/commons-httpclient-3.1.jar
lib/commons-logging-api.jar
...lot of jars...
lib/stax-api-1.0.1.jar" />
</manifest>
The required class is in commons-httpclient-3.1.jar
And here is how I set up classpath for compiling, that is fine:
<path id="libs.dir">
<fileset dir="lib" includes="**/*.jar"/>
</path>
UPD: Should I put jars with libs to my jar? Now I'm putting them to "lib" directory of my jar. So myjar.jar contains package with my classes, META-INF directory and lib directory.
Max, you can't insert jar libs into jar, assuming normal usage. Either you don't have to specify them manually at runtime as Romski suggested. When invoking java -jar myjar.jar it should locate all your jars provided that they are located in the lib directory. lib directory must be in the same directory that jar resides in. Doesn't matter if you call java executable directly or through ant java task.
Note that the current directory doesn't matter only the relation between the jar and the lib.
Now being overly explicit. Perform sanity test as follows: create a new tmp directory and copy files to it:
tmp/myjar.jar
tmp/lib/commons-httpclient-3.1.jar
Run java -jar tmp/myjar.jar
Edit: now I see I just wrote the same what is in Oracle jar tutorial. But I also made tests myself with a relative directory. I also see dozens of stackoverflow questions searching for jar in jar so please first search SO, then ask.
try to change the path like this.
<path id="libs.dir">
<fileset dir="./lib" includes="**/*.jar"/>
</path>
You need the manifestclasspath task.
Example:
Ant - how to get all files' name in a specific folder

Can ant replace text in files inside a jar/ear/war?

I want to build my ear file once and then use ant to change some settings in application.xml, property files etc.
Is there way to do this with ant?
[edit] Just found this
How do I modify a file in a jar file using ANT?
The only way you can modify a file inside your jar or ear is to use the <unzip> task, use the <replace> task to modify the fields in the file, and then rezip the file back up with either the <zip> or <jar>/<ear> task.
There are several ways you can handle this without having to unzip and rezip your ear/jar/war files:
The preferred method is to setup your application server, so it can find your properties outside of the ear itself. It is also possible to configure the application.xml file not to use relative directories when specifying locations instead of specifying locations from the root of the machine. By removing embedded environment information from your ear, you can use the same earfile on all of your environments.
We, unfortunately, are unable to do the above and must provide separate ear files for each environment. We use Jenkins as our continuous build server. When Jenkins does our builds, we build multiple ears, one for each environment, at the same time. This way, as we move from Dev to QA to STAGE to Production, we can at least refer to the same build number. We compile once, then use the AntContrib <foreach> task to ear up the earfile with the correct properties file settings and the correct application.xml file. We use <filterset> in our <copy> task to modify the properties and application.xml as we build the ear.
You can do something like this
<zip destfile="tmp.jar" >
<zipfileset src="lib/myjar.jar" excludes="org/example/My*.class" />
<zipfileset dir="bin" includes="org/example/My*.class" />
</zip>
<move file="tmp.jar" tofile="lib/myjar.jar"/>
In this example we create a tmp.jar using myjar.jar as the source but excluding all classees beginning My in the org/example directory. We then add our new version in from the bin directory. We then replace the jar file with our new version.

How to add resources to classpath

How do you add a folder (e.g. a resource folder containing arts) to the classpath of a netbeans project? I managed to do that manually via editing the NB generated jar file of the project (that is its MANIFEST.MF file + copying the resources manually), but there should be a way to tell netbeans as well to mind the resources, no?
The folder structure looks like this:
/project/art/
/project/dist/lib/
/project/dist/art/
/project/dist/project.jar
/project/lib/
/project/src/
I don't want to package the art into the jar because I'd like the art to be easily exchangeable. If I add the art folder to the src folder then NB compiles fine, but the art resources end up in the jar.
Adding the art folder to the netbeans project libraries (Properties -> Libraries -> Add JAR/Folder) seemed not to work, because then I ended up with an error '...\project\art is a directory or can't be read. Not copying the libraries.' which in turn prevents even the real libraries folder from being copied.
Any ideas?
Best regards
Chris
2 Observations made, based on the comments from gpeche:
a) Rather specifying the additional resources folder in the "Run" tab than in the "Compile" tab of the project properties -> Libraries doesn't seem to make a lot of difference in Netbeans (I'm currently using 6.9.1). The output (and thus error) stays the same, that is nothing gets copied at all:
Created dir: C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\dist
C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\art is a directory or can't be read. Not copying the libraries.
Not copying the libraries.
Building jar: C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\dist\VocabularyTrainer.jar
Another interesting aspect is that in the help menu of the Libraries panel nothing is explicitly mentioned regarding folders as libraries. Could it be possible, that the button in Netbeans is falsely named, that is only real jar's are allowed?
b) Adding the resources folder to the Libraries list does have the impact though, to add another entry to the MANIFEST.MF. While - and that's the smaller issue - the classpath entry seems to be always expecting the resource folder to be a subfolder of the library folder (e.g. "lib/arts") the major problem is that there seems to be a slash missing.
As mentioned the NB generated entry in the MANIFEST.MF will look like this "lib/arts" (which does not work for me), while (manually set) "lib/arts/" does?!
The way I use resources from the folder is something like this:
URL resource = getClass().getResource("/gui/refresh.png");
ImageIcon tmp = new ImageIcon(resource);
Edit:
Based on Tushars comment and this posting I found the following solution to be an acceptable tradeoff between functionality and comfort.
I override the ANT target from the auto generated 'build-impl.xml' file which creates the Class-Path in the MANIFEST.MF file in the basic 'build.xml' file of the Netbeans project. The code which goes to the 'build.xml' file looks like this:
<property name="art.classpath" value="art/" />
<target name="-post-jar">
<mkdir dir="${dist.dir}/art"/>
<copy todir="${dist.dir}/art">
<fileset dir="${basedir}/art">
<!-- <exclude name="**/!source/**"/> if you want to exclude something... -->
</fileset>
</copy>
</target>
<target name="-init-macrodef-copylibs">
<macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
<element name="customize" optional="true"/>
<sequential>
<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}" index="${jar.index}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Class-Path" value="${jar.classpath} ${art.classpath}"/>
<customize/>
</manifest>
</copylibs>
</sequential>
</macrodef>
</target>
The tradeoff is that for development in Netbeans I still have to add the resource folder (e.g. 'art') to the libraries list to make the project run in Netbeans. This will cause an additional entry in the MANIFEST.MF file ('lib/art') along with the effect that the libraries will not get automatically copied to the 'dist' folder, with the message
...\art is a directory or can't be read. Not copying the libraries.
Not copying the libraries.
This behavor is - afaik - intended (to force everything to be bundled up in a jar), even though there are discussions about it going on. To make a real distribution bundle I'd have to take away the resource folder(s) from the library list in NB and rebuild.
Ideas about a more streamlined setup without any tradeoffs are of course still welcome. :)
Adding resource folder to classpath:
When you Clean-&-Build a NetBeans Ant Based Project it creates a manifest.mf file in the root directory of the project. This file gets included in the JAR file also. Modify this file and add entry like follows:
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build
Class-Path: arts/
slash is important after arts in the class path.
Including the arts resource folder in the distribution
Either copy this folder in the dist folder after the build or add a ANT target to copy the required resources in the dist folder.
Add the target like as follows in the build.xml file:
<target name="-post-jar">
<mkdir dir="${dist.dir}/resources"/>
<copy todir="${dist.dir}/resources">
<fileset dir="${basedir}/resources" />
</copy>
</target>
Code to access such resources:
The code needed to access such resource files shall be as follows: (This will not work in design time but surely from the JAR file)
// pay attention to relative path
URL resource = ClassLoader.getSystemResource("gui/refresh.png");
ImageIcon tmp = new ImageIcon(resource);
NOTE: The files manifest.mf and build.xml located in the root directory of the project are accessible from the Files Panel in NetBeans IDE
Using NetBeans 8.0.2:
Right-click the project.
Select Properties.
Select Sources.
Click Add Folder for the Source Package Folders.
Select the the directory where the resources exist.
Click Open on the directory name.
Click OK to close the Project Properties dialog.
The resources are added to the project.
You'll see the directory added in your Navigation pane as well
In the other project, the resources are now available. For example, to read an image:
BufferedImage zero = ImageIO.read(OCR.class.getResourceAsStream("/0.bmp"));
In order to remove the lib/art from Class-Path and not get "is a directory or can't be read" need delete lib/art from path:
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
**<map from="${basedir}/art" to=""/> <!-- remove art from lib -->**
</pathconvert>

Categories