He leído de la pregunta Cómo obtener acceso a una instancia de ServletContext desde cualquier método? que si quiero acceder al contexto de Servlet desde cualquier clase en mi proyecto web Java, puedo declarar un campo estático que apunte al ServletContext de ServletContextListener , pero un campo estático es una mala práctica en las aplicaciones web Java porque el GC no puede recopilarlo hasta que la JVM esté apagada (corríjame si me equivoco en este punto). ¿Hay otra forma de acceder al ServletContext sin usar un oyente o recibirlo como parámetro? ¿Existe otra solución para resolver este problema? Estoy usando JSF 1.2 y JBoss 5.1 GA para la aplicación web.

Nota: sé que puedo usar

(ServletContext)FacesContext.getCurrentInstance().getExternalContext().getContext();

Para acceder al ServletContext, pero hay un método que se ejecuta al inicio que necesita acceder al ServletContext y el FacesContext.getCurrentInstance() no se ha inicializado.

Actualizar:

Necesitamos cargar algunas direcciones IP desde web.xml en constantes String cuando se inicia la aplicación web. Para hacer esto, hemos creado una clase Singleton que carga los parámetros de contexto en variables y luego llena las constantes String con algunos valores de la clase Singleton. Esta clase Singleton gestiona gran cantidad de datos y está dando errores de excepción de memoria. Para solucionar este problema, estamos modificando la clase Singleton para que sea una clase simple que se carga como un atributo ServerContext, pero luego las constantes String no se pueden cargar por la ausencia de la instancia de este Singleton (ya no).

3
Luiggi Mendoza 27 mar. 2012 a las 00:38
¿Dónde lo necesita exactamente y por qué? ¿Por qué no harías el trabajo en el mismo ServletContextListener? Por cierto, el FacesContext solo se inicializa en cada solicitud HTTP cuya URL coincide con el patrón de URL del FacesServlet y, por lo tanto, lo ha invocado.
 – 
BalusC
27 mar. 2012 a las 00:44
Hay una cadena constante que se carga en un método estático usando un parámetro de contexto en web.xml. Para hacer esto, necesita ServletContext#getInitParameter. La solución real para esto fue crear una clase Singleton que carga estos valores en una clase que implementa ServletContextListener pero genera problemas de memoria, por lo que necesitamos crear una instancia de la clase y cargarla como un atributo en el ServletContext, pero luego no puedo acceder en el método estático.
 – 
Luiggi Mendoza
27 mar. 2012 a las 00:58
"creando una clase Singleton que carga estos valores en una clase que implementa ServletContextListener" No puedo imaginar cómo eso tiene sentido. ¿Cuál es el requisito funcional? ¿Necesita que termine en una variable public static? ¿Por qué?
 – 
BalusC
27 mar. 2012 a las 01:07
He añadido el requisito a la pregunta.
 – 
Luiggi Mendoza
27 mar. 2012 a las 01:48
Su afirmación, but a static field is a bad practice in Java web applications because the GC can't collect it until the JVM is turned off es incorrecta. La JVM GC recopilará cualquier objeto que ya no tenga una referencia o que esté en isla . Consulte stackoverflow.com/a/5667747/650425 para obtener más detalles. Si elimina la referencia del objeto de la variable estática y ya no se hace referencia a ella por ninguna otra variable, entonces es elegible para la recolección de basura. Creo que a lo que te refieres es que el objeto Class en sí no se recopilará hasta que termine la JVM.
 – 
maple_shaft
27 mar. 2012 a las 15:32

1 respuesta

La mejor respuesta

No estoy seguro de por qué necesitas un singleton. Simplemente cree un bean que almacene en el ámbito de la aplicación.

@Override
public void contextInitialized(ServletContextEvent event) {
    ServletContext context = event.getServletContext();
    Set<String> ips = parseContextParamSomehow(context.getInitParam("ips"));
    Manager manager = new Manager();
    manager.setIps(ips);
    context.setAttribute("manager", manager);
}

Estará disponible por #{manager} en contexto EL. También como propiedad administrada de un bean administrado por JSF arbitrario. Una alternativa es crear un bean administrado JSF con ámbito de aplicación y hacer el trabajo en su constructor, pero luego pospondrá su construcción a la primera solicitud HTTP que involucre al bean.

2
BalusC 27 mar. 2012 a las 17:40
El Singleton era para una implementación de caché (sí, no tenemos idea de ehcache u otros marcos) pero esa fue una mala solución, así que en lugar de agregar este marco, mi jefe quiere resolver este problema con las clases que hemos programado. Por cierto, su solución parece interesante, pero ¿cómo puedo acceder a context en un método que no se llama en una solicitud HTTP?
 – 
Luiggi Mendoza
27 mar. 2012 a las 17:45