servletcontext servlet real obtener getservletcontext getrealpath contexto java jersey jax-rs

real - javax.servlet.servletcontext jar



Obtener ServletContext en la aplicaciĆ³n (6)

¿Podría posiblemente explicar cómo puedo obtener la instancia ServletContext en la subclase de mi Application ? ¿Es posible? He intentado hacerlo como en el siguiente fragmento de código pero parece que no funciona, el ctx no está configurado:

import javax.ws.rs.core.Application; import javax.ws.rs.core.Context; //... @ApplicationPath("/") public class MainApplication extends Application { @Context ServletContext ctx; @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<Class<?>>(); //... return classes; } }

web.xml:

<web-app ...> <context-param> <param-name>environment</param-name> <param-value>development</param-value> </context-param> <filter> <filter-name>jersey-filter</filter-name> <filter-class>org.glassfish.jersey.servlet.ServletContainer</filter-class> <init-param> <param-name>javax.ws.rs.Application</param-name> <param-value>my.MainApplication</param-value> </init-param> </filter> ... </web-app>

El problema es que necesito obtener parámetros de contexto de él. Si hay otra forma, agradecería que alguien me diera una pista.

Entiendo que la anotación de Context podría no estar diseñada para esto. En realidad, no necesito ServletContext . Si solo pudiera obtener parámetros de contexto de web.xml, estaría absolutamente feliz.

Aquí hay un ejemplo de lo que realmente necesito:

import java.util.HashSet; import java.util.Set; import javax.servlet.ServletContext; import javax.ws.rs.core.Application; import javax.ws.rs.core.Context; import org.glassfish.hk2.utilities.binding.AbstractBinder; public class MainApplication extends Application { @Context ServletContext ctx; @Override public Set<Object> getSingletons() { Set<Object> set = new HashSet<Object>(); final String environment = ctx.getInitParameter("environment"); //final String environment = ... get context parameter from web xml set.add(new AbstractBinder() { @Override protected void configure() { bind(new BaseDataAccess(environment)).to(DataAccess.class); } }); //... return set; } }

Gracias.


Desde Jersey 2.5, ServletContext se puede inyectar directamente en el constructor: https://java.net/jira/browse/JERSEY-2184

public class MyApplication extends ResourceConfig { public MyApplication(@Context ServletContext servletContext) { // TODO } }


Hay una declaración interesante en la documentación de la versión 1.18 de Jersey para la clase com.sun.jersey.spi.container.servlet.ServletContainer

El servlet o filtro puede configurarse para tener un parámetro de inicialización "com.sun.jersey.config.property.resourceConfigClass" o "javax.ws.rs.Application" y cuyo valor es un nombre completo de una clase que implementa ResourceConfig o Solicitud. Si la clase concreta tiene un constructor que toma un solo parámetro del tipo Mapa, entonces la clase se crea una instancia con ese constructor y una instancia de Mapa que contiene todos los parámetros de inicialización se pasa como parámetro.

Si mi entendimiento es correcto, el siguiente constructor debe ser invocado con "una instancia de Map que contenga todos los parámetros de inicialización"

public class ExampleApplication extends Application { public ExampleApplication(Map initParams) { } ... }

Aquí está la parte apropiada de 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>javax.ws.rs.Application</param-name> <param-value>experiment.service.ExampleApplication</param-value> </init-param> </servlet>

Pero de alguna manera me falló el siguiente mensaje:

GRAVE: Falta la dependencia para el constructor public experimental.service.ExampleApplication (java.util.Map) en el índice de parámetro 0

Y para la versión actual de Jersey (2.5.1) no hay tal declaración en documentstion: https://jersey.java.net/apidocs/latest/jersey/org/glassfish/jersey/servlet/ServletContainer.html


La inyección ocurre cuando usted ingresa el método de servicio. Compruebe si esto es un problema.


No use @Context en su Application sino en una clase de recursos.

@Path("/foos") public class FooResource { @Context ServletContext ctx; @GET public Response getFoos() { return Response.ok().build(); } }


Puede usar la interfaz ApplicationEventListener para obtener el ServletContext . Una vez finalizada la inicialización, puede "capturar" un ApplicationEvent y usar el ServletContext inyectado para trabajar.

Funciona bien con: org.glassfish.jersey: 2.12
Para versiones adicionales, los pls usan comentarios - no sé, sry.

Jersey Docs - 20.1.2. Oyentes del evento

Su MainApplication :

@ApplicationPath("/") public class MainApplication extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> set = new HashSet<Class<?>>(); set.add(MainApplicationListener.class); return classes; } }

... o MainResourceConfig alternativo (prefiero usar este):

public class MainResourceConfig extends ResourceConfig { public MainResourceConfig() { register(MainApplicationListener.class); } }

Y el ApplicationEventListener :

public class MainApplicationListener implements ApplicationEventListener { @Context private ServletContext ctx; //not null anymore :) @Override public void onEvent(ApplicationEvent event) { switch (event.getType()) { case INITIALIZATION_FINISHED: // do whatever you want with your ServletContext ctx break; } @Override public RequestEventListener onRequest(RequestEvent requestEvent) { return null; } }


@Context puede estar disponible en ResoureConfig inyectándolo como un parámetro de constructor usando @Context . Otra forma de acceder a él es a través de un controlador de eventos .

Pruebe el siguiente código.

@ApplicationPath("...") public class MyApplication extends ResourceConfig { public MyApplication() { register(StartupHandler.class); } private static class StartupHandler extends AbstractContainerLifecycleListener { @Context ServletContext ctx; @Override public void onStartup(Container container) { // You can put code here for initialization. } } // ...