3

I have read from the question How to gain access to a ServletContext instance from any method? that if I want to access the Servlet Context from any class in my Java web project I can declare a static field that points to the ServletContext from ServletContextListener, 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 (correct me if I'm wrong in this point). Is there another way to access the ServletContext without using a listener or receiving it as a parameter? There is another workaround for solve this problem? I'm using JSF 1.2 and JBoss 5.1 GA for the Web Application.

Note: I know I can use

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

to access the ServletContext, but there is a method that runs at startup that needs to access the ServletContext and the FacesContext.getCurrentInstance() has not been initialized.

UPDATE:

We need to load some IP's from the web.xml into String constants when the web application starts up. To do this, we have created a Singleton class that loads the context-params in variables and then fill the String constants with some values of the Singleton class. This Singleton class manages lot of data and is giving out of memory exception errors. To fix this problem, we're modifying the Singleton class to be a simple class that is loaded as a ServerContext attribute, but then the String constants can't be loaded for the absence of the instance of this (not anymore) Singleton.

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Where exactly do you need it and why? Why would you not just do the job in the `ServletContextListener` itself? The `FacesContext` is by the way only initialized on every single HTTP request whose URL matches the URL pattern of the `FacesServlet` and thus has invoked it. – BalusC Mar 26 '12 at 20:44
  • @BalusC There is a constant String that its loaded in a static method using a context-param in the web.xml. To do this, it needs `ServletContext#getInitParameter`. The actual workaround for this was creating a Singleton class that loads these values in a class that implements `ServletContextListener` but its generating memory problems, so we need to create an instance of the class and load it as an attribute in the ServletContext, but then I can't access in the static method. – Luiggi Mendoza Mar 26 '12 at 20:58
  • *"creating a Singleton class that loads these values in a class that implements ServletContextListener"* I can't imagine how that makes sense. What's the functional requirement? Do you need it to end up in a `public static` variable? Why? – BalusC Mar 26 '12 at 21:07
  • @BalusC I have added the requirement to the question – Luiggi Mendoza Mar 26 '12 at 21:48
  • @LuiggiMendoza Your assertion, `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` is incorrect. The JVM GC will collect any objects that no longer have a reference, or are on *island*. See http://stackoverflow.com/a/5667747/650425 for more details. If you remove the object reference from the static variable and it is no longer being referenced by any other variable then it is eligible for garbage collection. I think what you refer to is that the Class object itself will not be collected until the JVM terminates. – maple_shaft Mar 27 '12 at 11:32
  • Why do you think that out of memory errors will be solved if you load the **same** data on a different way? – BalusC Mar 27 '12 at 13:10
  • @BalusC because the data loaded in Singleton remains in memory for the static instance, every time I upload the web application on the web server the it creates a new Singleton instance and the last one keeps in memory and can't be deallocated (I have already made my tests). There is a moment when I upload the web application that the log outputs an OutOfMemory exception, and only happens in the upload time, there are no errors of this kind while the application is up. – Luiggi Mendoza Mar 27 '12 at 13:30
  • @downvoter at least explain your reasons... – Luiggi Mendoza May 28 '13 at 14:11

1 Answers1

2

I'm not sure why you need a singleton. Just create one bean which you store in the application scope.

@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);
}

It'll be available by #{manager} in EL context. Also as managed property of an arbitraty JSF managed bean. An alternative is to create an application scoped JSF managed bean and do the job in its constructor, but you're then postponing its construction to the first HTTP request which involves the bean.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • The Singleton was for a cache implementation (yes, we have no idea of ehcache or other frameworks) but that was a bad solutions, so instead of add this framework, my boss wants to solve this problem with the classes we have programmed. By the way your solution looks interesting, but how can I access to `context` in a method that's not called in a HTTP Request? – Luiggi Mendoza Mar 27 '12 at 13:45