Maven: Usage of external libraries for integration test - java

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 :-).

Related

Create standalone Java executable for different platforms without installation

I have created a Java application runtime image using jlink. I would like to be able to ship the software as an executable to different platforms. (Preferably by building on one platform, like cross-compiling.)
Ideally, it would be a single application file that users may double-click to launch, without installing anything.
How can this be accomplished?
What you're describing is what's called a native executable. There are programs that will wrap your Java application into an executable file but because Java runs it's code on the Java Virtual Machine (JVM), your users will need to have it pre-installed for your program to work out of the box. You can code an installer for your application in something like C++ or C# (C# runs on the .NET Runtime which comes pre-installed on all Windows machines) that installs the JVM and possibly your application alongside it, and then compile that code to a native executable. That way, the end user doesn’t need to go looking around for Java downloads. This is the approach that Minecraft takes I believe.
Wrap your Java executable into a native executable using any of:
Launch4J (Windows)
Oracle Docs (MacOS)
Discourse (Linux)
Quarkus (native executable, no installer)
Warp Packer (self-extracting executable, no installer)
Also, have a look at SubstrateVM. This is not a true Java, however, it may help you in some cases like simple command line applications.
Substrate VM is a framework that allows ahead-of-time (AOT)
compilation of Java applications under closed-world assumption into
executable images or shared objects (ELF-64 or 64-bit Mach-O).
Yes, as of Java 8 there are two ways of doing this, using the javapackager tool, or the JavaFX Ant Tasks (which aren't actually specific to JavaFX, and are provided with the Java 8 JDK).
Here's an example of packaging an application as a Jar, setting the main-class and classpath attributes, and copying all the dependencies into a folder, using Maven.
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>${project.groupId}.${project.artifactId}.DemoCLI</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
And here is the Ant build file to package the standalone application (exe for Windows, .app and .dmg on OS X, .deb and .rpm on Linux).
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<!--
Uses the JavaFX Ant Tasks to build native application bundles
(specific to the platform which it is built on).
See https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/javafx_ant_tasks.html
These tasks are distributed with version 8 of the Oracle JDK,
Amazon Corretto JDK, RedHat JDK, probably others, though they
do not seem to be the OpenJDK on Debian Linux
-->
<project
name="fxwebclient" default="default" basedir="."
xmlns:fx="javafx:com.sun.javafx.tools.ant">
<!-- In Java 8, java.home is typically the JRE of a JDK -->
<property name="jdk.lib.dir" value="${java.home}/../lib" />
<!-- Where to build our app bundles -->
<property name="build.dist.dir" value="${basedir}/target/dist" />
<echo>Using Java from ${java.home}</echo>
<target name="default" depends="clean">
<!-- get the ant-jfx.jar from the JDK -->
<taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
uri="javafx:com.sun.javafx.tools.ant"
classpath="${jdk.lib.dir}/ant-javafx.jar" />
<!-- Define our application entry point -->
<fx:application id="demo" name="demo"
mainClass="yourpackage.DemoCLI" />
<!-- Our jar and copied dependency jars (see pom.xml) -->
<fx:resources id="appRes">
<fx:fileset dir="${basedir}/target" includes="*.jar"/>
<fx:fileset dir="${basedir}/target/lib" includes="*.jar" />
</fx:resources>
<!-- Create app bundles [platform specific] -->
<fx:deploy nativeBundles="all"
outdir="${build.dist.dir}" outfile="DemoWebClient">
<fx:application refid="demo" />
<fx:resources refid="appRes" />
</fx:deploy>
</target>
<!-- clean up -->
<target name="clean">
<delete dir="${build.dist.dir}" includeEmptyDirs="true" />
<delete file="${basedir}/target/${ant.project.name}.jar" />
</target>
</project>
Double click to run executables on multiple platforms, requires prior registration of the file type with the operating system, or an existing file type to know how to handle the code.
jlink statically links the "required modules and their transitive dependencies" to the output.
There is no cross platform solution to this problem.
It is improbable(or to put it another way, not feasible) to include all platforms in a single file, since each executable type(COFF, ELF...), has a different structure. You could attempt to use a generic batch file to start the proper executable, but on Windows, that would require a text file type encoding; thus poisoning the remaining binary code.
Using jlink and the new jmod file format will allow you store native code in a Java container, and thus allowing the entry point into the embedded native JRE code in a single executable image for a single pre-defined platform.
The other side of this issue is the security implications. Since the embedded JRE is not subject to security updates, crackers may choose to embed a previously known flawed JRE, thus exposing corrected exploits to unknowing consumers.
The expected response from Anti-Virus programs would be to flag all non-updated embedded JRE's as viruses.

How to convert a java project to a plugin project in Ant?

I am currently trying to write a build.xml which will convert a normal java project say com.example.normal to com.example.plugin.jar.
I have the code for a basic build.xml which creates a jar of the source project. But normally creating a jar file is not the same as creating a plugin jar file. For this reason I need to create a plugin jar file using ant and not just a normal jar file which cannot act as a plugin.
This is the example code snippet for creating the jar file.
<jar destfile="generatedPlugins/com.example.normal.jar">
<fileset dir="JavaSource/com.example.normal"/>
</jar>
Manually, I can create a plugin with the following steps:
Right Click on project > Export > Plugin Development > Deployable
plug-ins and fragments.
In other words, I just need to automate this process using Ant. Any idea how to proceed?
Thanks!
This can't really be done with Ant alone. You should use Tycho or PDE Build to build bundle (plug-in) JARs. Take note that Tycho is the modern, preferred option; I'm not sure that PDE Build is even actively maintained or used any more.
You could try manually editing the build.xml, adding something like
<!-- This builds a .jar file, Assuming you have a set of .class files
created by some "compile" target. -->
<target name="build" depends="compile">
<!-- We need to set up class path for any required libraries so that we
can add it to the manifest file later. -->
<path id="build.classpath">
<pathelement location="${lib.location}"/>
</path>
<!-- Now we convert the class path we just set up to a manifest class
path - we'll call it manifest.cp. We also need to tell it where our
.jar file will be output. -->
<manifestclasspath property="manifest.cp" jarfile="${jar.output.dir}/filename.jar">
<!-- We just give it the classpath we set up previously. -->
<classpath refid="build.classpath"/>
</manifestclasspath>
<!-- Now we can make the .jar. It needs to know the base directory of
our compiled .class files. -->
<jar destfile="${jar.target}/filename.jar" basedir="${class.target}">
<!-- Set up the manifest file with the name of the main class and
the manifest class path we set up earlier. -->
<manifest>
<attribute name="Main-Class" value="name of main class"/>
<attribute name="Class-Path" value="${manifest.cp}"/>
</manifest>
</jar>
</target>
You can generate Ant scripts from the PDE tools by right-clicking on a relevant manifest file (e.g. plugin.xml) in the project and selecting PDE Tools --> Create Ant Build File.
This link from the Eclipse Mars documentation explains in detail.

Supporting i18n in GWT

Till now, our web application supports only English. Now we have to provide support for Italian as well. There is GWT module for some functionality. To support the Italian language I have added below line in the file "APP_Module.gwt.xml"
<extend-property name="locale" values="it"/>
I have also placed "XXX_it.properties" file under the source code where the properties file for en is kept.
Setting the locale in the jsp by following line:
<meta name="gwt:property" content="locale=${locale}">
Now, the issue is how to compile the code. I am debugging the application but it is not hitting the client code of GWT presented under WEB-INF/src.
I am very new to GWT. Please suggest how can I compile the code or there is no need of compilation. It will automatically take the changes done in "APP_Module.gwt.xml" and there is some other issue. How can I see logs of GWT?
To add support for locales to GWT application, you need to do the following in your xxx.gwt.xml:
under <module> add this to include the support:
<inherits name="com.google.gwt.i18n.I18N" />
and this to configure it:
<extend-property name="locale" values="en,it"/>
<set-property-fallback name="locale" value="en"/>
Add all your property files under some package like this:
src/main/resources/foo/bar/client/i18n/MyMessages.properties
src/main/resources/foo/bar/client/i18n/MyMessages_it.properties
Then you need to tell GWT to compile them into classes. This is example from a pom.xml file (if you don't use maven, you will have to use a different way, but you still need to configure it).
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>gwt-maven-plugin</artifactId>
<version>1.3.1.google</version>
<executions>
<execution>
<goals>
<goal>i18n</goal>
<goal>generateAsync</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<i18nMessagesBundles>
<resourceBundle>foo.bar.client.i18n.MyMessages</resourceBundle>
</i18nMessagesBundles>
</configuration>
</plugin>
Then you need to recompile the code. In maven mvn compile. And that's all, you will have your messages in generated sources folder ready to use.
For seeing the logs of gwt you can use gradlew gwt also you can use it to compile the code too.

In the Eclipe PMD plugin, can I reference the standard ruleset files?

I would like my eclipse PMD plugin configuration to access the same standard ruleset files as the maven-pmd-plugin.
You can configure the maven pmd plugin to use a custom set of rule sets like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>2.5</version>
<configuration>
<rulesets>
<!-- Two rule sets that come bundled with PMD -->
<ruleset>/rulesets/braces.xml</ruleset>
<ruleset>/rulesets/naming.xml</ruleset>
<!-- Custom local file system rule set -->
<ruleset>d:\rulesets\strings.xml</ruleset>
<!-- Custom remote rule set accessed via a URL -->
<ruleset>http://localhost/design.xml</ruleset>
</rulesets>
</configuration>
</plugin>
but in the eclipse plugin you can only switch on / turn off individual rules or specify a single ruleset file. Is there perhaps a way that ruleset file can include several others? Or do I have to aggregate that file automatically from the rulesets I want to use?
You can include other rulesets in a PMD ruleset file, e.g.
<ruleset ...>
...
<rule ref="rulesets/basic.xml"/>
...
<rule ref="rulesets/strings.xml">
<exclude name="AvoidDuplicateLiterals"/>
</rule>
...
</ruleset>
This is actually an excerpt from our own ruleset file, so it is proven to work :-)
As you can see, you can exclude/include individual rules from your ruleset, or even reconfigure them. One caveat: you must not mix rules for different languages in a single ruleset. I.e. in our case, we had to create separate rulesets for Java and JSP.
I learned the tricks myself from this page.

Executable war file that starts jetty without maven

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

Categories