OGNL stands for Object Graph Navigation Language.
It’s an expression language for getting/setting properties of Java objects and other extra functions. It works as a binding between GUI elements or UI components to model objects.
This post is a summary after studying Apache Struts 2 Documentation - ONGL.
Import tag lib
Before using ONGL, we need to import it in JSP page:
<%@ taglib prefix="s" uri="/struts-tags" %>
Control Tags
- if/elseif/else
- iterator
- append
- merge
- generator
- subset
- sort
if/elseif/else
if
and elseif
must have test
attribute in which should be a boolean expression.
// Set a parameter called 'age' with value 30
<s:set name="age" value="30"/>
<s:if test="#age>60">
old
</s:if>
<s:elseif test="#age>35">
adult
</s:elseif>
<s:else>
young
</s:else>
iterator
Tag to iterate a collection (List, set, array or map). It has three attributes:
Name | Required | Default | Description |
---|---|---|---|
begin | X | 0 | Index to start iteration |
end | X | size of collection | Index to end iteration |
status | X | Instance of IteratorStatus which will be pushed into stack upon each iteration | |
step | X | 1 | Iteration index will be increased by this value on each iteration |
value | X | Collection to iterate | |
var | X | Name used to reference the value pushed into the Value Stack |
Instance of IteratorStatus also has following functions:
if status="test"
,
#test.count
returns number of element already iterated. (equals toint getCount()
)#test.index
returns index of current element. (equals toint getIndex()
)#test.even
returns wether current element is even. (equals toboolean isEven()
)#test.odd
returns wether current element is odd. (equals toboolean isOdd()
)#test.first
returns wether current element is the first one. (equals toboolean isFirst()
)#test.last
returns wether current element is the last one. (equals toboolean isLast()
)
If now we have a list called employeeList which is List<Employee>
. Employee has two attributes name
and age
with getter/setter:
<table>
<s:iterator value="employeeList" status="list">
<tr>
<td><s:property value="#list.index" /></td>
<td><s:property value="name" /></td>
<td><s:property value="age" /></td>
</tr>
</s:iterator>
</table>
If it’s List<String>, use s:property
without value
to present a string element in the list:
<table>
<s:iterator value="numberList" status="list2">
<tr>
<td><s:property value="#list2.index" /></td>
<td><s:property/></td>
</tr>
</s:iterator>
</table>
If it’s Map:
<table>
<s:iterator value="keyValueMap" status="map">
<tr>
<td><s:property value="#map.index" /></td>
<td><s:property value="key" /></td>
<td><s:property value="value" /></td>
</tr>
</s:iterator>
</table>
append
It appends several collections to form a new collection.
The new collection has the following order (different from tag `merge):
- First Entry of the First Iterator
- Second Entry of the First Iterator
- Third Entry of the First Iterator
- First Entry of the Second Iterator
- Second Entry of the Second Iterator
- Third Entry of the Second Iterator
The following example shows three lists of type List<String>
to be appended together. These three lists are passed by some Action.
<s:append var="newList">
<s:param value="list1" />
<s:param value="list2" />
<s:param value="list3" />
</s:append>
<s:iterator value="#newList">
<s:property />
</s:iterator>
merge
The same as append
but in different order:
- First Entry of the First Iterator
- First Entry of the Second Iterator
- Second Entry of the First Iterator
- Second Entry of the Second Iterator
- Third Entry of the First Iterator
- Third Entry of the Second Iterator
generator
Generate an iterator based on give string. If var
not set, it will only exist in Value Stack which means you can not use it outside the tag. (Not in page context)
Name | Required | Default | Description |
---|---|---|---|
separator | O | The separator to be used in separating the val into entries of the iterator | |
val | O | The source to be parsed into an iterator | |
var | X | The name to store the resultant iterator into page context | |
count | X | Max number of entries to be in the iterator | |
converter | X | Convert the String entry parsed from val into an object |
A string separated by “,”:
<s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" count="3" separator=",">
<s:iterator>
<s:property />
</s:iterator>
</s:generator>
Generate an iterator with comparator attribute:
<s:generator val="%{'aaa,bbb,ccc,ddd,eee'}" separator="," converter="myConverter">
<s:iterator>
return<s:property /><br/>
</s:iterator>
</s:generator>
public class GeneratorTagAction extends ActionSupport {
...
// getMyConverter function name -> converter="myConverter"
public Converter getMyConverter() {
return new Converter() {
public Object convert(String value) throws Exception {
return "converter-"+value;
}
};
}
...
}
This will generate an iterator with each entries decided by the converter supplied. With this converter, it simply add “converter-“ to each entries.
subset
Outputs a subset of an iterator.
Name | Required | Default | Description |
---|---|---|---|
count | X | Indicate the number of entries to be in the resulting subset iterator | |
decider | X | Extension to plug-in a decider to determine if that particular entry is to be included in the resulting subset iterator | |
var | X | The name to store the resultant iterator into page context | |
source | X | Source to do subset | |
start | X | 0 | Indicate the startig index |
Simply subset:
<!-- myList is a List<String> given by action -->
<s:subset source="myList">
<s:iterator>
<s:property />
</s:iterator>
</s:subset>
With decider:
public class MySubsetTagAction extends ActionSupport {
...
public Decider getMyDecider() {
return new Decider() {
public boolean decide(Object element) throws Exception {
int i = ((Integer)element).intValue();
return (((i % 2) == 0)?true:false);
}
};
}
}
<!-- myList is a List<String> given by action -->
<s:subset source="myList" decider="myDecider">
<s:iterator>
<s:property />
</s:iterator>
</s:subset>
Sort
It sorts a List using a Comparator
Name | Required | Default | Description |
---|---|---|---|
comparator | O | The comparator to use (java.util.Comparator) | |
var | X | The name to store the resultant iterator into page context | |
source | X | Source to sort |
Example
Sort by string length:
<s:set name="test" value="{'aefi','abc','world!','kkkkk'}" />
<s:bean id="sort" name="action.SortComparator"></s:bean>
<s:sort source="test" comparator="sort">
<s:iterator>
<s:property />
</s:iterator>
</s:sort>
public class SortComparator implements Comparator<Object> {
public int compare(Object arg0, Object arg1) {
// Compare by length
return arg0.toString().length() - arg1.toString().length();
}
}
Data Tags
action
It could call actions directly from a JSP page by specifying the action name and an optional namespace.
Any result processor defined for this action in struts.xml will be ignored, unless the executeResult parameter is specified.
Name | Required | Default | Description |
---|---|---|---|
executeResult | x | false | Whether the result of this action (probably a view) should be executed/rendered |
var | X | Name used to reference the value pushed into the Value Stack | |
name | O | Name of the action to be executed (without the extension suffix eg. .action) | |
namespace | X | Namespace from where tag is used | Namespace of the action |
ignoreContextParams | X | false | Whether the request parameters are to be passed to the action |
rethrowException | X | false | Whether an exception should be rethrown, if the target action throws an exception |
Example
public class ActionTagAction extends ActionSupport {
public String execute() throws Exception {
return SUCCESS;
}
public String test() throws Exception {
ServletActionContext.getRequest().setAttribute("variable", "A variable");
return SUCCESS;
}
}
<action name="actionA" class="com.dong.test">
<result name="success">test.jsp</result>
</action>
<action name="actionB" class="com.dong.test" method="test">
<result name="success">test.jsp</result>
</action>
When we acess the test page with a request parameter - localhost:8000/index?author=Dong
:
<!-- success.jsp will be included in this page -->
<!-- And show "test - Dong"-->
<s:action name="actionA" executeResult="true" />
<!-- test.jsp will be included in this page-->
<!-- No request parameter is allowed, so could only show "test -"-->
<s:action name="actionB" executeResult="true" ignoreContextParams="true" />
<!-- test.jsp will NOT be included in this page-->
<!-- But put a String in request scope under an id "variable" which will be retrieved using property tag -->
<s:action name="actionB" executeResult="false" />
<s:property value="#attr.variable" /><!-- #attr is to access to PageContext if available , we use value="variable" directly -->