[ 
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

Reply via email to