18B - OGNL, Object Graph Navigation Language

Introduction:

  • This chapter will introduce you to OGNL and how to use OGNL for accessing values of objects from the ValueStack and the ActionContext. It is also known the “Expression Language”.

OGNL:

  • OGNL is the abbreviation for “Object Graph Navigation Language”. It is an open-source framework used for accessing the values stored in ValueStack (the value storing is demonstrated in previous chapter – Chapter 18 (a)).
  • The values on ValueStack are stored by using getter and setter methods (by getting and setting property of Java Beans)
  • OGNL references to JSTL (JSP standard tag library) and EL (Expression Language) of Java Server Pages (JSP) technology.
  • It is actually a graph like structure which has object and values pair, structured in form of an object graph. These values are retrieved by using getter and setter methods from Java Beans class and a mapping of these values is done to respective objects. The reason of using OGNL is, the values can be retrieved easily from ValueStack by using expression language. The uses of OGNL can be viewed in following figure:

                      

  • The main role of using OGNL is:
    • Accessing values of ValueStack
    • Accessing values of Java Collections such as Maps, Lists, Arrays
    • Using expression language which can be used in forms and request-response pages.
    • Providing type conversion during setting the form values to the Java beans type.
    • It can be used to invoke methods of the model.
    • It can also create lists, maps and graphs to be used with GUI in web application.
  • While running the web application, when HTML form is submitted, the values are transmitted as Strings through the HTTP Protocol. These String values have to be converted to the respective primitive or custom java types to set them in the beans.  During the process of setting the values, OGNL consults the type converters available in Struts 2 and helps in conversion of the form values to the destination types and will set into the Java Beans.

               

 

Accessing ValueStack using OGNL Expression Language:

  • ValueStack properties can be accessed by using Expression Language by using <s:property /> tag of struts-tags.
  • As the values in ValueStack are stored in form of arrays, the first element is indexed at level zero. That is, the values are stored as [0] [1] [2] … [n]. The first element of stack is placed at the index value of [0].
  • There are three general syntaxes for accessing elements of ValueStack as follows:

             

  1. [index_number].elementName

 

  1. [index_number][elementName]

 

  1. [index_number][“elementName”]

 

  • If the username is to retrieved, the property tag will be:

          <s: property value = “[0].username” />

           Or

          <s: property value = “[0][username]” />

          Or

          <s: property value = “[0][“username”]” />

 

Accessing ContextMap or ActionContext using OGNL Expression Language:

  • As discussed in previous chapter (Chapter 18 (a)), ActionContext is basically a container of objects which are created during a request, session, or application or locale scopes during a complete client server interaction. These objects are stored in the ValueStack in a proper sequence.
  • These objects can be accessed by using <s: property /> element of struts tags with “#” symbol.
  • The accessing of different ActionContext objects is as follows:

Request Parameters:

  • “Request” is a map containing the parameters in the current request.  It contains parameters as well as attributes.
  • The Request Parameters are returned in the form of Array. So to retrieve a parameter, we need to know in which index a parameter is present.
  • The syntax for the same is:

          # parameters.count[index_number]

  • For example, for accessing the first and top-most element  of ContextMap, that is the message of object on the top can be retrieved by:

          # parameters.count[0]

Request Attributes:

  • The request attributes contains values of specific attributes under the request parameter.
  • For example, for employee request parameter, the attributes can be:
    • Employee name
    • Employee salary
    • Employee designation etc.
  • To access request attributes, following syntaxes are used:

           # request. request parameter name. request attribute name    OR
           # request[‘request parameter name’] [‘request attribute name’]     OR
           # request[“request parameter name”] [“request attribute name”]

  • For example, for accessing employee details like name, salary, designation etc., following is used:

          # request.employee.name
          # request.employee.salary
          # request.employee.designation
         OR
          # request[‘employee’] [‘name’]
          # request[‘employee’] [‘salary’]
          # request[‘employee’] [‘designation’]
         OR
          # request[“employee”] [“name”]
          # request[“employee”] [“salary”]
          # request[“employee”] [“designation”]

Session Scope Attributes:

  • Session is a map containing the session attributes for the current user. It contains information like user’s credentials, user’s logged in time, user’s logout time and other related browser’s information.
  • To access session scope attributes following syntaxes are used:

       # session. request parameter name. request attribute name    OR
       # session [‘request parameter name’] [‘request attribute name’]     OR
       # session [“request parameter name”] [“request attribute name”]

  • For example, for accessing employee details like name, logged in time etc., following is used:

      # session.employee.name
      # session.employee.login_time
      # session.employee.useragent
      OR
      # session [‘employee’] [‘name’]
      #session [‘employee’] [‘login_time’]
      # session [‘employee’] [‘useragent]
      OR
      # session [“employee”] [“name”]
      # session [“employee”] [“login_time”]
      # session [“employee”] [“useragent”]

Application Scope Attributes:

  • Application is a map containing the ServletContext attributes. It contains information like servlet name, MIME types (in case of e-mail application), servlet initialization parameters, context path, etc.
  • To access session scope attributes following syntaxes are used:

      # application. request parameter name. request attribute name    OR
      # application [‘request parameter name’] [‘request attribute name’]     OR
      # application [“request parameter name”] [“request attribute name”]

  • For example, to know employees name, id, registration number, servlet name etc, following can be used:

      # application.employee.name
      # application.employee.id
      # application.employee.servlet_class
      OR
      # application [‘employee’] [‘name’]
      # application [‘employee’] [‘id’]
      # application [‘employee’] [‘servlet_class’]
      OR
      # application [“employee”] [“name”]
      # application [“employee”] [“id”]
      # application [“employee”] [“servlet_class”]

Attributes of Map:

  • Attribute Map is a map that searches for attributes in the following order: request, session, application. To access any of the above mentioned attributes, only “attr” prefix can be used.
  • The syntax for the same is:

      # attr[‘attribute_name’]

  • For example, to access the last accessed time of session of a logged in user, the attribute used is “lastAccessedTime”. The example can be written as:

      # attr[‘lastAccessedTime’]

  • Also, to access user-specific attributes, like employees name or id, the following can be used:

     # attr[‘employee’] [‘name’]
     # attr[‘employee’] [‘id’]
     OR
     # attr[“employee”] [“name”]
     # attr[“employee”] [“id”]

Example of ActionContext and ValueStack in Struts 2:

  • Let us now view the example of Struts application with ValueStack and ActionContext.
  • The program has already stored two variables in ValueStack. The web application will retrieve these values using expressions and will display the addition value in the output screen.
  • The first page will have a button, on the click event of which all the values will get unwind from ValueStack and stored to the local variables of class. These local variables will now get added.
  • So the first.jsp will be:
// first.jsp

<%-- 
    Document   : first
    Created on : Nov 20, 2014, 12:34:17 PM
    Author     : Admin
--%>

<%@page contentType = "text/html" pageEncoding = "UTF-8"%>
<%@taglib prefix = "s" uri = "/struts-tags" %>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv = "Content-Type" content = "text/html; charset = UTF-8">
        <title> Struts 2 Addition example using ActionContext and ValueStack </title>
    </head>
    <body>
        <h1>

            Struts 2 Addition example using ActionContext and ValueStack
        </h1>

        <hr/>
        <s:form action = "click">
             <s:label name = "Click the button to see example"/>
             <s:submit/>
        </s:form>
    </body>
</html>
  • The next page will have the added values of two inbuilt stored varaibels of ValueStack. So the next.jsp can be coded as follows:
// next.jsp

<%-- 
    Document   : next
    Created on : Dec 3, 2014, 3:30:59 PM
    Author     : Admin
--%>

<%@page contentType = "text/html" pageEncoding = "UTF-8"%>
<%@taglib prefix = "s" uri = "/struts-tags" %>
<!DOCTYPE html>
<html>
    <head>

    </head>
    <body>

       <h1>
               The numbers shown here are actually given in ValueStack in Action class
        </h1>
        <hr/>
        <h3>
            The addition of 
            <s:property value = "value1"/> 
            and
            <s:property value = "value2"/>  
            is : 
            <s:property value = "answer"/>
        </h3>
    </body>
</html>
  • Now the action class will retrieve the values of ValueStack and store them to local variables to perform addition. So the action class will be as follows:
// myclass.java

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package action_class;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.util.ValueStack;
Import Java. util. HashMap;
import java.util.Map;

/**
 *
 * @author Admin
 */
public class myclass extends ActionSupport{

    private String name;
    private Integer answer;

    public Integer getAnswer() {
        return answer;
     }
     public void setAnswer(Integer answer) {
        this.answer = answer;
     }
     public String getName() {
        return name;
     }
     public void setName(String name) {
        this.name = name;
     }
     public String execute()
     {
        Integer i1 = new Integer(10);
        Integer i2 = new Integer(20);
        ValueStack stack = ActionContext.getContext().getValueStack ();
        Map <String, Object> context = new HashMap <String,Object> ();
        context.put ("value1", i1);
        context.put ("value2", i2);    
        stack.push (context);    
        answer = i1 + i2;
        return SUCCESS;
     }
}
  • The struts.xml will be as follows:
// struts.xml

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
     <package name = "default" extends = "struts-default">
            <action name = "click" class = "action_class.myclass">
                        <result name = "success"> next.jsp </result>
            </action>
    </package>
</struts>
  • The web.xml will be as follows:
// web.xml

<?xml version = "1.0" encoding = "UTF-8"?>
<web-app version = "3.1" xmlns = "http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <filter>
        <filter-name> struts2 </filter-name>
        <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class>
    </filter>
    <filter-mapping>
        <filter-name> struts2 </filter-name>
        <url-pattern> /* </url-pattern>
    </filter-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file> jsp/first.jsp </welcome-file>
    </welcome-file-list>
</web-app>
  • The output for above example will be:

    

        Figure: first.jsp – click on the button the view addition of ValueStack numbers

     

Example of ValueStack and OGNL in Struts 2:

  • Now let us see the example of Object Graph Navigation Language by using expressions to retrieve information from action classes.
  • In our example, we create a map or hash table or an array of any data type and use the OGNL EL to access the values from action class.
  • Any structure can be created to access the values provided, it must have key-value pairs and the values are not null (probably).
// first.jsp

<%-- 
    Document   : first
    Created on : Nov 20, 2014, 12:34:17 PM
    Author     : Admin
--%>
<%@page contentType = "text/html" pageEncoding = "UTF-8"%>
<%@taglib prefix = "s" uri = "/struts-tags" %>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv = "Content-Type" content = "text/html; charset = UTF-8">
        <title>Struts 2 example using ValueStack and OGNL </title>
    </head>
    <body>
        <h1>
            Struts 2 example using ValueStack and OGNL
        </h1>

        <hr/>
        <s:form action = "click">

            <s:label name = "Click the button to see example"/>
            <s:submit/>
         </s:form>
     </body>
</html>
  • The next page will contain the retrived values from the hash table, map, object or the array. So the <s:property/> tag of Struts-tag is used here.
  • The next.jsp will be coded as follows:
// next.jsp
<%-- 
    Document   : next
    Created on : Dec 3, 2014, 3:30:59 PM
    Author     : Admin
--%>

<%@page contentType = "text/html" pageEncoding = "UTF-8"%>
<%@taglib prefix = "s" uri = "/struts-tags" %>
<!DOCTYPE html>
<html>
    <head>

    </head>
    <body>

       <h1>
               The values shown here are given in ValueStack in Action class and retrieved through OGNL
        </h1>
        <hr/>
        <h3>

                Print the contents of Array : <s:property value = "fruits"/> <br/><br/>

                The length of array is : <s:property value = "fruits.length"/> <br/> <br/>
            The first element of array is: <s:property value = "fruits[0]"/> <br/> <br/>
            The second element of array is: <s:property value = "fruits[1]"/> <br/> <br/>
            
</h3>
    </body>
</html>
  • The action class will create the array or hash, and store the name and value pairs accordingly.
  • These values will be retrieved by property tag in next.jsp.
  • So the action class can be coded as follows:
// myclass_2.java

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package action_class;

/**
 *
 * @author Admin
 */
public class myclass_2 {

   private String[] fruits = {"Apple", "Mango", "Orange", "Kiwi", "Pineapple"};

   public String execute()
    {
        return "success";
    }

    public String[] getFruits()
    {
        return fruits;
    }
    public void setFruits(String[] fruits)
    {
        this.fruits = fruits;
    }   
}
  • The struts.xml file will contain the code to accumulate the action class and the jsp pages and will put all the actions in place. Thus it can be coded as follows:
// struts.xml

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
     <package name = "default" extends = "struts-default">
            <action name = "click" class = "action_class.myclass_2">
                        <result name = "success"> next.jsp </result>
            </action>
    </package>
</struts>
  • Lastly, the web.xml will be as follows:
// web.xml

<?xml version = "1.0" encoding = "UTF-8"?>
<web-app version = "3.1" xmlns = "http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
    <filter>
        <filter-name> struts2 </filter-name>
        <filter-class> org.apache.struts2.dispatcher.FilterDispatcher </filter-class>
    </filter>
    <filter-mapping>
        <filter-name> struts2 </filter-name>
        <url-pattern> /* </url-pattern>
    </filter-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <welcome-file-list>
        <welcome-file> jsp/first.jsp </welcome-file>
    </welcome-file-list>
</web-app> 
  • The web application will run as follows:

              

                  Figure: first.jsp – click on the button the view the values of ValueStack using expression language

              

               Figure: next.jsp – the results of array values from ValueStack

 

 

Like us on Facebook