5

I want to start my application using jetty, so I have added the dependency mentioned below. and when I run the main method Jetty starts successfully.(I am working on a struts2+spring3+ hibernate maven project, i am able to deploy it in tomcat too)

Now I want to create a executable jar from a war packaging pom. So i added maven-assembly-plugin to my pom. (I tried with maven jar plug-in but it was not adding the dependencies)

Sources

plugins

<build>
    <plugins>
        <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.3</version>
        <configuration>
                 <archive>
            <manifest>
        <mainClass>com.dca.engine.StartDCA</mainClass>
            </manifest>
             </archive>
        <packagingExcludes>WEB-INF/lib/jetty*.jar,WEB-INF/lib/org.apache.taglibs.standard.glassfish*.jar,WEB-INF/lib/org.apache.jasper.glassfish*.jar,WEB-INF/lib/org.eclipse.jdt.core*.jar,WEB-INF/lib/javax.servlet.jsp*.jar,WEB-INF/lib/javax.el*.jar</packagingExcludes>
        <escapeString>\</escapeString>
        </configuration>
       </plugin>
       <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4</version>
        <configuration>
                 <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                 </descriptorRefs>
             <archive>
            <manifest>
        <mainClass>com.dca.engine.StartDCA</mainClass>
            </manifest>
             </archive>
        </configuration>
        <executions>
             <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                      <goal>single</goal>
                    </goals>
             </execution>
        </executions>
    </plugin>
 </plugins>
<resources>
    <resource>
        <directory>src/main/java</directory>
        <includes>
        <include>**/*.java</include>
        <include>**/*.xml</include>
        </includes>
    </resource>
    <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
    </resource>
</resources>
</build>

Embedded Jetty

<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-server</artifactId>
    <version>8.1.10.v20130312</version>
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-webapp</artifactId>
    <version>8.1.10.v20130312</version>
    <!-- <scope>provided</scope> -->
</dependency>
<dependency>
    <groupId>org.eclipse.jetty</groupId>
    <artifactId>jetty-jsp</artifactId>
    <version>8.1.10.v20130312</version>
    <!-- <scope>provided</scope>  -->
</dependency> 

main method

 Server server = new Server(8080);
        System.setProperty("is_DCA", "YES");
        WebAppContext webAppContext = new WebAppContext();
        webAppContext.setResourceBase("/home/myfolder/workspace/app/dca/src/main/webapp");
        webAppContext.setDescriptor("/home/myfolder/workspace/app/dca/src/main/webapp/WEB-INF/web.xml");
        webAppContext.setContextPath("/app");
        server.setHandler(webAppContext);
        server.start();
        server.join();

Starting the application

I run the created jar with java -jar /home/myfolder/workspace/app/dca/target/app-dca-1.0-jar-with-dependencies.jar

jetty starts with exception.

INFO  10-12 15:03:01,609 - jetty-8.y.z-SNAPSHOT
INFO  10-12 15:03:01,776 - Initializing Spring root WebApplicationContext
INFO  10-12 15:03:01,776 - Root WebApplicationContext: initialization started
INFO  10-12 15:03:01,843 - Refreshing Root WebApplicationContext: startup date [Tue Dec 10 15:03:01 IST 2013]; root of context hierarchy
INFO  10-12 15:03:01,885 - Loading XML bean definitions from class path resource [applicationContext-dca.xml]
ERROR 10-12 15:03:05,725 - Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler for XML schema namespace [http://www.springframework.org/schema/util]
Offending resource: class path resource [applicationContext-dca.xml]

    at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.java:68)
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:85)
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.java:80)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.error(BeanDefinitionParserDelegate.java:316)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1420)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(BeanDefinitionParserDelegate.java:1413)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:184)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:140)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.java:111)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.java:493)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.java:390)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:334)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.java:302)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:174)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.java:209)

Is there a possible way that i can start jetty using the war created. It has jars in /WEB-INF/lib/ folder, all properties file and xml files are in /WEB-INF/lib/ and I tried running the war

java -jar /home/myfolder/workspace/app/dca/target/app-dca-1.0.war

but it was not able to locate the main class.

worked when created executable war check sumit's answer

I was getting the exception as in this question. when I replaced jetty version to 7.6.7.v20120910 it worked

i dont know why it didn't worked with jetty 8.1.10.v20130312

Community
  • 1
  • 1
jos
  • 1,082
  • 5
  • 19
  • 45
  • You exception is saying that there is problem with applicationContext-dca.xml? Are you sure that /home/myfolder/workspace/app/dca/src/main/webapp/WEB-INF/web.xml is the correct web.xml location for a deployed executable war? I would think that it would have to be relative to the war? – Sumit Dec 10 '13 at 10:21
  • how to give a relative path ? suppose my jar is in /home/myfolder/app-dca-1.0.jar . – jos Dec 10 '13 at 13:35

4 Answers4

9

If you are not tied to using Jetty but are open to using Tomcat instead, the following will work beautifully:

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.0</version>
    <executions>
        <execution>
            <id>tomcat-run</id>
            <goals>
                <goal>exec-war-only</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <path>/standalone</path>
                <enableNaming>false</enableNaming>
                <finalName>standalone.jar</finalName>
                <charset>utf-8</charset>
            </configuration>
        </execution>
    </executions>
</plugin>

This will create an uberjar called "standalone.jar" that you can then run simply by calling

java -jar standalone.jar

this will start the application on http://localhost:8080/standalone

Selecting an alternate port is easy

java -jar standalone.jar -httpPort=7070

Thanks to Tomasz Nurkiewicz's blog entry for highlighting this http://www.nurkiewicz.com/2012/11/standalone-web-application-with.html

JedA
  • 119
  • 1
  • 4
  • NOPE! It says "INFO: Starting ProtocolHandler ["http-bio-8080"]" and localhost:8080 shows nothing at all. There is also a null pointer exception with the version 2.0 – 3xCh1_23 Jan 31 '16 at 16:25
  • Just works for me, but the url has to be http://localhost:8080/standalone since the configure path is /standalone – pdem Nov 02 '16 at 14:48
8

Instead of hacking the contents of a WAR file, as the accepted answer seems to be doing, you can create an executable JAR file using the maven-shade-plugin. This has the following advantages:

  • The plugin contains "transformers" for merging the contents of META-INF/services, LICENSE and README files.
  • You end up with a JAR file. WAR files were not designed to be executable (although it works).
  • By unpacking all dependencies into the same JAR file, you are forced to remove duplicate classes and make the contents harder to reverse-engineer.
Community
  • 1
  • 1
Gili
  • 86,244
  • 97
  • 390
  • 689
  • i'm doing this but am not sure what to do in the main method. with references to the war file it fails, saying it can't find the war file. and the war file isn't in the jar, struth. how do i get maven shade to include the war file? that seems wonky to me but wtf if it works. – barclay Sep 09 '14 at 19:23
  • @kewpiedoll99, you don't use a WAR file, period. First you need to figure out how to run Jetty out of an unpacked directory structure (that's a separate question you'll need to Google). Once you get that working, running out of an executable JAR will just work. – Gili Sep 10 '14 at 17:15
3

Take a look at http://uguptablog.blogspot.com/2012/09/embedded-jetty-executable-war-with.html

The relevant code is

    ProtectionDomain domain = Main.class.getProtectionDomain();
    URL location = domain.getCodeSource().getLocation();
    WebAppContext webapp = new WebAppContext();
    webapp.setContextPath("/");
    webapp.setWar(location.toExternalForm());
    server.setHandler(webapp);

hope that helps.

Sumit
  • 1,661
  • 1
  • 13
  • 18
  • could you please add some theory in your blog. and why executable jar not taking classes in WEB-INF insted creating folder like structure for the package ,all the depended jar too. – jos Dec 11 '13 at 04:41
  • I am getting the following exception when i tried your code `org.apache.jasper.JasperException: /common/taglibs.jsp(5,62) PWC6188: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application at org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:92)` – jos Dec 11 '13 at 10:39
  • i dont know why i get this error is it because of conflict jar? I have the jstl-1.2.jar in /WEB-INF/lib/ of the created war .And there is another folder created /javax/servlet/jsp/jstl/ which has core,fmt,sql,tlv folders in it – jos Dec 11 '13 at 10:44
  • Sorry, its not my blog. But you might need the tld files in a web-inf/tld folder – Sumit Dec 11 '13 at 18:07
2

The simpliest way I know (but never tried) is the , like Jenkins CI do (what a better example :D). It doesn't use Jetty (even I love this tool :D), but Winstone.

Maven Plugin Usage

<plugin>
    <groupId>net.sf.alchim</groupId>
    <artifactId>winstone-maven-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>embed</goal>
            </goals>
            <phase>package</phase>
        </execution>
    </executions>
</plugin>

Quite easy, isn't it ? :) It would generate a executable - standalone - jar : app-dca-1.0-standalone.jar

Documentation

Jean-Rémy Revy
  • 5,607
  • 3
  • 39
  • 65
  • Hm... the Winstone Maven plugin seems to be too old for recent versions of Maven now. I immediately got a NullPointerException when I tried it out. – Eric May 12 '16 at 09:02
  • Indeed, this answer is quite old regarding technologie evolution. As for now, I would (and I do) use spring-boot for such need. – Jean-Rémy Revy May 12 '16 at 20:25