Executable war file that starts jetty without maven - java

I'm trying to make an "executable" war file (java -jar myWarFile.war) that will start up a Jetty webserver that hosts the webapp contained in the WAR file I executed.
I found a page that described how to make what I'm looking for:
However, following that advice along with how I think I'm supposed to make an executable jar (war) isn't working.
I have an Ant task creating a WAR file with a manifest that looks like:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 1.5.0_18-b02 (Sun Microsystems Inc.)
Main-Class: Start
The contents of the WAR file look like:
> Start.class
> jsp
> build.jsp
> META-INF
> MANIFEST.MF
> WEB-INF
> lib
> jetty-6.1.22.jar
> jetty-util.6.1.22.jar
When I try to execute the WAR file, the error is:
Exception in thread "main" java.lang.NoClassDefFoundError: org/mortbay/jetty/Handler
Caused by: java.lang.ClassNotFoundException: org.mortbay.jetty.Handler
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
Could not find the main class: Start. Program will exit.
There appears to be two errors here: one where it seems the JAR files can't be found, and one where the Start class can't be found.
To fix the first one, I put the Jetty JAR files in the base of the WAR file and tried again -- same error. I also tried adding the WEB-INF/lib/<specific-JAR-files> to the Class-Path attribute of the manifest. That did not work either.
Does anyone have any insight as to what I'm doing right/wrong and how I can get this executable WAR file up and running?

The link you have in your question provides most of what you need. However, there are a few things that need to be done in addition to that.
Any class files that Jetty needs to start up will need to be located at the root of the war file when it's packaged. We can leverage Ant to do that for us before we <war> the file. The war's manifest file will also need a Main-Class attribute to execute the server.
Here's a step-by-step:
Create your Jetty server class:
This is adapted from the link you provided.
package com.mycompany.myapp;
import java.io.File;
import java.net.URL;
import java.security.ProtectionDomain;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.webapp.WebAppContext;
public final class EmbeddedJettyServer
{
public static void main(String[] args) throws Exception
{
int port = Integer.parseInt(System.getProperty("port", "8080"));
Server server = new Server(port);
ProtectionDomain domain = EmbeddedJettyServer.class.getProtectionDomain();
URL location = domain.getCodeSource().getLocation();
WebAppContext webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setDescriptor(location.toExternalForm() + "/WEB-INF/web.xml");
webapp.setServer(server);
webapp.setWar(location.toExternalForm());
// (Optional) Set the directory the war will extract to.
// If not set, java.io.tmpdir will be used, which can cause problems
// if the temp directory gets cleaned periodically.
// Your build scripts should remove this directory between deployments
webapp.setTempDirectory(new File("/path/to/webapp-directory"));
server.setHandler(webapp);
server.start();
server.join();
}
}
To see what all you can configure here, have a look at the Jetty API documentation.
Build the war with Ant:
This uses a staging directory to unpack the necessary class files into the root of the war so they're accessible when the war is executed.
<target name="war" description="--> Creates self-executing war">
<property name="staging.dir" location="${basedir}/staging"/>
<property name="webapp.dir" location="${basedir}/src/webapp"/>
<mkdir dir="${staging.dir}"/>
<!-- assumes you have all of your war content (excluding classes and libraries) already structured in a directory called src/webapp -->
<!-- e.g. -->
<!-- src/webapp/index.html -->
<!-- src/webapp/WEB-INF/web.xml -->
<!-- src/webapp/WEB-INF/classes/my.properties -->
<!-- etc ... -->
<copy todir="${staging.dir}">
<fileset dir="${webapp.dir}" includes="**/*"/>
</copy>
<unjar dest="${staging.dir}">
<!-- you'll have to locate these jars or appropriate versions; note that these include JSP support -->
<!-- you might find some of them in the downloaded Jetty .tgz -->
<fileset dir="path/to/jetty/jars">
<include name="ant-1.6.5.jar"/>
<include name="core-3.1.1.jar"/>
<include name="jetty-6.1.24.jar"/>
<include name="jsp-2.1-glassfish-2.1.v20091210.jar"/><!-- your JSP implementation may vary -->
<include name="jsp-api-2.1-glassfish-2.1.v20091210.jar"/><!-- your JSP implementation may vary -->
<include name="servlet-api-2.5-20081211.jar"/><!-- your Servlet API implementation may vary -->
</fileset>
<patternset><!-- to exclude some of the stuff we don't really need -->
<exclude name="META-INF/**/*"/>
<exclude name="images/**/*"/>
<exclude name=".options"/>
<exclude name="about.html"/>
<exclude name="jdtCompilerAdapter.jar"/>
<exclude name="plugin*"/>
</patternset>
</unjar>
<!-- copy in the class file built from the above EmbeddedJettyServer.java -->
<copy todir="${staging.dir}">
<fileset dir="path/to/classes/dir" includes="com/mycompany/myapp/EmbeddedJettyServer.class"/>
</copy>
<war destfile="myapp.war" webxml="${webapp.dir}/WEB-INF/web.xml">
<fileset dir="${staging.dir}" includes="**/*"/>
<classes dir="path/to/classes/dir"/><!-- your application classes -->
<lib dir="path/to/lib/dir"/><!-- application dependency jars -->
<manifest>
<!-- add the Main-Class attribute that will execute our server class -->
<attribute name="Main-Class" value="com.mycompany.myapp.EmbeddedJettyServer"/>
</manifest>
</war>
<delete dir="${staging.dir}"/>
</target>
Execute the war:
If everything's set up properly above, you should be able to:
java -jar myapp.war
// or if you want to configure the port (since we are using the System property in the code)
java -Dport=8443 -jar myapp.war

This is an adaptation for Maven of #RobHruska's answer. It just copies the files of the main class and merges the Jetty JAR files into the WAR file, nothing new, just to simplify your life if you are new -like me- to Maven:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>move-main-class</id>
<phase>compile</phase>
<configuration>
<tasks>
<copy todir="${project.build.directory}/${project.build.finalName}">
<fileset dir="${project.build.directory}/${project.build.finalName}/WEB-INF/classes/">
<include name="main/*.class" />
</fileset>
</copy>
<unjar dest="${project.build.directory}/${project.build.finalName}">
<!-- you'll have to locate these jars or appropriate versions; note that these include JSP support -->
<!-- you might find some of them in the downloaded Jetty .tgz -->
<fileset dir="${project.build.directory}/${project.build.finalName}/WEB-INF/lib/">
<include name="ant-1.6.5.jar"/>
<!--<include name="core-3.1.1.jar"/>-->
<include name="jetty*"/>
<include name="servlet-api*"/>
</fileset>
<patternset><!-- to exclude some of the stuff we don't really need -->
<exclude name="META-INF/**/*"/>
<exclude name="images/**/*"/>
<exclude name=".options"/>
<exclude name="about.html"/>
<exclude name="jdtCompilerAdapter.jar"/>
<exclude name="plugin*"/>
</patternset>
</unjar>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<archiveClasses>true</archiveClasses>
<archive>
<manifest>
<mainClass>main.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>

We have figured this out by using jetty-console-maven-plugin.
Whenever you run mvn package it creates another war that can be used with java -jar whateverpackage-runnable.war
<plugin>
<groupId>org.simplericity.jettyconsole</groupId>
<artifactId>jetty-console-maven-plugin</artifactId>
<version>1.45</version>
<executions>
<execution>
<goals>
<goal>createconsole</goal>
</goals>
</execution>
</executions>
<configuration>
<additionalDependencies>
<additionalDependency>
<artifactId>jetty-console-requestlog-plugin</artifactId>
</additionalDependency>
<additionalDependency>
<artifactId>jetty-console-gzip-plugin</artifactId>
</additionalDependency>
<additionalDependency>
<artifactId>jetty-console-ajp-plugin</artifactId>
</additionalDependency>
<additionalDependency>
<artifactId>jetty-console-startstop-plugin</artifactId>
</additionalDependency>
</additionalDependencies>
</configuration>
</plugin>
It also generates the init.d scripts and everything for you!

Hudson solves this exact problem using the Winstone servlet container, which supports this use case directly. http://winstone.sourceforge.net/#embedding
Perhaps this would work for you?

Even though this is kind of old another alternative with Jetty 8 is to simply include the Jetty jars as dependencies in your pom and add the following in your pom (versus an ant script that unpackages the war and repackages it):
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>true</createDependencyReducedPom>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>JettyStandaloneMain</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- The main class needs to be in the root of the war in order to be
runnable -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>move-main-class</id>
<phase>compile</phase>
<configuration>
<tasks>
<move todir="${project.build.directory}/${project.build.finalName}">
<fileset dir="${project.build.directory}/classes/">
<include name="JettyStandaloneMain.class" />
</fileset>
</move>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>

I take it that by "without maven" you want a jar that you can run by itself and not with "mvn jetty:run"--not that you don't want to use maven at all.
It took me way to long to figure this out because I found many options--none of them dirt simple. Eventually I found this maven plugin from simplericity. It works wonderfully.

This is my example ANT extract. The idea is to unpackage the Jetty dependencies and then include them locally just like a normal JAR file:
<!-- Hack: Java doesn't support jars within jars/wars -->
<unjar src="${lib.dir}/container/jetty.jar" dest="${build.dir}/unjar"/>
<unjar src="${lib.dir}/container/jetty-util.jar" dest="${build.dir}/unjar"/>
<unjar src="${lib.dir}/container/servlet-api.jar" dest="${build.dir}/unjar"/>
<unjar src="${lib.dir}/container/jsp-api.jar" dest="${build.dir}/unjar"/>
<!-- Build war file as normal, just including the compiled and unjar'ed files -->
<war destfile="${war.file}" webxml="${config.dir}/web.xml">
<fileset dir="${build.dir}/classes"/>
<fileset dir="${build.dir}/unjar"/>
<fileset dir="${resources.dir}" excludes="*.swp"/>
<lib dir="${lib.dir}/runtime"/>
<manifest>
<attribute name="Main-Class" value="Start"/>
</manifest>
</war>
Note:
The WEB-INF/lib direcory is for the web applications dependencies. In this case we're packaging the WAR file so that it works like the normal Jetty JAR file on startup

Putting .jars inside a .war file root does nothing
Putting .jars inside WEB-INF/lib doesn't help the JVM find the Jetty files to even begin launching your .war. It's "too late" to put them there.
Putting .jars in the manifest Class-Path only works for external .jar files, not those contained in the .jar
So what to do?
Use a build script to simply merge all the .jar files you need into the .war file. This takes a little extra work. It's also a bit ugly in that the compiled code is part of the servable files in the .war
Add dependent .jars to the JVM's classpath with "java -cp jetty.jar:... ..." Works though this kind of defeats the purpose of one stand-alone .war

I have done a similar thing before but are you launchign the app as "java -jar xxx.war" ?. You have only 2 jars and it is not going to be enough I think. Also try using Jetty 7.0.0M1 (which is the latest version). When I added jetty-server and jetty-webapp as two dependencies (they are from org.eclipse.jetty) I get the following jar's in the lib directory. FYI the org.mortbay.jetty.Handler was in the jetty-server*.jar.
jetty-continuation-7.0.0.M1.jar
jetty-http-7.0.0.M1.jar
jetty-io-7.0.0.M1.jar
jetty-security-7.0.0.M1.jar
jetty-server-7.0.0.M1.jar
jetty-servlet-7.0.0.M1.jar
jetty-util-7.0.0.M1.jar
jetty-webapp-7.0.0.M1.jar
jetty-xml-7.0.0.M1.jar

Related

Google API Client Library in Java set-up error in Eclipse

I am trying to download the source-code of Google API Client Library written in Java and perform some local developments. However, setting up the project seems to be a big hurdle.
I meticulously followed the instructions written here:
https://developers.google.com/api-client-library/java/google-api-java-client/contribute
However, I am still getting a bunch of error, possibly due to maven settings. I have tried updating the projects and downloading sources and Javadoc. Still, I am getting these errors. Spend nearly 3-4 hours.
The main errors are of these kinds:
1.Missing artifact com.google.api-client:google-api-client-servlet:jar:1.21.0-SNAPSHOT
Error Point:
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client-servlet</artifactId>
</dependency>
2.Plugin execution not covered by lifecycle configuration: org.apache.maven.plugins:maven-antrun-plugin:1.6:run (execution: generate-sources, phase: generate-sources)
Error Point:
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<target>
<mkdir dir="target/generated-test-sources" />
<exec failonerror="true" executable="protoc">
<arg value="--java_out=target/generated-test-sources" />
<arg value="src/test/java/com/google/api/client/googleapis/batch/mock_data.proto" />
<arg value="src/test/java/com/google/api/client/googleapis/batch/error_output.proto" />
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
3.The container 'Maven Dependencies' references non existing library '/home/sohamgrad/.m2/repository/com/google/oauth-client/google-oauth-client-appengine/1.21.0-SNAPSHOT/google-oauth-client-appengine-1.21.0-SNAPSHOT.jar'
No error point in this case.
These are the main 3 types of errors. These types of errors are happening in multiple places.
I would appreciate any kind of help in this.

Maven concat files specific files in a directory

I have a directory with unknown depth and folder names.
>A
-> AB
--> configuration.xml
--> ABC
---> configuration.xml
-> AD
--> configuration.xml
-> allconfigurations.xml
I need a maven plugin to concat all the configuration.xml files and create allconfigurations.xml file in the root. Unfortunately folder names and depth is unknown. It would be great to accomplish it within the pom.xml file without needing any other files.
just a quick google for you: the maven-shade-plugin with the XmlAppendingTransformer could help.
sample config is here
While struggling I realized that the real problem is to put a header and footer for the compiled allconfigurations.xml file, since each configuration.xml file is a fragment and when I concat all of them together resulting xml is not a valid xml.
here is the case;
an xml file is something like:
<Configuration xmlns="abc">
...
<connectionTimeoutInMs>240000</connectionTimeoutInMs>
<socketTimeoutInMs>240000</socketTimeoutInMs>
<persist>false</persist>
<internal>false</internal>
...
</Configuration>
and putting many of them is not valid thus result xml must be something like;
<AllConfigurations xmlns="abc">
...
<Configuration xmlns="abc">
...
</Configuration >
...
<AllConfigurations xmlns="abc">
so the first and last lines must be added to the result.
here is the solution I came up with;
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>default-cli</id>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<!--<phase>process-resources</phase>-->
<!--<phase>compile</phase>-->
<configuration>
<target>
<concat destfile="${project.basedir}/.../allConfigurations.xml"
force="yes">
<fileset dir="${project.basedir}/...">
<include name="xmlHeaderForConfiguration"></include>
</fileset>
<fileset dir="${project.basedir}/...">
<include name="**/configuration.xml"></include>
</fileset>
<fileset dir="${project.basedir}/...">
<include name="xmlFooterForConfiguration"></include>
</fileset>
</concat>
</target>
</configuration>
</execution>
</executions>
</plugin>
where xmlHeaderForConfiguration is a file with content; <AllConfigurations xmlns="abc"> and xmlHeaderForConfiguration has </AllConfigurations>

Jena schemagen in maven processing multiple ontologies

I am working on a project which uses multiple ontologies defined over several files. I am hoping to use Jena to generate the java classes to help with development but I can't seem to find a way to have Jena process multiple files as a maven goal.
I have never used Jena through maven before but I have used it on the command line (never for multiple ontologies at the same time).
The relevant part of my pom.xml is listed below (this was largely copied from the Jena website):
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>jena.schemagen</mainClass>
<commandlineArgs>
--inference \
-i ${basedir}/src/main/resources/ontologies/exception.owl \
--package com.borwell.dstl.mexs.ontology \
-o ${project.build.directory}/generated-sources/java \
</commandlineArgs>
<commandlineArgs>
--inference \
-i ${basedir}/src/main/resources/ontologies/location.owl \
--package com.borwell.dstl.mexs.ontology \
-o ${project.build.directory}/generated-sources/java \
</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
I have had a good look around on the Jena website and other sites (my googlefoo is usually quite good) but I have been unable to find anyone else having this problem or any documentation explaining how to do this.
Any help on this would be very useful.
I wrote a custom Maven task for Jena Schemagen, which is now part of the standard Jena distribution. See the documentation here
EDIT
This Answer now exists and calls out a more standard solution. Namely, the existence of a schemagen-maven plugin that the poster had developed which is included in the standard Jena distribution.
Original Answer
You have two options, create a custom maven plugin (which is actually not that difficult) or shell out to something outside maven to handle your needs. I made a hack in the past which I'll share with you. It's not pretty, but it works well.
This approach uses Maven Ant Tasks to call out to an ant build.xml from within the generate-sources phase of a maven build.
You begin by modifying your pom.xml to including the following:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<taskdef resource="net/sf/antcontrib/antcontrib.properties"
classpathref="maven.runtime.classpath" />
<property name="runtime-classpath" refid="maven.runtime.classpath" />
<ant antfile="${basedir}/src/main/ant/build.xml"
inheritRefs="true">
<target name="my.generate-sources" />
</ant>
</target>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>ant-contrib</groupId>
<artifactId>ant-contrib</artifactId>
<version>1.0b3</version>
<exclusions>
<exclusion>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
In the build.xml file (which, as you can see, is located in src/main/ant/build.xml, is the following.
<?xml version="1.0" encoding = "UTF-8"?>
<!DOCTYPE project>
<project name="my" default="my.error">
<property name="vocab.out.root" location="${basedir}/src/main/java" />
<property name="vocab.package" value = "put something here" />
<property name="vocab.ns" value="put something here" />
<path id="my.vocabulary">
<fileset dir="${basedir}/src/main/resources/put something here" casesensitive="yes" >
<include name="**/*.owl" />
</fileset>
</path>
<scriptdef language="javascript" name="make-proper">
<attribute name="string" />
<attribute name="to" />
<![CDATA[
var raw_string = attributes.get( "string" );
var string_elements = raw_string.split('-');
var nameComponents;
var finalName = "";
var i;
for(i = 0; i < string_elements.length; i++){
var element = string_elements[i];
finalName += element.substr(0,1).toUpperCase() + element.substr(1);
}
project.setProperty( attributes.get( "to" ), finalName );
]]>
</scriptdef>
<!-- target for processing a file -->
<target name="my.schemagen-file">
<echo message="${vocab.file}" />
<!-- for constructing vocab file name -->
<local name="source.file.dir" />
<dirname property="source.file.dir" file="${vocab.file}" />
<local name="source.file" />
<basename property="source.file" file="${vocab.file}" suffix=".owl" />
<local name="vocab.name" />
<make-proper string="${source.file}" to="vocab.name" />
<!-- for constructing destination file name -->
<local name="vocab.package.path" />
<propertyregex property="vocab.package.path" input="${vocab.package}" regexp="\." replace="/" global="true" />
<local name="dest.file" />
<property name="dest.file" value="${vocab.out.root}/${vocab.package.path}/${vocab.name}.java" />
<!-- Determine if we should build, then build -->
<outofdate>
<sourcefiles path="${vocab.file}" />
<targetfiles path="${dest.file}" />
<sequential>
<!-- Actual construction of the destination file -->
<echo message="--inference --ontology -i ${vocab.file} -a ${vocab.ns} --package ${vocab.package} -o ${vocab.out.root} -n ${vocab.name}" />
<java classname="jena.schemagen" classpath="${runtime-classpath}">
<arg line="--ontology --nostrict -i ${vocab.file} -a ${vocab.ns} --package ${vocab.package} -o ${vocab.out.root} -n ${vocab.name}" />
</java>
</sequential>
</outofdate>
</target>
<!-- Maven antrun target to generate sources -->
<target name="my.generate-sources">
<foreach target="my.schemagen-file" param="vocab.file" inheritall="true">
<path refid="my.vocabulary"/>
</foreach>
</target>
<target name="my.error">
<fail message="This is not intended to be executed from the command line. Execute generate-sources goal using maven; ex:\nmvn generate-sources" />
</target>
</project>
Walking you through the whole thing.
The maven-antrun-plugin executes our build script , making sure that antcontrib are available as well as the maven.runtime.classpath. This ensures that properties that would be available within maven are available within the ant task as well.
If build.xml is called without specifying a task, it intentionally fails. This helps to keep you from using it wrong.
If the my.generate-sources target is executed, then we can use foreach from antcontrib in order to process each file within your specified directory. Adjust this file pattern however you need to. Note that an assumed extension of .owl is used elsewhere.
For each owl file, the my.schemagen-file target is called. I utilize local variables in order make this function.
A custom ant task (defined in javascript, named make-proper) helps to generate the destination file names for your files. I use a convention where my vocabulary files are in some-hyphenated-lowercase-structure.owl. My desired class name for that would be SomeHyphenatedLowercaseStructure.java. You should customize this however you see fit.
For each derived file name, we test to see if it exists and if it is out of date. This convenience only allows schemagen to run if the source file is newer than the destination file. We use the outofdate task to do this.
We run schemagen. I use flags specific to OWL vocabularies. You can adjust this however best suits your system.
After more generalised searching and thanks to DB5 I have found the solution to be multiple executions. I was hoping for a more elegant solution but this does work.
Credit to DB5

Maven: Usage of external libraries for integration test

Currently, I set up an integration test suite. The base is a Maven project with several modules which are dependent to each other to setup a database, to put some data into it and to run tests on it, before wrapping everything up. Additionally, I have modules with some utilities and test data in there.
The first step (not mentioned above) is the copy of a zipped image which includes a lot of JAR files which make up the software suite to be tested. Unfortunately, the software is not build by Maven, but by Ant, so I can not find the stuff in an Artifactory or something similar.
My problem is now, that I copy and unzip the image with an integration test method, but I do not know, how I can add the JAR files to the Maven classpath. All other modules need to compile and run against the jars extracted from the ZIP file.
How can I add the JARs to the Maven class path for later compiling and test runs? The destination of the ZIP content is always the same directory. Unfortunately, the names of the JARs contain version information (build numbers) which change. So an easy usage of system and the tag is not working so easily. A path entry like ${package.path}/lib/*/.jar would be great. Is there a plugin, maybe?
Or does anyone have a better idea to setup an integration test against prebuild JARs?
Create a single jar from all of your dependencies, everything in ${package.path}/lib/*/.jar.
You could use an ant task to create this jar, either before you run maven, or as part of your maven build.
To merge your jars, you can use the Ant Jar Task (see section Merging Archives). From there:
<jar destfile="build/main/checksites.jar">
<fileset dir="build/main/classes"/>
<restrict>
<name name="**/*.class"/>
<archives>
<zips>
<fileset dir="lib/main" includes="**/*.jar"/>
</zips>
</archives>
</restrict>
</jar>
This creates a jar file which embeds all the classes from all the jars in lib/main.
You can then use the system scope which points at this jar as normal in maven. Note: if you create the jar in maven (via ant), then you should create the jar in target, so that it gets cleaned correctly.
To use an ant build file from maven, you can use the maven antrun plugin, similarly to:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<property name="local.project.artifact.name" value="${project.build.finalName}" />
<property name="local.distribution.artifact.name" value="${local.project.artifact.name}-distribution" />
<property name="local.distribution.artifact.file" value="${project.build.directory}/${local.distribution.artifact.name}.zip" />
<ant antfile="build-deploy.xml" />
</tasks>
</configuration>
</execution>
</executions>
</plugin>
This runs the ant build file build-deploy.xml in the package phase. The modifications necessary for your system are left as an exercise for the reader :-).

How to create war files

What are the best practices of creating war files (using eclipse) to run on tomcat? tutorials, links, examples are highly appreciated.
You can use Ant to set up, compile, WAR, and deploy your solution.
<target name="default" depends="setup,compile,buildwar,deploy"></target>
You can then execute one click in Eclipse to run that Ant target. Here are examples of each of the steps:
Preconditions
We'll assume that you have your code organized like:
${basedir}/src: Java files, properties, XML config files
${basedir}/web: Your JSP files
${basedir}/web/lib: Any JARs required at runtime
${basedir}/web/META-INF: Your manifest
${basedir}/web/WEB-INF: Your web.xml files
Set up
Define a setup task that creates the distribution directory and copies any artifacts that need to be WARred directly:
<target name="setup">
<mkdir dir="dist" />
<echo>Copying web into dist</echo>
<copydir dest="dist/web" src="web" />
<copydir dest="dist/web/WEB-INF/lib" src="${basedir}/../web/WEB-INF/lib" />
</target>
Compile
Build your Java files into classes and copy over any non-Java artifacts that reside under src but need to be available at runtime (e.g. properties, XML files, etc.):
<target name="compile">
<delete dir="${dist.dir}/web/WEB-INF/classes" />
<mkdir dir="${dist.dir}/web/WEB-INF/classes" />
<javac destdir="${dist.dir}/web/WEB-INF/classes" srcdir="src">
<classpath>
<fileset dir="${basedir}/../web/WEB-INF/lib">
<include name="*" />
</fileset>
</classpath>
</javac>
<copy todir="${dist.dir}/web/WEB-INF/classes">
<fileset dir="src">
<include name="**/*.properties" />
<include name="**/*.xml" />
</fileset>
</copy>
</target>
Build WAR
Create the WAR itself:
<target name="buildwar">
<war basedir="${basedir}/dist/web" destfile="My.war"
webxml="${basedir}/dist/web/WEB-INF/web.xml">
<exclude name="WEB-INF/**" />
<webinf dir="${basedir}/dist/web/WEB-INF/">
<include name="**/*.jar" />
</webinf>
</war>
</target>
Deploy
Finally, you can set up a task to deploy the WAR directly into your Tomcat deploy location:
<target name="deploy">
<copy file="My.war" todir="${tomcat.deploydir}" />
</target>
Click and go!
Once all this is set up, simply launching the default target from Eclipse will compile, WAR, and deploy your solution.
The advantage of this approach is that it will work outside Eclipse as well as within Eclipse and can be used to easily share your deployment strategy (e.g. via source control) with other developers who are also working on your project.
I've always just selected Export from Eclipse. It builds the war file and includes all necessary files. Providing you created the project as a web project that's all you'll need to do. Eclipse makes it very simple to do.
We use Maven (Ant's big brother) for all our java projects, and it has a very nifty WAR plugin. Tutorials and usage can be found there.
It's a lot easier than Ant, fully compatible with Eclipse (use maven eclipse:eclipse to create Eclipse projects) and easy to configure.
Maven's homepage
Maven WAR plugin
Sample Configuration:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-alpha-2</version>
<configuration>
<outputDirectory>${project.build.directory}/tmp/</outputDirectory>
<workDirectory>${project.build.directory}/tmp/war/work</workDirectory>
<webappDirectory>${project.build.webappDirectory}</webappDirectory>
<cacheFile>${project.build.directory}/tmp/war/work/webapp-cache.xml</cacheFile>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>pdf</nonFilteredFileExtension>
<nonFilteredFileExtension>png</nonFilteredFileExtension>
<nonFilteredFileExtension>gif</nonFilteredFileExtension>
<nonFilteredFileExtension>jsp</nonFilteredFileExtension>
</nonFilteredFileExtensions>
<webResources>
<resource>
<directory>src/main/webapp/</directory>
<targetPath>WEB-INF</targetPath>
<filtering>true</filtering>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</webResources>
<warName>Application</warName>
</configuration>
</plugin>
A war file is simply a jar file with a war extension, but what makes it work is how the contents is actually structured.
The J2EE/Java EE tutorial can be a start:
http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/WebComponents3.html
And the Servlet specification contains the gory details:
http://java.sun.com/products/servlet/download.html
If you create a new web project in Eclipse (I am referring to the Java EE version), the structure is created for you and you can also tell it where your Appserver is installed and it will deploy and start the application for you.
Using the "Export->WAR file" option will let you save the war file.
If you are not sure what to do and are starting from scratch then Maven can help get you started.
By following the the below steps you can get a new war project setup perfectly in eclipse.
Download and install Maven
Go the command line run: mvn archetype:generate
Follow the prompted steps - choosing the simple java web project (18) and a suitable name.
When it is finished run: mvn eclipse:eclipse
Start Eclipse. Choose File -> Import -> Existing project. Select the directory where you ran the mvn goals.
That's it you should now have a very good start to a war project in eclipse
You can create the war itself by running mvn package or deploy it by setting up a server in eclipse and simply adding adding the project to the server.
As some others have said the downside of using maven is that you have to use the maven conventions. But I think if you are just starting out, learning the conventions is a good idea before you start making your own. There's nothing to stop you changing/refactoring to your own preferred method at a later point.
Hope this helps.
Use the following command outside the WEB-INF folder. This should create your war file and is the quickest method I know.
(You will need JDK 1.7+ installed and environment variables that point to the bin directory of your JDK.)
jar -cvf projectname.war *
Reference Link
Use the Ant war task
Use ant build code
I use this for my project SMS
<property name="WEB-INF" value="${basedir}/WebRoot/WEB-INF" />
<property name="OUT" value="${basedir}/out" />
<property name="WAR_FILE_NAME" value="mywebapplication.war" />
<property name="TEMP" value="${basedir}/temp" />
<target name="help">
<echo>
--------------------------------------------------
compile - Compile
archive - Generate WAR file
--------------------------------------------------
</echo>
</target>
<target name="init">
<delete dir="${WEB-INF}/classes" />
<mkdir dir="${WEB-INF}/classes" />
</target>
<target name="compile" depends="init">
<javac srcdir="${basedir}/src"
destdir="${WEB-INF}/classes"
classpathref="libs">
</javac>
</target>
<target name="archive" depends="compile">
<delete dir="${OUT}" />
<mkdir dir="${OUT}" />
<delete dir="${TEMP}" />
<mkdir dir="${TEMP}" />
<copy todir="${TEMP}" >
<fileset dir="${basedir}/WebRoot">
</fileset>
</copy>
<move file="${TEMP}/log4j.properties"
todir="${TEMP}/WEB-INF/classes" />
<war destfile="${OUT}/${WAR_FILE_NAME}"
basedir="${TEMP}"
compress="true"
webxml="${TEMP}/WEB-INF/web.xml" />
<delete dir="${TEMP}" />
</target>
<path id="libs">
<fileset includes="*.jar" dir="${WEB-INF}/lib" />
</path>
Another option would be to build it automatically using Eclipse. Of course if you have continuous integration environment Ant or Maven is recommended. The export alternative is not very convenient because you have to configure every time the export properties.
STEPS:
Enable "Project Archives" support; this might depend on your project (I used it on Java EE/Web project). Right-click project root directory; Configure -> Add Project Archives Support.
Go and create a new archive in the "Project Archives" top dir. You have only jar option, but name you archive *.war.
Configure Fileset-s, i.e what files to be included. Typical is to configure two filesets similar how the Web Deployment Assembly (project property) is configured.
copy /WebContent to /
copy /build/classes to WEB-INF/classes (create this fileset after you define the WEB-INF/classes directory in the archive)
You might need to tweek the fileset exclude property depending where you placed some of the config files or you might need more filesets, but the idea is that once you configured this you don't need to change it.
Build the archive manually or publish directly to server; but is also automatically built for you by Eclipse
Another common option is gradle.
http://www.gradle.org/docs/current/userguide/application_plugin.html
To build your war file in a web app:
In build.gradle, add:
apply plugin: 'war'
Then:
./gradlew war
Use the layout from accepted answer above.
Simpler solution which also refreshes the Eclipse workspace:
<?xml version="1.0" encoding="UTF-8"?>
<project name="project" default="default">
<target name="default">
<war destfile="target/MyApplication.war" webxml="web/WEB-INF/web.xml">
<fileset dir="src/main/java" />
<fileset dir="web/WEB-INF/views" />
<lib dir="web/WEB-INF/lib"/>
<classes dir="target/classes" />
</war>
<eclipse.refreshLocal resource="MyApplication/target" depth="infinite"/>
</target>
</project>
Simplistic Shell code for creating WAR files from a standard Eclipse dynamic Web Project. Uses RAM File system (/dev/shm) on a Linux platform.
#!/bin/sh
UTILITY=$(basename $0)
if [ -z "$1" ] ; then
echo "usage: $UTILITY [-s] <web-app-directory>..."
echo " -s ..... With source"
exit 1
fi
if [ "$1" == "-s" ] ; then
WITH_SOURCE=1
shift
fi
while [ ! -z "$1" ] ; do
WEB_APP_DIR=$1
shift
if [ ! -d $WEB_APP_DIR ] ; then
echo "\"$WEB_APP_DIR\" is not a directory"
continue
fi
if [ ! -d $WEB_APP_DIR/WebContent ] ; then
echo "\"$WEB_APP_DIR\" is not a Web Application directory"
continue
fi
TMP_DIR=/dev/shm/${WEB_APP_DIR}.$$.tmp
WAR_FILE=/dev/shm/${WEB_APP_DIR}.war
mkdir $TMP_DIR
pushd $WEB_APP_DIR > /dev/null
cp -r WebContent/* $TMP_DIR
cp -r build/* $TMP_DIR/WEB-INF
[ ! -z "$WITH_SOURCE" ] && cp -r src/* $TMP_DIR/WEB-INF/classes
cd $TMP_DIR > /dev/null
[ -e $WAR_FILE ] && rm -f $WAR_FILE
jar cf $WAR_FILE .
ls -lsF $WAR_FILE
popd > /dev/null
rm -rf $TMP_DIR
done
**Making War file in Eclips Gaynemed of grails web project **
1.Import project:
2.Change the datasource.groovy file
Like this: url="jdbc:postgresql://18.247.120.101:8432/PGMS"
2.chnge AppConfig.xml
3.kill the Java from Task Manager:
run clean comand in eclips
run 'prod war' fowllowed by project name.
Check the log file and find the same .war file in directory of workbench with same date.

Categories