How to include a property file in WEB-INF folder of war - java

I am using ant to build my web-app. I am trying to include a property file in the WEB-INF folder from a source folder. I have included it in the war/WEB-APP/classes folder. But the application is not reading it. Hence, i want to include it in the WEB-INF folder directly to read it in the application.
I have tried the following but nothing seems to work. my build.xml looks like this :
<target name="build-dev" description="Package GWT app to web archive and deploy to web server">
<echo message="Package GWT app to web archive" />
<copy toDir="${basedir}/war/WEB-INF/lib">
<fileset dir="${basedir}/lib" includes="*.jar" />
<fileset dir="${gwt.home}" includes="*.jar" />
</copy>
<copy todir="${basedir}/war" file="${basedir}/src/etc/dev/GroupQuoteUI.properties" />
<war basedir="${war.dir}" destfile="${deploy.dir}/${app.name}.war" webxml="${webinf.dir}/web.xml">
<webinf dir="${webinf.dir}/">
<include name="*." />
<exclude name="**/web.xml" />
</webinf>
<classes dir="${basedir}/src/etc/dev/" includes="*.properties" />
</war>
</target>
i have tried to use :
"include name="${war.dir}/GroupQuoteUI.properties" in "webinf" tag but it did'nt worked.
Also includes="${war.dir}/GroupQuoteUI.properties" inside the tag.
Also this inside "webinf" folder again :
"zipfileset dir="${basedir}/war/" includes="GroupQuoteUI.properties" fullpath="${webinf.dir}/GroupQuoteUI.properties"
but this is giving an error during build stating "cannot have src dir together".
So what should i do to include this file in the WEB-INF directory of the war. All other directories and web.xml file is included.

You cannot read a file that is packed into a war, or jar by accessing it with
new FileInputStream()
Instead you can do the following:
this.getClass().getResourceAsStream(filename)
this will load a resource (your properties-file) from the classpath, so it will read the file in a war-archive.
It does this by using the same ClasseLoader which has been used to load the class that belongs to this.getClass()
Here you can find an example:
How to really read text file from classpath in Java

Related

Splash-Screen works in IDE but not as .jar - issue with ANT?

I'm attempting to add a splash-screen to a large Java project. The application is compiled into an executable .jar file using ANT.
I am able to get the splash screen working easily from NetBeans by simply adding -splash:src/com/.../.../image.PNG to my main project's VM options. However, adding SplashScreen-Image: com/.../.../image.PNG to my manifest file fails with "SplashScreen.getSplashScreen() returned null"
I have already opened up my .jar archive to confirm that things were set up correctly: my META-INF\MANIFEST.MF file includes the SplashScreen-Image line. I have tried moving it before or after Main-Class. My actual image.PNG is also in the archive, in the correct path location.
I compile this java project with ANT, which I can guess is the source of my problems (I was able to make a simple, "jar cmf ..." example work just fine).
I use the following to get the project elements ready for achiving:
<target name="compile" depends="init"
description="Compile the source">
<!-- Compile the java code from ${src} into ${build} -->
<path id="lib.path.ref">
<fileset dir="${path_to_jre}" includes="*.jar"/>
</path>
<javac srcdir="${src}" destdir="${build}" source="${java_ver}" target="${java_ver}"
includeantruntime="false">
<!--compilerarg value="-Xbootclasspath/p:${toString:lib.path.ref}" compiler="javac1.7"/-->
<compilerarg value="-Xlint:unchecked"/>
<classpath>
<fileset dir="${LibDir}">
<include name="*.jar"/>
</fileset>
<pathelement path="${dependant_jar}"/>
<pathelement path="${another_dependant_jar}"/>
</classpath>
</javac>
<!-- Copy the .png files -->
<copy todir="${build}">
<fileset dir="${src}" casesensitive="false">
<include name="**/*.PNG"/>
</fileset>
</copy>
</target>
Notice that I use a copy to move .PNG files in with .class files. My image.PNG for the Splash Screen is just in with the others. I added it to my netbeans project by simply copying it there - nothing fancy.
My achieve target is as follows:
<target name="archive" depends="compile"
description="Generate the .jar file">
<!-- Put everything in ${build} into the .jar file -->
<jar jarfile="${jarfile}" basedir="${build}">
<!-- Merge in contents of dependency .jars -->
<zipfileset src="${LibDir}/snakeyaml.jar"/>
<zipfileset src="${dependant_jar}"/>
<zipfileset src="${another_dependant_jar}"/>
<!-- Specify main class in manifest -->
<manifest>
<attribute name="SplashScreen-Image" value="com/../../image.PNG"/>
<attribute name="Main-Class" value="${mainclass}"/>
</manifest>
</jar>
</target>
So my manifest in the eventual .jar is created here, which is also where I eventually realized to add the splashscreen tag.
I am somewhat new to working with ANT, so any advice regarding how to handle this or what to look for is appreciated.
It is not an issue with Ant. The problem is that the -splash option takes a file name, but the SplashScreen-Image manifest attribute must refer to a jar entry. If com/example/brian/image.PNG isn’t in the .jar file, it won’t be usable by SplashScreen-Image. The purpose of a .jar file is to be act as a self-contained module or application, so it should include all of the resources it needs.
The solution is to include the image in your .jar file:
<jar jarfile="${jarfile}" basedir="${build}">
<fileset dir="${src}" includes="**/*.PNG"/>
Update: Your build file was already adding the images to the .jar with a <copy> task, and I failed to notice it.
I have a solution, although I'm sure someone else will understand this better than I do.
I was able to run, with a splash-screen, using the Java binary in ../jre/lib/Java.exe, however I had initially been working from ../lib/Java.exe.
Looks like this is a known bug? Link here: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7129420. I guess the path to the SplashScreen dll is hardcoded.
Note: Thanks to user VGR for the exhaustive help.

ant: include resources in subdirectory to war file

I would like to include a set of resource files to my war file.
I know that I can specify either fileset or webinf as an inner element of my war element in build.xml, but in both of these cases, when I deploy the war file, the resource files end up in either top level directory or WEB-INF directory respectively.
I would like to place them into a subdirectory (say, WEB-INF/resources). Actually, these resource files are in a subdirectory in my source three already, I just need to include this subdirectory as is to the war file.
How is this done?
You can use zipfileset with prefix attribute to add a subdirectory to zip/war file. If the resource files is in src/resource, and you want to pack them into WEB-INF/resource. Here is the example:
<target name="build">
<war destfile="test.war">
<fileset dir="webapps">
<include name="**" />
</fileset>
<zipfileset dir="src/resource" prefix="WEB-INF/resource" />
</war>
</target>

How to include library files while creating jar files without copying library separately

I need to include some third party jar file to my project jar. I mentioned it in my build.xml and include this to MANIFEST.MF. Now i get thirdparty1.jar thirdparty2.jar file into inside the project jar. But still i can't able to use the jars. Is it need any addition configuration
Here is my build.xml
<manifest>
<attribute name="Class-Path" value="thirdparty1.jar thirdparty2.jar thirdparty3.jar"/>
If i copy the two jar separately it works well. But i don't understand what is the need for copy these separate. How it solve with out copying jar separately.
If the dependency jar is packaged inside the project jar, you need a solution to load it from there. The standard class-path handling in Java won't access jar files located inside other jar files.
See this answer: Classpath including JAR within a JAR. Specifically the One Jar solution: http://one-jar.sourceforge.net/.
It's also possible to use zipgroupfileset for that.given is the sample ant task for that.
<!-- Build JAR file -->
<target name="jar" depends="init-build-dir,compile-main">
<!--creating a temp jar contains all jar -->
<jar jarfile="${project.build.lib.dir}/external-libs.jar">
<zipgroupfileset dir="${project.lib.redist.dir}">
<include name="**/*.jar" />
</zipgroupfileset>
</jar>
<sleep seconds="1" />
<!-- creating main jar with temp jar-->
<jar jarfile="${project.build.lib.dir}/${ant.project.name}.jar" manifest="MANIFEST.MF">
<fileset dir="${project.build.main.classes.dir}" includes="**/*.*" />
<zipfileset src="${project.build.lib.dir}/external-libs.jar">
<exclude name="*" />
</zipfileset>
</jar>
<!--removing temp jar -->
<delete>
<fileset dir="${project.build.lib.dir}">
<include name="external-libs.jar" />
</fileset>
</delete>
</target>

Creating a WAR file using Java

How do I create a deployable WAR file for Apache Tomcat servers programmatically with Java?
Is there a library for such a task?
I am working on a small own IDE for special purposes. The IDE is written in Java and JavaScript, so I need to create the WAR file using those.
If you want to build it from code try to do it from the command line with
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("jar cvf /path/to/your/project/your-file.war");
Of course, the same thing would work using ANT or Maven (as long as those tools are installed on the final platform).
Edit: added improvement suggestion
I don't know of libraries, but a WAR file is just a ZIP file with a different ending.
Just create the inner folder structure and files (google the java code for that) and package as zip (java has methods for that too I think, again google) and rename the file from "myfile.zip" to "myfile.war"
I don't know how you would do it using the IDE you have. But a WAR file has the following structure:
web resources go to the root
project classes (including their package folders) go to a folder WEB-INF/classes
project dependency jars go to WEB-INF/lib
So if you want to build a WAR by hand, you need to create that file structure inside a zip file with a .war extension and you need to copy that to the proper location of the server to deploy it. Most servers also allow 'exploded deployment', meaning that you don't need an actual war file, you can just deploy the stuff to a directory with the same name as your war (IE. 'myapp.war').
You can do this a number of ways, for a quick example if you are using maven you just need to use <packaging>war</packaging>
You could just export the war as has been mentioned, but it's not exactly "programmatic".
If you're using Ant - you can find a tutorial for this here
<?xml version="1.0" ?>
<path id="compile.classpath">
<fileset dir="WebContent/WEB-INF/lib">
<include name="*.jar"/>
</fileset>
</path>
<target name="init">
<mkdir dir="build/classes"/>
<mkdir dir="dist" />
</target>
<target name="compile" depends="init" >
<javac destdir="build/classes" debug="true" srcdir="src">
<classpath refid="compile.classpath"/>
</javac>
</target>
<target name="war" depends="compile">
<war destfile="/APP/jboss-5.1.0.GA/server/all/deploy/DispatchActionEx.war" webxml="WebContent/WEB-INF/web.xml">
<fileset dir="WebContent"/>
<lib dir="WebContent/WEB-INF/lib"/>
<classes dir="build/classes"/>
</war>
</target>
<target name="clean">
</target>
Just write an build.xml file(i have give an example),
change "project name" and "war destfile" which will be ".../apache-tomcat/webapps/projectname.war"
put it in your project folder
open it in eclipse.
right click on it>>run as>>ant build
check whether the war file is created in the webapps folder in apache-tomcat

How Apache Ant deploys .war file to Tomcat

I'm using Apache Ant 1.8 to deploy a web application into a local Tomcat server, and the build.xml file (below) produces the desired effect when I run 'ant deploy' at the command line.
My question is, I noticed that the .war file gets placed where I expect it to (deploy.dir is defined in my home directory's build.properties file), but it also unexpectedly unpacked the .war and extracted the context itself into that same directory. Where in the below build.xml file is that configured?
<target name='init'>
<property file='${user.home}/build.properties'/>
<property name='app.name' value='${ant.project.name}'/>
<property name='src.dir' location='src'/>
<property name='lib.dir' location='lib'/>
<property name='build.dir' location='build'/>
<property name='classes.dir' location='${build.dir}/classes'/>
<property name='dist.dir' location='${build.dir}/dist'/>
</target>
<target name='initdirs' depends='init'>
<mkdir dir='${classes.dir}'/>
<mkdir dir='${dist.dir}'/>
</target>
<target name='compile' depends='initdirs'>
<javac srcdir='${src.dir}/java' destdir='${classes.dir}'>
<!--
<classpath>
<fileset dir='${lib.dir}/development' includes='javaee.jar'/>
<fileset dir='${lib.dir}/production' includes='jr.jar'/>
</classpath>
-->
</javac>
</target>
<target name='war' depends='compile'>
<war destFile='${dist.dir}/${app.name}.war' webxml='${src.dir}/web/WEB-INF/web.xml'>
<classes dir='${classes.dir}'/>
<!--
<zipfileset dir='${lib.dir}/production' includes='jr.jar' prefix='WEB-INF/lib' />
-->
<fileset dir='${src.dir}/web' excludes='WEB-INF/web.xml' />
</war>
</target>
<target name='build' depends='war' description='compile and create the war' />
<target name='clean' depends='init' description='Use for a clean build'>
<delete dir='${build.dir}' />
</target>
<target name='ffbuild' depends='clean, build' description='clean and create the war'/>
<target name='deploy' depends='initdirs' description='copy the war file to the app server'>
<delete verbose='true' dir='${deploy.dir}/${app.name}'/>
<fail unless='deploy.dir' message='build.properties must exist in your home directory and define deploy.dir' />
<copy todir='${deploy.dir}' file='${dist.dir}/${app.name}.war'/>
</target>
Tomcat has an autodeploy folder in which any war file that you place will be automatically unpacked and deployed. Your ant file is simply copying the war file into this directory by calling a special URL in the tomcat-manager web application (which is prepackaged into the tomcat).
From this point on everything is handled by the tomcat core automatically, just if you copied the war file into the webapps directory manually.
You can have ant do a lot more with some specific ant tasks for tomcat. Especially if the Tomcat server is not on the local machine. See this link for details.
You have autodeploy turned on in your Tomcat installation. This link gives a detailed overview of autodeploy, but in a nutshell, Tomcat scans certain directories for updated web.xml and war files. If it finds a war file it deploys it automatically.
A better way to deploy (especially if you'll ever need to deploy to a remote machine) is to use the Ant tasks that come with Tomcat. This page shows how to set up your build file so you can deploy and undeploy from Ant. The page is old but the information is still good. Here's a snippet of a build.xml I use to deploy to Tomcat:
<taskdef name="deploy" classname="org.apache.catalina.ant.DeployTask">
<classpath>
<path location="${build-jars}/catalina-ant.jar" />
</classpath>
</taskdef>
<target name="buildAndDeploy" depends="buildWar">
<deploy url="${tomcat.manager.url}"
username="${tomcat.manager.username}"
password="${tomcat.manager.password}"
path="/${target.name}"
update="true"
war="file:${basedir}/deploy/${target.name}.war" />
</target>
You can find catalina-ant.jar in Tomcat's lib directory.
I've had very good luck with Tomcat's Ant tasks for deployment. Have a look at the Executing Manager Commands With Ant documentation for information. If you decide to go that route, you should be able to get it working in short order.
Probably, you're first copying all your files in your dest dir an then making war file, you should instead copy your files to some temp directory, create war file, copy it to dest dir, remove temp directory.

Categories