Static methods cannot be overridden but can be redefined in child Class

class Animal 
{
  static void doStuff() 
  {
    System.out.print("animal");
  }
}

class Dog extends Animal 
{
   // it's a redefinition
   // not an override
   static void doStuff() 
   { 					
     System.out.print("dog");
   }

   public static void main(String [] args) 
   {
      Animal [] a = {new Animal(), new Dog(), new Animal()};
     
      for(int x = 0; x < a.length; x++)
     	a[x].doStuff();               // invoke the static method 

    }
}

Output

animal animal animal

Method overriding is made possible by dynamic dispatching, meaning that the declared type of an object doesn’t determine its behavior, but rather its runtime type

Animal lassie = new Dog();
lassie.speak(); // outputs "woof!"
Animal kermit = new Frog();
kermit.speak(); // outputs "ribbit!"

Even though both lassie and kermit are declared as objects of type Animal, their behavior (method .speak()) varies because dynamic dispatching will only bind the method call .speak() to an implementation at run time – not at compile time.

Now, here’s where the static keyword starts to make sense: the word “static” is an antonym for “dynamic”. So the reason why you can’t override static methods is because there is no dynamic dispatching on static members – because static literally means “not dynamic”. If they dispatched dynamically (and thus could be overriden) the static keyword just wouldn’t make sense anymore.

public class Why {

  public static void test() {
    System.out.println("Passed");
  }

  public static void main(String[] args) {
    Why NULL = null;
    NULL.test();
  }
}

test() is a static method. A static member belongs to the type, and do not require an instance to access.

A static member should ONLY be accessed via a type expression. That is, you should’ve written it as follows:

Why.test(); // always invoke static method on the type it belongs to!

Java does allow you to access a static member via an object reference expression, but this is VERY misleading, since this is NOT the actual semantics of a static member access.

Why aNull = null; 
aNull.test(); // DO NOT EVER DO THIS!
// invokes Why.test(), does NOT throw NullPointerException

When accessing a static member through an object reference expression, only the declared type of the reference matters. This means that:

  1. It doesn’t matter if the reference is actually null, since no instance is required
  2. If the reference is not null, it doesn’t matter what the runtime type of the object is, there is no dynamic dispatch!!!

What is Serialization?
Serialization is the conversion of an object to a series of bytes, so that the object can be easily saved to persistent storage or streamed across a communication link.The byte stream can then be deserialized – converted into a replica of the original object.In Java, the serialization mechanism is built into the platform, but you need to implement the Serializable interface to make an object serializable.

You can also prevent some data in your object from being serialized by marking the attribute as transient.

Finally you can override the default mechanism, and provide your own; this may be suitable in some special cases.

private void writeObject(ObjectOutputStream out) throws IOException;
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException;

This way you can create your own custom serialization to make it more “whatever” (safe, fast, rare, easy etc. )

It is important to notice that what gets serialized is the “value” of the object, or the contents, and not the class definition.

import java.util.*;

// This class implements "Serializable" to let the system know
// it's ok to do it. You as programmer are aware of that.
public class SerializationSample implements Serializable {

    // These attributes conform the "value" of the object.

    // These two will be serialized;
    private String aString = "The value of that string";
    private int    someInteger = 0;

    // But this won't since it is marked as transient.
    private transient List<File> unInterestingLongLongList;

    // Main method to test.
    public static void main( String [] args ) throws IOException  { 

        // Create a sample object, that contains the default values.
        SerializationSample instance = new SerializationSample();

        // The "ObjectOutputStream" class have the default 
        // definition to serialize an object.
        ObjectOutputStream oos = new ObjectOutputStream( 
                               // By using "FileOutputStream" we will 
                               // Write it to a File in the file system
                               // It could have been a Socket to another 
                               // machine, a database, an in memory array, etc.
                               new FileOutputStream(new File("o.ser")));

        // do the magic  
        oos.writeObject( instance );
        // close the writing.
        oos.close();
    }
}

Real World Example
ATM: When the account holder tries to withdraw money from the server through ATM, the account holder information like withdrawl details will be serialized and sent to server where the details are deserialized and used to perform operations.

How serialization is performed in java.

  1. Implement “java.io.Serializable” interface.(marker interface so no method to implement)
  2. Persist the object : Use java.io.ObjectOutputStream class, a filter stream which is a wrapper around a lower-level byte stream. (to write Object to file systems or transfer a flattened object across a network wire and rebuilt on the other side.)
    1. writeObject(<>) – to write an object
    2. readObject() – to read an serialized Object

When you serialize an object, only the object’s state will be saved, not the object’s class file or methods.

What are the Steps when object is serialized and de-serialized?

  1. First writes the serialization stream magic data
  2. Then it writes out the metadata of the class associated with an instance.( length of the class, the name of the class, serialVersionUID)
  3. Then it recursively writes out the metadata of the superclass until it finds java.lang.object.
  4. Then starts with the actual data associated with the instance.
  5. Finally writes the data of objects associated with the instance starting from metadata to actual content.

How not to serialize any field in class.
Use transient keyword

When child class is serialized does parent class get serialized?
No, Only meta data of parents get serialized till object class.

When parent is serialized does child class get serialized?
Yes, by default child class also get serialized.

How to avoid child class from getting serialized?
Override writeObject and readObject method and throw NotSerializableException exception.also you can mark all fields transient in child class.

Some system-level classes such as Thread, OutputStream, and its subclasses, and Socket are not serializable.

If you have a child class which implements serializable and parent class is not serializable then parent class will be reset to the values they were given during the original construction of the object

 
class Cat
{ 
 public String name = "Cat";
} 

class Tiger extends Cat implements Serializable 
{ 
 public int weight; 

 Tiger(int pWeight, String pName)
 {
   name   = pName;
   weight = pWeight;
 }
} 

class SerialTest
{
 public static void main(String args[])
 {
   Tiger  objTiger = new Tiger(150, "Bengal");
   sysout("Before Serialization : Weight -"+ objTiger.getWeight + " Name -"+ objTiger.getName); 
 }
 
}

Output

 Before Serialization : Weight - 150 Name - Bengal 
 After Serialization : Weight - 150  Name - Cat

After serialization the Parent class Cat Name would be set to Original name which is Cat.This is because non-serializable class constructor will run.

 class Animal implements Serializable
 { 
   transient String swims = "Y";
 }

When the Animal has deserialized the value of swims would be set to null since it is marked as transient.

If you serialize a collection(ArrayList, LinkedList) or an array, every element must be Serializable. If any element in the collection is non-serializable then serialization fails. Collection interfaces are non serializable(List,Map) whereas concrete collection classes are serializable(ArrayList, LinkedList)

Static Variables are not serializable
Static variables are not saved as part of object state because they do not belong to object they belong to Class

What are serializable and not serializable

  1. Instance Variables: These variables are serialized, so during deserialization we will get back the serialized state.
  2. Static Variables: These variables are not serialized, So during deserialization static variable value will loaded from the class.(Current value will be loaded.)
  3. transient Variables: transient variables are not serialized, so during deserialization those variables will be initialized with corresponding default values (ex: for objects null, int 0).
  4. Super class variables: If super class also implemented Serializable interface then those variables will be serialized, otherwise it won’t serialize the super class variables. and while deserializing, JVM will run default constructor in super class and populates the default values. Same thing will happen for all superclasses.

I have a scenario where a scheduled job being run by Quartz will update an arraylist of objects every hour.

But I need this arraylist of objects to be visible to all sessions created by Tomcat. So what I’m thinking is that I write this object somewhere every hour from the Quartz job that runs so that each session can access it.

Store the list in the ServletContext as an application-scoped attribute. Pulling the data from a database instead is probably less efficient, since you’re only updating the list every hour. Creating a ServletContextListener might be necessary in order to give the Quartz task a reference to the ServletContext object. The ServletContext can only be retrieved from JavaEE-related classes like Servlets and Listeners.In the ServletContextListener, when you create the job, you can pass the list into the job by adding it to a JobDataMap.

public class MyServletContextListener implements ServletContextListener{
  public void contextInitialized(ServletContextEvent event){
    ArrayList list = new ArrayList();

    //add to ServletContext
    event.getServletContext().setAttribute("list", list);

    JobDataMap map = new JobDataMap();
    map.put("list", list);
    JobDetail job = new JobDetail(..., MyJob.class);
    job.setJobDataMap(map);
    //execute job
  }

  public void contextDestroyed(ServletContextEvent event){}
}

//Quartz job
public class MyJob implements Job{
  public void execute(JobExecutionContext context){
    ArrayList list = (ArrayList)context.getMergedJobDataMap().get("list");
    //...
  }
}

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);
    }
}