javajava-8jerseyjersey-2.0java-17

ContextResolver Not Working After Migrating from Jersey 1.x to 2.x


While updating my project from JDK 8 to 17, I found that jersey-server 1.19.2 is not compatible with JDK 17. Therefore, I tried updating it to 2.43 (if I go beyond 2.x, I'll also have to update javax to jakarta). After migrating, I am getting a null value in ContextResolver. This was working fine with Java 8 and Jersey 1.

@Context
public void setMyProvider(ContextResolver<MyProducer> myProvider){
    if(myProvider != null) // getting null value here
        this.myProducer = myProvider.getContext(MyProducer.class);
}

Here are the changes I made when upgrading to Jersey 2.x:

Jersey1 pom dependencies

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

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

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

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

Jersey2 Pom dependencies changes:

        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet</artifactId>
            <version>2.43</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>2.43</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>2.43</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.inject</groupId>
            <artifactId>jersey-hk2</artifactId>
            <version>2.43</version>
        </dependency>

Jersey1 web.xml:

    <servlet>
        <servlet-name>Jersey Web Application</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.patientkeeper.jerseydemo</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

jersey2 web.xml changes:

    <servlet>
        <servlet-name>Jersey Web Application</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.example.jerseydemo</param-value>
        </init-param>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Jersey Web Application</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

These are the provider and resource class[no change]

@Provider
public class TestProucer implements ContextResolver<MyProducer> {

    public TestProucer(){
        System.out.println("Test Producer working");
    }

    @Override
    public MyProducer getContext(Class<?> aClass) {
        return new MyProducer("this is a test");
    }
}
@Path("/hello-world")
public class HelloResource {

    private MyProducer myProducer;

    @Context
    public void setMyProvider(ContextResolver<MyProducer> myProvider2){
        if(myProvider2 != null)
            this.myProducer = myProvider2.getContext(MyProducer.class);
    }

    @GET
    @Produces("text/plain")
    public String hello() {
        System.out.println(myProducer);
        return "Hello, World!";
    }
}

For the minimum working project where I can reproduce the issue, search for Jersery2DemoJDK17 on GitHub, as I am not able to post the link here.

some other specs: Java: 17 Jersey: 2.43 Tomcat server: 9 Maven: 3.8.8 IntelliJ: 2021.3.3 Ultimate

I also tried to register the provider differently by creating a ResourceConfig class:

public class ResourceApp extends ResourceConfig {
    public ResourceApp() {
        packages("com.example.jerseydemo2");
        register(TestProucer.class);
        register(JacksonFeature.class);
        register(HelloResource.class);
    }
}

and adding it to web.xml:

        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.example.jerseydemo2.ResourceApp</param-value>
        </init-param>

But I still got a null value for ContextResolver.


Solution

  • You need to inject Providers instead of directly injecting the ContextResolver:

    public void setMyProvider(@Context Providers providers){
        ContextResolver<MyProducer> myprovider = providers.getContextResolver(MyProducer.class, MediaType.WILDCARD_TYPE);
        if(myProvider != null)
            this.myProducer = myProvider.getContext(null);
    }