I need to built a thread/process that is always running, and can be queried through other servelts and JSP pages...
This thread/process will be dealing with large files, so it will cache file blocks to reduce file accesses (plus some other processing)...
So, that thread/process will be loaded and waiting for any queries coming, to answer... as long as the server is running.
I though about making a static class common between all the servelt classes, but I found out that will not work (tomcat deals with each new servelt as a totally new program)
So what are the other options I can try??
I think you have two options:
Use the ServletContext to access application-wide scope objects.
Use a more sophisticated solution, such as ehcache to put your data in memory.
Other options in addition to the ones proposed by Morritz
Inside Tomcat: register a global object accessible by all servlets using the Global JNDI
Within the same JVM: start you shared resources (your static class, repository, etc...) and Tomcat programmatically (embedded) using a launcher like The Java Service Wrapper. You will need to define a small API implemented by your shared resource and usable by your servlets.
Distributed accross JVM: memcached, hazelcast, etc...
Related
This link says that earlier versions of Tomcat (before 7.0.54) "renews its threads" thru ThreadPoolExecutor.run().
Why doesn't the init() method of contained Servlets seem to get called again?
A Servlet is initialized only once, either at web application startup or upon first use.
The same instance will then be used to serve all incoming requests, if necessary even multiple requests at the same time (unless you use the deprecated option to synchronize access, but even then there will be just a single instance, and a queue of requests for it).
I have done a lot of looking around on this topic but all I could find related to database connections etc.
I'm building a web service which loads a Shapefile and uses the GeoTools library to do some funky location based stuff. What I'd like to do is load the Shapefile once, get all the 'Features' in memory for the Shapefile, and then just be able to check against that collection each time - note there are actually many shapefiles loaded now.
I've wrapped my Geo-based stuff in a class, with it loading the shapefiles into a collection when the class is instantiated. My #WebService class checks to see if myGeoClass is instantiated, else it creates it and loads the files into memory. These files never change, so I'd like to keep the same instance of the object between multiple requests, but I've added some traces in and it seems to be creating a new instance in with every request.
Is there a way to keep the single instance in memory, shared across all requests?
Cheers!
At the very least you could use a static variable.
If it is a web app , then you can set it as an attribute of the ServletContext.
If you are using Java EE 6 then you can define your class as a managed bean #ApplicationScoped or a Singleton
I have a Struts based web application that has a structure similar to the one shown below. (Not this is just an example)
$TOMCAT_HOME/webapps/myapp
|-css
|-myapp.css
|-js
|-myapp.js
|-forum
|-index.jsp
|-list.jsp
|-users.jsp
|-Articles
|-index.jsp
|-ListArticles.jsp
|-Guestbook
|-viewGuestBook.jsp
|-AddnewEntry.jsp
|-WEB-INF
|-classes
com
|-myapp
|-forum
|-DisplayForum.class
|-ListUsers.class
|-article
|-ArticleList.class
|-AddArticle.class
|-guestbk
|-LoadGuestBook.class
|-ProcessGuestBook.class
Currently, the application is built using ANT and deployed to the Tomcat application server as a single war file (named myapp.war). I would like to separate the application so that it is deployed using multiple war files for each module. (i.e. forum.war, articles.war and guestbook.war). The contents of the new war file will only contain files related to the module. For example, the forum.war file will contain
$TOMCAT_HOME/webapps/forum
|-forum
|-index.jsp
|-list.jsp
|-users.jsp
|-WEB-INF
|-classes
com
|-myapp
|-forum
|-DisplayForum.class
|-ListUsers.class
There are a couple of things i am not sure about with this approach.
Shared static resources
The *.css and *.js files are common across each war file. If i have different war files i will have a copy of the css files in each war file. Is there any way i can deliver the resource files (css, js, static files) in a common approach so that they are shared. I am thinking that maybe i should include a new war file called common.war and include the shared static data. (I think the other war files can access these files using the URL as they are static resources. right?)
Shared classes
There are some classes that are shared globally. As an example, there is a class called UserSession. When the user logs-on to the application, the UserSession object is created and stored in a Hashtable and the user's session id as the key for the Hashtable. Anytime a user tries to acess any part of the application, the session id is checked against the sesion id's in the Hashtable.
The UserSession object does a number of things - such as
Validating user login
Track user's activity
Log user login history to the database
And more...
I need all war files (applications/modules) to have access to the UserSession object but that only one is associated with each session. How should i architect this so that the user's session spans across the different war files?
I have been reading around about how to share objects and came up with two options
Shared object via JNDI
Shared object via Tomcat ServletContext
As i understand it, if an object is stored in the ServletContext, it can be accessed by any application (i.e. war file). How would this work though if i want a different instance per user session. For example,
User1 logs on - UserSession stored in ServletContext
User2 logs on - Where do i store User2's UserSession object?
At the moment i store the sessionID in HTTPSession and the UserSession object in a HashTable.
HttpSession session = request.getSession(true);
UserSession userSession = getUserSession(session.getId());
Does User1 get the same sessionId regardless of the war file he/she is accessing? If so Could i Store another List object in ServletContext that contains the sessionIDs?
I have also seen references to object sharing using JNDI. I am not very familiar with JNDI. I have used JNDI for DataSources but that is as far as it goes. How exactly would it work? I would appreciate if someone can point me to an example showing how JNDI can be used for sharing data. Is it true that JNDI is the better approach and why?
And finally, where would the UserSession.class file reside? I know i can put it in a jar file in $TOMCAT_HOME/lib but this is usually not recommended. The problem though is if it is in the WEB-INF/lib folder of one of the war files it cant be accessed by any other war file.
Would appreciate some input/suggestions. I would be interested to know what strategy you use to deploy an application made up of multiple war files.
Thanks
Edit
Ok i forgot to mention why i want to split the war file. Basically, we have several teams of developers. We have had situations where one team is working on a specific area of the application and another team is working on a different area.
For example assume the following scenario -
Team1 is working on the Forums module due to be released next month.
Team2 has been asked to deliver a change for the Articles and should be released next week.
If Team1 has checked in their code and are performing system/integration tests which will take more than a week, Team2 is stuffed as they have to wait.
These kinds of problems are usually solved using Branching but we tend to avoid branching as it introduces a lot of complications with merging that we decided to avoid Branching.
The other reason is that we have an older application that i am considering to reuse with this application. The older application based on pure HTTPServlet. I.e not based on any framework (i.e. structs, spring etc). If i want to integrate it with my existing app i will need to use the session/servletcontext.
Also, a lot of people are skeptical of the fact that if you make a simple change (e.g. you add a new stylesheet definition to a single css file), you have to rebuild and redeploy the whole application.
Other reasons include
Could Simplify scalability/load balancing - (possibly?) Not sure about this one. I am thinking in terms of deploying each war file to a different server/cluster.
Reduces PERMGEN memory requirements
etc...
I'm not sure if you understood correctly, but the HttpSession is different for each user (browser session), and for each application as well, AFAIK, so you can't use it to share data.
Basically, you need communication between your web applications.
You could have one war to act as data manager for your UserSession, and all other wars communicating to this one. The data manager application needs to expose a service, e.g. UserSessionManager that can be accessed via other applications.
JNDI is a traditional solution for this. Spring has some helpers for this, but the JNDI API is not too complicated either. In the data manager war, you could do something like this in an initialization method:
DataManager mgr = new DataManagerImpl(...);
InitialContext ic = new InitialContext();
ic.rebind("java:global/env/datamanager", mgr);
The interface and the data objects you use needs to be put in a jar that is shared in all 'client' wars, the implementation is only in the data manager war. In your client wars, you can then do:
InitialContext ic = new InitialContext();
DataManager mgr = (DataManager)ic.lookup("java:global/env/datamanager");
Hope this helps,
Geert.
If Team1 has checked in their code and are performing system/integration tests which will take more than a week, Team2 is stuffed as they have to wait.
These kinds of problems are usually solved using Branching but we tend to avoid branching as it introduces a lot of complications with merging that we decided to avoid Branching.
Well, there's your problem right there. This is exactly what branching is for. If it's giving you problems, then the answer is to solve those problems, not to avoid branching entirely. It might be as simple as switching to a better VCS. (Which one are you using right now?)
Also, a lot of people are skeptical of the fact that if you make a simple change (e.g. you add a new stylesheet definition to a single css file), you have to rebuild and redeploy the whole application.
That's the nature of Java web apps. If you put the CSS files into a separate war, then you still have to rebuild and redeploy that war. And with multiple wars, the process will become more complicated, not less.
Anyway, every Java IDE lets you do this with a single key press, so I don't see what the big deal is.
Could Simplify scalability/load balancing - (possibly?)
Possibly. But you know what they say about premature optimization.
I got a situation that I must serve files from different folders then the one of the context my web app is running. As an example, suppose my web app is running in a servlet context on "/opt/tomcat/webapps/ROOT/" and I must serve files existent in "/opt/my_other_folder/". These folders can be changed in runtime by the client, so I can't simply add a new context pointing to these directories. I would like a solution that I wouldn't have to rewrite a web server only for that. Also, the product I work on is generic, so I can't have a solution specific to some servlet container.
Thanks!
If you're only serving files, I would consider fronting your servlet container with something like Apache HTTP Server, where you could simply use its various directives to provide a "virtual directory" pointing to an easily configured location.
Otherwise, you could write and configure a standard Java servlet that would do essentially the same thing - storing the actual path in a Java properties file that would be read by the servlet. But while this isn't a lot of work, it would be significantly more work that the above Apache HTTP Server solution. This would be very similar to several of the answers posted at Servlet for serving static content . Specifically, you could either use or extend upon Apache Tomcat's DefaultServlet. (There are some Tomcat-specific classes used in here, but they could be easily replaced with generic equivalents.) http://balusc.blogspot.com/2009/02/fileservlet-supporting-resume-and.html looks even closer to what you'd be looking for, and it is completely generic - while still having some additional, significant features.
Either of these options would be very generic, and not specific to any particular servlet container.
I have implemented my domain layer classes and i have used them in a java application.
Now i want to use same classes in a java web application,but i don't know how can i do it?
In the java application we make and run some objects in main(class and method) and use them while program is running.
for example an object that hold a collection of data that will be needed for all user requests.
My question is:
How can i create and hold such objects and data that should be available for all users and clients.
Place them in the application context. I.e. in a Servlet call getServletContext().setAttribute("name", yourCollection);
Then they can be retrieved by getServletContext().getAttribute("name")
You could create a singleton which represents the common application logic, initialising and cleaning up the common information and objects on web-app startup and shutdown.
All servkets can use the application singleton to retrieve and store.
To initialise and cleanup on web-app startup and shutdown you can define an administrative servlet which has the load-on-startup flag set in the deployment descriptor web.xml managing the application singleton from the init() and destroy() methods.