How to inject an object into jersey request context?

armin picture armin · Dec 27, 2014 · Viewed 34.3k times · Source

I have this scenario where I want to write a filter and I want this filter to insert some object into the current request and pass it on so that when the resource class gets the request it can use the object.

Filter class

@Override
public void filter(ContainerRequestContext request) throws IOException {
    MyObject obj = new MyObject();
    // Inject MyObject to request which I dont know how
}

Resource Class

@PUT @Consumes("application/json")
@Path("/")
public String create(
        JSONParam sample,
        @Context MyObject obj) {

    System.out.println(obj.getName());

    return "";
}

Answer

Paul Samsotha picture Paul Samsotha · Dec 27, 2014

You could just use ContainterRequestContext.setProperty(String, Object). Then just inject the ContainerRequestContext

@Override
public void filter(ContainerRequestContext crc) throws IOException {
    MyObject obj = new MyObject();
    crc.setProperty("myObject", myObject);
}

@POST
public Response getResponse(@Context ContainerRequestContext crc) {
    return Response.ok(crc.getProperty("myObject")).build();
}

Another option to inject the MyObject directly is to use the HK2 functionality Jersey 2 offers.

Create a factory the inject the ContainerRequestContext and return the MyObject. For example

import javax.inject.Inject;
import javax.ws.rs.container.ContainerRequestContext;
import jetty.plugin.test.domain.MyObject;
import org.glassfish.hk2.api.Factory;

public class MyObjectFactory implements Factory<MyObject> {
    
    private final ContainerRequestContext context;
    
    @Inject
    public MyObjectFactory(ContainerRequestContext context) {
        this.context = context;
    }

    @Override
    public MyObject provide() {
        return (MyObject)context.getProperty("myObject");
    }

    @Override
    public void dispose(MyObject t) {}  
}

You then need to bind the factory:

public class InjectApplication extends ResourceConfig {
    
    public InjectApplication() {
        ...
        register(new AbstractBinder(){
            @Override
            protected void configure() {
                bindFactory(MyObjectFactory.class)
                        .to(MyObject.class)
                        .in(RequestScoped.class);
            } 
        });
    }
}

With the same setting of the property as in the filter example above, you can then just inject the MyObject with the @Context

@GET
public Response getTest(@Context MyObject myObject) {
    return Response.ok(myObject.getMessage()).build();
}


UPDATE

Please see this question for a problem with this implementation.

See Also: