terça-feira, 29 de maio de 2007

Struts 2: Annotation Action

uma característica interessante do Struts 2 é o suporte a anotações, nesse caso vou falar sobre o suporte para definição de action...


.:verifique o post de correção desse [link]:.


segue os respectivos códigos


/WEB-INF/[web.xml] configuração da aplicação
tendo os jar´s básicos do struts 2 e o plugin: struts2-codebehind-plugin-2.x.jar

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_S2AA" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>struts2_action_annotations</display-name>  
  <!-- ======= -->   
    <filter>
        <filter-name>struts</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    <init-param>
      <!-- define os pacotes que irá considerar contendo classes actions -->
      <param-name>actionPackages</param-name>
      <!--  para definir mais de um pacote utilize "," -->
      <param-value>actions</param-value>
    </init-param>
    </filter>
  <!-- ======= -->
    <filter-mapping>
        <filter-name>struts</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  <!-- ======= -->    
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
</web-app>


Obs.: usando esse tipo de definição de mapeamento de action não é necessário definir nenhum mapeamento no struts.xml para as actions do pacote indicado


actions.[AnnotationAction] : classe action

package actions;

import org.apache.struts2.config.Result;
import com.opensymphony.xwork2.ActionSupport;

@Result(name="success", value="/jsp/success.jsp")
public class AnnotAction extends ActionSupport {
  private static final long serialVersionUID = 1L;
  public String execute() {
    return "success";
  }  
}


ps.: a página JSP de resultado da action contém nesse exemplo um texto qualquer, apenas para verificar o funcionamento da action...


considerações:


quanto a esse tipo de mapeamento verifiquei que funcionou apenas para o método execute da classe action, sendo que esta herdava de ActionSupport para ser reconhecida como uma action dentro desse pacote....

tentei acessar outros metodos internos na mesma action, mapeada dessa forma, verifiquei que o Struts 2 não localizava tais métodos...


de modo geral esse tipo de action é bom para casos de actions onde conterá apenas um método executor, no caso padrão o public String execute()...

minhas opinião final: achei esse suporte muito fraco, foi menos que minha espectativa inicial :(

Struts 2 + Tiles 2

outra funcionalidade muito utilizada em aplicações web que reduzem o tempo de desenvolvimento referente a interface é o esquema de templates e layout de interface, no caso com Struts 2 temos 2 possibilidades/soluções que podemos utilizar para essa finalidade:

- SiteMesh
- Tiles

no caso como anteriormente tive boas experiências no uso do Tiles junto com o Struts 1, resolvi verificar como está o uso entre Struts 2 com a nova versão do Tiles 2...

um pequeno problema...
opa calma, deixa eu explica, o problema que tive inicialmente foi encontrar uma fonte que realmente contivesse a informação de como realizar a integração entre ambos, a qual fui achar somente em um forum da França, no respectivo [link]

bom vamos aos códigos agora...


[web.xml] configurando a aplicação para utilizar Struts 2 com Tiles 2
( necessário dos jar´s do Struts 2 e do Tiles 2 [usei o 2.0.3, core e api] na lib da aplicação )

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_Struts_Tiles" version="2.4" 
  xmlns="http://java.sun.com/xml/ns/j2ee" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    <display-name>Struts Tiles - Example</display-name>
  <!-- ======= -->   
    <filter>
        <filter-name>struts</filter-name>
        <filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
  <!-- ======= -->
    <filter-mapping>
        <filter-name>struts</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
  <!-- ======= -->    
  <listener>
      <listener-class>org.apache.tiles.listener.TilesListener</listener-class>
    </listener>  
  <!-- ======= -->    
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>default.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

</web-app>


WEB-INF/[tiles.xml] configuração referente ao layout/templates

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE tiles-definitions PUBLIC
        "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
        "http://struts.apache.org/dtds/tiles-config_2_0.dtd">     
<tiles-definitions>
   <!-- definição do layout da página principal -->
   <definition name="template.page" template="/template/layout.jsp">
      <put name="title" value="Struts 2 + Tiles 2"/>
      <put name="header" value="/template/headerMain.jsp"/>
      <put name="menu" value="/template/menuMain.jsp"/>        
      <put name="footer" value="/template/footerMain.jsp" />
   </definition>
   <definition name="welcome.page" extends="template.page">
      <put name="body" value="/jsp/welcome.jsp"/>
   </definition>
</tiles-definitions>


ps.: nessa aplicação defini os respectivos diretório no root da aplicação:
- jsp : para os jsp´s de resultado das action
- template : para os layout de tela a ser setados no Tiles


/template/[layout.jsp] layout da tela

<%taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<%taglib prefix="s" uri="/struts-tags" %>
<%-- atributo da request --%>
<tiles:importAttribute name="title" scope="request"/>
<%-- definição do layout --%>
<html>
  <head>
    <!-- recupera o atributo setado na definição do tiles.xml -->
    <title><tiles:getAsString name="title"/></title>
  </head>
  <body>  
    <table width="100%" height="100%">
      <tr bgcolor="yellow">
        <td colspan="2">
          <tiles:insertAttribute name="header" />
        </td>
      </tr>
      <tr>
        <td bgcolor="gray">
          <tiles:insertAttribute name="menu" />
        </td>
        <td>
          <tiles:insertAttribute name="body" />
        </td>
      </tr>
      <tr bgcolor="yellow">
        <td colspan="2">
          <tiles:insertAttribute name="footer" />
        </td>
      </tr>
    </table>  
  </body>
</html>


ps.: os outros .jsp dentro do diretório possui nesse exemplo apenas textos, indicando : [ cabeçalho, meno e rodapé ]


usando como tipo de retorno de uma action, a definição da action deverá conter o seguinte formato:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>

   <package name="base" extends="struts-default">
      <result-types>
         <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
      </result-types>
        
      <action name="index">
         <result type="tiles">welcome.page</result>
      </action>
   </package>  

</struts>




e com essas dicas já é possível iniciar o uso do Struts 2 integrado com Tiles 2 =]

Struts 2: Saída de stream com parametros dinâmicos

usando o novo framework Struts 2, depois de um tempo brigando com a falta de conhecimento finalmente consegui montar uma action onde seto dinâmicamente os parametros para a definição do result

observe os respectivos códigos:

java: classe action
import java.io.ByteArrayInputStream;
import java.io.InputStream;

public class DynamicStreamAction {
  //--------------------------------------------------------------------------
  // parametros para uso na saída da action
  private String contentType;
  private int contentLength;
  private String contentDisposition;
  // definição da saída do stream
  private InputStream myStream;
  //--------------------------------------------------------------------------
  public String execute() {
    
    // definindo o tipo de conteúdo
    this.setContentType"application/xml" );
    // definindo que será em anexo( solicitará o salvamento do arquivo )
    this.setContentDisposition"attachment; filename=XmlAction.xml" );
    
    
    // definindo o XML de saida
    String xml = "<tag>xml teste de saída áéíóú ç à...</tag>";
        
    // setando o stream para o tributo
    this.setMyStreamnew ByteArrayInputStreamxml.getBytes() ) );

    // definindo o tamanho do contentLength
    this.setContentLengthxml.getBytes().length );    
    return "success";
  }
  //--------------------------------------------------------------------------  
  
  // get´s & set´s

}


respectivo mapeamento da action com definição dos parametros do result, tipo stream dinâmicos
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>

    <package name="stream" namespace="/stream" extends="struts-default">

        <action name="dynamic" class="stream.DynamicStreamAction">
      <result name="success" type="stream">
        <param name="inputName">myStream</param>  
        <param name="contentType">${contentType}</param>  
        <param name="contentDisposition">${contentDisposition}</param>
        <param name="contentLength">${contentLength}</param>
      </result>
        </action>

    </package>
</struts>


* Observe: que os parametros definidos no mapeamento da action são respectivamente os mesmo nomes dos atributos da classe action...