Creating a WAR file using Java - 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

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.

Need help understanding how a build.xml file works

Forewarning: I'm not very bright so the question may seem extremely idiotic.
I need to make an ant file that will compile my source files to a target directory.
In addition, it needs to test all the JUnit files in my project.
However, I understand next to nothing in a build.xml.
At the moment I have my project folder in eclipse contain two separate package folders that hold all my java files.
Would the following be along the right path?
<project name="PersonPersistence" default="compile" basedir=".">
<target name="compile" description="Compiles java source files.">
<mkdir dir="target"/>
<javac srcdir="src" destdir="target"/>
</target>
<target name="test" depends="compile" description="Tests JUnit files.>
<java jar="src/packOne/Test1.java"/>
</target>
</project>
Or do I need to do something else for the "test" portion? Such as putting all my test files into a jar file?

How to set up a Java workspace without an IDE

I usually code with IDEs like Intellij Idea or Eclipse, but due to several reasons, I no longer have access to an IDE, and I'd like to be able to code in Java on a remote Linux machine through a ssh terminal.
Making simple progams with only a few classes is easy, but some of my projects have several libraries and several separate .java files. I also need to export to a .jar file.
For example, I have the following file organisation:
project/
src/
a.java
b.java
c.java
libs/
lib1.jar
lib2.jar
out/
export_here.jar
someconfig.conf
The java app consists of the a, b, and c .java files, uses libraries lib1 and lib2, and the file someconfig.conf needs to be inside the export jar.
I want to know how to easily compile and build a project such as this.
In other words, I just want to know how to export my project into a runnable jar the right way.
I expect this can be done with a few commands. If so, I plan to make a shell script to automate everything.
Thanks in advance!
As suggested by other users you need to use a build management tool to do this like Ant, Maven etc. I have used Ant quiet frequently to do these kind of automated tasks. In order to install and Use Ant you can refer How To Install Apache Ant
After that the main task is to write your automation script and that is called a build xml in ant world. Here is a sample build.xml file you can refer to start with:
<project>
<target name="clean">
<delete dir="build"/>
</target>
<target name="compile">
<mkdir dir="build/classes"/>
<javac srcdir="src" destdir="build/classes"/>
</target>
<target name="jar">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/HelloWorld.jar" basedir="build/classes">
<manifest>
<attribute name="Main-Class" value="oata.HelloWorld"/>
</manifest>
</jar>
</target>
<target name="run">
<java jar="build/jar/HelloWorld.jar" fork="true"/>
</target>
</project>
And for more information on the above sample You can visit this
In General you can read more at How to create build.xml
After creating your build.xml you can run ant by ant <path to build.xml> or ant in case your build.xml lies in current directory
Hope this helps you in right direction

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.

what is the best practice to create a .jar file from a java project?

what is the best practice to create a .jar file from a java project??
Some points to consider:
Create proper MANIFEST.MF, which should contain:
Build date;
Author;
Implementation-version;
Use a script/program - like an Ant task - which takes care of properly creating a manifest file.
Here's a simple ant file which builds a java project, adapted from the Ant tutorial:
<project>
<target name="clean">
<delete dir="build"/>
</target>
<target name="compile">
<mkdir dir="build/classes"/>
<javac srcdir="src" destdir="build/classes"/>
</target>
<target name="jar">
<mkdir dir="build/jar"/>
<jar destfile="build/jar/HelloWorld.jar" basedir="build/classes">
<manifest>
<attribute name="Implementation-Version" value="1.0"/>
</manifest>
</jar>
</target>
<target name="run">
<java jar="build/jar/HelloWorld.jar" fork="true"/>
</target>
</project>
Read up on the basics of Sun's JAR format at this tutorial. In my opinion you should learn the basics -- namely MANIFESTs, the SDK tools -- before jumping into third party tools such as the following.
The Jar command line tool distributed with the Sun JDK:
jar -cf myjar.jar base_src_folder
Where base_src_folder is the parent directory holding your source code.
Alternatively you could use a build tool such as Apache Ant. It has features such as the JAR task to do this for you.
Apache Maven, for projects which are dependent on other projects.
Admittedly, Maven may be overkill for learning projects, but it is invaluable for larger, distributed ones.
Eclipse IDE is the best way for new comers. Just select the project right click export File, select jar anf filename.
Apache Ant
Ant is not quite easy to begin with. Instead, I would suggest using an IDE, for instance NetBeans, which creates an Ant script under the hood. All you have to do is to hit "build", and you get a .jar file as result.

Categories