5

I have a project with multiple modules.

Two of them generate war files.

  • One war file is a REST application and provides a couple of resources.

  • The Other war file is a Angular JS web application (static content only) to talk to the REST backend.

For demo purposes I'd like to deploy both war-files very easily with mvn jetty:run

For development purposes I'd like to deploy them from my IDE (e.g. Eclipse Servers View).

When I do the deployment on a single Jetty Server (v9.0.7.v20131107) manually by starting the server and copiing the war-files to the deployment folder everything comes up.

When starting the jetty by mvn jetty:run both war files get deployed, but somehow the REST Resources do not get deployed.

I am using Jersey 2. When deploying manually I get a log message like

Nov 14, 2013 10:44:37 PM org.glassfish.jersey.server.ApplicationHandler initialize INFO: Initiating Jersey application, version Jersey: 2.4 2013-10-24 18:25:49...

However this message is not been shown when starting with mvn jetty:run. Therefore I assume that Jersey does not kick in.

For Dependency-Injection I use spring.


This is the parent pom in /pom.xml with the jetty-maven-plugin configuration

<project ...>
...
<build>
    <plugins>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>9.0.7.v20131107</version>
        <configuration>
            <scanIntervalSeconds>2</scanIntervalSeconds>
            <contextHandlers>
                <contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext">
                    <war>module1/target/module1-${project-version}.war</war>
                    <contextPath>/module1</contextPath>
                </contextHandler>
                <contextHandler implementation="org.eclipse.jetty.webapp.WebAppContext">
                    <war>module2/target/module2-${project.version}.war</war>
                    <contextPath>/module2/contextPath>
                </contextHandler>
            </contextHandlers>
        </configuration>
    </plugins>
</build>
...
</project>

This is the pom for module1 (the REST module)

    <parent>
        ...
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>module1</artifactId>
    <packaging>war</packaging>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <springVersion>3.1.4.RELEASE</springversion>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.ext</groupId>
            <artifactId>jersey-spring3</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-multipart</artifactId>
            <version>2.4</version>
        </dependency>

        <!-- Dependencies to internal modules -->
        ...
        <!-- Depenencies to internal modules END -->

    </dependencies>
</project>

This is the web.xml for module1

<web-app ...
     version="3.0">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

This is the applicationContext.xml for module1

<beans ...>

    <context:annotation-config/>
    <context:component-scan base-package="com.stackoverflow.zip"/>
    <aop:aspectj-autoproxy/>
</beans>

This is the Module1Application class for module1

import org.glassfish.jersey.media.multipart.MultiPartFeature;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import java.util.HashSet;
import java.util.Set;


@ApplicationPath("/rest")
public class Module1Application extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(Resource1.class);
        classes.add(Resource2.class);
        classes.add(MultiPartFeature.class);
        return classes;
    }
}

This is the pom for module2 (the AngularJS app) Very light :)

<project ...>

    <parent>
        ...
    </parent>   
    ...
    <modelVersion>4.0.0</modelVersion>
    <artifactId>module2</artifactId>
    <packaging>war</packaging>
</project>

Do you have any idea why the Jersey Application does not get instantiated while running with mvn jetty:run but when running it manually?

I appreciate any input on this topic.

Kind regards - zip

zip
  • 579
  • 1
  • 3
  • 16
  • there appears to be a typo in your pom.xml. However, I'm not sure that this will fix your problem (so for the moment I won't post it as answer): `mdule2/target/module2-${project.version}.war` should probably read `module2/target/module2-${project.version}.war`. – ljgw Nov 17 '13 at 11:37
  • Hey ljgw thanks for you comment. I simplyfied my code and made it more easily to read. Therefore it is just a typo in the question and not in my source code. I fixed it in the question. Thanks again for your comment :) – zip Nov 17 '13 at 15:30
  • Hey @zip, what do you mean "the REST Resources do not get deployed". Are your Jersey Resource classes not packaged into the war files when you `mvn jetty:run`? – yegeniy Nov 18 '13 at 03:52
  • @yegeniy Everything is in the war files. But somehow when deploying them with `mvn jetty:run` Jersey 2 does not kick in. Therefore I cannot access the rest resources, e.g. `http://localhost:8080/module1/rest/hello` because Jersey 2 did not scan the class path and did not bind the Resource Classes to its URLs – zip Nov 18 '13 at 09:10
  • I noticed that you don't have a `servlet` element in your web.xml. Is there a specific reason for this? I was under the impression that you need on to wire everything together. – yegeniy Nov 18 '13 at 15:36
  • @yegeniy I use Jersey Annotations to define the mappings. So I was under the impression I do not need a servlet configuration in my web.xml. I am still thinking it is a mvn jetty:run issue, because it works in a standalone application (e.g. tomcat or jetty). I will try the servlet version thingy. – zip Nov 19 '13 at 20:30

2 Answers2

0

Your javax.servlet version is 2.5 in pom.xml, but 3.0 in web.xml. Try upgrading it to 3.0 in pom.xml. Is it possible that the IDE provides a servlet 3.0 for you?


Also, since Jetty provides a javax.servlet container, try putting the Servlet Api into provided scope in pom.xml. Something like this:

  <dependency>
     <groupId>javax.servlet</groupId>
     <artifactId>javax.servlet-api</artifactId>
     <version>3.0.1</version>
     <!-- http://stackoverflow.com/a/15601606 http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html#Dependency_Scope -->
     <!-- This allows us to compile the application locally but does not include the jar in the package step -->
     <scope>provided</scope>
  </dependency>

It's possible that you want to add a <load-on-startup>1</load-on-startup> element to your web.xml. Check out http://tutorials.jenkov.com/java-servlets/web-xml.html#load-on-startup

That's whole tutorial is pretty good.

Disclaimer: I'm not familiar with what the Spring dependencies are doing to help your application bootstrap itself. You can always try removing dependencies on a separate branch, and adding them back in as you get things running

yegeniy
  • 1,272
  • 13
  • 28
  • Hey thanks for the javax.servlet version hint. I already fixed that, due to Tomcat was complaining about exactly the same thing. I don't have a servlet configured because I was under the impression that Jersey 2 uses Annotation based configuration to wire everything else together. But I will try. Thanks so far. – zip Nov 19 '13 at 20:28
  • Hey @yegeniy, I changed the version appropriately, but doesn't solve the problem. I tried using the `mvn jetty:run` plugin directly in the rest module and it worked. I assume that `mvn jetty:run` handles the application loading different than a jetty standalone would. I decided to skip using `mvn jetty:run`, because it took too much time already. – zip Nov 20 '13 at 09:43
  • 1
    Maybe try to run `jetty:run-war`, since your .war files seem to be in good order. http://www.eclipse.org/jetty/documentation/current/jetty-maven-plugin.html#running-assembled-webapp-as-war – yegeniy Nov 20 '13 at 13:27
0

I haven't had a chance to play with Jersey 2.x so far, but from what I see in your web.xml, it doesn't look like you have Jersey setup correctly.

In a non-Spring application, you would have something like the following:

<web-app ...>  
    ...
    <servlet>
        <servlet-name>Jersey REST Service</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>

        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.your.foo.rest</param-value>
        </init-param>

        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Jersey REST Service</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    ...
</web-app>  

In a Spring-based one, you would use:

<web-app ...>
    ...
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.your.foo</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    ...
</web-app>

Furthermore, check that you have these Maven dependencies:

    <dependency>
        <groupId>com.sun.jersey.contribs</groupId>
        <artifactId>jersey-spring</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
    </dependency>
carlspring
  • 31,231
  • 29
  • 115
  • 197
  • Hey @carlspring. Thanks for your answer. I do not need to setup Jersey 2 in my web.xml. That is jersey 1 code. Jersey 2 scans your classpath and uses annotation based configuration. – zip Nov 20 '13 at 09:45
  • Good to know, but doesn't Jersey still need to know what the base package with the REST classes is? – carlspring Nov 20 '13 at 10:40
  • you could do that, but you do not necessarily have to. Most of the time Jersey will find the resources automatically. It will get a bit more complicated when you want to use featuers which are not auto discoverable (e.g. MultiPartFeature). Then you need to define your Resources manually. Anyway, I have a "Module1Application" Application class in my classpath of module1. This defines the resources for Jersey 2. See https://jersey.java.net/documentation/latest/deployment.html for more information. – zip Nov 20 '13 at 16:04
  • Thanks for this information! I'm afraid I wasn't of much help, as you already seem to know what you're doing better than me. Good luck! – carlspring Nov 20 '13 at 16:47
  • If you can put a simplified example of the code somewhere on Github, I could have a quick look and give it a go, perhaps find something... – carlspring Nov 20 '13 at 16:48
  • I added the code to the question (Module1Application). Thanks for your help. I only need to define it manually, because the MultiPartFeature does not support auto discovery. Without MultiPartFeature I only need a class with @ApplicationPath Annotation (no getClasses() method) – zip Nov 21 '13 at 08:18