Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 295
twilbrand Avatar asked Mar 16 '10 21:03

twilbrand


People also ask

How do I run a WAR file on a jetty server?

The easiest way to deploy a web application to Jetty server is probably by copying the WAR file into the $JETTY_HOME/webapps directory. Jetty will scan its $JETTY_HOME/webapps directory at startup for web applications to deploy. Our new app will be deployed at /jetty-app context.

How do you start a Jetty?

To start Jetty, switch on the command line to the installation directory and issue the following command. To stop Jetty press Ctrl + C . To start Jetty as Windows service you can use Apache Procrun.

Are war files executable?

5) a WAR file can be runnable/executable (though this is more common with JAR files). Even if it is not, it is almost never used as a "library" for other programs (which is common with JAR files).

How do I run a jar on a jetty server?

Standalone Startup The easiest way to start Jetty, is to use the start. jar that comes with the distribution. The default options may be specified in the start. ini file, or if that is not present, they are defined in the start.


1 Answers

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 
like image 125
Rob Hruska Avatar answered Oct 16 '22 09:10

Rob Hruska