Hello all, I have an applet, that connects to a servlet called GetMessages. The servlet sends some data (messages) back to the applet for display. The servlet gets all this data from another class, MessageManager. MessageManager is a singleton class that connects to the DB and gets all available messages during instantiation. This is in order to stop each client from connecting to the database. (it is not crucial that the data is current) Everything is located on one PC. I have just started working on this, so the MessageManager is mostly abstract at the momement. It only returns the default message. Applet -> Servlet -> MessageManager I get the: "IllegalAccessError: tried to access class MessageManager from class GetMessages" I am running Apache + Tomcat (4.1..if I remember correctly) I tried placing the MessageManager class in common/classes and shared/classes folder, restarting the Tomcat service each time (running on Windows 2000). I get this error in both situations. If I place the MessageManager into my regular "javacode" directory (that is included in the CLASSPATH variable) - classloader throws a ClassNotFound: MessageManager exception. Everything works as expected if I place the MessageManager class into the WEB-INF\classes\ folder. However, I understand this would result in a new MessageManager class created for each session, as each MessageManager's scope will be this current session. Is that correct? If so, it would defeat the whole purpose of having this class. I am trying to make it so the database is only queried once, when the first request for messages comes in. I would appreciate any additional information regarding this, as I am not very clear as to how the scope for each object is decided. What would you think is the best way to implement what I am trying to do? I want to get the data from the DB when the first request comes in, and have it available in a singleton class if additional requests arrive.
You wrote: Everything works as expected if I place the MessageManager class into the WEB-INF\classes\ folder. However, I understand this would result in a new MessageManager class created for each session, as each MessageManager's scope will be this current session. This is nearly the correct solution. It's certainly the right place to put your class files. Depending on how you have coded your Singleton, there will probably only be one MessageManager object for each web application. However, I have to ask why you think you need this to be a Singleton. Sure you only want one MessageManager object, but it's easy enough to just create one instance of a regular class and put it in the shared application context for all requests to access:
For more information on why using Singleton may not be a good idea, search for "Singleton" in the OO, Patterns and UML forum.
Thanks for your reply. I was trying to use a singleton pattern because I was not clear as to how ServletContext works. I have read about singleton pitfalls in this situation (e.g. there is a chance several classes will be instantiated), but decided that it would not be a problem because everything would still work if this would happen. Clearly, the solution you provided is a much more elegant way of doing this. I have a couple of questions about it. ServletContext context = getServletContext(); Since getServletContext() is a method from ServletConfig, wouldn't this line have to be: ServletContext context = config.getServletContext(); ? From reading documentation from Tomcat website, I get an understanding that ServletContext is created when Tomcat loads. This would mean that ServletContext is created first, then my MessageManager object is created when the first request comes in, and it is made available to all subsequent requests. Is this correct? You wrote: search for "Singleton" in the OO, Patterns and UML forum Frankly, I have been working mostly from books up until this point. My web research on java has been mostly just searching for keywords in Google. That is how I stumbled upon JavaRanch (great site, btw!). I would appreciate any links you can provide.
Joined: Jan 07, 1999
Since getServletContext() is a method from ServletConfig, wouldn't this line have to be: ServletContext context = config.getServletContext(); ? It could be. But note that getServletContext() is also a method in GenericServlet, which is a superclass of HttpServlet, so the method is also available in your servlet code. All it does is call the getServletContext() method of the ServletConfig object that you passed in to super.init(ServletConfig) earlier. I usually us this version because it makes my code slightly smaller From reading documentation from Tomcat website, I get an understanding that ServletContext is created when Tomcat loads. This would mean that ServletContext is created first, then my MessageManager object is created when the first request comes in, and it is made available to all subsequent requests. Is this correct? Almost. It's important to remember that a servlet container can hold several independent web applications at one time, so you need to distinguish between when the container (e.g. Tomcat) is started, and when a particular application is started. A ServletContext (also known as the "application" context in JSP) is created when each application is initialised. This will happen when the container is started, but can also happen when a new or updated application is deployed to the container. By default, the "init" method of servlets in the application is only called when the first request for that servlet arrives. So you are correct that the MessageManager object will be created at that point. If you want this processing to always happen when the application or container is started, you can mark your servlet as "load-on-startup" in the web.xml. I often put a "setup" servlet in my applications whicg does nothing except initislise this sort of stuff ready for the other servlets to use:
If you don't declare doGet and doPost methods in such a servlet, it will never get called by a request, so it's safe to just use it for initialisation. If you only have one servlet in your application, you might as well put all the initialisation in there and declare it as load-on-startup. As for searching. Here at JavaRanch we have lots of forums about separate aspects of Java development, and each has a "search" link near the top right. To look up past discussions of Singletons, for example, go to the OO, Patterns, UML and Refactoring forum, click the search link, and enter singleton to see a list of past threads containing that word. I hope this has helped - good luck!
Joined: Jan 16, 2004
Great! Thanks a lot for your help. I cannot wait to play with this stuff on Tuesday
subject: servlet throws IllegalAccessError when trying to access another class