¿Cómo inyectar un objeto en el contexto de solicitud jersey?

Tengo este escenario en el que quiero escribir un filtro y quiero que este filtro inserte algún objeto en la solicitud actual y lo pase para que cuando la clase de recurso reciba la solicitud pueda usar el objeto.

Clase de filtro

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

Clase de recursos

 @PUT @Consumes("application/json") @Path("/") public String create( JSONParam sample, @Context MyObject obj) { System.out.println(obj.getName()); return ""; } 

Solo podría usar ContainterRequestContext.setProperty(String, Object) . Entonces simplemente inyecta el 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(); } 

Otra opción para inyectar MyObject directamente es usar la funcionalidad HK2 que ofrece Jersey 2.

Cree una fábrica, inyecte ContainerRequestContext y devuelva MyObject . Por ejemplo

 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 { 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) {} } 

Luego debes unir la fábrica:

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

Con la misma configuración de la propiedad que en el ejemplo de filtro anterior, puede simplemente inyectar MyObject con el @Context

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

  • Ver más en Custom Injection

ACTUALIZAR

Por favor, vea esta pregunta para un problema con esta implementación.

Ver también:

  • Si usa web.xml en lugar de ResourceConfig

Tengo una solución para esto que no requiere un contenedor DI, pero aún así da la mayor parte del beneficio.

Hay dos partes El primero es cómo obtener instancias en el mecanismo de inyección de @Context en lugar de proporcionar clases en el objeto ApplicationConfig.

Aquí hay una técnica para hacer eso:

 private static class CustomContextResteasyBootstrap extends org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap{ private final Map, Object> additionalContextObjects = new HashMap, Object>(); public  CustomContextResteasyBootstrap addContextObject(Class< ? super E> clazz, E obj){ additionalContextObjects.put(clazz, obj); return this; } @Override public void contextInitialized(ServletContextEvent event) { super.contextInitialized(event); deployment.getDispatcher().getDefaultContextObjects().putAll(additionalContextObjects); } } 

y lo usas así:

  webAppContext.addEventListener( new CustomContextResteasyBootstrap() .addContextObject(MyCustom.class, myCustom) .addContextObject(AnotherCustom.class, anotherCustom) // additional objects you wish to inject into the REST context here ); 

ahora puedes usar esas clases con la anotación @Context:

 @GET public MyCustom echoService(@Context MyCustom custom) { return custom; } 

La siguiente parte del rompecabezas es cómo proporcionar objetos de contexto por solicitud. Para hacer esto, agregue el siguiente código en algún lugar cerca de la parte superior de la jerarquía de llamadas de jax-rs (básicamente, todo lo que reciba llamadas debajo de esta línea tendrá acceso al objeto de contexto):

  ResteasyProviderFactory.pushContext(MyContextSpecific.class, new MyContextSpecific()); 

A continuación, puede hacer referencia a esto a través de inyección en cualquier lugar por debajo de ese nivel:

 @GET public String contextSpecificEchoService(@Context MyContextSpecific contextSpecific) { return custom.toString(); } 

Esta es la DI de un pobre, pero funciona muy bien para servidores de descanso integrados.