0

This is the sample code, illustrating the usage of instance variable and request attribute:

    @WebServlet(name = "Upload", urlPatterns = {"/upload"})
    @MultipartConfig()
    public class Upload extends HttpServlet {

    private String txt;

    protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       try{
        String txt2 = (String) request.getAttribute("txt2");
        //txt and txt2 variables are available for processing.
         ..........
          } finally {
        txt = null;//Prepare variable for next request.
       }
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            .....
        request.setAttribute("txt2", someValue);
        //vs
        txt = someValue;

    processRequest(request, response);
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            .....
     processRequest(request, response);
      }
    }

Now I know that instance variables should be never declared in servlets, because the same servlet is shared between concurent requests. But what about request attributes? Is it safe to use them?

Ernestas Gruodis
  • 8,567
  • 14
  • 55
  • 117

2 Answers2

1

Not sure what you mean by initializing variables. On a servlet you mean or where?

Depending on what you need to do, maybe there are APIs involved in which you don't have control about the contracts (since they are not your APIs).

For example, when requesting is being processed by a filter chain. Maybe one filter is interested on data being set by a filter executed previously in the chain. You don't have means to pass data on the filter chain contract. Request attribute might be an option. Playing with ThreadLocal might be another, but it has performance implications and is not always suitable.

Another example, maybe you forward one request from a servlet to another. Again, you will not have an option to play with whatever member variable you define.

Also, if you were thinking on adding member variables on a servlet, remember Servlets are not thread-safe. What would you do? synchronize request processing, only one request being processed per servlet?

albert_nil
  • 1,648
  • 7
  • 9
  • Let's think it this way - just one servlet, without forwardings and other filters. And the page has several input fields and uses POST method addressed to the same servlet. Perhaps it is not logical to use attributes here? The request scope only. – Ernestas Gruodis Aug 05 '17 at 22:40
  • I think I found the answer [here](https://stackoverflow.com/questions/9555842/why-servlets-are-not-thread-safe) - it is about the thread safety, and it states, that *"You'd need to fix the servlet code as such that request or session scoped data is never assigned as an instance variable of the servlet."* And: *"Variables declared in the methods are thread safe..."* – Ernestas Gruodis Aug 05 '17 at 23:08
  • that's what i stated at the end of my comment. servlets are not thread-safe, so you cannot use member variables without protecting thread safety. and making them so would break scalability on request processing – albert_nil Aug 05 '17 at 23:12
  • So it means the only way/the right way is to use request scope attributes instead of instance variables? – Ernestas Gruodis Aug 05 '17 at 23:13
  • the only way to what? that's the point you don't specify. you have local variables you can use on your method. You can use whatever API you define to call other components of your application etc – albert_nil Aug 05 '17 at 23:15
  • I've uploaded sample code. – Ernestas Gruodis Aug 05 '17 at 23:33
  • 1
    the sample code you provide does not need request attribute at all. Just change method signature of processRequest to allow more parameters there, then you can solve that by local variables. As said, Request Attributes main reason is to pass information when you are dealing with APIs for which you don't have control and do not expose any other way to pass parameters. – albert_nil Aug 06 '17 at 06:26
  • Yes, thats the good point. Thanks for help indeed. – Ernestas Gruodis Aug 06 '17 at 09:00
1

Your servlet is going to serve hundreds on concurrent request each one of them will use same shared instance of the servlet, therefore using private instance variable will lead to inconsistent behavior. Unless you synchronize access to it, which will lead to greater contention on access to this private field, therefore slowing down response time, producing bottleneck.

While storing attribute within binded to single request will allow you to avoid such problem, moreover it was designed to overcome issues similar to yours.

Artem Barger
  • 40,769
  • 9
  • 59
  • 81