Cleanest way to initialize a session variable in a servlet - java

What would be a clean and neat way to initialize a session variable in a servlet, considering session variables are not inherently thread-safe?
Consider the following code:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// NOT thread safe
if( request.getSession().getAttribute("mySessionVariable") == null )
request.getSession().setAttribute("mySessionVariable", new AtomicInteger(0));
((AtomicInteger) request.getSession().getAttribute("mySessionVariable")).incrementAndGet();
}
In the above code, there is a chance that two threads will concurrently see that the variable is null, and therefor both initialize it to 0. To avoid this, of course one could use a synchronized block:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
synchronized(this){
if( request.getSession().getAttribute("mySessionVariable") == null )
request.getSession().setAttribute("mySessionVariable", new AtomicInteger(0));
((AtomicInteger) request.getSession().getAttribute("mySessionVariable")).incrementAndGet();
}
}
But I'm wondering, are there any cleaner and "prettier" ways of achieving the same thing?

When the user Session is created, you could add the mySessionVariable attribute in the session :
session.setAttribute("mySessionVariable", new AtomicInteger(0));
If you don't handle explicitly the creation of the Session in a servlet, you can do the initialization with HttpSessionListener in the public void sessionCreated(HttpSessionEvent arg0) method.
So, this code becomes thread safe since you don't need to initialize the attribute any longer and AtomicInteger sets atomically the int value, :
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException{
((AtomicInteger)request.getSession().getAttribute("mySessionVariable")).incrementAndGet();
}

Related

Passing Session parameters to Thread

I wanted to do two tasks simultaneously in web project in the Servlet once the user clicks on submit button
1. Run a code to trigger some backend activity
2. Display a webpage to the user.
I tried with the code sample here
As I have few session attributes being set I need to set this in one of the thread. I tried putting point one in one thread and point two in second but variables are not getting resolved to the thread from doPost() method.
Servlet:
public class JOBRUN extends HttpServlet{
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AESASNewOpenPeriod=request.getParameter("AESASNewOpenPeriod");
ScriptRunOption = Integer.parseInt(request.getParameter("AESASJOBRUNOPTION"));
HttpSession session=request.getSession();
String Stream="aaaa";
session.setAttribute("AEStream", Stream);
//Do Job 1 (Update table)
//Do Job 2 (Display webpage to user)
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
You can create an anonymous thread (if you don't want a dedicated Thread class for ) Job 1.
new Thread(new Runnable() {
Session localSession = session;// assign the session object to thread variable.
public void run() {
// you can access localSession here. and do the JOB 1
}
}).start();// this will run asynchrously(non blocking).
Also if you want to pass only some attributes to do the Job 1(i,e if u don't want to change the session), you can pass relevant attributes only.For example
String threadStream = session.setAttribute("AEStream");//local memeber variable inside anonymous thread
Then from the next line after thread, you can do Job 2.
Note: If you mean something else- running an asychrounous worker thread with request , you start wit Servlet 3.x AsyncContext

Create method outside POST method is servlet

Hi I have created a private method inside the servlet.
The method will be called from the post method. My questions is, will it be threadsafe since it will be called via ajax by many many user?
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
callPrivateMethod();
}
private static void callPrivateMethod(){
}
As long as callPrivateMethod() is thread safe, i.e. it does not use a class member variable, then you will be fine.
No, your private method won't be thread safe as doPost is not thread safe in servlet.
It is static method with immutable objects as parameters in your case (no parameters) is Thread safe
Servlets should be stateless. Hawever, if you need to use class members or any other thread-unsafe element, you always could use "synchronized" sentences.
The servlet is instanced only once at loading. If you want to make call to callPrivateMethod() thread safe, you can put it inside a synchronized block.
private Object mutex = new Object();
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
synchronized (mutex){
callPrivateMethod();
}
}
private static void callPrivateMethod(){
}

doGet calls doPost OR vise versa

I've bring this example from a book:
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
ServletOutputStream out = resp.getOutputStream();
out.setContentType(“text/html”);
out.println("<html><h1>Output to Browser</h1>");
out.println("<body>Written as html from a Servlet<body></html>");
}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
doPost(req, resp); //call doPost() for flow control logic.
}
Questions:
Why doPost can't call doGet?
What does flow control mean?
The example mean all the request whether it is GET or POST it will be going to be handle by the single method.You can move the doPost code to doGet and call doGet method from doPost,thr will be no issue.
You can call doGet() from doPost() and vice-versa. No issues. But, you should not do such things. Both the methods have different purpose.
Ideally, the pre-processing task has to be done in doGet() method. For example, suppose you want to validate where a user has logged in or not, before forwarding the request to the user home page, that you would do in doGet() method. While the post-processing task has to be done in doPost(). For example, when a user submits a form, then you would like to get the values that are in the form, and validate them. Such logic go in doPost() method.
You should not mix them. If they were the same, there wouldn't be need of both methods. For more details on those methods see our servlet tag wiki.
I know it's old, but still...
About Q1, everybody gives a really interesting and exact answer but the truth is out there... Just take a look at this "minified" code, you will understand:
protected void doGet(HttpServletRequest req, HttpServletResponse resp){
doPost(req, resp);
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp){
//
//Do something
//
//Can I call doGet() ?
}
Yes it is an infinite loop if you do so: doPost call doGet that call doPost that call doGet...
If you need the doGet calls doPost, then it is better to use the "service".
protected void service((HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//do something you need
}

Can i override doPost method of servlet many times

I am calling another servlet from main servlet,It would have been easy by implementing jsp ,but my aim for this experiment is to use only servlet,pls help
You can't override a method more than once in a class, so you can't override the doPost several times.
If you mean overload it, there's not a good reason for doing that. In the end, only one of those methods will be called by the Servlet Container.
If you want to handle more than 1 kind of requests using a single Servlet, you can send a parameter indicating the action you will perform. For example:
#WebServlet("/person")
public class PersonCRUDServlet extends HttpServlet {
private static final String ADD = "add";
private static final String DELETE = "delete";
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String action = request.getParameter("action");
//using if assuming you work with Java SE 6
if (ADD.equals(action)) {
add(request, response);
} else
if (DELETE.equals(action)) {
delete(request, response);
} else {
//submitted action can't be interpreted
//or no action was submitted
errorForward(request, response);
}
}
private void add(HttpServletRequest request, HttpServletResponse response) {
//handle logic for add operation...
}
private void delete(HttpServletRequest request, HttpServletResponse response) {
//handle logic for delete operation...
}
private void errorForward(HttpServletRequest request, HttpServletResponse response) {
//handle logic for delete operation...
}
}
Note that this is a lot of work to handle manually (this is a reason why Java Web MVC frameworks exists). You can also refer to
Java EE web development, where do I start and what skills do I need?
What to learn for making Java web applications in Java EE 6?

Java Exception handling and HttpSession

As part of exception handling, I want to print data from HTTP session like below:
try{
//business logic
} catch(Exception ex){
String user = session.get("userId"); //get user from HTTP Session.
log.info("Exception when processign the user "+user);
}
My question is do I get the correct UserId for which exception occurred since there will be mulitple threads updating the session?
The HttpSession is not shared among clients. So that part is safe already. The remnant depends on your own code as to obtaining and handling the HttpSession instance. If you're for example assinging the HttpSession as an instance variable of an application wide class, like the servlet itself, then it is indeed not thread safe as it might be overridden by another request at the moment you're accessing it.
public class SomeServlet extends HttpServlet {
private HttpSession session;
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
session = request.getSession();
// ...
Object object = session.getAttribute("foo"); // Not threadsafe!
}
See also:
How do servlets work? Instantiation, sessions, shared variables and multithreading
Session will be unique for each user (if code is according to standard).
Here is sun tutorial on how session works

Categories