[
https://issues.apache.org/jira/browse/WW-3937?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13645338#comment-13645338
]
Ken McWilliams edited comment on WW-3937 at 4/30/13 7:19 AM:
-------------------------------------------------------------
Here is a working demo of dynamically creating a tiles result. Only partial
annotation based configuration is possible:
{code:title="TestTilesDynamicDefinitionResult.java"|borderStyle=solid}
package com.kenmcwilliams.employmentsystem.action.test;
import com.opensymphony.xwork2.ActionSupport;
import java.util.HashMap;
import java.util.Map;
import org.apache.struts2.convention.annotation.Result;
import org.apache.tiles.Attribute;
@Result(type = "tiles-definition", location = "dynamic-tiles-definition",
params = {
"template", "/WEB-INF/test/test-template.jsp",
"attributes", "attrs" //the value of "attributes" (which is "attrs") is
evaluated using the value stack in the request
})
public class TestTilesDynamicDefinitionResult extends ActionSupport {
private Map<String, Attribute> attrs = new HashMap();
@Override
public String execute(){
attrs.put("body", new
Attribute("/WEB-INF/test/test-dynamic-definition.jsp"));
return SUCCESS;
}
public Map<String, Attribute> getAttrs() {
return attrs;
}
public void setAttrs(Map<String, Attribute> attrs) {
this.attrs = attrs;
}
}
{code}
{code:title="TilesDefinitionResult.java"|borderStyle=solid}
package com.kenmcwilliams.tiles.result;
import com.opensymphony.xwork2.ActionInvocation;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.ServletDispatcherResult;
import org.apache.tiles.Attribute;
import org.apache.tiles.Definition;
import org.apache.tiles.TilesContainer;
import org.apache.tiles.access.TilesAccess;
import org.apache.tiles.mgmt.MutableTilesContainer;
import org.apache.tiles.request.ApplicationContext;
import org.apache.tiles.request.servlet.ServletRequest;
import org.apache.tiles.request.servlet.ServletUtil;
public class TilesDefinitionResult extends ServletDispatcherResult {
private static final Logger log =
Logger.getLogger(TilesResult.class.getName());
private String template;
private String name = "dynamic-tiles-definition"; //definition name
private String extendz;
private String preparer;
private String attributes;
private Map<String, Attribute> evaluatedAttributes;
private String addMissing = "false";
public TilesDefinitionResult() {
super();
}
public TilesDefinitionResult(String location) {
super(location);
}
//location in this case refers to a previous tiles definition
@Override
public void doExecute(String location, ActionInvocation invocation) throws
Exception {
//location = "test.definition"; //for test
//setLocation(location);
//if (location != null && location.length() > 0){
// this.template = location;
//String conditionalParse = this.conditionalParse(attributes,
invocation);
evaluatedAttributes = (Map<String, Attribute>)
invocation.getStack().findValue(attributes);
log.log(Level.INFO, "TilesResult doExecute() location: {0}", location);
log.log(Level.INFO, "evaluatedAttributes['body']:{0}",
evaluatedAttributes.get("body"));
ServletContext context = ServletActionContext.getServletContext();
ApplicationContext applicationContext =
ServletUtil.getApplicationContext(context);
TilesContainer container = TilesAccess.getContainer(applicationContext);
//must use a mutable container
if (container instanceof MutableTilesContainer) {
} else {
throw new Exception("A Mutable Tiles Container is required");
}
MutableTilesContainer mc = (MutableTilesContainer) container;
Definition def = new Definition();
if (template != null && template.length() > 0) {
def.setTemplateAttribute(Attribute.createTemplateAttribute(template));
}
if (name != null && name.length() > 0) {
def.setName(name);
}
if (extendz != null && extendz.length() > 0) {
def.setExtends(extendz);
}
if (preparer != null && preparer.length() > 0) {
def.setPreparer(preparer);
}
if (evaluatedAttributes != null && evaluatedAttributes.size() > 0) {
if (addMissing.equalsIgnoreCase("true")) {
def.addMissing(evaluatedAttributes);
} else {
def.addAll(evaluatedAttributes);
}
}
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletRequest servletRequest = new ServletRequest(applicationContext,
request, response);
mc.register(def, servletRequest);
container.render(name, servletRequest);
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setExtends(String extendz) {
this.extendz = extendz;
}
public String getExtends() {
return extendz;
}
public String getPreparer() {
return preparer;
}
public void setPreparer(String preparer) {
this.preparer = preparer;
}
public String getAttributes() {
return attributes;
}
public void setAttributes(String attributes) {
this.attributes = attributes;
}
public String getAddMissing() {
return addMissing;
}
public void setAddMissing(String addMissing) {
this.addMissing = addMissing;
}
}
{code}
Very basic testing has shown this to work but no serious testing was done.
was (Author: ken_mcwilliams):
Here is a working demo of dynamically creating a tiles result. Only partial
annotation based configuration is possible:
{code:title="TestTilesDynamicDefinitionResult.java"|borderStyle=solid}
package com.kenmcwilliams.employmentsystem.action.test;
import com.opensymphony.xwork2.ActionSupport;
import java.util.HashMap;
import java.util.Map;
import org.apache.struts2.convention.annotation.Result;
import org.apache.tiles.Attribute;
//Attributes can be list attributes and are nested or regular attributes
//Attributes have a number of paramers
//as such a string based only configuration would be terribly complex to use
//or only partially implemented
@Result(type = "tiles-definition", location = "dynamic-tiles-definition",
params = {
"template", "/WEB-INF/test/test-template.jsp",
"attributes", "attrs" //the value of "attributes" (which is "attrs") is
evaluated using the value stack in the request
})
public class TestTilesDynamicDefinitionResult extends ActionSupport {
private Map<String, Attribute> attrs = new HashMap();
@Override
public String execute(){
attrs.put("body", new
Attribute("/WEB-INF/test/test-dynamic-definition.jsp"));
return SUCCESS;
}
public Map<String, Attribute> getAttrs() {
return attrs;
}
public void setAttrs(Map<String, Attribute> attrs) {
this.attrs = attrs;
}
}
{code}
{code:title="TilesDefinitionResult.java"|borderStyle=solid}
package com.kenmcwilliams.tiles.result;
import com.opensymphony.xwork2.ActionInvocation;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.ServletDispatcherResult;
import org.apache.tiles.Attribute;
import org.apache.tiles.Definition;
import org.apache.tiles.TilesContainer;
import org.apache.tiles.access.TilesAccess;
import org.apache.tiles.mgmt.MutableTilesContainer;
import org.apache.tiles.request.ApplicationContext;
import org.apache.tiles.request.servlet.ServletRequest;
import org.apache.tiles.request.servlet.ServletUtil;
public class TilesDefinitionResult extends ServletDispatcherResult {
private static final Logger log =
Logger.getLogger(TilesResult.class.getName());
private String template;
private String name = "dynamic-tiles-definition"; //definition name
private String extendz;
private String preparer;
private String attributes;
private Map<String, Attribute> evaluatedAttributes;
private String addMissing = "false";
public TilesDefinitionResult() {
super();
}
public TilesDefinitionResult(String location) {
super(location);
}
//location in this case refers to a previous tiles definition
@Override
public void doExecute(String location, ActionInvocation invocation) throws
Exception {
//location = "test.definition"; //for test
//setLocation(location);
//if (location != null && location.length() > 0){
// this.template = location;
//String conditionalParse = this.conditionalParse(attributes,
invocation);
evaluatedAttributes = (Map<String, Attribute>)
invocation.getStack().findValue(attributes);
log.log(Level.INFO, "TilesResult doExecute() location: {0}", location);
log.log(Level.INFO, "evaluatedAttributes['body']:{0}",
evaluatedAttributes.get("body"));
ServletContext context = ServletActionContext.getServletContext();
ApplicationContext applicationContext =
ServletUtil.getApplicationContext(context);
TilesContainer container = TilesAccess.getContainer(applicationContext);
//must use a mutable container
if (container instanceof MutableTilesContainer) {
} else {
throw new Exception("A Mutable Tiles Container is required");
}
MutableTilesContainer mc = (MutableTilesContainer) container;
Definition def = new Definition();
if (template != null && template.length() > 0) {
def.setTemplateAttribute(Attribute.createTemplateAttribute(template));
}
if (name != null && name.length() > 0) {
def.setName(name);
}
if (extendz != null && extendz.length() > 0) {
def.setExtends(extendz);
}
if (preparer != null && preparer.length() > 0) {
def.setPreparer(preparer);
}
if (evaluatedAttributes != null && evaluatedAttributes.size() > 0) {
if (addMissing.equalsIgnoreCase("true")) {
def.addMissing(evaluatedAttributes);
} else {
def.addAll(evaluatedAttributes);
}
}
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
ServletRequest servletRequest = new ServletRequest(applicationContext,
request, response);
mc.register(def, servletRequest);
container.render(name, servletRequest);
}
public String getTemplate() {
return template;
}
public void setTemplate(String template) {
this.template = template;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setExtends(String extendz) {
this.extendz = extendz;
}
public String getExtends() {
return extendz;
}
public String getPreparer() {
return preparer;
}
public void setPreparer(String preparer) {
this.preparer = preparer;
}
public String getAttributes() {
return attributes;
}
public void setAttributes(String attributes) {
this.attributes = attributes;
}
public String getAddMissing() {
return addMissing;
}
public void setAddMissing(String addMissing) {
this.addMissing = addMissing;
}
}
{code}
Very basic testing has shown this to work but no serious testing was done.
> The annotation @Result can have an extra attribute to hold tiles attributes
> ---------------------------------------------------------------------------
>
> Key: WW-3937
> URL: https://issues.apache.org/jira/browse/WW-3937
> Project: Struts 2
> Issue Type: Improvement
> Components: Plugin - Tiles
> Affects Versions: 2.3.7
> Reporter: Daniel Woo
> Priority: Minor
> Fix For: 2.3.15
>
>
> Currently the @Result annotation for tiles can only specify a location to
> render, e.g.
> {code:java}
> @Action(value = "/home", results = {@Result(name = "success", location =
> "home", type = "tiles")})
> {code}
> What I want is to add a new attribute like this:
> {code:java}
> @Action(value = "/home", results = {@Result(name = "success", location =
> "home", tilesAttr={"loadcss", "/css/home.css"}, type = "tiles")})
> {code}
> The reason is to utilize wildcard tiles definition. Suppose we have the
> wildcard tiles definition below,
> {code:xml}
> <definition name="*.*.*" extends="{3}-layout">
> <put-attribute name="body" value="/view/{1}/{2}.jsp"/>
> <put-attribute name="loadcss" value=""/>
> </definition>
> {code}
> The tiles attribute 'loadcss' should be set dynamically, or specified in the
> annotation. Currently since the tiles plugin does not support the attribute
> yet, we have to do that in the tiles configuration file with <put-attribute>,
> that means we have to explicitly define each tiles definition without
> wildcard support.
--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira