0

We're just starting a new project, and are looking into spring-boot for kickstarting our development. spring-boot seems powerful, but there's some magic going on that we yet don't understand.

I've cloned the spring-boot samples and ran the Jersey Example. https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-jersey So far so good.

I then converted this to Groovy/Gradle.

relevant sections of the build script looks like this

.
.
buildscript {
    repositories {
        jcenter()
//        maven { url "http://repo.spring.io/snapshot" }
        maven { url "http://repo.spring.io/milestone" }
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.0.M2")
        classpath 'org.springframework:springloaded:1.2.0.RELEASE'
    }
}
.
.
apply plugin: 'spring-boot'
.
.
dependencies {
    compile project(':domain')
    compile "org.springframework.boot:spring-boot-starter-jersey",
            "org.glassfish.jersey.media:jersey-media-moxy:2.13",
            "org.springframework:spring-webmvc"
}

when running gradle bootRun the server starts, and the EndPoint resource in the samples are working.

No I want to serialize my domain object to json, creating a PersonResource class

@Component
@Path("/internal/v1/core/person")
class PersonResource {

    @GET
    def hello() {
        "hello"
    }

    @GET
    @Path("/greet/{firstName}")
    String greet(@PathParam('firstName') String firstName) {
        def p = Person.findByFirstName(firstName)
        return p ? "Hello ${p.firstName}!" : "Person not found"
    }

    @GET
    @Path("/{firstName}")
    @Produces(APPLICATION_JSON)
    def getPerson(@PathParam('firstName') String firstName) {
        def p = Person.findByFirstName(firstName)
        if (p) {
            return p
        } else {
            return Response.status(NOT_FOUND).build()
        }
    }


    @POST
    @Path("{firstName},{lastName}")
    Response addPerson(@PathParam('firstName') String firstName, @PathParam('lastName') String lastName) {
        Person.withTransaction {
            def p = new Person(firstName: firstName, lastName: lastName).save()
            if (p) {
                return Response.created().build()
            } else {
                return Response.status(BAD_REQUEST).build()
            }
        }
    }


}

When running the example, I use curl to create a new Person. See the last method -> addPerson

When accessing the the "greet" resource, this also works fine, returning a String

However, when trying to return a json represenation of Person using the "getPerson" method, this fails with

java.lang.NoClassDefFoundError: org/glassfish/jersey/internal/inject/SecurityContextInjectee
    at org.glassfish.jersey.server.ServerBinder.configure(ServerBinder.java:190)
    at org.glassfish.hk2.utilities.binding.AbstractBinder.bind(AbstractBinder.java:171)
    at org.glassfish.jersey.internal.inject.Injections.bind(Injections.java:154)
    at org.glassfish.jersey.internal.inject.Injections._createLocator(Injections.java:144)
    at org.glassfish.jersey.internal.inject.Injections.createLocator(Injections.java:123)
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:303)
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:284)
    at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311)
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:168)
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:358)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:884)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.proceractProtocol.java:611)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1736)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1695)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.ClassNotFoundException: org.glassfish.jersey.internal.inject.SecurityContextInjectee
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
    ... 28 common frames omitted

I've added the "org.glassfish.jersey.media:jersey-media-moxy:2.13" as a dependency, according to Jersey 2 docs

https://jersey.java.net/documentation/latest/media.html#json.moxy

This should be a Auto-Discoverable feature, so this should work without requiring registrating moxy as a feature

So, I think, maybe this is related to my other issues with spring-boot-jersey and gradle? So to exclude this possibility, and add the following to the spring-boot-sample-jersey code

public class Person {

    public String firstName;
    public String lastName;
}

 @GET
    @Path("/person")
    @Produces(APPLICATION_JSON)
    public Person person() {
        Person p = new Person();
        p.firstName = "Elvis";
        p.lastName = "Presley";
        return p;
    }

and to the pom

<dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
            <version>2.13</version>
        </dependency>

However, this also fails, although with a different exception

java.lang.NoClassDefFoundError: org/glassfish/hk2/api/ServiceLocatorFactory$CreatePolicy
    at org.glassfish.jersey.internal.inject.Injections._createLocator(Injections.java:138)
    at org.glassfish.jersey.internal.inject.Injections.createLocator(Injections.java:123)
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:303)
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:284)
    at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311)
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:168)
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:358)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1284)
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:884)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:134)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:503)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:421)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1736)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1695)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:744)

I am missing something obvious here? Or is this a problem with spring-boot-jersey?

Community
  • 1
  • 1
runeaen
  • 461
  • 5
  • 22

1 Answers1

1

You're trying to use version 2.13 of jersey-media-moxy with Boot 1.2.0.M2. Boot 1.2.0.M2 uses version 2.7 of the other Jersey modules. Dropping back to 2.7 of the jersey-media-moxy module should fix the problem. Alternatively, Boot's latest 1.2.0 snapshots are now using Jersey 2.13 so you could update your Boot dependency to 1.2.0.BUILD-SNAPSHOT instead.

Andy Wilkinson
  • 108,729
  • 24
  • 257
  • 242
  • This solves my initial problem. However, when returning more complex domain entities with relations/collections from the jersey resource, 404 is returned. And no logging provided from jersey on the 404, so I have to dig deeper into that. (jersey logs other things though, just not this) – runeaen Oct 30 '14 at 08:14