Publishing attributes via ServletContext#setAttribute is thread-safe! This can be derived from the Java Servlet Specification, chapter 4.5: (…) Any attribute bound into a context is available to any other servlet that is part of the same Web application.(…).

(Reason: Making objects available to other servlets means also to make them available to other threads. This is only possible, if proper synchronization is used, so synchronization is mandatory for ServletContext#setAttribute).

So the same is also true for reading published attributes via ServletContext#getAttribute.

Note
But if an object like a HashMap is shared between different threads, the developer must ensure that this shared object itself is accessed in a proper, thread-safe way! Using a ConcurrentHashMap is a possible solution, but does not solve the race condition when the attribute is initialized, as the null check will not be atomic.

ConcurrentMap<String, Object> shared = (...)servletContext.getAttribute("sharedData");
if (shared == null) {
    shared = new ConcurrentHashMap<>();
    servletContext.setAttribute("sharedData", shared);
}

Context is stored at the application level scope where as request is stored at page level.If you use an absolute path(full path) such as (“http://www.computerhope.com/jargon/a/index.jsp”), there is no difference.

If you use relative path, you must use HttpServletRequest.getRequestDispatcher(). ServletContext.getRequestDispatcher() doesn’t allow it.

RequestDispatcher dispatcher = 
        request.getRequestDispatcher("index.jsp");
    dispatcher.forward( request, response ); 

Will forward the request to the page http://example.com/myapp/subdir/index.jsp

request.getSession() will return a current session. if current session will not exist the it will create a new one.

request.getSession(true) will return current session. If current session will not exist then it will create new session.

So basically there is not difference between both method.

request.getSession(false) will return current session if current session will not exist then it will NOT create new session.

In JSP new session is created by default, if non present, so you will always get non null session. You can disable that by adding following page directive to your page:

 <%@ page session="false" %>

JSPs create a session unless explicitly configured not to.Instead of checking for the existence of a session check for a value in the session.

When session calls invalidate() it removes that session from server context and all associated data with that session.When you make new request it creates new one and so you see null as the data because new session doesn’t have data in it

You should check for a logical attribute inside session to validate it user is logged in or not, instead of session itself

getSession(false) – will return current session if current session will not exist then it will NOT create new session.

Calling session.invalidate() removes the session from the registry. Calling getSession(false) afterwards will return null (note that getSession() or getSession(true) will create a new session in this case). In addition all session attributes bound to the session are removed. However if your code still has references to the session or any of its attributes then these will still be accessible:

  if(request.getSession() != null)
  {
    System.out.println("Session is Created for Each Request with Unique Session ID");
  }

  HttpSession session = request.getSession();
  session.setAttribute("Name", "Mugil");

  String Name = (String) session.getAttribute("Name");
  System.out.println(session.getId());
  System.out.println(session.getAttribute("Name"));

  session.invalidate();

  if(session == null)
  {
    System.out.println("session is Null");
  }

  if(request.getSession(false) == null)
  {
    System.out.println("request.getSession(false) is Null");
  }

  if(request.getSession() != null)
  {
    System.out.println("request.getSession() is Not Null");
  }

  System.out.println(session.getId());
  System.out.println(Name);    

Output

Session is Created for Each Request with Unique Session ID
7A46A65BCDC436030AA10385998F0272
Mugil
request.getSession(false) is Null
request.getSession() is Not Null
7A46A65BCDC436030AA10385998F0272
Mugil

Note
Session is created for each request. So if you are invalidating a session of login page in the next page you should check for existence of userName as session attribute instead of checking session is null because session can never be null

 <%@ page session="false" %>

One reason would be performance and memory. If you have a page that doesn’t need to be involved in a session (like say, an about.jsp or faq.jsp) then the default behaviour of involving every JSP in a session will impose the overhead of creating a new session object (if one doesn’t already exist) and increased memory usage as more objects reside on the heap.

This effect will be greatly exaggerated in case of a single page seeing high traffic from many unique users combined with a high bounce rate i.e. they users do not continue to browse but leave the site immediately after viewing that one page- the container will create a new session object per user which will never be used again and will ultimately be garbage collected after it times out – added over head of object creation, memory usage and garbage collection without giving you any real value.

Posted in JSP.

The problem is that the requested page is been loaded from the browser cache instead of straight from the server. You just need to instruct the browser to not cache all the restricted JSP. This way the browser is forced to request the page from the server instead of from the cache and hence all login checks on the server will be executed.

You can do this using a Filter which sets the necessary response headers in the doFilter() method:

@WebFilter
public class NoCacheFilter implements Filter 
{
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException 
   {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");       
        response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        response.setDateHeader("Expires", 0); // Proxies.
        chain.doFilter(req, res);
    }
    // ...
}

Map this Filter on an url-pattern of interest, for example *.jsp.

@WebFilter("*.jsp")

Or if you want to put this restriction on secured pages only, then you should specify an URL pattern which covers all those secured pages. For example, when they are all in the folder /app, then you need to specify the URL pattern of /app/*.

 @WebFilter("/app/*")

Even more, you can do this job in the same Filter as where you’re checking the presence of the logged-in user.

Complete Authentication Filter
The filter (the interceptor) shouldn’t check the validity of the username/password combo. That’s the responsibility of the servlet (the controller).

The filter should merely check if the user is logged-in or not (usually by just checking the presence of a session attribute) and then continue the request or block it by redirecting back to the login page.

@WebFilter("/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {    
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);
        String loginURI = request.getContextPath() + "/login";

        boolean loggedIn = session != null && session.getAttribute("user") != null;
        boolean loginRequest = request.getRequestURI().equals(loginURI);

        if (loggedIn || loginRequest) {
            chain.doFilter(request, response);
        } else {
            response.sendRedirect(loginURI);
        }
    }

    // ...
}

The servlet should collect the submitted data, find the associated User in database and if found then store it as a session attribute and then redirect to the home page, else redisplay the form with validation errors.

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @EJB
    private UserService userService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        Map<String, String> messages = new HashMap<String, String>();

        if (username == null || username.isEmpty()) {
            messages.put("username", "Please enter username");
        }

        if (password == null || password.isEmpty()) {
            messages.put("password", "Please enter password");
        }

        if (messages.isEmpty()) {
            User user = userService.find(username, password);

            if (user != null) {
                request.getSession().setAttribute("user", user);
                response.sendRedirect(request.getContextPath() + "/home");
                return;
            } else {
                messages.put("login", "Unknown login, please try again");
            }  
        }

        request.setAttribute("messages", messages);
        request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
    }
}

A common misunderstanding among starters is that they think that the call of a forward(), sendRedirect(), or sendError() would magically exit and “jump” out of the method block, hereby ignoring the remnant of the code. For example:

protected void doPost() {
    if (someCondition) {
        sendRedirect();
    }
    forward(); // This is STILL invoked when someCondition is true!
}

This is thus actually not true. They do certainly not behave differently than any other Java methods (expect of System#exit() of course). When the someCondition in above example is true and you’re thus calling forward() after sendRedirect() or sendError() on the same request/response, then the chance is big that you will get the exception:

java.lang.IllegalStateException: Cannot forward after response has been committed

If the if statement calls a forward() and you’re afterwards calling sendRedirect() or sendError(), then below exception will be thrown:

java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed

To fix this, you need either to add a return; statement afterwards

protected void doPost() 
{
    if (someCondition) 
    {
        sendRedirect();
        return;
    }
    forward();
}

… or to introduce an else block.

protected void doPost() {
    if (someCondition) {
        sendRedirect();
    } else {
        forward();
    }
}

Another probable cause is that the servlet writes to the response while a forward() will be called, or has been called in the very same method.

protected void doPost() 
{
    out.write("some string");
    // ... 
    forward(); // Fail!
}

The response buffer size defaults in most server to 2KB, so if you write more than 2KB to it, then it will be committed and forward() will fail the same way:

java.lang.IllegalStateException: Cannot forward after response has been committed

Solution is obvious, just don’t write to the response in the servlet. That’s the responsibility of the JSP. You just set a request attribute like so request.setAttribute(“data”, “some string”) and then print it in JSP like so ${data}

The best way to resolve this problem just set the page (where you suppose to forward the request) dynamically according your logic. That is:

protected void doPost(request , response){
String returnPage="default.jsp";
if(condition1){
 returnPage="page1.jsp";
}
if(condition2){
   returnPage="page2.jsp";
}
request.getRequestDispatcher(returnPage).forward(request,response); //at last line
}
  1. The Way aspect function calls are made are through proxy classes internally
  2. Internally the Spring framework creates proxy classed and calls to the code generated as per the xml are run in proxy class methods before the actual class are called
  3. In the below example in DrawingApp.java I try to create a object for the class circle by invoking factoryService getBean Method
  4. This method returns a Object of class ShapeServiceProxy with the custom methods for xml code added

ShapeService.java

package com.mugil.shapes;

public class ShapeService {
	private Circle objCircle;
	private Triangle objTriangle;
		
	public Circle getObjCircle() {
		return objCircle;
	}
	public void setObjCircle(Circle objCircle) {
		this.objCircle = objCircle;
	}
	public Triangle getObjTriangle() {
		return objTriangle;
	}
	public void setObjTriangle(Triangle objTriangle) {
		this.objTriangle = objTriangle;
	}	
}

ShapeServiceProxy.java

package com.mugil.shapes;

public class ShapeServiceProxy extends ShapeService {
	
	public Circle getObjCircle() {
		new LoggingAspect().getLogMessage();
		return super.getObjCircle();
	}
}

DrawingApp.java

package com.mugil.shapes;

public class DrawingApp
 {
	public static void main(String[] args) 
        {
		FactoryService objFactSer = new FactoryService();
		ShapeService objSS = (ShapeService)objFactSer.getBean("ShapeService");
		objSS.getObjCircle();
	}
}

FactoryService.java

package com.mugil.shapes;

public class FactoryService {
	
	public Object getBean(String className)
	{
		if(className.equals("Circle"))
			return new Circle();
		else if(className.equals("Triangle"))
			return new Triangle();
		else if(className.equals("DrawingApp"))
			return new DrawingApp();
		else if(className.equals("ShapeService"))
			return new ShapeServiceProxy();
			
		return null;
	}
}
getParameter() getAttribute()
getParameter will return the value of a parameter that was submitted by an HTML form or that was included in a query string getAttribute returns an object that you have set in the request, the only way you can use this is in conjunction with a RequestDispatcher. You use a RequestDispatcher to forward a request to another resource
the return type for a parameter is a String The return type for attributes is an Object
The Scope of parameter is per individual request attribute is a server variable that exists within a specified scope
application, available for the life of the entire application
session, available for the life of the session
request, only available for the life of the request
page (JSP only), available for the current JSP page only
request.getParameter(“parameterName”) in java is used for accessing variable from JSP or HTML RequestDispatcher.forward(request, response) in java and request.getAttribute(“attributeName”) in jsp are used for accessing variables
Posted in JSP.

StringEquals.java

package com.apryll.package1;

public class StringEquals 
{
  public static void main(String[] args) 
  {
	jack();
	jill();
  }

  public static void jack() 
  {
	String s1 = "hill5";
	String s2 = "hill" + "5";
	System.out.println(s1 == s2);
  }

  public static void jill() 
  {
	String s1 = "hill5";
	String s2 = "hill" + s1.length();
	System.out.println(s1 == s2);
  }
}

Output

true
5
false

Reason
Because, when a string object is instantiated it cross checks with a memory pool if that String is already created. If it is already created then it maps the new variable to the already existing variable. Therefore both these variables are same objects. In jack() at compile time java knows that both the object are same and uses the same instance for referring to it.

In jill First “hill” is created as a String object, then a new StringBuilder object is created which will help in concatenating two values. After the concatenation is done then it is converted back to a new String object. Real values are known at runtime only.

————————————————————————-

StringClass.java

public class StringClass 
{
	public static void main(String[] args) 
	{
		int a = 10 + 20;
		System.out.println(a);
	}

}

class String 
{
	private final String str;

	public String(String str) 
	{
		this.str = str;
	}

}

Output

Error: Main method not found in class StringClass, please define the main method as:
   public static void main(String[] args)
...

Reason
We do not have a main method with the expected signature. “main” method should have a String array as argument, but in our code the String array is compiled to be our custom String class and not the “java.lang.String” class. Therefore we get the error as main method missing.

Fix
Change the main method signature as public static void main(java.lang.String[] args).

————————————————————————-