Search code examples
javaeclipsemavenmaven-assembly-plugin

Using Maven-assembly to pack single jar


I want to create a REST server.

I added maven dependencies, my pom.xml looks like this:

<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>abptc_server</groupId>
    <artifactId>abptc_server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <build>
        <sourceDirectory>src</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.0</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>

            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-server</artifactId>
            <version>9.1.3.v20140225</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.jetty</groupId>
            <artifactId>jetty-servlet</artifactId>
            <version>9.1.3.v20140225</version>
        </dependency>

        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>jsr311-api</artifactId>
            <version>1.1.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-core</artifactId>
            <version>1.18.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-server</artifactId>
            <version>1.18.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-client</artifactId>
            <version>1.18.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-servlet</artifactId>
            <version>1.18.1</version>
        </dependency>

        <dependency>
            <groupId>com.sun.jersey</groupId>
            <artifactId>jersey-json</artifactId>
            <version>1.18.1</version>
        </dependency>

    </dependencies>
</project>

I added the maven-assembly-plugin because I want a single jar, which I can execute:

java -cp target/abptc_server-0.0.1-SNAPSHOT-jar-with-dependencies.jar server.MinimalServerRest

When I run the server in eclipse, it works well, but when I execute the jar, the server fails after one REST request: GET http://localhost:9999/employee/getEmployee

The error:

2014-03-20 11:40:46.996:INFO::main: Logging initialized @576ms
2014-03-20 11:40:47.133:INFO:oejs.Server:main: jetty-9.1.z-SNAPSHOT
2014-03-20 11:40:47.176:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@7dbe444b{/,null,AVAILABLE}
2014-03-20 11:40:47.194:INFO:oejs.ServerConnector:main: Started ServerConnector@6bb9db06{HTTP/1.1}{0.0.0.0:9999}
2014-03-20 11:40:47.194:INFO:oejs.Server:main: Started @777ms
márc. 20, 2014 11:40:53 DE com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
  rest
márc. 20, 2014 11:40:53 DE com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
  class rest.EmployeeSvc
  class rest.StudentSvc
márc. 20, 2014 11:40:53 DE com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
márc. 20, 2014 11:40:54 DE com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18.1 02/19/2014 03:28 AM'
márc. 20, 2014 11:40:54 DE com.sun.jersey.spi.container.ContainerResponse write
SEVERE: A message body writer for Java class dto.Employee, and Java type class dto.Employee, and MIME media type application/json was not found.
The registered message body writers compatible with the MIME media type are:
*/* ->
  com.sun.jersey.core.impl.provider.entity.FormProvider
  com.sun.jersey.core.impl.provider.entity.StringProvider
  com.sun.jersey.core.impl.provider.entity.ByteArrayProvider
  com.sun.jersey.core.impl.provider.entity.FileProvider
  com.sun.jersey.core.impl.provider.entity.InputStreamProvider
  com.sun.jersey.core.impl.provider.entity.DataSourceProvider
  com.sun.jersey.core.impl.provider.entity.XMLJAXBElementProvider$General
  com.sun.jersey.core.impl.provider.entity.ReaderProvider
  com.sun.jersey.core.impl.provider.entity.DocumentProvider
  com.sun.jersey.core.impl.provider.entity.StreamingOutputProvider
  com.sun.jersey.core.impl.provider.entity.SourceProvider$SourceWriter
  com.sun.jersey.core.impl.provider.entity.XMLRootElementProvider$General
  com.sun.jersey.core.impl.provider.entity.XMLListElementProvider$General

márc. 20, 2014 11:40:54 DE com.sun.jersey.spi.container.ContainerResponse logException
SEVERE: Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException: com.sun.jersey.api.MessageException: A message body writer for Java class dto.Employee, and Java type class dto.Employee, and MIME media type application/json was not found.

    at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:284)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1510)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1419)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1409)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:409)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:540)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:715)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:711)
    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:552)
    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:219)
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1112)
    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:479)
    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:183)
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1046)
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
    at org.eclipse.jetty.server.Server.handle(Server.java:462)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:281)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:232)
    at org.eclipse.jetty.io.AbstractConnection$1.run(AbstractConnection.java:505)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:607)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:536)
    at java.lang.Thread.run(Thread.java:744)
Caused by: com.sun.jersey.api.MessageException: A message body writer for Java class dto.Employee, and Java type class dto.Employee, and MIME media type application/json was not found.

    ... 24 more

I searched SO for answers:

https://stackoverflow.com/a/12427046/598280 and https://stackoverflow.com/a/6027161/598280 I already added jersey-json depencency.

https://stackoverflow.com/a/11936282/598280 I dont have web.xml and the server runs well, when I execute in eclipse, so the problem is with maven.

https://stackoverflow.com/a/13108540/598280 Same.

According to Mark Needham blog, my server class looks fine:

ServletHolder sh = new ServletHolder(ServletContainer.class);
sh.setInitParameter("com.sun.jersey.config.property.resourceConfigClass", "com.sun.jersey.api.core.PackagesResourceConfig");

// Set the package where the services reside
sh.setInitParameter("com.sun.jersey.config.property.packages", "rest");
sh.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");

Server server = new Server(9999);
ServletContextHandler context = new ServletContextHandler(server, "/", ServletContextHandler.SESSIONS);
context.addServlet(sh, "/*");
server.start();
server.join();

How can I solve this problem?

UPDATE:

My packed jar looks like this:jar

I didnt checked all depencency (it has 23 individual depencency) but it looks fine from here. Should I check all?

Here is maven clean install output: http://pastebin.com/Whk2qr2i


Solution

  • Hmm, the problem with this approach is that if multiple JARS have the same files they get overwritten. E.g. All those jars probably have META-INF/MANIFEST.MF files but only one will actually be present. This could apply to other files. This can cause odd behaviour

    I would try building them as separate JARS with maven and then try running and see if that works. You can use the assembly plugin to build a ZIP containing your application JAR and all the JAR files in a lib folder, and a script to run it. E.g. The contents of the zip would look like:

    abptcserver/
        lib/
            dependency1.jar
            dependency2.jar
            dependency3.jar
        abptcserver.jar
        run.sh
        run.bat
    

    Youc an then configure the shell and batch scripts to run your server with all JARS in the lib directory on the class path. I imagine you'll get less unexpected behaviour this way, its also more robust and more user friendly to run