Blankman
Blankman

Reputation: 267280

Embedded Jetty with Spring MVC

I have a multiple maven module for my spring MVC and hibernate application.

My layout is as follows:

/myapp-web
/myapp-web/src/main/java
/myapp-web/src/main/webapp
/myapp-web/src/main/webapp/web-inf
/myapp-web/src/main/webapp/web-inf/web.xml
/myapp-web/src/main/webapp/web-inf/web-context.xml (spring wiring code etc)
/myapp-web/src/main/webapp/web-inf/config/hibernate.cfg.xml
/myapp-web/src/main/webapp/assets/... (folder for css, javascript, images)
/myapp-web/src/main/webapp/views (folders with freemarker .ftl files)

My pom.xml:

    ..
    <packaging>war</packaging>
    ..
    <dependency>
        <artifactId>jetty-server</artifactId>
        <groupId>org.eclipse.jetty</groupId>
        <version>${jetty-version}</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-servlet</artifactId>
        <version>${jetty-version}</version>
    </dependency>
    <dependency>
        <groupId>org.eclipse.jetty</groupId>
        <artifactId>jetty-webapp</artifactId>
        <version>${jetty-version}</version>
    </dependency>

I have another instance of embedded jetty that I successfully setup and I can run. I even setup a start/stop script so it works on Ubuntu. This wasn't a spring mvc application so it was a easier since it doesn't have a web.xml file etc. I created an /assembly/assembly.xml file, do I need to do that for a spring mvc application also?

I then added this to my pom.xml plugins section:

         <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>${maven-assembly-plugin}</version>
            <configuration>
                <descriptors>
                    <descriptor>src/main/assembly/assembly.xml</descriptor>
                </descriptors>
            </configuration>
        </plugin>
        <!-- jar plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>${maven-jar-plugin}</version>
            <configuration>
                <archive>

                </archive>
            </configuration>
        </plugin>
        <!-- jetty plugin -->
        <plugin>
            <!-- This plugin is needed for the servlet example -->
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>jetty-maven-plugin</artifactId>
            <version>${jetty-version}</version>
        </plugin>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.1</version>
            <executions>
                <execution>
                    <goals>
                        <goal>java</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <mainClass>com.myapp.HttpServer</mainClass>
            </configuration>
        </plugin>

Do I need to do the same for my spring mvc application?

I found a few threads on stackoverflow, but I can't understand the ant part as I am not using ant. I am also not sure how to port it to work with maven:

I'm surprised that there isn't a single good reference on how to do this, other than for single servlet example.

Do I need to create a /assembly/assembly.xml file for this, or for a web application things are different?

Can someone explain this to me step by step so I can get this to work? Please ask and I will post anything necessary for my project, but I think I covered all that my current environment has, i.e.:

The goal is to be able to deploy this war file, create the startup/stop scripts so I can deploy this to my server and start/stop the jetty instance.

Upvotes: 2

Views: 8798

Answers (3)

Vincent Devillers
Vincent Devillers

Reputation: 1628

You don't need assembly.xml file.

Jetty is used to start webapp, springified or not. So, you have to create a Jetty server in a main class, add your webapp context and start the server. You can solve your problem in 2 ways: - create a web.xml like with a "common" Java EE server, and add this descriptor to your Jetty server. - load your Spring context in the main class with the servlet context programmaly: https://github.com/s4nchez/jetty-spring-mvc-jar

Upvotes: 8

Pablojim
Pablojim

Reputation: 8582

I have a very similar setup that I think you could use with minimal changes. I'm running a webapp with maven, spring, hibernate and freemarker etc. I haven't needed any assembly.xml or ant tasks.

My approach is to package the application as a jar. This jar then has a main class that starts jetty and essentially deploys itself as a war. See here for more details:

http://draconianoverlord.com/2009/01/10/war-less-dev-with-jetty.html

This class can be easily customised to take parameters such as the port number etc.

To run the application I think there are two good choices:

Simply execute the class with Java. The gotcha here though is setting the classpath correctly. For this I use maven dependency:build-classpath goal. This outputs the full classpath which can be used in your java execution command. The downside of this is that you need maven and a maven repo configured on the machine where you are running this. In my case this is acceptable and this approach works very well.

Or you could create an executable jar with dependencies. For this I recommend the maven shade plugin. See http://maven.apache.org/plugins/maven-shade-plugin/examples/executable-jar.html The downsides of this approach is that you end up with one huge file so that classpath errors and dependency issues can be hard to resolve. Also if libraries are dependent on Meta-Inf files they sometimes can overwrite each other. Maven shade plugin provides ways to workaround this but it can still be a hard to diagnose problem.

Both of these approaches should allow you to keep your current folder structure and web.xml etc. but if you do have any problems - let me know in the comments and I can expand the answer.

Upvotes: 0

Atilla Ozgur
Atilla Ozgur

Reputation: 14721

assembly.xml file is mostly used for creating zip files. For simple web archive ,war files maven's normal structure should be enough.

You asked for multi-module examples. I suggest to look for app fuse examples. Even you do not use app fuse framework, it has good structure of maven files. I created multi-module hibernate spring mvc application with its quick starts.

This is directory structure of project.

D:.
    core
        src
            main
                java
                resources
                    META-INF
    src
        site
    web
        src
            main
                java
                    com
                    mycompany
                        webapp
                            controller
                            filter
                            jsp
                            listener
                            search
                            spring
                            taglib
                            util
            resources
                META-INF
            webapp
                common
                decorators
                images
                scripts
                    calendar
                WEB-INF

This is web project pom.xml's relevant parts.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<parent>
    <groupId>com.mycompany</groupId>
    <artifactId>myproject</artifactId>
    <version>1.0-SNAPSHOT</version>
    <relativePath>../pom.xml</relativePath>
</parent>

<artifactId>web</artifactId>
<packaging>war</packaging>

<build>
    <plugins>
        <plugin>
            <groupId>org.mortbay.jetty</groupId>
            <artifactId>maven-jetty-plugin</artifactId>
            <version>6.1.26</version>
            <configuration>
                <contextPath>/</contextPath>
                <scanIntervalSeconds>3</scanIntervalSeconds>
                <scanTargetPatterns>
                    <scanTargetPattern>
                        <directory>src/main/webapp/WEB-INF</directory>
                        <excludes>
                            <exclude>**/*.jsp</exclude>
                        </excludes>
                        <includes>
                            <include>**/*.properties</include>
                            <include>**/*.xml</include>
                        </includes>
                    </scanTargetPattern>
                </scanTargetPatterns>
            </configuration>
        </plugin>
    </plugins>
...
<dependencies>
    <dependency>
        <groupId>${project.parent.groupId}</groupId>
        <artifactId>core</artifactId>
        <version>${project.parent.version}</version>
    </dependency>
 ...
</dependencies>
</project>

It has dependency on core project. Whenever you compile multi-module project, it has all necessary parts. But if you need to work from web project directory only. You need to execute mvn install in core directory, this way it is installed on your local repository and your web project can use it. If you made any changes to core project you need to compile from main directory. Otherwise you can use maven from web project directory as normal.

As you can see there is no need for assembly.xml file. You should use assembly.xml file for more complex structures than war file, for example custom installer structure which will contain ; war files, help files, web server executable files, installer files for putting all of them together.

I can use mvn package command in main directory to create war file. Also I can use jetty:run command in web project directory to run jetty and test web application.

Upvotes: 1

Related Questions