I was wondering if there is a global session concept in tomcat (à la PHP). Imagine a really vanilla webapp with a servlet that takes input via POST and dumps them into an object (ignore obvious security concerns). The index page then just displays all the input so far.
I would like to put this object into a global variable. I can go the static methods / singleton route but just wondering if tomcat supports global variables.
Thanks!
There is many context in the Servlet specifications:
Servlet or application context. This let you store object that can be shared across of all the application a for all the clients (browsers). The objects stored in this context are alive until the application is undeployed or the container (Tomcat) is shutted down
Session context. This let you store objects in the session of the client (browser session). Also this objects are alive until the session of the users expires
Request context. This let to you store objects across the different requests. The objest stored in the requests are alive until the request is completed
I hope this can help you.
Related
I have a tomcat server running a webapp. In the webapp's startup, I'm setting few context parameters using an implemented class for interface ServletContextListener. The parameter that I am initializing here are a couple of connection objects for a database running on a different machine.
The doubt that i have is whether the connection objects that I created here are one for each instance (since tomcat creates one instance per client request), or one for the entire webapp itself?.
If it is one per webapp, then can the server handle large simultaneous requests (in the order of thousand request per second) to perform the CRUD operations on the database?.
ServletContext is created one per webApp. The server reads the web.xml file from the web app and creates a ServletContext based on the configuration you provide on web.xml. Once created it is shared between the components of the web app. If you have multiple webapp installed on your server, you will have multiple ServletContext - each for the web app.
For reference please have a look here
A webapp has only one instance of ServletContext and the atributes in ServletContext are application scoped.
Regarding you database connection, it's better to use connection pooling (DataSource) instead of adding Connection objects as attributes in ServletContext.
Not sure if you mean this but the requests are handled by Servlets and not ServletContext.
If your setting an attribute on the ServletContext the attribute will be scoped for the entire application.
From the Java EE 7 Spec:
There is one instance object of the ServletContext interface
associated with each Web application deployed into a container.
only one ServletContext is loaded irrespective of the number of requests made.
This is even the advantage of servlets over CGI.
Hope it helps.
I'm far from an expert of the intricacies of Resource Injection, and of indeed DataSources in Java, but I generally understand the process of doing a lookup for a predefined JNDI resource to get a datasource from.
Using Resource Injection as an alternate method, the below syntax works:
#Resource(name="jdbc/Foo")
private javax.sql.DataSource con;
However, I am using this in a servlet and as such wondering, how long this injected connection object's value will exist? Presumably, as it's simply an object within the servlet, it will inject when the servlet is first instantiated and exist for the same duration as the servlet (assuming I don't manually change it). Is this correct? Or does the servlet re-inject the resource everytime the servlet is used?
Thanks
A servlet container only ever creates one instance of your servlet. The IoC container you're using will then instantiate and inject the DataSource, so the value in con will remain the same for the life of your servlet, ie. the life of the application.
As to the underlying connection the DataSource is trying to make will, that's up to your datasource.
it will inject when the servlet is first instantiated and exist for the same duration as the servlet
Correct.
Or does the servlet re-inject the resource everytime the servlet is used?
No, this couldn't be happening because each request is served by a different thread. It wouldn't be good if those threads would modify the fields of the servlet. Request processing methods of the servlet must not modify its fields.
Generally container managed resources are injected using #Resources annotation. And container managed resources live as long as the container is running ( unless your are not manually kill it or any exception happens). Several applications can use the same resource object, provided that they live in the same application server ecosystem (same application server or cluster or server domain). But servlets are managed by your applications and lives within the application's scope as long as your application is running! So in terms of life span, if you compare resources are longer living than servlets.
And yes you are right, if you inject resources to a servlet, the reference of the resource will remain from the creation of the servlet to the end of the servlet's life cycle. The injection is not related with, how you are using the servlet or the resource.
Hope, this answers your question, Thanks!
The object I'm saving to the session is a LocalizationContext, which is not serializable, and my Tomcat is 5.5.28, while the qa server is Tomcat 5.5.30. This is from the Tomcat docs:
Whenever Catalina is shut down
normally and restarted, or when an
application reload is triggered, the
standard Manager implementation will
attempt to serialize all currently
active sessions to a disk file located
via the pathname attribute. All such
saved sessions will then be
deserialized and activated (assuming
they have not expired in the mean
time) when the application reload is
completed.
In order to successfully restore the
state of session attributes, all such
attributes MUST implement the
java.io.Serializable interface. You
MAY cause the Manager to enforce this
restriction by including the
<distributable> element in your web
application deployment descriptor
(/WEB-INF/web.xml).
This makes me think it should be breaking on my local as well, and that you can never save a session attribute in Tomcat unless it implements Serializable.
EDIT:
Sorry, to be more clear, my question is two-fold. Do all session attributes have to be serializable, and if they do, why might it still work on my local environment?
It is preferable that session attributes (and hence sessions) are serializable, especially when developing for environments where user sessions can be persisted only to be restored later. This is more or less a pre-requisite for failover/migration of sessions in a cluster.
But clustering is not the only scenario where sessions will be serialized. In a single container, sessions can be persisted when the container is being shutdown, and will be de-serialized when the container is brought back again. This of course, depends on the container support, and a lot of containers including Tomcat support this feature.
The rational answer on why the error does not manifest in the local environment is that the error is flagged only when there is an attempt to serialize the session. The container does not include checks on whether the attribute values in the session, on whether they are serializable or not. Containers wouldn't implement this check; after all, such a test would include actual serialization of the session, which can be performance intensive, with the only benefit of being defensive against programming mistakes.
I have an applet that communicates with a servlet using Http (Not sockets). Currently, each instance of the applet (i.e. when each applet is run by a different client on a different computer), all the instances communicate with the same servlet. What I want is that each instance of the applet communicate with different instances of the same servlet. Is this possible?
You don't want to have different instances of the same servlet in webapp's lifetime. The normal practice is to use the HttpSession to distinguish between clients. You need to pass the HttpSession#getId() as parameter to the applet in question:
<param name="jsessionid" value="${pageContext.session.id}">
Then, in the Applet connect the Servlet as follows:
String jsessionid = getParameter("jsessionid");
URL servlet = new URL(getCodeBase(), "servleturl;jsessionid=" + jsessionid);
URLConnection connection = servlet.openConnection();
// ...
Here servleturl obviously should match servlet's url-pattern in web.xml. You can alternatively also set a Cookie request header using URLConnection.setRequestProperty().
Finally, in the Servlet, to get and store client specific data, do as follows:
// Store:
request.getSession().setAttribute("data", data);
// Get:
Data data = (Data) request.getSession().getAttribute("data");
Hope this helps.
From your question it seems that your servlet contains state. Every applet will have a session with the servlet container which your servlet can access. You can create an object that holds the state per session and place that object as attribute in the session of the caller. This way the servlet container is free to share one servlet instance among many clients.
The usual way to handle instance-specific actions is to have information stored in the session scope made available by the servlet container, not by having information stored in the servlet itself.
For it to work, your applet must correctly send cookies or the JSESSIONID attribute as provided by the web container or the applet must request a instance specific URL inside the servlet.
I would suggest you familiarize yourself further with the Servlet API specification in order to learn more about what is available to you.
Also note that some application servers support the notion of "clients" which are programs invoked with code served from the application server which have direct access to the inside of the application server code. The actual communication is handled by libraries also provided by the applcation server so this is simple. Glassfish and Trifork can do this.
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.