开发者

Trouble implementing Singleton pattern in Tomcat web application due to Class Loader

I'm trying to implement a Singleton in Tomcat 6.24 on Linux with x86_64 OpenJDK 1.6.

My application is just a bunch of JSPs and some static content and the JSPs make calls to my Java code. Currently the web.xml just looks like this:

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/java开发者_JS百科ee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

<description>
    App Name
</description>
<display-name>App Name</display-name>

<!-- The Usual Welcome File List -->
<welcome-file-list>
    <welcome-file>pages/index.jsp</welcome-file>
 </welcome-file-list>

</web-app>

Before when I was trying to load my Singleton it was getting instantiated twice since the class was getting loaded by two different class loaders (I'm not sure why) and each loader would create an instance of the singleton which is not acceptable for my application. I finally figured out if I exported my code as a jar and put it in $CATALINA_HOME/lib then there was only one instance, but this is not an elegant solution.

I've been googling for hours, but I haven't come up with anything yet. I'm wondering if there is some other solution. Currently I'm not precompling my JSPs, could this be part of the problem? Could I write a servlet to ensure the singleton is created? If so how do I do that?


Ok, I finally figured out the problem.

I had made my application the default application for the server by adding a to server.xml and setting the path to "". However, when I was accessing it through the URL http://localhost/somepage.jsp for somethings, but also the URL http://localhost/appname/anotherpage.jsp for other things.

Once I changed all the URLs to use http://localhost/ instead of http://localhost/appname the problem was fixed.


To ensure correct initialisation of the Singleton, you should check that you are using the default parent-first classloader, see http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html.

Then define a ServletContextListener and intialise your Singleton in the method:

contextInitialized(ServletContextEvent sce)  

which is guaranteed to be called before any of your servlets or filters.

All ServletContextListeners are notified of context initialization before any filter or servlet in the web application is initialized.

Define your ServletContextListener in your web.xml


When is the singleton created first? You could force it to be created when the index.jsp is loaded by including a:

<%! MySingleton instance = MySingleton.getInstance(); %>

line.

If you precompile the jsp's and configure tomcat to never auto-reload classes or jsp's the singleton should stay single :-)


Once I changed all the URLs to use http://localhost/ instead of http://localhost/appname the problem was fixed.

This implies that you've 2 deployed webapplications and expected them to use the same classloader. This is untrue. If you want a shared library which is used by all webapplications, then you should put it in the path as denoted by "Tomcat Shared" (which is configureable by shared.loader in catalina.properties file). You only need to ensure that you do not have this library in the webapp's own library or in Tomcat/lib.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜