Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

Working with Session and Filter in JSF

See in this article how to work with Sessions and Filters in JSF to increase security and reliability

Know how to work with sessions in any web language is extremely important to use key features such as: user logged chosen products and etc. On the other hand the use of filters in JSF help us to carry out important operations before you complete your navigation flow. With these two hands resources can create powerful and complex structures.

In this article we will learn how sessions work and how to apply them in JSF to complement the article we will see how to work with filters in conjunction with the session we created.

Sessions and Cookies

You may have heard about Sessions and Cookies even minimally. Both store information that must be maintained throughout the user navigation, but what a difference these?

The big difference between them lies in the fact that cookies are stored in the browser and sessions are stored on the web server. In some cases it is better to record sensitive information in sessions and not in cookies, just because we do not want her to be traveling on the Web.

Imagine for example when you access your "Online Banking" you would not want the password for your account to be tracked by a cracker, so the session ensures greater security from this point of view.

All this is necessary because HTTP is stateless, it means that it does not maintain a state / connection to each request new data is sent and the old ones are lost, HTTP can not know that the next request came from same source as the previous one.

Filters in JSF

The filters work as navigation flow redirectors, in other words you can prevent the user can access certain content if some condition is not accepted, or you could create a system of logs recording user access to all system pages leaving continuing with the same flow. The filter has several uses and not just "login systems."

In this article we will see the use of filters to previous historical record navigation, allowing the user to return when needed. Commonly we use the "history.back()" JavaScript to allow the user to return to a previously accessed page, but this command has some problems:

  • Depending on the browsing history you can continue on the same page there was a refresh her and this is not always desired. In the event that the user is in a registration form and want to go back to records list, that can be a nuisance.
  • If you disable JavaScript then history.back no longer work.

In our solution always engrave the current navigation and previous browsing user, if it makes a refresh on the same page so we check that the page accessed is the same and not change anything.

Developing SessionContext

Our SessionContext class work with the pattern of Singleton design, so we guarantee that there will only be one instance of this object throughout the application. We will show the complete class and then explain it in parts, as shown in Listing 1.

Listing 1. SessionContext

 import javax.faces.context.ExternalContext;
  import javax.faces.context.FacesContext;
  import javax.servlet.http.HttpSession;
   
   
  public class SessionContext {
      
      private static SessionContext instance;
      
      public static SessionContext getInstance(){
         if (instance == null){
             instance = new SessionContext();
         }
         
         return instance;
      }
      
      private SessionContext(){
         
      }
      
      private ExternalContext currentExternalContext(){
         if (FacesContext.getCurrentInstance() == null){
             throw new RuntimeException("FacesContext can’t be called outside of a HTTP request");
         }else{
             return FacesContext.getCurrentInstance().getExternalContext();
         }
      }
      
      
      public void encerrarSessao(){
         currentExternalContext().invalidateSession();
      }
      
      public Object getAttribute(String name){
         return currentExternalContext().getSessionMap().get(name);
      }
      
      public void setAttribute(String name, Object value){
         currentExternalContext().getSessionMap().put(name, value);
      }
      
  }

The above class follows the Singleton pattern to prevent multiple instances of the same application context. The currentExternalContext () method is very important for functioning of our session, your goal is to return a ExternalContext object through the current HTTP request and this is only possible if a request was shot. This means you can not call this method out of an HTTP request, you will get the following error:

 throw new RuntimeException("FacesContext can’t be called outside of a HTTP request");

You can ask, but what is the difference between FacesContext and ExternalContext? We will not go into detail about their differences but the important thing to know for this article is that ExternalContext works in a "layer" lower than the FacesContext, and the FacesContext is designed to work directly with JSF features specifically, while the ExternalContext can work with HTTP servlet, HTTP request, etc., that are not connected to the JSF, they are used by JSF.

Soon after we have the encerrarSessao() method which as its name implies, it is responsible for closing the open session. If you look at how we are ending the session:

 currentExternalContext().invalidateSession();

You will notice that we use the return currentExternalContext() method, immediately all saved attributes are lost and there is no open session for the current user. This method is useful for performing logout systems, so the user will need to login again and create a new session.

Finally we have two methods: setAttribute() and getAttribute(), see:

 public Object getAttribute(String name){
         return currentExternalContext().getSessionMap().get(name);
      }

The ExternalContext has a method called getSessionMap() that returns a Map with the attributes saved in the current session. We use this method to capture the attribute value by name:

 public void setAttribute(String name, Object value){
         currentExternalContext().getSessionMap().put(name, value);
      }

Also the getAttribute() method, the setAttribute() method uses the getSessionMap() to return the session attributes in the form of Map, but this time using the put () to enter the required values.

How we will use our session? Remember that we can only make use of this class when an HTTP request, it means you can not call the SessionContext without a request coming from the client (browser). See how we can use adding attributes the session:

 SessionContext.getInstance().setAttribute(“value”,123);

We can recover this information in any part of our application. Very useful to maintain values as user logged on, logged time last accessed page, bank attributes that can last throughout the application, avoiding the continuous search of this data.

Developing the filter

Our filter will capture any and all user access and maintain the previous page and current being accessed, so we can ensure that he can return to the previous page whenever you need.

How we'll keep this information? Through our SessionContext class created in the previous section, so we can recover any part of the previous page code to give the possibility of quick and safe return.

A filter is responsible for filtering, as its name suggests, the user navigation flow, allowing it to proceed or not. At this point the filter is being done, you can perform numerous tasks, such as: save the page being accessed for future audits, perform specific processing for the page to be rendered correctly, etc. In our case we will save the page accessed and let the user continue to flow normally, so it will be clear this process. Notice in Listing 2.

Listing 2. PageFilter

 package com.jwebbuild.filter;
   
  import java.io.IOException;
   
  import javax.servlet.Filter;
  import javax.servlet.FilterChain;
  import javax.servlet.FilterConfig;
  import javax.servlet.ServletException;
  import javax.servlet.ServletRequest;
  import javax.servlet.ServletResponse;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpSession;
   
  public class PageFilter implements Filter {
   
      public void destroy() {
         // TODO Auto-generated method stub
   
      }
   
      public void doFilter(ServletRequest request, ServletResponse response,
             FilterChain chain) throws IOException, ServletException {
   
         HttpSession sess = ((HttpServletRequest) request).getSession(true);
   
         String newCurrentPage = ((HttpServletRequest) request).getServletPath();
   
         if (sess.getAttribute("currentPage") == null) {
             sess.setAttribute("lastPage", newCurrentPage);
             sess.setAttribute("currentPage", newCurrentPage);
         } else {
   
             String oldCurrentPage = sess.getAttribute("currentPage").toString();
             if (!oldCurrentPage.equals(newCurrentPage)) {
               sess.setAttribute("lastPage", oldCurrentPage);
               sess.setAttribute("currentPage", newCurrentPage);
             }
         }
   
         chain.doFilter(request, response);
   
      }
   
      public void init(FilterConfig arg0) throws ServletException {
         // TODO Auto-generated method stub 
      }
   
  }

Our filter is a bit more complex than SessionContext class created previously, because our PageFilter implements the Filter interface because only then it is possible that our filter works and is mapped in web.xml (we will see later). Soon we have the implementation of the destroy() method that has no logic as not he will use. The destroy() method and the init() method are generally used to filter settings, but in this case we will give attention only to doFilter().

The doFilter() method is called whenever a page is being accessed, this page should be being monitored by our filter.

Right at the beginning we have to recover the current session or creating a new event does not exist:

 HttpSession sess = ((HttpServletRequest) request).getSession(true);

We use the request object to capture the session as a HttpSession. After capture the current page being accessed:

 String newCurrentPage = ((HttpServletRequest) request).getServletPath();

Then immediately check whether there is a current page recorded in the session, if this is true then we know it is the first user access. In this case we will write the last page and the current page to be the same:

 if (sess.getAttribute("currentPage") == null) {
             sess.setAttribute("lastPage", newCurrentPage);
             sess.setAttribute("currentPage", newCurrentPage);
         }

Not to confuse the concepts we call the current page being accessed right now PAR (page Current Real), the current page that was saved from PAH (current history page) and the previous page of PANT.

If there is already a PAH in session, you must turn the page and previous page saved in newCurrentPage object (PAR) should be the real current page. The problem is that we must always check that PAR is not equal to PAH, not we override the previous page and lose information.

Imagine the following example:

  1. The user first accesses the system, the index.xhtml page. The PANT receives index.xhtml value as well as PAH, because it is the first access.
  2. In the second user access it accesses the home.xhtml page, so we found that PAR is home.xhtml which is different from PAH, therefore our PANT becomes the HAP and our HAP become the PAR.
  3. If the second user access it access home.xhtml? Parameter = hello, this still means that it is on the same page then we should not change anything, so we checked PAR equals HAP and in this case we do nothing.

Finally, following this logic we will run the method that allow the user to proceed with your navigation flow:

chain.doFilter(request, response);

So that the filter is activated we have to configure it in our web.xml file of the project, so it will begin to monitor pages accessed and verify whether or not pass any filters. Let's look at Listing 3.

Listing 3. Enabling filter in web.xml

  <filter>
       <filter-name>PageFilter</filter-name>
       <filter-class>com.meuprojeto.filter.PageFilter</filter-class>     
   </filter>
   
   <filter-mapping>
      <filter-name>PageFilter</filter-name>
      <url-pattern>/core/*</url-pattern>
  </filter-mapping>

Above we have two tags to define the filter: filter and filter-mapping, where each has other internal tags.

The filter tag defines the name of our filter through filter-name and where he is in our project through the filter-class. Since the filter-mapping tag is responsible for defining which pages this filter will monitor in our case everything within the directory "/core".

Okay, now we have a filter that makes the use of SessionContext to record the data handled in doFilter(). Let's recap what will happen in our navigation flow:

1. When the user access for the first time, if it is sailing in the folder "/ core" our PageFilter will be called and therefore it should not be created session, the PageFilter will be responsible for initializing a new session through this line:

HttpSession sess = ((HttpServletRequest) request).getSession(true);

This guarantees the existence of a session to save the required attributes.

2. With the session created we recorded the page being accessed (following the same logic that we have explained in previous sections).

Monitoring session created

How can we know when a session is created or destroyed? The ideal is to create a listener to be able to track this life cycle of our session. Let's see how to make the Listing 4 code.

Listing 4. SessionListener

  import java.text.SimpleDateFormat;
  import java.util.Date;
   
  import javax.servlet.http.HttpSessionEvent;
  import javax.servlet.http.HttpSessionListener;
   
  public class SessionListener implements HttpSessionListener {
      
   
      public void sessionCreated(HttpSessionEvent event) {        
           System.out.println("Created session " + event.getSession().getId());
      }
   
      public void sessionDestroyed(HttpSessionEvent event) {     
           String lastAccess = (new SimpleDateFormat("dd/MM/yyyy HH:mm:ss")).format(new Date(event.getSession().getLastAccessedTime()));
           System.out.println("Expired session "+event.getSession().getId()+". Last access = "+ lastAccess);
      }
   
  }

Our SessionListener class implements the interface HttpSessionListener which is mandatory so that the listener function. The sessionCreated() method shows the session ID when it is created, since the sessionDestroyed() method shows the session ID that is being destroyed and the date and time of last access:

Created session 7F37598DEAEBF1E8B0FAD186DE784853

The session was created with the mentioned ID. From this point we can start recording our attributes:

 Expired session 53C60A043734D9CCCC889F81CE93CE5C. Last access = 03/08/2015 13:41:33

We have two ways to destroy a session:

1. Calling invalidateSession() method; we use in SessionContext:

public void finishSession() {
       currentExternalContext().invalidateSession();
    }

2. The other way is to let the session expire at a set time in the web.xml, as shown in Listing 5.

Listing 5. Defining time to expire session

 <session-config>
    <session-timeout>60</session-timeout>
</session-config>

Above we have the session-timeout setting in 60 minutes, or in 60 minutes there is no client-server request the session will expire automatically and the message shown above appears.

If we call the invalidatesession() method to display message will also be the same as shown above, but that does not mean that the session has timed out. In this case it was destroyed manually. You can improve this message making it more generic example: Session completed in time Session expired or destroyed.

If you start your server now and try to see the messages you will see that will not work because there is still a setting: Add the Listener in our web.xml, as shown in Listing 6.

Listing 6. Adding the listener in web.xml

 <listener>
	<listener-class>com.meuprojeto.util.SessionListener</listener-class>
</listener>

Above we created the mapping of our SessionListener in web.xml using the and internally that will map our SessionListener, now whenever a session SessionListener class is created or destroyed will be called, as it implements HttpSessionListener otherwise could not do this mapping.

We have seen in this article how to use sessions and filters with JSF. We created a class called SessionContext that is capable of storing attributes in the current session and use these attributes in our PageFilter that stores the page accessed by the user.

The application of both concepts goes beyond just the attributes of storage, it is up to you the reader, given the concepts taught in this article, develop the logic necessary for your project. The important thing is to have knowledge of the entire base as the session and the filter work.



Fabrí­cio Galdino is a software expert and has worked with IT analysis and business development for more than five years. It has extensive experience with testing, back and front-end technologies.

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login