Struts 2 Control Tags Example Tutorial

We learned about Struts 2 Data tags in the last post, today we will look into the control tags provided by Struts 2 framework.

Control tags are used for manipulation and navigation of data from a collection. Some of the important Struts 2 control tags are:

  1. if-elseif-else tags: These are the basic control tags used for conditional logic in result pages. elseif and else tags always work with if tags. if and elseif tags have test attribute where we can provide expression that should result in boolean values, true or false. Example usage is:
    <s:if test="expression">
    //do something
    </s:if>
    <s:elseif test="expression">
    //do something
    </s:elseif>
    <s:else>
    //do something
    </s:else>
    

    else tag doesn’t have any attribute.

  2. iterator tag: We can use iterator tag to loop through a collection of objects. The collection could be array, list, map etc. iterator tags provide option to define a variable in the ActionContext with status attribute. IteratorStatus provides the current status of iterator and expose some methods to get count, odd or even, first or last element etc. Example usage is:
    <s:iterator value="list" status="itStatus">
        <s:property/>
    </s:iterator>
    

    For iterating a map, we need to provide property tag value as key and value.

    <s:iterator value="map">
    Key=<s:property value="key"/>, Value=<s:property value="value"/><br>
    </s:iterator>
    

    The other control tags are provided to work with iterators.

  3. append tag: This tag can be used to append multiple lists and then use them in iterator. The lists to append are provided with param tag and lists are appended one after another. So first list elements will be retrieved first by iterator then second list elements and so on. Example usage is:
    <s:append var="myList">
    	<s:param value="list1"></s:param>
    	<s:param value="list2"></s:param>
    </s:append>
    <s:iterator value="#myList">
    	<s:property/>
    </s:iterator>
    
  4. merge tag: We can use merge tag to merge multiple lists. The first elements from all the lists are merged first, then second element and so on. We can use merge tag like below.
    <s:merge var="myList">
    	<s:param value="list1"></s:param>
    	<s:param value="list2"></s:param>
    </s:merge>
    <s:iterator value="#myList">
    	<s:property/><br>
    </s:iterator>
    
  5. sort tag: We can use sort tag to get the sorted list. We need to provide a comparator to be used for sorting the list. We can use it like below.
    <s:bean name="MyComparator" var="myComparator"></s:bean>
    <s:sort comparator="#myComparator" source="list">
    <s:iterator>
    	<s:property/><br>
    </s:iterator>
    </s:sort>
    
  6. subset tag: We can use subset tag to get the subset of an iterator. We need to provide a Decider implementation that will be used by subset tag to filter elements as whether to include them in iterator or not. We can use it like below.
    <s:subset source="list" decider="myDecider">
    <s:iterator>
    <s:property/><br>
    </s:iterator>
    </s:subset>
    
  7. generator tag: We can use generator tag to create an iterator from given values. We can provide separator to use the delimiter for the values and we can also provide Converter implementation to convert the String to an Object. We can use it like below.
    <s:generator val="%{'1,2,3'}" separator="," var="intsIterator" />
    <s:iterator value="#intsIterator">
         <s:property /><br/>
    </s:iterator>
    

Let’s see control tags in action with a simple struts 2 project. Our project structure will look like below image.

struts2-control-tags-project

Configuration Files

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>Struts2ControlTagsExample</display-name>

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

	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Struts2ControlTagsExample</groupId>
  <artifactId>Struts2ControlTagsExample</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
  	<dependencies>
		<dependency>
			<groupId>org.apache.struts</groupId>
			<artifactId>struts2-core</artifactId>
			<version>2.3.15.1</version>
		</dependency>
	</dependencies>
  
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
          <source>1.6</source>
          <target>1.6</target>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.3</version>
        <configuration>
          <warSourceDirectory>WebContent</warSourceDirectory>
          <failOnMissingWebXml>false</failOnMissingWebXml>
        </configuration>
      </plugin>
    </plugins>
    <finalName>${project.artifactId}</finalName>
  </build>
</project>
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
	"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
	"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="false"></constant>
<constant name="struts.convention.result.path" value="/"></constant>

<package name="user" namespace="/" extends="struts-default">
	<action name="home" class="com.journaldev.struts2.actions.HomeAction">
	<result name="success">/home.jsp</result>
	</action>

</package>

</struts>

Configuration files are self explanatory and used to configure Struts2 framework and action configuration for our example.

Java Bean

package com.journaldev.struts2.model;

import java.util.List;
import java.util.Map;

public class Employee {

	private int id;
	private String role;
	
	private List<String> citiesList;
	private List<String> countryList;
	private Map<String, String> propertiesMap;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getRole() {
		return role;
	}
	public void setRole(String role) {
		this.role = role;
	}
	public Map<String, String> getPropertiesMap() {
		return propertiesMap;
	}
	public void setPropertiesMap(Map<String, String> properties) {
		this.propertiesMap = properties;
	}
	public List<String> getCitiesList() {
		return citiesList;
	}
	public void setCitiesList(List<String> cities) {
		this.citiesList = cities;
	}
	public List<String> getCountryList() {
		return countryList;
	}
	public void setCountryList(List<String> countryList) {
		this.countryList = countryList;
	}
	
}

A simple java bean class that will be used in Action class to set some values and then in JSP page to showcase the struts2 control tags usage.

Comparator Class

package com.journaldev.struts2.util;

import java.util.Comparator;

public class StringComparator implements Comparator<String> {

	@Override
	public int compare(String param1, String param2) {
		return param1.compareToIgnoreCase(param2);
	}

}

A simple Comparator implementation that will be used in result page sort tag example. We can use Comparator to sort a list of custom objects also, please read more at Java Comparator Example.

Action Class

package com.journaldev.struts2.actions;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.struts2.util.SubsetIteratorFilter.Decider;

import com.journaldev.struts2.model.Employee;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

public class HomeAction extends ActionSupport implements ModelDriven<Employee>{

	private static final long serialVersionUID = 1L;

	@Override
	public String execute(){
		emp.setId(100);
		emp.setRole("Developer");
		
		List<String> cities = new ArrayList<String>();
		cities.add("San Jose");
		cities.add("New Delhi");
		cities.add("Bangalore");
		cities.add("Los Angeles");
		emp.setCitiesList(cities);
		
		List<String> countries = new ArrayList<String>();
		countries.add("India");
		countries.add("USA");
		countries.add("UK");
		emp.setCountryList(countries);
		
		Map<String, String> props = new HashMap<String, String>();
		props.put("salary", "10000$");
		props.put("group", "directors");
		props.put("company", "journaldev");
		props.put("age", "25 years");
		emp.setPropertiesMap(props);
		
		return SUCCESS;
	}

	public Decider getCountryDecider(){
		return new Decider(){

			@Override
			public boolean decide(Object obj) throws Exception {
				String input = (String) obj;
				if (input.equalsIgnoreCase("USA"))
					return false; //not included in sublist
				else
					return true; //included in sublist
			}
			
		};
	}
	
	private Employee emp = new Employee();

	public Employee getEmp() {
		return emp;
	}

	public void setEmp(Employee emp) {
		this.emp = emp;
	}

	@Override
	public Employee getModel() {
		return emp;
	}
	
	
}

A simple action class implementation where we are populating Employee bean variables to be used in result page. The important point to note is getCountryDecider() method that will be used in result page subset tag example to get the subset iterator.

Result Page

<%@ page language="java" contentType="text/html; charset=US-ASCII"
    pageEncoding="US-ASCII"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Home Page</title>
</head>
<body>
<h4>Struts 2 Control Tags Example</h4>

<!-- if-elseif-else example -->
<s:if test="emp.id < 100">
	<strong>User id is under 100.</strong>
</s:if>
<s:elseif test="emp.role=='Developer'">
	<strong>User is Developer and id is greater than or equal to 100.</strong>
</s:elseif>
<s:else>
	<strong>User is NOT Developer and id is greater than or equal to 100.</strong>
</s:else>
<br><br>
<!-- iterator tag example -->
Cities are:<br>
<s:iterator value="emp.citiesList" begin="0" step="1" 
				var="citiesIterator" status="iteratorStatus">
<s:if test="#iteratorStatus.first">First City = <s:property/><br></s:if>
<s:elseif test="#iteratorStatus.last">Last City = <s:property/></s:elseif>
<s:else>City <s:property value="#iteratorStatus.count"/> = <s:property/><br></s:else>
</s:iterator>
<br><br>
Properties Map table is:
<table border="1" cellspacing="0" cellpadding="1">
<tr>
  <th>Name</th><th>Value</th>
</tr>
<s:iterator value="emp.propertiesMap" status="maprowStatus">
  <tr>
    <s:if test="#maprowStatus.odd == true">
      <td style="background: grey"><s:property value="key"/></td>
      <td style="background: grey"><s:property value="value"/></td>
    </s:if>
    <s:else>
      <td><s:property value="key"/></td>
      <td><s:property value="value"/></td>
    </s:else>
  </tr>
</s:iterator>
</table>
<br><br>

Appending Cities and Countries List:<br>
<s:append var="appendedList">
	<s:param value="emp.citiesList"></s:param>
	<s:param value="emp.countryList"></s:param>
</s:append>

<s:iterator value="#appendedList" status="myListStatus">
	<s:property value="#myListStatus.count"/>. <s:property/><br>
</s:iterator>
<br><br>

Merging Cities and Countries List:<br>
<s:merge var="mergedList">
	<s:param value="emp.citiesList"></s:param>
	<s:param value="emp.countryList"></s:param>
</s:merge>
<s:iterator value="#mergedList" status="myListStatus">
	<s:property value="#myListStatus.count"/>. <s:property/><br>
</s:iterator>
<br><br>

Sorting Cities List:<br>
<s:bean name="com.journaldev.struts2.util.StringComparator" var="myComparator"></s:bean>
<s:sort comparator="#myComparator" source="emp.citiesList">
<s:iterator status="myListStatus">
	<s:property value="#myListStatus.count"/>. <s:property/><br>
</s:iterator>
</s:sort>
<br><br>

Excluding USA from the countries list:<br>
<s:subset source="emp.countryList" decider="countryDecider">
<s:iterator>
<s:property/><br>
</s:iterator>
</s:subset>
<br><br>

Generate iterator example:<br>
<s:generator val="%{'apple|banana|orange'}" separator="|" var="fruitsIterator" />
 <s:iterator value="#fruitsIterator">
     <s:property /><br/>
 </s:iterator>

</body>
</html>

This is the result page where we are using Struts2 control tags to manipulate data and collections. Please look into the usage of different tags carefully for better understanding.

When we invoke home action in browser, we get following response page.

Struts2-control-tags-example

Download the complete project from above link and play around with different attributes of the control tags to learn more about them.

That’s all for Struts2 Control tags example tutorial, I hope you liked it.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Current day month ye@r *