1

I've a normal Java EE Web-application which does not use any of the frameworks like Struts, JSF etc. In this web-application, I've a custom XML (custom-config.xml) file which has a list of configurations specific to that application. I don't want to mention this configuration information in web.xml file. Now when the container first initializes any of the servlet, I need to read the configuration information mentioned in custom-config.xml file. To achieve this I have created a custom Servlet Class say CustomServlet which extends from HttpServlet and all my Servlets will extend frm this CustomServlet. So when the Serlvet Class loads, my CustomServlet class will also be loaded.

In my CustomServlet class, I have a static method which is expected to load custom-config.xml file and understand the configurations mentioned in this.

I've two questions. Is this the correct way to go about this? Or should I put this in the init() method of CustomServlet class? How do I load the custom-config.xml file from classpath? I can't use ServletConfig.getResourceAsStream() since I'm trying to load custom-config.xml from static method.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Apps
  • 3,284
  • 8
  • 48
  • 75
  • Why exactly does it need to be a static method? – BalusC Sep 14 '12 at 12:02
  • What I thought is this needs to be done only once when the CustomServlet class is first loaded to memory by Class loader. – Apps Sep 14 '12 at 14:39
  • So, you think that servlets are newly created/initialized on every HTTP request or so insteadof just only once during application's startup? – BalusC Sep 14 '12 at 14:40
  • Servlets should be initialized only once. But I will have multiple servlets that extends from this CustomServlet class. I think the init() method of CustomServlet will be called again. Please correct me if my understanding is wrong. – Apps Sep 14 '12 at 14:48
  • 1
    Oh, that way. You could add a `static AtomicBoolean` or go ahead with `ServletContextListener` approach. I've edited the answer. – BalusC Sep 14 '12 at 14:50

2 Answers2

2

Doing it in a static method makes no sense. It would not be possible to get ServletContext from there. You need to do it in the init() method. You could use a static AtomicBoolean to check if it has already been loaded in the current JVM.

public abstract class CustomServlet extends HttpServlet {

    private static AtomicBoolean loaded = new AtomicBoolean();

    @Override
    public void init() throws ServletException { 
        if (!loaded.getAndSet(true)) {
            InputStream input = getServletContext().getResourceAsStream("/WEB-INF/custom-config.xml");
            // ...
        }
    }

    // ...
}

Alternatively, use a ServletContextListener.

@WebListener
public class Config implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        InputStream input = event.getServletContext().getResourceAsStream("/WEB-INF/custom-config.xml");
        // ...
    }

    // ...
}

You could put the parsed XML results in application scope to make it available to all servlets.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks a lot for the guidance. I need the parsed results to be available across all servlets and need to create some class level variables based on the XML. The first approach should be the suitable one right? – Apps Sep 14 '12 at 15:06
  • 1
    I would prefer the `ServletContextListener` approach. Doing atomic/synchronized/static operations is always itchy. "Just do once at the right moment" is easier. Just store it in application scope and retrive from there when necessary (you could of course use a (static) helper method for that). – BalusC Sep 14 '12 at 15:13
  • 1
    If the XML file is converted in flavor of a Javabean (e.g. JAXB is able to do that) and stored in application scope by `getServletContext().setAttribute("config", config)`, then you should be able to access it in EL without any pain, e.g. `${config.foo}` and so on. – BalusC Sep 14 '12 at 15:24
  • Oh Great.. we are using JAXB to access the XML document. – Apps Sep 14 '12 at 15:27
-1

First of all why do you have a static method to load the xml file? static methods belong to the class and not to the object. Have a default constructor in super class and make it to load xml.

public abstract class BaseServlet extends HttpServlet{

public Base(){
loadXml();
}
private void loadXml(){
...
}
}

public class Servlet1 extends BaseServlet {
...
}

If the xml is classpath, you can load the xml file with FileInputStream().

jaks
  • 4,407
  • 9
  • 53
  • 68
  • Your last statement is worth a downvote. Further, doing the job in the constructor doesn't allow you to use `ServletContext#getResourceAsStream()`. – BalusC Sep 14 '12 at 12:02