jetty hangs on when accessing ServletRequest methods in async context - java

I am running the code given in answer to this question-
Servlet-3 Async Context, how to do asynchronous writes?
Instead of response.getWriter().write(some_big_data); I've changed that line to
ServletRequest req= ctx.getRequest();
response.getWriter().write(req.getContentType());
Now, request is just timing out. How can I access request object?

I'm assuming you are having problems using that code snippet from within your own thread after a startAsync() call.
Per the Servlet 3.0 spec, section 2.3.3.4, access to the Request and Response objects are not thread-safe. In fact, depending on the state of the object lifecycle, the request and response objects can even be recycled.
It is encouraged that you grab what you need from the Request and Response objects before you startAsync() and use those references from your own thread.
In other words, your use of ctx.getRequest() and response.getWriter() should be done before you startAsync()

Related

request.setAttribute("name",name); is not working when project is run in 2nd time [duplicate]

Suppose, I have a webserver which holds numerous servlets. For information passing among those servlets I am setting session and instance variables.
Now, if 2 or more users send request to this server then what happens to the session variables?
Will they all be common for all the users or they will be different for each user?
If they are different, then how was the server able to differentiate between different users?
One more similar question, if there are n users accessing a particular servlet, then this servlet gets instantiated only the first time the first user accessed it or does it get instantiated for all the users separately?
In other words, what happens to the instance variables?
ServletContext
When the servlet container (like Apache Tomcat) starts up, it will deploy and load all its web applications. When a web application is loaded, the servlet container creates the ServletContext once and keeps it in the server's memory. The web app's web.xml and all of included web-fragment.xml files is parsed, and each <servlet>, <filter> and <listener> found (or each class annotated with #WebServlet, #WebFilter and #WebListener respectively) will be instantiated once and be kept in the server's memory as well, registred via the ServletContext. For each instantiated filter, its init() method is invoked with a new FilterConfig argument which in turn contains the involved ServletContext.
When a Servlet has a <servlet><load-on-startup> or #WebServlet(loadOnStartup) value greater than 0, then its init() method is also invoked during startup with a new ServletConfig argument which in turn contains the involved ServletContext. Those servlets are initialized in the same order specified by that value (1 is 1st, 2 is 2nd, etc). If the same value is specified for more than one servlet, then each of those servlets is loaded in the same order as they appear in the web.xml, web-fragment.xml, or #WebServlet classloading. In the event the "load-on-startup" value is absent, the init() method will be invoked whenever the HTTP request hits that servlet for the very first time.
When the servlet container is finished with all of the above described initialization steps, then the ServletContextListener#contextInitialized() will be invoked with a ServletContextEvent argument which in turn contains the involved ServletContext. This will allow the developer the opportunity to programmatically register yet another Servlet, Filter or Listener.
When the servlet container shuts down, it unloads all web applications, invokes the destroy() method of all its initialized servlets and filters, and all Servlet, Filter and Listener instances registered via the ServletContext are trashed. Finally the ServletContextListener#contextDestroyed() will be invoked and the ServletContext itself will be trashed.
HttpServletRequest and HttpServletResponse
The servlet container is attached to a web server that listens for HTTP requests on a certain port number (port 8080 is usually used during development and port 80 in production). When a client (e.g. user with a web browser, or programmatically using URLConnection) sends an HTTP request, the servlet container creates new HttpServletRequest and HttpServletResponse objects and passes them through any defined Filter in the chain and, eventually, the Servlet instance.
In the case of filters, the doFilter() method is invoked. When the servlet container's code calls chain.doFilter(request, response), the request and response continue on to the next filter, or hit the servlet if there are no remaining filters.
In the case of servlets, the service() method is invoked. By default, this method determines which one of the doXxx() methods to invoke based off of request.getMethod(). If the determined method is absent from the servlet, then an HTTP 405 error is returned in the response.
The request object provides access to all of the information about the HTTP request, such as its URL, headers, query string and body. The response object provides the ability to control and send the HTTP response the way you want by, for instance, allowing you to set the headers and the body (usually with generated HTML content from a JSP file). When the HTTP response is committed and finished, both the request and response objects are recycled and made available for reuse.
HttpSession
When a client visits the webapp for the first time and/or the HttpSession is obtained for the first time via request.getSession(), the servlet container creates a new HttpSession object, generates a long and unique ID (which you can get by session.getId()), and stores it in the server's memory. The servlet container also sets a Cookie in the Set-Cookie header of the HTTP response with JSESSIONID as its name and the unique session ID as its value.
As per the HTTP cookie specification (a contract any decent web browser and web server must adhere to), the client (the web browser) is required to send this cookie back in subsequent requests in the Cookie header for as long as the cookie is valid (i.e. the unique ID must refer to an unexpired session and the domain and path are correct). Using your browser's built-in HTTP traffic monitor, you can verify that the cookie is valid (press F12 in Chrome / Firefox 23+ / IE9+, and check the Net/Network tab). The servlet container will check the Cookie header of every incoming HTTP request for the presence of the cookie with the name JSESSIONID and use its value (the session ID) to get the associated HttpSession from server's memory.
The HttpSession stays alive until it has been idle (i.e. not used in a request) for more than the timeout value specified in <session-timeout>, a setting in web.xml. The timeout value defaults to 30 minutes. So, when the client doesn't visit the web app for longer than the time specified, the servlet container trashes the session. Every subsequent request, even with the cookie specified, will not have access to the same session anymore; the servlet container will create a new session.
On the client side, the session cookie stays alive for as long as the browser instance is running. So, if the client closes the browser instance (all tabs/windows), then the session is trashed on the client's side. In a new browser instance, the cookie associated with the session wouldn't exist, so it would no longer be sent. This causes an entirely new HttpSession to be created, with an entirely new session cookie being used.
In a nutshell
The ServletContext lives for as long as the web app lives. It is shared among all requests in all sessions.
The HttpSession lives for as long as the client is interacting with the web app with the same browser instance, and the session hasn't timed out at the server side. It is shared among all requests in the same session.
The HttpServletRequest and HttpServletResponse live from the time the servlet receives an HTTP request from the client, until the complete response (the web page) has arrived. It is not shared elsewhere.
All Servlet, Filter and Listener instances live as long as the web app lives. They are shared among all requests in all sessions.
Any attribute that is defined in ServletContext, HttpServletRequest and HttpSession will live as long as the object in question lives. The object itself represents the "scope" in bean management frameworks such as JSF, CDI, Spring, etc. Those frameworks store their scoped beans as an attribute of its closest matching scope.
Thread Safety
That said, your major concern is possibly thread safety. You should now know that servlets and filters are shared among all requests. That's the nice thing about Java, it's multithreaded and different threads (read: HTTP requests) can make use of the same instance. It would otherwise be too expensive to recreate, init() and destroy() them for every single request.
You should also realize that you should never assign any request or session scoped data as an instance variable of a servlet or filter. It will be shared among all other requests in other sessions. That's not thread-safe! The below example illustrates this:
public class ExampleServlet extends HttpServlet {
private Object thisIsNOTThreadSafe;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Object thisIsThreadSafe;
thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
}
}
See also:
What is the difference between JSF, Servlet and JSP?
Best option for Session management in Java
Difference between / and /* in servlet mapping url pattern
doGet and doPost in Servlets
Servlet seems to handle multiple concurrent browser requests synchronously
Why Servlets are not thread Safe?
Sessions
In short: the web server issues a unique identifier to each visitor on his first visit. The visitor must bring back that ID for him to be recognised next time around. This identifier also allows the server to properly segregate objects owned by one session against that of another.
Servlet Instantiation
If load-on-startup is false:
If load-on-startup is true:
Once he's on the service mode and on the groove, the same servlet will work on the requests from all other clients.
Why isn't it a good idea to have one instance per client? Think about this: Will you hire one pizza guy for every order that came? Do that and you'd be out of business in no time.
It comes with a small risk though. Remember: this single guy holds all the order information in his pocket: so if you're not cautious about thread safety on servlets, he may end up giving the wrong order to a certain client.
Session in Java servlets is the same as session in other languages such as PHP. It is unique to the user. The server can keep track of it in different ways such as cookies, url rewriting etc. This Java doc article explains it in the context of Java servlets and indicates that exactly how session is maintained is an implementation detail left to the designers of the server. The specification only stipulates that it must be maintained as unique to a user across multiple connections to the server. Check out this article from Oracle for more information about both of your questions.
Edit There is an excellent tutorial here on how to work with session inside of servlets. And here is a chapter from Sun about Java Servlets, what they are and how to use them. Between those two articles, you should be able to answer all of your questions.
When the servlet container (like Apache Tomcat) starts up, it will read from the web.xml file (only one per application) if anything goes wrong or shows up an error at container side console, otherwise, it will deploy and load all web applications by using web.xml (so named it as deployment descriptor).
During instantiation phase of the servlet, servlet instance is ready but it cannot serve the client request because it is missing with two pieces of information:
1: context information
2: initial configuration information
Servlet engine creates servletConfig interface object encapsulating the above missing information into it
servlet engine calls init() of the servlet by supplying servletConfig object references as an argument. Once init() is completely executed servlet is ready to serve the client request.
Q) In the lifetime of servlet how many times instantiation and initialization happens ??
A)only once (for every client request a new thread is created)
only one instance of the servlet serves any number of the client request ie, after serving one client request server does not die. It waits for other client requests ie what CGI (for every client request a new process is created) limitation is overcome with the servlet (internally servlet engine creates the thread).
Q)How session concept works?
A)whenever getSession() is called on HttpServletRequest object
Step 1: request object is evaluated for incoming session ID.
Step 2: if ID not available a brand new HttpSession object is created and its corresponding session ID is generated (ie of HashTable) session ID is stored into httpservlet response object and the reference of HttpSession object is returned to the servlet (doGet/doPost).
Step 3: if ID available brand new session object is not created session ID is picked up from the request object search is made in the collection of sessions by using session ID as the key.
Once the search is successful session ID is stored into HttpServletResponse and the existing session object references are returned to the doGet() or doPost() of UserDefineservlet.
Note:
1)when control leaves from servlet code to client don't forget that session object is being held by servlet container ie, the servlet engine
2)multithreading is left to servlet developers people for implementing ie., handle the multiple requests of client nothing to bother about multithread code
Inshort form:
A servlet is created when the application starts (it is deployed on the servlet container) or when it is first accessed (depending on the load-on-startup setting)
when the servlet is instantiated, the init() method of the servlet is called
then the servlet (its one and only instance) handles all requests (its service() method being called by multiple threads). That's why it is not advisable to have any synchronization in it, and you should avoid instance variables of the servlet
when the application is undeployed (the servlet container stops), the destroy() method is called.
Sessions - what Chris Thompson said.
Instantiation - a servlet is instantiated when the container receives the first request mapped to the servlet (unless the servlet is configured to load on startup with the <load-on-startup> element in web.xml). The same instance is used to serve subsequent requests.
The Servlet Specification JSR-315 clearly defines the web container behavior in the service (and doGet, doPost, doPut etc.) methods (2.3.3.1 Multithreading Issues, Page 9):
A servlet container may send concurrent requests through the service
method of the servlet. To handle the requests, the Servlet Developer
must make adequate provisions for concurrent processing with multiple
threads in the service method.
Although it is not recommended, an alternative for the Developer is to
implement the SingleThreadModel interface which requires the container
to guarantee that there is only one request thread at a time in the
service method. A servlet container may satisfy this requirement by
serializing requests on a servlet, or by maintaining a pool of servlet
instances. If the servlet is part of a Web application that has been
marked as distributable, the container may maintain a pool of servlet
instances in each JVM that the application is distributed across.
For servlets not implementing the SingleThreadModel interface, if the
service method (or methods such as doGet or doPost which are
dispatched to the service method of the HttpServlet abstract class)
has been defined with the synchronized keyword, the servlet container
cannot use the instance pool approach, but must serialize requests
through it. It is strongly recommended that Developers not synchronize
the service method (or methods dispatched to it) in these
circumstances because of detrimental effects on performance
No. Servlets are not Thread safe
This is allows accessing more than one threads at a time
if u want to make it Servlet as Thread safe ., U can go for
Implement SingleThreadInterface(i)
which is a blank Interface there is no
methods
or we can go for synchronize methods
we can make whole service method as synchronized by using synchronized
keyword in front of method
Example::
public Synchronized class service(ServletRequest request,ServletResponse response)throws ServletException,IOException
or we can the put block of the code in the Synchronized block
Example::
Synchronized(Object)
{
----Instructions-----
}
I feel that Synchronized block is better than making the whole method
Synchronized
As is clear from above explanations, by implementing the SingleThreadModel, a servlet can be assured thread-safety by the servlet container. The container implementation can do this in 2 ways:
1) Serializing requests (queuing) to a single instance - this is similar to a servlet NOT implementing SingleThreadModel BUT synchronizing the service/ doXXX methods; OR
2) Creating a pool of instances - which's a better option and a trade-off between the boot-up/initialization effort/time of the servlet as against the restrictive parameters (memory/ CPU time) of the environment hosting the servlet.

jersey ws 2.0 #suspended AsyncResponse, what does it do?

I am analyzing some jersey 2.0 code and i have a question on how the following method works:
#Stateless
#Path("/mycoolstuff")
public class MyEjbResource {
…
#GET
#Asynchronous //does this mean the method executes on child thread ?
public void longRunningOperation(#Suspended AsyncResponse ar) {
final String result = executeLongRunningOperation();
ar.resume(result);
}
private String executeLongRunningOperation() { … }
}
Lets say im at a web browser and i type in www.mysite/mycoolstuff
this will execute the method but im not understanding what the asyncResponse is used for neither the #Asynchronous annotation. From the browser how would i notice its asychnronous ? what would be the difference in removing the annotation ? Also the suspended annotation after reading the documentation i'm not clear its purpose.
is the #Asynchronous annotation simply telling the program to execute this method on a new thread ? is it a convenience method for doing "new Thread(.....)" ?
Update: this annotation relieves the server of hanging onto the request processing thread. Throughput can be better. Anyway from the official docs:
Request processing on the server works by default in a synchronous processing mode, which means that a client connection of a request is processed in a single I/O container thread. Once the thread processing the request returns to the I/O container, the container can safely assume that the request processing is finished and that the client connection can be safely released including all the resources associated with the connection. This model is typically sufficient for processing of requests for which the processing resource method execution takes a relatively short time. However, in cases where a resource method execution is known to take a long time to compute the result, server-side asynchronous processing model should be used. In this model, the association between a request processing thread and client connection is broken. I/O container that handles incoming request may no longer assume that a client connection can be safely closed when a request processing thread returns. Instead a facility for explicitly suspending, resuming and closing client connections needs to be exposed. Note that the use of server-side asynchronous processing model will not improve the request processing time perceived by the client. It will however increase the throughput of the server, by releasing the initial request processing thread back to the I/O container while the request may still be waiting in a queue for processing or the processing may still be running on another dedicated thread. The released I/O container thread can be used to accept and process new incoming request connections.
#Suspended have more definite if you used it, else it will not make any difference of using it.
Let's talk about benefits of it:
#Suspended will pause/Suspend the current thread until it gets response,by default #NO_TIMEOUT no suspend timeout set. So it doesn't mean your request response (I/O)thread will get free and be available for other request.
Now Assume you want your service to be a response with some specific time, but the method you are calling from resource not guarantee the response time, then how will you manage your service response time? At that time, you can set suspend timeout for your service using #Suspended, and even provide a fall back response when time get exceed.
Below is some sample of code for setting suspend/pause timeout
public void longRunningOperation(#Suspended AsyncResponse ar) {
ar.setTimeoutHandler(customHandler);
ar.setTimeout(10, TimeUnit.SECONDS);
final String result = executeLongRunningOperation();
ar.resume(result);
}
for more details refer this
The #Suspended annotation is added before an AsyncResponse parameter on the resource method to tell the underlying web server not to expect this thread to return a response for the remote caller:
#POST
public void asyncPost(#Suspended final AsyncResponse ar, ... <args>) {
someAsyncMethodInYourServer(<args>, new AsyncMethodCallback() {
#Override
void completed(<results>) {
ar.complete(Response.ok(<results>).build());
}
#Override
void failed(Throwable t) {
ar.failed(t);
}
}
}
Rather, the AsyncResponse object is used by the thread that calls completed or failed on the callback object to return an 'ok' or throw an error to the client.
Consider using such asynchronous resources in conjunction with an async jersey client. If you're trying to implement a ReST service that exposes a fundamentally async api, these patterns allow you to project the async api through the ReST interface.
We don't create async interfaces because we have a process that takes a long time (minutes or hours) to run, but rather because we don't want our threads to ever sleep - we send the request and register a callback handler to be called later when the result is ready - from milliseconds to seconds later - in a synchronous interface, the calling thread would be sleeping during that time, rather than doing something useful. One of the fastest web servers ever written is single threaded and completely asynchronous. That thread never sleeps, and because there is only one thread, there's no context switching going on under the covers (at least within that process).
The #suspend annotation makes the caller actually wait until your done work. Lets say you have a lot of work to do on another thread. when you use jersey #suspend the caller just sits there and waits (so on a web browser they just see a spinner) until your AsyncResponse object returns data to it.
Imagine you had a really long operation you had to do and you want to do it on another thread (or multiple threads). Now we can have the user wait until we are done. Don't forget in jersey you'll need to add the " true" right in the jersey servlet definition in web.xml to get it to work.

Jersey Client proper way to execute parallel POST requests

I'm looking for the proper way of executing POST requests using jersey client (with apache http client 4.x)
Since Client instance and WebResource instance are thread-safe, the natural way of coding the method will be:
public AuthorizedAccount createAuthTokenFromUserPass(Credentials credentials)
throws AuthenticationServiceClientException {
ClientResponse response = resource.accept("application/x-protobuf").post(
ClientResponse.class, credentials);
return getAuthorizedAccountFromResponse(response);
}
ClientResponse instance is properly released.
When this method is executed from multiple threads, it ends-up by POSTing same credential instance to the server, for each thread.
A solution will be to synchronise the method, but will end-up by executing the POSTs in sequence.
Is there a different way to do it? (avoiding the re-creation of Client instance)
After spending a lot of time trying to figure out what is not working properly, I found out that the issue was not really in jersey client implementation but in my own code. I have used a custom implementation of MessageBodyWriter, where I was not careful enough. I did not read properly the contract of the interface. I have shared an instance variable between call of getSize() and writeTo(), and the MassageBodyWriter is reused.

Call HttpServletResponse a second time

I'm trying to set up a servlet that I can use to call webservices asynchronously. For the most part, it is working fine. I have a servlet with a doGet method and a js that calls it. I have a callback method in the js that the servlet correctly calls when it has finished doing its thing.
The complication is that one of the web services I am calling is also asynchronous, and I would like to be able to essentially call the js callback method a second time after the asynchronous ws callback has finished. For example, if you have a status field, when you call the synchronous web service, it immediately updates to "Beginning Synchronous Call" and then when the servlet callback arrives it changes to the callback value, which is the result of the web service.
When you call the asynchronous web service, the update field immediately updates to "Beginning Asynchronous Call", and shortly receives the first callback from the servlet indicating that the web service has been requested, so we update the field to "Processing Web Service" or whatever. The problem is that once the web service finishes and calls back to the servlet, I can't seem to figure out how to send the result to the js callback method.
I'm pretty new at AJAX and servlets, so maybe this is a horrible way to accomplish what I want.
The web services are both being called in the Servlet, mostly using Netbeans auto-generated WS calls. The WS calls themselves work fine, but once I get the result of the asynchronous WS, I am stuck inside of the handleResponse method of the webservice callback and no longer have any reference to the response element for the document I want to update.
I tried to store the original response variable as a static member variable and use it in the handleResponse method like so:
javax.xml.ws.AsyncHandler<WsClients.Op11Response> asyncHandler = new javax.xml.ws.AsyncHandler<WsClients.Op11Response>() {
public void handleResponse(javax.xml.ws.Response<WsClients.Op11Response> asyncResponse) {
try {
storedResponse.setContentType("text/xml");
String returnString = asyncResponse.get().getReturn();
storedResponse.getWriter().write("<returnData><content>"
+ returnString + "</content></returnData>");
} catch (Exception ex) {
}
}
};
This will not compile with a debugger attached and does not seem to be able to assign a reference anyway.
Is there a better way to do this?
The nature of HTTP is that you cannot send anything back to the client unless client requested this information either by polling or by keeping the connection open.
The operation to start the asynchronous call ends immediately and you need to return from the servlet doGet method (while technically you can stay in the servlet call until your async call finishes I wouldn't recommend that as it ties up the server resources. It is generally a good practice to return from the servlet as soon as you can).
The best course of action would be:
Have internal data structure (e.g. HashMap with appropriate synchronization) to hold the asynchronous calls that are executing.
When you start a new call, assign it pseudo-random key and return it from the initial call.
Using the above key, have browser-side javascript AJAX calls periodically poll the status of the call and display the results.
Do not forget to clean up finished or stale calls (for example by running a timer thread).
When you comfortable with the polling implementation in step 3 above, you may want to consider Comet, a.k.a. long poll to replace client-side polling.
Servlet cannot send response again. HTTP protocol is synchronous, and only client can initiate a request-response exchange.
For async updates you need to perform polling from the client side to the server side, and accumulate messages on the server side (in the sessions) until client picks them up or they expire.

How to clone a detached HttpServletRequest and HttpServletResponse provided by the Servlet Container?

I want to implement the following logic:
when I receive HttpServletRequeset and HttpServletResponse in main servlet's doService method (in the main web Container thread),I start A,B,C three threads (thread managed by my own program) to process other servlet in parallel mode,and then join each response from these servlet in main thread,and if one of my own thread (assume A thread) work slow,the main thread will finish,so main response will return to user.and the A thread must continue work properly,I will request the response of the A thread using AJAX in browser side later.
So,I want to clone the HttpServlettRequest and HttpServletResponse provided by the Servlet Container,and the cloned request and response must be detached(When container's HttpServletTrequest and HttpServletResponse finished,the cloned request and reponse still work properly).
The behave of the cloned request and response must be same as the Container's from my code's view.It can be followed and included.
Any idea?
Thanks very much!
L.J.W
Cloning HTTP request and response is possible via HttpServletResponseWrapper class http://docs.oracle.com/javaee/1.3/api/javax/servlet/http/HttpServletResponseWrapper.html. You can find an example of usage on Sun documentation https://web.archive.org/web/20120626033905/http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Servlets8.html.
Notice this was a workaround from (at that time) Sun to address this problem as it was never planned that you could modify request and response information before committed.
You can use the wrapper to make a copy of Http information and the pass it to a different thread.
Sounds like you need to create classes to act as a delegate to the HttpRequest and HttpResponse objects and then pass a reference to on to a Runnable object to process.
There are certain operations that can only be done once to an HttpRequest object ( reading from the inputstream springs to mind ), the delegate class would have to cater for this.
Not sure what you're going to do if the A, B and C threads make conflicting changes to the HttpResponse object though.
I think I'd prefer to not pass the HttpResponse object through to the processing threads and leave the logic for populating the response in the controlling servlet class
I think you are asking to much of the HttpServletRequest. Once a request has been completed you shouldn't count on the request object being of any use. I don't recommend threading inside a J2EE container in most cases anyway but that's a different issue.
If you must handle the request in parallel I recommend you extract the data you need from the request object and send that to your threads and make the worker threads mostly Servlet ignorant with the exception of the HttpSession where they could store their computed values for the Ajax retrieval.
The request and response classes aren't designed to be cloned or accessed from multiple threads. If you try to do so, you're bound to run into problems. I suggest that you re-think your requirements.

Categories

Resources