December 31, 2011

Spring - Hibernate framework Integration - Hello World Example

0) To proceed with this example, complete the Spring Hello World Example and the Hibernate Hello World Example

1) Put 2 jar files from the Apache Commons collection in the WebContent/WEB-INF/lib folder of the web application - download the jars from this link

2) Add the following elements to the Spring configuration file, applicationContext.xml
Integrating Spring with Hibernate results in the hibernate.cfg.xml becoming obsolete - the configuration in hibernate.cfg.xml is now put in the applicationContext.xml

Configuration for DataSource (Database Connection properties)

<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
   <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
   <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" />
   <property name="username" value="system" />
   <property name="password" value="system" />
</bean>

Configuration for Hibernate (of hibernate.cfg.xml)


<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   <property name="dataSource" ref="dataSource"/>
   <property name="mappingResources">
      <list>
         <value>info/icontraining/hibernate/Message.hbm.xml</value>
      </list>
   </property>
   <property name="hibernateProperties">
      <props>
         <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
      </props>
   </property>
</bean>

Configuration for HibernateTemplate, DAOs, etc.

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
   <property name="sessionFactory" ref="sessionFactory" />
</bean>
 
<bean id="myDao" class="info.icontraining.dao.MyDAO">
   <property name="hibernateTemplate" ref="hibernateTemplate" />
</bean>


3) Create a MyDAO.java class in the src folder of the web application - this class does the actual persistence

package info.icontraining.dao;

import java.util.List;
import info.icontraining.hibernate.Message;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class MyDAO {

   private HibernateTemplate hibernateTemplate;
 
   public void setHibernateTemplate(HibernateTemplate template) {
      this.hibernateTemplate = template;
   }
 
   public void saveData(String str) {
      Message message1 = new Message(str);
      hibernateTemplate.save(message1);
   }

   public int retrieveData() {
      List<Message> messages = hibernateTemplate.find("from Message as m order by m.text asc");
      return messages.size();
   } 
}


4) Create a client JSP - springHibernate.jsp - in the WebContent folder of the web application


<%@ page  import="org.springframework.context.*,org.springframework.web.context.*,info.icontraining.spring.*,info.icontraining.dao.*"%>
<html>
<body>

<% 
 ApplicationContext factory = 
  (ApplicationContext) this.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

 MyDAO mydao = (MyDAO)factory.getBean("myDao");
 mydao.saveData("Spring Hibernate");
 
 int numMessages = mydao.retrieveData();
%>
 
<%= numMessages + " messages found." %>

</body>
</html>

5) Test the example with the following URL in the browser,

http://localhost:8080/WebAppName/springHibernate.jsp

Log into Oracle Database and check the contents of the appropriate table

Spring Bean Scope Demo - Prototype & Singleton

1) Create 2 beans - PrototypeBean.java & SingletonBean.java - in the src folder of the web application

package info.icontraining.spring;

public class PrototypeBean {
   private int i;
 
   public PrototypeBean() {
      i = 3;
   }
 
   public void changeValue() {
      i = 5;
   }
 
   public int getValue() {
      return i;
   }
}



package info.icontraining.spring;

public class SingletonBean {

   private int i;
 
   public SingletonBean() {
      i = 3;
   }
 
   public void changeValue() {
      i = 5;
   }
 
   public int getValue() {
      return i;
   } 
}

2) Configure both beans in the WebContent/WEB-INF/applicationContext.xml file - the PrototypeBean bean is configured with the scope attribute set to 'prototype'

<bean id="singleton" class="info.icontraining.spring.SingletonBean" />
 
<bean id="prototype" class="info.icontraining.spring.PrototypeBean" scope="prototype" />

3) Create a client JSP - singletonPrototypeDemo.jsp - in the WebContent folder of the web application

<%@ page  import="org.springframework.context.*,org.springframework.web.context.*,info.icontraining.spring.*"%>
<html>
<body>

 <% 
 ApplicationContext factory = 
  (ApplicationContext) this.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

 SingletonBean s1 = (SingletonBean)factory.getBean("singleton");
 s1.changeValue();
 
 SingletonBean s2 = (SingletonBean)factory.getBean("singleton"); 
 %>
 
 <%= "SingletonBean on Reference-1 after changing value = " + s1.getValue() %><br/>
 <%= "SingletonBean on Reference-2 without changing value = " + s2.getValue() %>

<br/><br/>

<% 
 PrototypeBean p1 = (PrototypeBean)factory.getBean("prototype");
 p1.changeValue();
 
 PrototypeBean p2 = (PrototypeBean)factory.getBean("prototype"); 
 %>

 <%= "PrototypeBean on Reference-1 after changing value = " + p1.getValue() %><br/>
 <%= "PrototypeBean on Reference-2 without changing value = " + p2.getValue() %>

</body>
</html>

4) Test the example with the following URL in the browser

http://localhost:8080/WebAppName/singletonPrototypeDemo.jsp

Breaking a large applicationContext.xml configuration file into multiple files

0) Complete the Spring Framework Hello World example at this link

1) Create a new configuration file - applicationContext2.xml - in the WebContent/WEB-INF folder of the web application. Make sure that the root <beans> element is the same as in the applicationContext.xml

Move the <bean> configuration for the greetingService bean to the new configuration file and delete it from the applicationContext.xml

2) Modify the configuration in the web.xml by adding the new configuration file name, as follows,

<context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>/WEB-INF/applicationContext.xml /WEB-INF/applicationContext2.xml</param-value>
  </context-param>

3) Test the Hello World example as in the Hello World example

Initializing, Destroying Spring Beans & instantiating a Spring Bean through a factory method

1) Create an interface - InitDestroyDemo.java - in the src folder of the web application

package info.icontraining.spring;

public interface InitDestroyDemo {
   public void businessMethod();
}


2) Create a Spring Bean that implements the interface - InitDestroyDemoImpl.java - in the src folder of the web application

package info.icontraining.spring;

public class InitDestroyDemoImpl implements InitDestroyDemo {

   private InitDestroyDemoImpl() { }
 
   public void myInitMethod() {
      System.out.println("Inside Init Method of Spring Bean");
   }
 
   public void businessMethod() {
      System.out.println("Inside Business Method of Spring Bean");
   }
 
   public void myDestroyMethod() {
      System.out.println("Inside Destroy Method of Spring Bean");
   }
 
   public static InitDestroyDemo getInstance() {
      return new InitDestroyDemoImpl();
   }
}


3) Configure the Spring Bean in the WebContent/WEB-INF/applicationContext.xml file

The bean is configured with an initializing method using the init-method attribute, with a destroying method using the destroy-method attribute.

The constructor of the bean is made private, and instantiation is instead done through a static factory method, getInstance() - this is configured using the factory-method attribute

<bean id="initDestroyDemo" class="info.icontraining.spring.InitDestroyDemoImpl" init-method="myInitMethod" destroy-method="myDestroyMethod" factory-method="getInstance" />


4) Create a client JSP - springInitDestroy.jsp - in the WebContent folder of the web application

<%@ page  import="org.springframework.context.*,org.springframework.web.context.*,info.icontraining.spring.*"%>
<html>
<body>

View output on Server console

 <% 
 ApplicationContext factory = 
  (ApplicationContext) this.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);

 InitDestroyDemo test = (InitDestroyDemo)factory.getBean("initDestroyDemo");
 test.businessMethod();
 
 %>
</body>
</html>


5) Test the example with the following URL in the browser,

http://localhost:8080/WebAppName/springInitDestroy.jsp

November 27, 2011

Anonymous Arrays Code Example

Anonymous Arrays in Java are those arrays that are constructed without specifying the size nor assigned a reference. Anonymous arrays are created on-the-fly when needed and cannot be re-accessed (since there is no reference available to the array object), therefore they become eligible for garbage-collection as soon as the code that uses it completes it.

package info.icontraining.core;

public class AnonymousArrays {

   public static void main(String[] args) {
  
      int[] arr1 = {1, 2, 3, 4, 5};
  
      for(int i: arr1) {
         System.out.print(i);
      }
  
      for(int i: new int[]{1, 2, 3, 4, 5} ) {
         System.out.print(i);
      }  
   }
}

November 26, 2011

Writing Unicode characters in Java

Create the following class in the src folder of the Java Project in Eclipse


package info.icontraining.core;

public class CharExample {

   public static void main(String args[]) {
 
      char c='\u0915';
      System.out.println(c);
   } 
}


To enabled Unicode character display in the console of Eclipse, make the following 3 configurations in Eclipse:

1) Open the "Run" menu > Choose "Open Run Dialog ..." > Choose your application and the particular class (in this case, CharExample) > Click on the "Common" tab > Choose "Console Encoding" as "Other" and "UTF-8" from the drop-down list

2) Next, go on the "Arguments" tab > Copy the string "-Dfile.encoding=UTF-8" in the VM arguments text area (without the double quotes). Click "Apply" and then "Close".

3) Finally, go to the "Window" menu > Choose "Preferences ..." > Next, choose "General" > Then "Workspace" > In the "Text File Encoding" select "Other" and "UTF-8" from the drop-down list

October 9, 2011

Access Modifiers for Class members in Java

There are 3 access modifiers for class members: public, private, protected
and 4 access levels: public, private, protected, default (none of the modifiers present)

public access level
A public member (variable or method) can be accessed from another class regardless of the package in which the other class is present.
public members can be inherited by a subclass regardless of the package in which the subclass is present.

package info.icontraining.p1;
public class Test {
   public int i;           // public member variable
}

package info.icontraining.p2;
import info.icontraining.p1.Test;
public class A {
   public void m1() {
      Test t = new Test();
      t.i = 3;       // public members can be accessed 
                     // by code in another class that is
   }                 // present in a different package 
}

package info.icontraining.p2;

import info.icontraining.p1.Test;
public class B extends Test {
   public void m1() {
      i = 3;         // public members can be inherited
   }                 // by another class that is present
}                    // in a different package


private access level
A private member cannot be accessed by code in any class except by code in the class in which the private member is present.
private members cannot be inherited by any subclass.

package info.icontraining.p1;
public class Test {
   private int i;           // private member variable
   public void m1() {
      i = 3;           // private members can be accessed
   }                   // only by code within the class
}                      // in which it is declared

package info.icontraining.p1;
public class A {
   public void method1() {
      Test t = new Test();
      t.i = 3;           // this line will not compile
   }
}

package info.icontraining.p1;
public class B extends Test {
   public void method1() {
      i = 3;            // this line will not compile
   }
}

default access level
A default member can be accessed from another class if both classes are present in the same package.
default members can be inherited by a subclass is both classes are present in the same package.

package info.icontraining.p1;
public class Test {
   int i;              // default member variable
}

package info.icontraining.p1;
public class A {
   public void m1() {
      Test t = new Test();
      t.i = 3;         // can be accessed by a class
   }                   // in same package
}

package info.icontraining.p1;
public class B extends Test {
   public void m2 {
      i = 3;       // can be inherited by a class
   }               // in same package
}

package info.icontraining.p2;
import info.icontraining.p1.Test;
public class C {
   public void m1() {
      Test t = new Test();
      t.i = 3;         // will not compile, cannot be 
   }                   // accessed in another package
}

package info.icontraining.p2;
import info.icontraining.p1.Test;
public class D extends Test {
   public void m2 {
      i = 3;       // will not compile, cannot be
   }               // inherited in another package
}

protected access level
A protected member can be accessed by another class in the same package only.
However, protected members can be inherited by a subclass present in a different package also.


package info.icontraining.p1;
public class Test {
   protected int i;              // protected member variable
}

package info.icontraining.p1;
public class A {
   public void m1() {
      Test t = new Test();
      t.i = 3;         // can be accessed by a class
   }                   // in same package
}

package info.icontraining.p1;
public class B extends Test {
   public void m2 {
      i = 3;       // can be inherited by a class
   }               // in same package
}

package info.icontraining.p2;
import info.icontraining.p1.Test;
public class C {
   public void m1() {
      Test t = new Test();
      t.i = 3;         // will not compile, cannot be
   }                   // accessed in another package
}

package info.icontraining.p2;
import info.icontraining.p1.Test;
public class D extends Test {
   public void m2 {
      i = 3;       // can be inherited by a class
   }               // in another package
}

October 8, 2011

Timer Interval functions in Javascript

Code Example


<html>
<head>
<script type="text/javascript">

var timerId;

var setAlerts = function() {
   timerId = setInterval("myfunction();",3000);
}

var removeAlerts = function() {
   clearInterval(timerId);
}

function myfunction() {
   alert("Hi");
}

window.onload = function() {
   document.getElementById("setButton").onclick=setAlerts;
   document.getElementById("clearButton").onclick=removeAlerts;
}

</script>
</head>
<body>

<button id="setButton">Set Interval</button><br/>
<button id="clearButton">Clear Interval</button><br/>

</body>
</html>

Javascript to set cookies and get hold of a specific cookie

Write Javascript code to store a cookie and retrieve it - also check if cookies are enabled on the client.

Solution

<html>
<head>
<script type="text/javascript">

var cookieFunction = function() {
   
if (navigator.cookieEnabled) {
var name = prompt("Enter cookie name");
      var value= prompt("Enter cookie value");
      if ((name) && (value)) {
         var date = new Date("1 Jan 2015 11:30:00");
         document.cookie= name + "="+value+"; expires="+date.toGMTString()+";";
      }
   } else {
      alert("Cookies Not enabled");
   }
}

var getCookie = function() {
   var cookies=document.cookie;
   alert(cookies);
}

var getSpecificCookie = function() {
   var c_name = prompt("Enter cookie name");
   var all_cookies = document.cookie.split( ';' );
   for (i=0;i<all_cookies.length;i++) {
      x = all_cookies[i].substr(0, all_cookies[i].indexOf("="));
      y = all_cookies[i].substr(all_cookies[i].indexOf("=")+1);
      x = x.replace(/^\s+|\s+$/g,"");
      if (x == c_name) {
        alert( unescape(y));
        return;
     }
   }

   alert("Cookie does not exist");
}

window.onload = function() {
   document.getElementById("getCookieButton").onclick=getCookie;
   document.getElementById("getSpecificCookieButton").onclick=getSpecificCookie;
   document.getElementById("diceButton").onclick=rollDice;
}

</script>
</head>
<body>
<button id="cookieButton">Set Cookie</button>
<button id="getCookieButton">Get Cookies</button>
<button id="getSpecificCookieButton">Get Specific Cookie</button>

</body>
</html>

Javascript simulation of rolling of a dice


Write Javascript code to simulate the rolling of a dice. When the user clicks a button, the result should be the simulation of a dice - a value between 1 to 6 is displayed in the String, "Your roll of the dice displayed 3"

Hint: Math.random(), document.getElementById(), innerHTML, onclick event

Solution


<html>
<head>
<script type="text/javascript">

var rollDice = function() {
   var diceElementNode = document.getElementById("diceValue");
   var diceElementNodeChildren = diceElementNode.childNodes;

   if (diceElementNodeChildren[0] != null) {
      diceElementNodeChildren[0].nodeValue = "The dice value is " + Math.ceil((Math.random() * 6));
   } else {
      var diceTextNode = document.createTextNode("");
      diceTextNode.nodeValue ="The dice value is " + Math.ceil((Math.random() * 6));
      diceElementNode.appendChild(diceTextNode);
   }
}

window.onload = function() {
   document.getElementById("diceButton").onclick=rollDice;
}

</script>
</head>
<body>
<button id="diceButton">Roll Dice</button>
<div id="diceValue"></div>

</body>
</html>

September 30, 2011

Service Locator & Business Delegate Design Patterns for an EJB Client

HelloClient.java - This is the EJB Client class

package info.icontraining.ejb.client;

public class HelloClient {
 
   public static void main(String[] args) {  
      System.out.println(MyBusinessDelegate.sayHello("Dinesh"));
   }
}

MyBusinessDelegate.java

package info.icontraining.ejb.client;

import java.util.Hashtable;
import javax.naming.*;

public class MyBusinessDelegate {

   public static String sayHello(String name) {

      Object obj = MyServiceLocator.getStub("MyEarApp/" 
                  + HelloUserBean.class.getSimpleName() + "/remote");
  
      HelloUser helloUser = (HelloUser) obj;
      return helloUser.sayHello(name);
   }
}

MyServiceLocator.java


package info.icontraining.ejb.client;

import java.util.Hashtable;
import javax.naming.*;

public class MyServiceLocator {

   public static Object getStub(String jndiName) {
  
      Hashtable env = new Hashtable(); 
      env.put("java.naming.factory.initial",
            "org.jnp.interfaces.NamingContextFactory");
      env.put("java.naming.factory.url.pkgs",
            "org.jboss.naming:org.jnp.interfaces"); 
      env.put("java.naming.provider.url","localhost:1099"); 

      Context context;
      Object obj = null;
     
      try {
         context = new InitialContext(env);
         obj = context.lookup(jndiName);
      } catch (NamingException e) {
         e.printStackTrace();
      }

      return obj;
   }
}

Adapter Design Pattern code example in Java

Adaptee Concrete

public class Plug {
   private String specification = "5 AMP";
   public String getInput() {
      return specification;
   }
}

Target interface

public interface Socket {
   public String getOutput();
}

Adapter Concrete

public class PlugAdapter implements Socket {

   Plug plug;

   public String getOutput() {
      plug = new Plug();
      String output = plug.getInput();
      return output;
   }
}

Client

public class Client {
   Socket socket;

   public void m1() {
      socket = new PlugAdapter();
      socket.getOutput();
   }
}

Singleton Design Pattern code example in Java

Singleton Class

public class SingletonClass {

   private static SingletonClass uniqueInstance;
   // other variables here

   private SingletonClass() { }

   public static synchronized SingletonClass getInstance() {

      if (uniqueInstance == null)
         uniqueInstance = new SingletonClass();
      return uniqueInstance;
   }

   // other methods here
}

Decorator Design Pattern code example in Java

Abstract Type


public interface IEmail {
   public String getContents();
}

Concrete Type

public class Email implements IEmail {
   private String content;
   public Email(String content) {
      this.content = content;
   }

   @Override
   public String getContents() {
      //general email stuff
      return content;
   }
}

Abstract Type Decorator

public abstract class EmailDecorator implements IEmail {
  
   //wrapped component
   IEmail originalEmail;

   public IEmail getOriginalEmail() {
      return this.originalEmail;
   }

   public void setOriginalEmail(IEmail email) {
      this.originalEmail = email;
   }
}

Concrete Type Decorator

public class SecureEmailDecorator extends EmailDecorator {

   private String content;
   public SecureEmailDecorator(IEmail basicEmail) {
      setOriginalEmail(basicEmail);
   }

   @Override
   public String getContents() {
      //  secure original
      content = encrypt(getOriginalEmail().getContents());
      return content;
   }

   private String encrypt(String message) {
      //encrypt the string
      return  encryptedMessage;
   }
}

Client

public class EmailSender {

   public void sendEmail(IEmail email) {
      // get hold of email contents
      email.getContents();

      // send email code here
   }

   public static void main(String[] args) {
      EmailSender emailSender = new EmailSender();

      IEmail email = new Email();

      // Sending normal email
      emailSender.sendEmail(email);

      // Sending Secure email
      emailSender.sendEmail(new SecureEmailDecorator(email));
   }
}

Observer Design Pattern code example in Java

The Subject Abstract Type

import Observer;

public interface Subject {
   public void addObserver(Observer o);
   public void removeObserver(Observer o);
   public String getState();
   public void setState(String state);
}

The Observer Abstract Type

import Subject;

public interface Observer {
   public void update(Subject s) { ... }
}

Concrete Implementation of Observer Abstract Type (Subscriber)

import Subject;

public class ObserverImpl implements Observer {
   private String state = "";

   public void update(Subject o) {
      state = o.getState();
      System.out.println("Update received from Subject, state changed to : " + state);
   }
}

Concrete Implementation of Subject Abstract Type (Publisher)

import Observer;

public class SubjectImpl implements Subject {
   private List observers = new ArrayList();

   private String state = "";

   public String getState() {
      return state;
   }

   public void setState(String state) {
      this.state = state;
      notifyObservers();
   }

   public void addObserver(Observer o) {
      observers.add(o);
   }

   public void removeObserver(Observer o) {
      observers.remove(o);
   }

   public void notifyObservers() {
      Iterator i = observers.iterator();
      while (i.hasNext()) {
         Observer o = (Observer) i.next();
         o.update(this);
      }
   }
}

The Client

import Subject;
import SubjectImpl;
import Observer;
import ObserverImpl;

public class Client {
   public static void main(String[] args) {
      Observer o = new ObserverImpl();
      Subject s = new SubjectImpl();
      s.addObserver(o);
      s.setState("New State");
   }
}

Strategy Design Pattern code example in Java

The Abstract Type (the dependency)

public interface SortInterface {
   public void sort(List l);
}

The Concrete Implementations of the Abstract Type

public class QuickSort implements SortInterface {
   public void sort(List l) { ... }
}

public class BubbleSort implements SortInterface {
   public void sort(List l) { ... }
}

The Dependent Abstract Type

import SortInterface;

public abstract class Sorter {
   private SortInterface si;

   public void setSorter(SortInterface si) {
      this.si = si; 
   }

   public SortInterface getSorter() {
      return this.si; 
   }

   public void doSort(List listToSort);
}

The Dependent Concrete Type

public class MySorter extends Sorter {

   public void doSort(List listToSort) {
      getSorter().sort(listToSort);
      // other processing here
   }
}

The Client

import MySorter;
import BubbleSort;

public class Client {
   MySorter mysorter = new MySorter();

   mysorter.setSorter(new BubbleSort());
   mysorter.doSort();

   mysorter.setSorter(new QuickSort());
   mysorter.doSort();
}

Accessing request headers in a Struts 2 action

1) Create an action class - HeaderReader.java - in the src folder of the web application

package info.icontraining.struts2;

import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.interceptor.ServletRequestAware;
import com.opensymphony.xwork2.ActionSupport;

public class HeaderReader extends ActionSupport implements ServletRequestAware {

   private HttpServletRequest request;
 
   public void setServletRequest(HttpServletRequest request) {
      this.request = request;
   }
 
   public String execute() {

      Enumeration e = request.getHeaderNames();
      String headerName = null;

      while(e.hasMoreElements()) {
         headerName = (String) e.nextElement();
         System.out.println(headerName + ": "); 
         System.out.println(request.getHeader(headerName) + "\n");
      }

      return SUCCESS;
   } 
}

2) Add a headers.html file to the WebContent folder of the web application

<html>
<body>
Check Server console log for Header names and values
</body>
</html>

3) Configure the action class in the struts.xml configuration file

<action name="headerReader" class="info.icontraining.struts2.HeaderReader">
   <result>headers.html</result> 
</action>

4) Test the example by accessing the following URL,

http://localhost:8080/WebAppName/headerReader.action

Setting a cookie in the response in Struts 2

1) Create an action class - CookieWriter.java - in the src folder of the web application

package info.icontraining.struts2;

import javax.servlet.http.Cookie;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;

public class CookieWriter extends ActionSupport {

   public String execute() throws Exception {
      ServletActionContext.getResponse()
                    .addCookie(new Cookie("firstName", "Dinesh"));
      return SUCCESS;
   }
}

2) Create the result JSP - cookieWrite.jsp - in the WebContent folder of the web application. The JSP displays the cookie sent in the response

<html>
<head>
<script type="text/javascript">

function readCookie(name) {
   var nameEQ = name + "=";
   var ca = document.cookie.split(';');
   for(var i=0;i < ca.length;i++) {
      var c = ca[i];
      while (c.charAt(0)==' ') 
         c = c.substring(1,c.length);
      if (c.indexOf(nameEQ) == 0) 
         alert("value of " + name + " cookie is " 
                    +  c.substring(nameEQ.length,c.length));
   }
   return null;
}
</script>
</head>
<body>
Setting cookie that came with the response.<br/><br/>
<a href="javascript:readCookie('firstName')" href="#">Read cookie</a>

</body>
</html>

3) Configure the action in the struts.xml configuration file

<action name="cookieWrite" class="info.icontraining.struts2.CookieWriter">
   <result>/cookieWrite.jsp</result>
</action>

4) Test the code by accessing the URL in the browser,

http://localhost:8080/WebAppName/cookieWrite.action

Reading a cookie from the request in Struts2

1) Create an action class - CookieReader.java - in the src folder of the Struts 2 enabled Web Application

package info.icontraining.struts2;

public class CookieReader {
 
   private String message;
   private String userName;
   public static final String SUCCESS = "success";

   public String getUserName() {
      return userName;
   }

   public void setUserName(String userName) {
      this.userName = userName;
   }

   public void setMessage(String message) {
      this.message = message;
   }
   
   public String getMessage() {
      return this.message;
   }
   
   public String execute() throws Exception {
      setMessage("Hello " + getUserName());
      return SUCCESS;
   }
}

2) Create the result JSP - cookieRead.jsp - in the WebContent folder of the web application

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
<title>Cookie Read Example</title>
</head>
<body>
   <h1><s:property value="message"/></h1>
</body>
</html>

3) Configure the action in the struts.xml, along with the configuration for the cookie interceptor. The <param> element indicates the name of the cookie that to be read from the request,

<action name="cookieRead" class="info.icontraining.struts2.CookieReader">
   <result>/cookieRead.jsp</result>
   <interceptor-ref name="cookie">
      <param name="cookiesName">userName</param>
   </interceptor-ref>
</action>

4) Create an .html file to set the cookie on the browser - cookieTest.html - add the file to the WebCon tent folder of the web application

<html>
<head>
<script type="text/javascript">
   document.cookie="userName=dinipc";
</script>
</head>
<body>
Cookie userName set.
</body>
</html>

5) Test the example by first accessing the cookieTest.html from the browser. This will set the cookie.

http://localhost:8080/WebAppName/cookieTest.html

Next, access the cookieRead.jsp from the browser

http://localhost:8080/WebAppName/cookieRead.jsp

September 28, 2011

Changing the Struts2 default .action extension

In order to change the default extension, which is .action, in Struts 2 to something else, configure the <constant> element in the struts.xml configuration file as follows,

<struts>
   
   <constant name="struts.action.extension" value="dud"/>

   <package name="myPackage" extends="struts-default">
   
   ...

   </package>
</struts>

Test the Hello World - Struts 2 example with the following URL in the browser,

http://localhost:8080/WebAppName/Name.dud

Session Management Example in Struts2

0|) Implement the Hello World Example for the Struts 2 framework as explained in this example

1) Modify the execute() method within the HelloWorld.java action class to set a session attribute on the SessionMap object as follows,

public String execute()  {

   ActionContext context = ActionContext.getContext();
     
   ((SessionMap) context.getSession()).put("username", getName());
     
   setCustomGreeting( GREETING + getName() );
   return Action.SUCCESS;
}

2) Modify the Hello.jsp result JSP to add an additional link as follows,

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
  <title>HelloWorld</title>
</head>
<body>

  <h1><s:property value="customGreeting"/></h1>
  <br/><br/>

  <s:a action="Linked">Click here</s:a>
</body>
</html>

3) Add a JSP - linkedPage.jsp - in the WebContent folder of the Web application,

<%@ page contentType="text/html; charset=UTF-8" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
  <title>Linked Page</title>
</head>
<body>
   <h1>In Linked Page: <s:property value="%{#session.username}"/></h1>
</body>
</html>

4) Configure the new action in the struts.xml file as follows,

<action name="Linked">
   <result>/linkedPage.jsp</result>
</action>

5) Test the example with the following URL in the browser,

http://localhost:8080/WebAppName/Name.action

Upload a text/binary file to the server using a Servlet

1) Create the UploadFile.html file in the WebContent folder of the web application.

<html>
<head>
<title>Upload File</title>
</head>
<body>

<form action="uploadServlet" enctype="multipart/form-data" method="post">
Specify a file to upload <br/>
<input type="file" name="datafile" size="40">
<br/>
<input type="submit" value="Upload">
</form>

</body>
</html>

2) Create the UploadServlet.java servlet class in the src folder of the web application.

package info.icontraining.servlets;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class UploadServlet extends HttpServlet {

   public void doPost(HttpServletRequest request, HttpServletResponse response) 
                     throws ServletException, IOException {
  
      PrintWriter out = response.getWriter();
      String contentType = request.getContentType();
  
      if ((contentType != null) 
               && (contentType.indexOf("multipart/form-data") >= 0)) {

         DataInputStream in = new DataInputStream(request.getInputStream());

         InputStream is = request.getInputStream();
         int formDataLength = request.getContentLength();
   
         // copy incoming bytes into a byte array
         byte dataBytes[] = new byte[formDataLength];
         int byteRead = 0;
         int totalBytesRead = 0;

         while (totalBytesRead < formDataLength) {
            byteRead = in.read(dataBytes, totalBytesRead, formDataLength);
            totalBytesRead += byteRead;
         } 

         // retrieve uploaded filename
         String file = new String(dataBytes);
         String saveFile = file.substring(file.indexOf("filename=\"") + 10);
         saveFile = saveFile.substring(0, saveFile.indexOf("\n"));
         saveFile = saveFile.substring(saveFile.lastIndexOf("\\") + 1,
                                          saveFile.indexOf("\""));
   
         // clip off the file content
         int lastIndex = contentType.lastIndexOf("=");
         String boundary = contentType.substring(lastIndex + 1, 
                                          contentType.length());
         int pos;
         pos = file.indexOf("filename=\"");
         pos = file.indexOf("\n", pos) + 1;
         pos = file.indexOf("\n", pos) + 1;
         pos = file.indexOf("\n", pos) + 1;
         int boundaryLocation = file.indexOf(boundary, pos) - 4;
         int startPos = ((file.substring(0, pos)).getBytes()).length;
         int endPos = ((file.substring(0, 
                              boundaryLocation)).getBytes()).length; 

         String outputfile = this.getServletContext().getRealPath(saveFile);
         FileOutputStream os = new FileOutputStream (outputfile);

         os.write(dataBytes, startPos, (endPos - startPos));
         os.flush();
         os.close();

         out.println("You have successfully uploaded the file");
      }
   }
}

3) Configure the servlet in the web.xml deployment descriptor present in the WebContent/WEB-INF folder of the web application

<servlet>
   <servlet-name>uploadServlet</servlet-name>
   <servlet-class>info.icontraining.servlets.UploadServlet</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>uploadServlet</servlet-name>
   <url-pattern>/uploadServlet</url-pattern>
</servlet-mapping>

4) Test the code with the following URL in the browser. The file will be uploaded to the context root (folder) of the web application.

http://localhost:8080/WebAppName/UploadFile.html

Retrieve Request Headers in a Servlet

1) Create a Java Servlet class - HeaderTest.java - in the src folder of the Web Application

package info.icontraining.servlets;

import java.io.*;
import java.util.Enumeration;
import javax.servlet.*;
import javax.servlet.http.*;

public class HeaderTest extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)
                     throws ServletException, IOException {
  
      PrintWriter out = response.getWriter();

      Enumeration e = request.getHeaderNames();
      String headerName = null;

      while(e.hasMoreElements()) {
         headerName = (String) e.nextElement();
         out.println(headerName + ": "); 
         out.println(request.getHeader(headerName) + "\n");
      }
  
      out.close();
   }
}

2) Configure the servlet in the web.xml deployment descriptor in the WebContent/WEB-INF folder

<servlet>
   <servlet-name>headerTest</servlet-name>
   <servlet-class>info.icontraining.servlets.HeaderTest</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>headerTest</servlet-name>
   <url-pattern>/headerTest</url-pattern>
</servlet-mapping>

3) Test the servlet with the following URL in the browser,

http://localhost:8080/WebAppName/headerTest

Servlet Filter - Hello World Example

1) Create a MyFilter.java filter class in the src folder of the Web Application

package info.icontraining.filters;

import java.io.IOException;
import javax.servlet.*;

public class MyFilter implements Filter {

   private FilterConfig filterConfig;
 
   public void init(FilterConfig filterConfig) throws ServletException {
      this.filterConfig = filterConfig;
   }
 
   public void destroy() {
      System.out.println("Clean-up code in Filter");
   }

   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  
      System.out.println("Filter processing request");
      chain.doFilter(request, response);
      System.out.println("Filter processing response");
   }
}

2) Configure the filter in the web.xml deployment description in the WebContent/WEB-INF folder, as follows,

<filter>
   <filter-name>myFilter</filter-name>
   <filter-class>info.icontraining.filters.MyFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>myFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

This filter will intercept requests to all URLs (of servlets, JSPs, etc.) in the Web Application

3) Test the filter by accessing any valid URL (servlet URL or JSP) of the Web Application, and check the server console log,

http://localhost:8080/WebAppName/anyValidURL

September 7, 2011

Java Message Service (JMS) Topic- Hello World Example with MessageListener

1) Configure the JMS Topic in the JBoss 4.2.2GA Server, in the file ${JBOSS_SERVER}/server/default/deploy/jms/jbossmq-destinations-service.xml

<mbean code="org.jboss.mq.server.jmx.Topic"
  name="jboss.mq.destination:service=Topic,name=myTopic1">
  <depends optional-attribute-
  name="DestinationManager">jboss.mq:service=DestinationManager</depends>
</mbean>

Ensure that the name myTopic1 is unique within the XML file

2) The ConnectionFactory administered object is pre-configured with the default JNDI name 'ConnectionFactory' in JBoss

Note: Add the following jar file to the classpath / build path of the Java Project / Application:

%JBOSS_HOME%\client\jbossall-client.jar

3) Create the TopicPublisherClient.java

package info.icontraining.topic;

import javax.jms.*;
import javax.naming.*;
import java.util.*;

public class TopicPublisherClient {

   public static void main(String[] args) {

      TopicConnection conn = null;
      TopicSession session = null;
      Topic topic = null;
   
      try {
         Properties props = new Properties();
         props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.NamingContextFactory");
         props.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
         props.put(Context.PROVIDER_URL, "localhost:1099");
         props.put("java.naming.rmi.security.manager", "yes");

         InitialContext iniCtx = new InitialContext(props);

         Object cf = iniCtx.lookup("ConnectionFactory");
         TopicConnectionFactory tcf = (TopicConnectionFactory) cf;
    
         conn = tcf.createTopicConnection();

         topic = (Topic) iniCtx.lookup("topic/myTopic1");
    
         session = conn.createTopicSession(false, TopicSession.AUTO_ACKNOWLEDGE);
         conn.start();

         TopicPublisher topicPublisher = session.createPublisher(topic);

         TextMessage message = session.createTextMessage();
         message.setText("this is a test message");
         topicPublisher.publish(message);
         System.out.println("Message published.");

         topicPublisher.close();

      } catch (NamingException e) {   
         System.out.println(e.toString());
      } catch (JMSException e) {
         System.out.println("JMS Exception");
      } finally {
         if (conn != null) {
            try {
               conn.close();
            } catch (JMSException e) {}
         }
      }
   }
}

4) Create the TopicSubscriberClient.java

package info.icontraining.topic;

import javax.jms.*;
import javax.naming.*;
import java.util.*;

public class TopicSubscriberClient
{
   public static void main(String[] args) {
      TopicConnection topicConnection = null;
      char answer = '\0';
  
      try 
      {
         Properties props = new Properties();

          props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.NamingContextFactory");
          props.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces");
          props.put(Context.PROVIDER_URL, "localhost:1099");
          props.put("java.naming.rmi.security.manager", "yes");

          Context context = new InitialContext(props);
          TopicConnectionFactory tcf= (TopicConnectionFactory) context.lookup("ConnectionFactory");
          topicConnection = tcf.createTopicConnection();

          String topicName = "topic/myTopic1";
          Topic topic = (Topic) context.lookup(topicName);
   
          TopicSession topicSession = topicConnection.createTopicSession(false,  TopicSession.AUTO_ACKNOWLEDGE);
          topicConnection.start();

          TopicSubscriber topicSubscriber = topicSession.createSubscriber(topic);
   
          topicSubscriber.setMessageListener(new MyMessageListener());

          for(;;) {}
      }
      catch (JMSException e) {
         System.out.println("JMS Exception");
      } catch (Exception e) {
         System.out.println(e.toString());
      } finally {
         if (topicConnection != null) {
            try {
               topicConnection.close();
            } catch (JMSException e) {}
         }
      }
   }

   static class MyMessageListener implements MessageListener { 

      public void onMessage(Message message) {

         TextMessage tm = (TextMessage) message;

         try {
            System.out.println("onMessage==>"+ tm.getText());
         } catch(Throwable t) {
            t.printStackTrace();
         }
      }
   }
}

5) Run multiple instances of TopicSubscriberClient in multiple heaps. Next, run TopicPublisherClient to send the message to the JMS Topic.

September 5, 2011

javax.naming.NoInitialContextException: Cannot instantiate class: org.jboss.naming.NamingContextFactory [Root exception is java.lang.ClassNotFoundException

Topic: Java Message Service (JMS)

Application Server: JBoss 4.2.2 GA

Exception:

javax.naming.NoInitialContextException: Cannot instantiate class: org.jboss.naming.NamingContextFactory [Root exception is java.lang.ClassNotFoundException: org.jboss.naming.NamingContextFactory]
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.init(Unknown Source)
at javax.naming.InitialContext.(Unknown Source)
at info.icontraining.queue.QueueSenderClient.main(QueueSenderClient.java:27)
Caused by: java.lang.ClassNotFoundException: org.jboss.naming.NamingContextFactory
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at com.sun.naming.internal.VersionHelper12.loadClass(Unknown Source)
... 5 more

Resolution:

This exception is thrown with the JMS client code resides outside the JBoss application server. In order to resolve, add the following jar file to the build path / classpath of the application:

%JBOSS_HOME%\client\jbossall-client.jar

August 28, 2011

JSP Life-cycle methods

The 3 life-cycle methods of a JSP are,
  • jspInit()
  • _jspService()
  • jspDestroy()
The jspInit() executes when the object of the JSP servlet class is created by the Container, right after the constructor finishes executing.

The jspDestroy() executes when the JSP Servlet object is removed or taken down by the Container.

The _jspService() method executes everytime a request is sent to the JSP. Code in scriptlets and expressions lands in the _jspService() method.

Code in the JSP declaration element lands outside the _jspService() method but inside the JSP Servlet class, after translation.

The jspInit() and jspDestroy() methods execute only once in the life of the JSP Servlet object. The _jspService() executes n times, where n = number of requests sent to the JSP

Create a JSP - JspLifecycleDemo.jsp - in the WebContent folder of the web application,

<html>
<head>
<title>JSP lifecycle methods</title>
</head>
<body>
<%!
public void jspInit() {
   System.out.println("JSP initialized"); 
}

public void jspDestroy() {
   System.out.println("JSP Destroyed"); 
}
%>

<%= "Inside _jspService() method"  %>

</body>
</html>

Test the code with the following URL in the browser,

http://localhost:8080/WebAppName/JspLifecycleDemo.jsp

Check the server/console log for the output of the jspInit() method. Stopping the server will display the output of the jspDestroy() on the server/console log.

JSP Implicit Objects Demo

The 9 JSP implicit objects are,
  • request (HttpServletRequest)
  • response (HttpServletResponse)
  • out (JspWriter)
  • session (HttpSession)
  • config (ServletConfig)
  • application (ServletContext)
  • page (Object)
  • pageContext (PageContext)
  • exception (Throwable)
Create a JSP - ImplicitObjectsDemo.jsp - in the WebContent folder of the web application,

<html>
<head>
   <title>Implicit Objects Demo</title>
</head>
<body>
<%= "test = " + request.getParameter("test") %>

<% response.setHeader("MyHeader", "MyValue"); %>
<br/><br/>
<%= "Session Id= " + session.getId() %>
<br/><br/>
<%= "Servlet API version supported (through ServletContext): " + application.getMinorVersion() + "." + application.getMinorVersion() %>
<br/><br/>
<%= "The JSP Servlet name (through ServletConfi) " + config.getServletName() %>
<br/><br/>
<%= "JSP Servlet class name (through page) is " + page.getClass().getName() %>

</body>
</html>

Test the code with the following URL in the browser,

http://localhost:8080/WebAppName/ImplicitObjectsDemo.jsp?test=abcd

HttpSessionBindingListener Event Handler Implementation

The HttpSessionBindingListener interface is part of the Servlet API and lets us create an event-handler class that listens to events on an object that is bound to the session object as an attribute, namely, the binding and un-binding of the attribute object to the session.

The HttpSessionBindingEvent object that is passed as an argument to the listener methods provides a handle to the HttpSession object as well as access to the name and value object of the attribute.

1) Create an attribute class that implements the HttpSessionBindingListener interface methods, valueBound() and valueUnbound()

package info.icontraining.servlets;

import javax.servlet.http.*;

public class MyAttribute implements HttpSessionBindingListener {

   String id;
 
   public MyAttribute(String id) {
      this.id = id;
   }
 
   public String getId() {
      return this.id;
   }
 
   public void valueBound(HttpSessionBindingEvent hsbe) {
      HttpSession session = hsbe.getSession();
      System.out.println("Attribute added to session. Id = " + ((MyAttribute)hsbe.getValue()).getId());
   }

   public void valueUnbound(HttpSessionBindingEvent hsbe) {
      System.out.println("Attribute removed from session. Id = " + ((MyAttribute)hsbe.getValue()).getId());
   }
}

2) For the HttpSessionBindingListener class, configuration in the web.xml with the <listener> element is not required.

3) Create a servlet class that adds and removes the attribute to and from the session,

package info.icontraining.servlets;

import java.io.*;
import javax.servlet.http.*;

public class SessionServlet extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

        HttpSession session = request.getSession();
        
        session.setAttribute("newAttr", new MyAttribute("20"));
        session.removeAttribute("newAttr");
   }
}

4) Configure the servlet in the web.xml deployment descriptor,

<servlet>
   <servlet-name>sessionServlet</servlet-name>
   <servlet-class>info.icontraining.servlets.SessionServlet</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>sessionServlet</servlet-name>
   <url-pattern>/sessionServlet</url-pattern>
</servlet-mapping>

5) Test the example with the following URL in the browser, and check the server/console log

http://localhost:8080/WebAppName/sessionServlet

ServletRequestAttributeListener Event Handler Implementation

The ServletRequestAttributeListener interface is part of the Servlet API and lets us create an event-handler class that listens to events on the ServletRequest object, namely, the addition, removal and replacement of attributes on the request object.

The ServletRequestAttributeEvent Event object that is passed as an argument to the listener methods provides a handle to the ServletRequest object and the name and value object of the attribute.

1) Create a class that implements the ServletRequestAttributeListener interface methods, attributeAdded(), attributeRemoved() and attributeReplaced()

package info.icontraining.servlets.listeners;

import javax.servlet.*;
import javax.servlet.http.*;

public class MyRequestAttributeListener implements ServletRequestAttributeListener {

   public void attributeAdded(ServletRequestAttributeEvent srae) {
      System.out.println("New request attribute added");
      HttpServletRequest request = (HttpServletRequest) srae.getServletRequest();
      System.out.println("Name of Attribute added: " + srae.getName());
      System.out.println("Value of Attribute added: " + srae.getValue());
   }

   public void attributeRemoved(ServletRequestAttributeEvent srae) {
      System.out.println("Request attribute Removed");
      System.out.println("Name of Attribute removed: " + srae.getName());
      System.out.println("Value of Attribute removed: " + srae.getValue());
   }

   public void attributeReplaced(ServletRequestAttributeEvent srae) {
      System.out.println("Request attribute Replaced");
      System.out.println("Name of Attribute replaced: " + srae.getName());
      System.out.println("Value of Attribute replaced: " + srae.getValue());
   }
}

2) Configure the listener in the web.xml deployment descriptor,

<listener>
   <listener-class>    
      info.icontraining.servlets.listeners.MyRequestAttributeListener
   </listener-class>
</listener>

3) Create a servlet class that handles a request,

package info.icontraining.servlets;

import java.io.*;
import javax.servlet.http.*;

public class RequestListenerServlet extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
      request.setAttribute("attr1", "value1");
      request.setAttribute("attr1", "value2");
      request.removeAttribute("attr1");
   }
}

4) Configure the servlet in the web.xml deployment descriptor,

<servlet>
   <servlet-name>requestListenerServlet </servlet-name>
   <servlet-class>info.icontraining.servlets.RequestListenerServlet </servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>requestListenerServlet </servlet-name>
   <url-pattern>/RequestListenerServlet </url-pattern>
</servlet-mapping>

5) Test the example with the following URL in the browser, and check the server/console log

http://localhost:8080/WebAppName/requestListenerServlet

ServletRequestListener Event Handler Implementation

The ServletRequestListener interface is part of the Servlet API and lets us create an event-handler class that listens to events on the ServletRequest object, namely, the request object creation and destruction.

TheServletRequest Event object that is passed as an argument to the 2 listener methods provides a handle to the ServletRequest object.

1) Create a class that implements the ServletRequestListener interface methods, requestInitialized() and requestDestroyed()

package info.icontraining.servlets.listeners;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;

public class MyServletRequestListener implements ServletRequestListener{

   public void requestDestroyed(ServletRequestEvent sre) {
      System.out.println("Request serviced & object destroyed by container");
   }

   public void requestInitialized(ServletRequestEvent sre) {
      System.out.println("New Request received and object created");
      HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
      // do something when a new request arrives
   }
}
2) Configure the listener in the web.xml deployment descriptor,

<listener>
   <listener-class>    
      info.icontraining.servlets.listeners.MyServletRequestListener
   </listener-class>
</listener>

3) Create a servlet class that handles a request,

package info.icontraining.servlets;

import java.io.*;
import javax.servlet.http.*;

public class RequestListenerServlet extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
      request.setAttribute("attr1", "value1");
      request.setAttribute("attr1", "value2");
      request.removeAttribute("attr1");
   }
}

4) Configure the servlet in the web.xml deployment descriptor,

<servlet>
   <servlet-name>requestListenerServlet </servlet-name>
   <servlet-class>info.icontraining.servlets.RequestListenerServlet </servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>requestListenerServlet </servlet-name>
   <url-pattern>/RequestListenerServlet </url-pattern>
</servlet-mapping>

5) Test the example with the following URL in the browser, and check the server/console log

http://localhost:8080/WebAppName/requestListenerServlet

HttpSessionAttributeListener Event Handler Implementation

The HttpSessionAttributeListener interface is part of the Servlet API and lets us create an event-handler class that listens to events on the HttpSession object, namely, the addition, removed and replacement of attributes on the HttpSession object.

The HttpSessionBindingEvent object that is passed as an argument to the 2 listener methods provides a handle to the HttpSession object as well as access to the name and value object of the attribute.

1) Create a class that implements the HttpSessionAttributeListener interface methods, attributeAdded(), attributeRemoved() and attributeReplaced()

package info.icontraining.servlets.listeners;

import javax.servlet.http.*;

public class MySessionAttrListener implements HttpSessionAttributeListener {

   public void attributeAdded(HttpSessionBindingEvent hsbe) {
      System.out.println("New Session attribute added");
      HttpSession session = hsbe.getSession();
      System.out.println("Name of Attribute added: " + hsbe.getName());
      System.out.println("Value of Attribute added: " + hsbe.getValue());
   }

   public void attributeRemoved(HttpSessionBindingEvent hsbe) {
      System.out.println("Session attribute Removed");
      System.out.println("Name of Attribute removed: " + hsbe.getName());
      System.out.println("Value of Attribute removed: " + hsbe.getValue());
   }

   public void attributeReplaced(HttpSessionBindingEvent hsbe) {
      System.out.println("Session attribute replaced");
      System.out.println("Name of Attribute replaced: " + hsbe.getName());
      System.out.println("Value of Attribute replaced: " + hsbe.getValue());
   } 
}
2) Configure the listener in the web.xml deployment descriptor,

<listener>
   <listener-class>    
      info.icontraining.servlets.listeners.MySessionAttrListener
   </listener-class>
</listener>

3) Create a servlet class that starts a session and adds, replaces and removes a session attribute,

package info.icontraining.servlets;

import java.io.*;
import javax.servlet.http.*;

public class SessionServlet extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response)  
   throws IOException {

      HttpSession session = request.getSession();
      session.setAttribute("attr1", "value1");
      session.setAttribute("attr1", "value2");
      session.removeAttribute("attr1");
      session.invalidate();
   }
}

4) Configure the servlet in the web.xml deployment descriptor,

<servlet>
   <servlet-name>sessionServlet</servlet-name>
   <servlet-class>info.icontraining.servlets.SessionServlet</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>sessionServlet</servlet-name>
   <url-pattern>/sessionServlet</url-pattern>
</servlet-mapping>

5) Test the example with the following URL in the browser, and check the server/console log

http://localhost:8080/WebAppName/sessionServlet

HttpSessionListener Event Handler Implementation

The HttpSessionListener interface is part of the Servlet API and lets us create an event-handler class that listens to events on the HttpSession object, namely, the HttpSession object creation and destruction.

The HttpSessionEvent object that is passed as an argument to the 2 listener methods provides a handle to the HttpSession object in order to set any attributes.

1) Create a class that implements the HttpSessionListener interface methods, sessionCreated() and sessionDestroyed()

package info.icontraining.servlets.listeners;

import javax.servlet.http.*;

public class MySessionListener implements HttpSessionListener {

   public void sessionCreated(HttpSessionEvent se) {
      System.out.println("Created new session with client");
      HttpSession session = se.getSession();
      System.out.println("Printing Session Id: " + session.getId());
   }

   public void sessionDestroyed(HttpSessionEvent se) {
      System.out.println("Session "+ se.getSession().getId() +" ended");
   }
}

2) Configure the listener in the web.xml deployment descriptor,

<listener>
   <listener-class>    
      info.icontraining.servlets.listeners.MySessionListener
   </listener-class>
</listener>

3) Create a servlet class that starts a session

package info.icontraining.servlets;

import java.io.*;
import javax.servlet.http.*;

public class SessionServlet extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
      HttpSession session = request.getSession();
      session.invalidate();
   }
}

4) Configure the servlet in the web.xml deployment descriptor,

<servlet>
   <servlet-name>sessionServlet</servlet-name>
   <servlet-class>info.icontraining.servlets.SessionServlet</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>sessionServlet</servlet-name>
   <url-pattern>/sessionServlet</url-pattern>
</servlet-mapping>

5) Test the example with the following URL in the browser, and check the server/console log

http://localhost:8080/WebAppName/sessionServlet

ServletContextAttributeListener Event Handler Implementation

The ServletContextAttributeListener interface is part of the Servlet API and lets us create an event-handler class that listens to events on the ServletContext object, namely, addition, removal and replacement of attributes on the ServletContext.

The ServletContextAttributeEvent object that is passed as an argument to the 2 listener methods provides a handle to the ServletContext object and the name and value object of the attribute.

1) Create a class that implements the ServletContextAttributeListener interface methods, attributeAdded(), attributeReplaced() and attributeRemoved()

package info.icontraining.servlets.listeners;

import javax.servlet.*;

public class MyContextAttributeListener implements ServletContextAttributeListener {

   public void attributeAdded(ServletContextAttributeEvent scae) {
      System.out.println("New Context attribute added");
      ServletContext sc = scae.getServletContext();
      System.out.println("Name of Attribute added: " + scae.getName());
      System.out.println("Value of Attribute added: " + scae.getValue());
   }

   public void attributeRemoved(ServletContextAttributeEvent scae) {
      System.out.println("Context attribute removed");
      System.out.println("Name of Attribute removed: " + scae.getName());
      System.out.println("Value of Attribute removed: " + scae.getValue());
   }

   public void attributeReplaced(ServletContextAttributeEvent scae) {
      System.out.println("Context attribute replaced");
      System.out.println("Name of Attribute replaced: " + scae.getName());
      System.out.println("Value of Attribute replaced: " + scae.getValue());
   }
}


2) Configure the listener in the web.xml deployment descriptor,

<listener>
   <listener-class>    
      info.icontraining.servlets.listeners.MyContextAttributeListener
   </listener-class>
</listener>

3) Create a servlet class that adds, replaces and removes an attribute from the ServletContext

package info.icontraining.servlets;

import java.io.*;

import javax.servlet.ServletContext;
import javax.servlet.http.*;

public class ContextAttribute extends HttpServlet {

   public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
      ServletContext sc = getServletContext();
      sc.setAttribute("attr1", "value1");
      sc.setAttribute("attr1", "value2");
      sc.removeAttribute("attr1");  
   }
}

4) Configure the servlet in the web.xml deployment descriptor,

<servlet>
   <servlet-name>contextAttribute</servlet-name>
   <servlet-class>info.icontraining.servlets.ContextAttribute</servlet-class>
</servlet>
<servlet-mapping>
   <servlet-name>contextAttribute</servlet-name>
   <url-pattern>/contextAttribute</url-pattern>
</servlet-mapping>

5) Test the example with the following URL in the browser, and check the server/console log

http://localhost:8080/WebAppName/contextAttribute

ServletContextListener Event Handler Implementation

The ServletContextListener interface is part of the Servlet API and lets us create an event-handler class that listens to events on the ServletContext object, namely, the ServletContext object creation/initialization and the ServletContext object destruction.

The ServletContextEvent object that is passed as an argument to the 2 listener methods provides a handle to the ServletContext object in order to set any attributes.

1) Create a class that implements the ServletContextListener interface methods, contextInitialized () and contextDestroyed()

package info.icontraining.servlets.listeners;

import javax.servlet.*;

public class MyServletContextListener implements ServletContextListener {
   public void contextInitialized(ServletContextEvent sce) {
      System.out.println("Servlet Context created");

      // code to acquire resource, to set as 
      // attr in application scope

      ServletContext sc = sce.getServletContext();
      sc.setAttribute("attr-name", "attr-value");
   }

   public void contextDestroyed(ServletContextEvent sce) {
      // any clean-up code
      System.out.println("Servlet Context destroyed");
   }
}

2) Configure the listener in the web.xml deployment descriptor,

<listener>
   <listener-class>    
      info.icontraining.servlets.listeners.MyServletContextListener
   </listener-class>
</listener>

3) Deploy the application to the Application Server/ Web Container and check in the server/console log for the following output,

INFO  [STDOUT] Servlet Context created

July 21, 2011

XML Namespaces example with 2 XML Schemas (XSDs)

A working example of a XML document that references and contains elements from 2 XML Schema Documents (XSDs). Both the XSDs contain an element with a common name, demonstrating the utility of XML namespaces.

XSD-1: schema01.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           xmlns:s="http://example.org/s">

   <xs:import namespace="http://example.org/s" 
              schemaLocation="schema02.xsd"/>

   <xs:element name="root" type="RootType"/>

   <xs:complexType name="RootType">
     <xs:sequence>
       <xs:element name="qty" type="xs:integer" maxOccurs="unbounded"/>
       <xs:element ref="s:qty" maxOccurs="unbounded"/>
     </xs:sequence>
   </xs:complexType>
</xs:schema>

XSD-2: schema02.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
       targetNamespace="http://example.org/s"t
       xmlns:s="http://example.org/s"
       elementFormDefault="qualified">

   <xs:element name="qty" type="xs:string"/>

</xs:schema>

XML: test.xml

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:noNamespaceSchemaLocation="schema01.xsd" 
       xmlns:s="http://example.org/s">
   <qty>12</qty>
   <s:qty>Twelve</s:qty>
</root>

July 20, 2011

Creating a new XML document with DOM Parser and persisting the DOM Tree

The following code example demonstrates the power of the DOM Parser by creating an XML document on-the-fly with the create methods from the DOM Parser API - something that is not possible to do with a SAX Parser. The code also shows how to take a DOM Tree and convert it to a String (XML content). This String can then be persisted to an XML document file.

package info.icontraining.parsers;

import java.io.StringWriter;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
import org.xml.sax.*;

public class DOMParserNewDocument implements ErrorHandler {
   public static void main(String[] args) throws TransformerException {

      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

      try {
         factory.setNamespaceAware(true);
         factory.setValidating(true);

         DocumentBuilder dom = factory.newDocumentBuilder();            
         dom.setErrorHandler(new DOMParserNewDocument());
         Document doc = dom.newDocument();

         Element invoiceElement = doc.createElement("Invoice");
         Attr invoiceNumberAttr = doc.createAttribute("invoice-number");
         invoiceNumberAttr.setNodeValue("123456");
         invoiceElement.setAttributeNode(invoiceNumberAttr);
         doc.appendChild(invoiceElement);

         Element dateElement = doc.createElement("date");         
         Element monthElement = doc.createElement("month");         
         Element dayElement = doc.createElement("day");
         Element yearElement = doc.createElement("year");

         monthElement.appendChild(doc.createTextNode("July"));
         dayElement.appendChild(doc.createTextNode("22"));
         yearElement.appendChild(doc.createTextNode("2011"));

         dateElement.appendChild(monthElement);          
         dateElement.appendChild(dayElement);
         dateElement.appendChild(yearElement);

         invoiceElement.appendChild(dateElement);  
         // convert DOM tree to XML string
   
         Transformer transformer =
                        TransformerFactory.newInstance().newTransformer();
         transformer.setOutputProperty(OutputKeys.INDENT, "yes");

         StreamResult result = new StreamResult(new StringWriter());
         DOMSource source = new DOMSource(doc);
         transformer.transform(source, result);

         String xmlString = result.getWriter().toString();
         System.out.println(xmlString);
     
      } catch (ParserConfigurationException e) {
         e.printStackTrace();
      } 
   }
 
   public void fatalError(SAXParseException err)
        throws SAXException {
      System.out.println("** Fatal Error"
                          + ", line " + err.getLineNumber()
                          + ", uri " + err.getSystemId());
      System.out.println(" " + err.getMessage());
   }

   public void error(SAXParseException err)        
         throws SAXParseException {
      System.out.println("** Error"
                          + ", line " + err.getLineNumber()
                          + ", uri " + err.getSystemId());
      System.out.println(" " + err.getMessage());
   }

   public void warning(SAXParseException err)         
        throws SAXParseException {
      System.out.println("** Warning"
                          + ", line " + err.getLineNumber()
                          + ", uri " + err.getSystemId());
      System.out.println(" " + err.getMessage());
   }
}

Parsing XML with a DOM Parser

The DOM Parser in the example code below is a validating parser. The parser code, processes the element, attribute and the text nodes of the document and prints them to the console (while ignoring the rest of the XML artifacts). It does not modify the XML document eventhough it maintains an in-memory representation of the XML Document.

package info.icontraining.parsers;

import java.io.IOException;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.xml.sax.*;

public class DOMParserWithDTD implements ErrorHandler {
 
   public static void main(String[] args) throws SAXException, IOException  {
  
      DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  
      try {
         factory.setNamespaceAware(true);
         factory.setValidating(true);
         factory.setFeature("http://apache.org/xml/features/validation/schema", true);
         factory.setIgnoringElementContentWhitespace(true);
   
         DocumentBuilder dom = factory.newDocumentBuilder();
         dom.setErrorHandler(new TestDOMParser());
         Document doc = dom.parse("Invoice.xml");
   
         processNode(doc);

      } catch (ParserConfigurationException e) {
         e.printStackTrace();
      }     
   } 
   
   private static void processNode(Node node) {

      NodeList list = node.getChildNodes();   
      for(int i=0; i<list.getLength(); i++) {
 
         if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
            processElementNode(list.item(i));
            processNode(list.item(i));
         }
   
         if (list.item(i).getNodeType() == Node.TEXT_NODE) {
            processTextNode(list.item(i));
         }
      }
   }
 
   private static void processTextNode(Node text) {  
      if (text.getNodeValue().trim().length() != 0)
         System.out.println(text.getNodeValue().trim());
   }    

   private static void processElementNode(Node element) {
  
      String temp = "";
      temp = temp + "<" + element.getNodeName();
  
      if (element.hasAttributes()) {
         NamedNodeMap map = element.getAttributes();
        
         for(int i=0; i<map.getLength(); i++) {
            temp = temp + " " + map.item(i).getNodeName();
            temp = temp + "=\"" + map.item(i).getNodeValue() + "\"";
         }
      }
  
      temp = temp + ">";
      System.out.println(temp);
   }
 
   public void fatalError(SAXParseException err) throws SAXException {

      System.out.println("** Fatal Error" 
                          + ", line " + err.getLineNumber() 
                          + ", uri " + err.getSystemId());
      System.out.println(" " + err.getMessage());
   }     

   public void error(SAXParseException err) throws SAXParseException {
      System.out.println("** Error" 
                          + ", line " + err.getLineNumber() 
                          + ", uri " + err.getSystemId());
      System.out.println(" " + err.getMessage());
   }

   public void warning(SAXParseException err) throws SAXParseException {
      System.out.println("** Warning" 
                          + ", line " + err.getLineNumber()              
                          + ", uri " + err.getSystemId());
      System.out.println(" " + err.getMessage());
   }
}

July 18, 2011

Access outer class instance from within the inner class method

MyOuter is the outer class which contains MyInner which is the inner class. The seeOuter() method within the inner class can access the inner class instance with the this keyword. In order to access the outer class instance from within the seeOuter() method, the syntax is use the outer class name with the this keyword - the syntax looks like this: OuterClassName.this

The code example below demonstrates the same,

package info.icontraining.basic;

public class MyOuter {
     private int x = 3;
 
   class MyInner {
      private int x = 5;
  
      public void seeOuter() {
         System.out.println("Inner x is = " + this.x);
         System.out.println("Outer x is = " + MyOuter.this.x );
      }
   }
 
   public static void main(String[] args) {
      MyOuter.MyInner inner = new MyOuter().new MyInner();
      inner.seeOuter();
   }
}

July 16, 2011

Externalizing literal values from the applicationContext.xml into a properties file

0) Refer to the example for wiring collections into a spring bean here

1) Add the following configuration in the applicationContext.xml to enable externalizing literal values into a properties file

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location"   
       value="classpath:resources/MessageResources.properties" />
</bean>

2) Add a new properties file - MessageResources.properties in the resources package (within the src folder). Add the following contents in the MessageResources.properties

list.string1=String 1 externalized
list.string2=String 2 externalized
list.string3=String 3 externalized

3) Modify the configuration for the bean in the wiring collections example, in the applicationContext.xml, as follows,

<bean id="listExample"
         class="info.icontraining.spring.CollectionsExample">
   <property name="myList">
      <list>
         <value>${list.string1}</value>
         <value>${list.string2}</value>
         <value>${list.string3}</value>
      </list>
   </property>
   <property name="myMap">
      <map>
         <entry key="key1" value="value1" />
         <entry key="key2" value="value2" />
         <entry key="key3" value="value3" />
      </map>
   </property>
</bean>

4) Test the code with the following URL in the browser,

http://localhost:8080/TestWebApp/springTest.jsp

Wiring Collections in a Spring bean

0) Setup the Spring framework in the web application by executing the Hello World example at this link

1) Create the interface for the spring bean, ICollections.java, as follows,

package info.icontraining.spring;

public interface ICollections {
   public void printList();
   public void printMap();
}

2) Create a spring bean class, CollectionsExample.java as follows,

package info.icontraining.spring;

import java.util.*;

public class CollectionsExample implements ICollections {

   List list;
   Map map;
 
   public void printList() {
      for(String s: list) {
         System.out.println(s);
      }
   }
 
   public void printMap() {
      for(String s: map.keySet()) {
         System.out.println(s + ": " + map.get(s));
      }
   }
 
   public void setMyList(List list) {
      this.list = list;
   }
 
   public void setMyMap(Map map) {
      this.map = map;
   }
}

3) Add the following configuration for the spring bean in the applicationContext.xml file in WebContent/WEB-INF folder - this configuration injects a List and a Map into the spring bean.

<bean id="listExample" class="info.icontraining.spring.CollectionsExample">
   <property name="myList">
      <list>
         <value>String 1</value>
         <value>String 2</value>
         <value>String 3</value>
      </list>
   </property>
   <property name="myMap">
      <map>
         <entry key="key1" value="value1" />
         <entry key="key2" value="value2" />
         <entry key="key3" value="value3" />
      </map>
   </property>
</bean>

4) Create a JSP, springTest.jsp as follows,

<%@ page  import="org.springframework.context.*,org.springframework.web.context.*,info.icontraining.spring.*"%>
<html>
<body>
View output on Server console
<%
ApplicationContext factory =
  (ApplicationContext) this.getServletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); ICollections collection = (ICollections)factory.getBean("listExample");
collection.printList();
collection.printMap();
%>

</body>
</html>

5) Test the example with the following URL in the browser,

http://localhost:8080/WebAppName/springTest.jsp

Struts 2 - Spring framework Integration - Hello World Example

0) Ensure that both Struts 2 and Spring are setup in the web application. For Struts 2-enable the web application, refer this link and to Spring-enable the web application refer this link.

1) Download the Struts-Spring plugin jar from the link here and copy it in the WebContent/WEB-INF/lib folder of the web application

2) Modify the Struts 2 filter configuration in the web.xml file as follows,

<filter>
   <filter-name>struts2</filter-name>
   <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>

3) Copy the following configuration for the action element in the struts.xml file. The class attribute of the action element is assigned to the bean id from the applicationContext.xml rather than the actual class name

<action name="hello" class="greetingService">
   <result>/successSpring.jsp</result>
</action>

4) Modify the GreetingServiceImpl.java class to enter the following execute() and getGreeting() methods,

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

public String getGreeting() {
   return this.greeting;
}

5) Create a JSP - successSpring.jsp - in the WebContent folder of the web application

<%@taglib uri="/struts-tags" prefix="s"%>
<html>
<body>   <s:property value="greeting" />
</body>
</html>

6) Test the example with the following URL in the browser,

http://localhost:8080/WebAppName/hello.action

July 14, 2011

Declarative Exception Handling in Struts 2

1) Create an action class - ErrorProne.java - and place it in the src folder of the Web Application. The execute() method of this class throws an exception,

package info.icontraining.struts2;

public class ErrorProne { 
   public String execute() throws Exception {
      throw new Exception ( "Routine Code Explosion");
   }
}

2) Configure the action in the struts.xml file within the package element

<package ... >
   ...
   <global-results>
      <result name="Error">/error-struts2.jsp</result>
   </global-results>

   <global-exception-mappings>
      <exception-mapping exception="java.lang.Exception" result="Error"/>
   </global-exception-mappings>
   ...
   <action name="ErrorProne" class="info.icontraining.struts2.ErrorProne">
   ...
</package>

3) Create the custom JSP that will be displayed when the exception occurs - error-struts2.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<body>
  <p>This is a custom error page that displays when an Exception is thrown in any Struts2 component</p>
  <br/>
  <s:property value="%{exception.message}" />
  <s:property value="%{exceptionStack}" />
</body>
</html>

3) Test the code with the following URL in the browser,

http://localhost:8080/WebAppName/ErrorProne.action

Struts 2 - Creating a custom logging interceptor

1) Create a class that implements the Interceptor interface and implement the intercept() method

package info.icontraining.struts2;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

public class MyLoggingInterceptor implements Interceptor {

   public void destroy() { }

   public void init() { }

   public String intercept(ActionInvocation invocation) throws Exception {

      // pre-processing task
      String className = invocation.getAction().getClass().getName();
      long startTime = System.currentTimeMillis();  
      System.out.println("Before calling action: " + className);
  
      // invoking the next interceptor or the action
      String result = invocation.invoke();
  
      // post-processing task
      long endTime = System.currentTimeMillis();
      System.out.println("After calling action: " + className
  + " Time taken: " + (endTime - startTime) + " ms");
  
      return result;
   }
}

2) Configure the created interceptor in the struts.xml file. Make sure that this configuration appears at the top of the XML file within the <package> element

...
<package name="myPackage" extends="struts-default">

   <interceptors>
      <interceptor name="myLogger" 
         class="info.icontraining.struts2.MyLoggingInterceptor" />

      <interceptor-stack name="myStack">
         <interceptor-ref name="myLogger" />
         <interceptor-ref name="defaultStack" />
      </interceptor-stack>   
   </interceptors>

   <default-interceptor-ref name="myStack" />

   ...
</package>
...

3) Test the interceptor with any URL that invokes a Struts2 action. Check the server console for output statements from the interceptor.

http://localhost:8080/WebAppName/AnyAction.action

Struts 2 - Front-end validation with the Validation Framework

In this code example, we replace the validate() method for basic validation method in the example here with the validation framework.

Front-end validation with the Validation framework lets us configure the validations in a XML file (validation meta-data) and re-use the various, default validators that are provided by the framework.

1) Create the FeedbackForm.jsp and FeedbackDone.jsp files in the WebContent folder of the Web Application

FeedbackForm.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<body>
<h4>Enter Feedback</h4>
  <s:form action="PostFeedback">
     <s:textfield name="emailAddress" label="Email Address" />
     <s:textfield name="phoneNumber" label="Phone Number" />
     <s:textarea name="message" label="Message" cols="20" rows="4" />
     <s:submit/>
  </s:form>
</body>
</html>

FeedbackDone.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<body>
<h3>Your feedback is as follows</h3>
   <s:property value="emailAddress"/><br/>
   <s:property value="phoneNumber"/><br/>
   <s:property value="message"/><br/>
</body>
</html>

2) Create the action class - Feedback.java - in the src folder of the Web Application.

package info.icontraining.struts2;

import com.opensymphony.xwork2.*;

public class Feedback extends ActionSupport {

   public String execute() { 
      return Action.SUCCESS;
   }
 
   private String emailAddress;
   private String phoneNumber;
   private String message;
 
   public String getEmailAddress() {
      return emailAddress;
   }
   public void setEmailAddress(String emailAddress) {
      this.emailAddress = emailAddress;
   }
 
   public String getPhoneNumber() {
      return phoneNumber;
   }
   public void setPhoneNumber(String phoneNumber) {
      this.phoneNumber = phoneNumber;
   }
 
   public String getMessage() {
      return message;
   }
   public void setMessage(String message) {
      this.message = message;
   }
}

3) Configure the actions in the struts.xml configuration file,

<action name="Feedback" >
   <result>/FeedbackForm.jsp</result>
</action>
  
<action name="PostFeedback" class="info.icontraining.struts2.Feedback">
   <result>/FeedbackDone.jsp</result>
   <result name="input">/FeedbackForm.jsp</result>
</action>

4) Add a new validation framework XML configuration file for the action. This file should be added inside the package where the action class is present along with the properties file. The properties file will prevent the hard-coding of error messages inside the XML configuration file.

The naming convention for the Validation XML file for Struts 2 is ActionClassName-validation.xml
Therefore, create a file, Feedback-validation.xml and add it to the package in which the action class Feedback.java is present

<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
   <field name="emailAddress">
      <field-validator type="requiredstring">
         <message>Please enter email address</message>
      </field-validator>
      <field-validator type="email">
         <message key="email.invalid" />
      </field-validator>
   </field>
   <field name="phoneNumber">
      <field-validator type="requiredstring">
         <message>Please enter phone number</message>
      </field-validator>
      <field-validator type="regex">
         <param name="expression"><![CDATA[^(\d){3}-(\d){3}-(\d){4}$]]></param>
         <message key="phone.invalid" />
      </field-validator>
   </field>
   <field name="message">
      <field-validator type="requiredstring">
         <message>Please enter message</message>
      </field-validator>
   </field>
</validators>

5) Add the Feedback.properties tile to the package in which the action class Feedback.java is present

email.invalid=Please enter valid email
phone.invalid=Please enter valid phone (xxx-xxx-xxxx)

6) Access the action by typing the following URL in the browser,

http://localhost:8080/WebAppName/Feedback.action

July 5, 2011

DispatchAction functionality in Struts2

In Struts 1.x, the in-built DispatchAction action allows us to group similar functional actions/requests into a single action.

1) In Struts 2, every action class is equipped to provide this functionality. First, there should be several methods (based on functions) similar in signature to the execute() method in the action class.

package info.icontraining.struts2;

import com.opensymphony.xwork2.*;

public class UserAction extends ActionSupport {

   private String message;

   public String execute() {
      message = "Inside execute method";
      return SUCCESS;
   }

   public String add() {
      message = "Inside add method";
      return SUCCESS;
   }

   public String update() {
      message = "Inside update method";
      return SUCCESS;
   }

   public String delete() {
      message = "Inside delete method";
      return SUCCESS;
   }

   public String getMessage() {
      return message;
   }

   public void setMessage(String message) {
      this.message = message;
   }
}

2) For each of the additional methods such as add(), update(), etc., other than the execute() method, that we would want to be executed on a client invocation, add a separate <action> element configuration in the struts.xml file

<action name="User" class="info.icontraining.struts2.UserAction">
   <result name="success">/success.jsp</result>
</action>

<action name="addUser" method="add" class="info.icontraining.struts2.UserAction">
   <result name="success">/success.jsp</result>
</action>

<action name="updateUser" method="update" class="info.icontraining.struts2.UserAction">
   <result name="success">/success.jsp</result>
</action>

<action name="deleteUser" method="delete" class="info.icontraining.struts2.UserAction">
   <result name="success">/success.jsp</result>
</action>

3) Add the following JSPs to invoke the respective methods (functions) in the action class. By default, the execute() method is invoked.

userActions.jsp

<%@taglib uri="/struts-tags" prefix="s"%>

<html>
<body><s:form action="User">
   <s:submit />
   <s:submit action="addUser" value="Add User" />
   <s:submit action="updateUser" value="Update User" />
   <s:submit action="deleteUser" value="Delete User" />
</s:form>
</body>
</html>

success.jsp

<%@taglib uri="/struts-tags" prefix="s"%>

<html>
<body>
   <s:property value="message" />
</body>
</html>

4) Test the code with the following URL in the browser,

http://localhost:8080/WebAppName/userActions.jsp