Apache Struts 2

47 respostas
W

Alguém usou em projetos, já está estável ?? poderiam me passar alguma informação.

SDS.
William Silva

47 Respostas

A

Estamos iniciando um projeto aqui na empresa com o Struts 2.0.1 beta pois acreditamos na evolução dessa versão do framework. O projeto já havia começado com o Struts 1.2.9 e estamos migrando o que já havia sido desenvolvido para a versão 2.0.1. Até o momento só tivemos problemas na composição das telas com o Tiles (daí estamos migrando para Freemarker) e na validação dinâmica (então estamos construindo a validação dentro das actions mesmo).

W

Olá alexandremlima ,
Diga o que está achando do novo Struts (WebWork2.0), passe suas impressões sobre ele

  • está sentindo falta das ActionsForms e DynaForms ??
  • pretende integra-lo com o Spring ??
  • etc.
    Dei uma olhada ontem a noite em uma app exemplo e tive a impressão que ele está bem mais produtivo que os Struts 1.xx , mais ainda preciso analizar a documentação e ver os recursos possíveis.
A

Eu não somente tive a impressão de que agora está bem mais produtivo como senti isso ao migrar o projeto que estava em desenvolvimento aqui para o novo framework.

Não sinto falta nenhuma dos dynaforms que usava na aplicação. Agora o trabalho ficou muito melhor e mais fácil. Repetição de código praticamente não existe com o novo framework o que está tornando o código mais limpo e fácil de compreender.

Não pretendo integrá-lo com Spring porque nunca usei este framework. Aqui sempre utilizamos Actions (Struts) + Façade + Model + DAO (sem e com Hibernate). Mas com o Spring já integrado ao Struts 2 talvez eu passe a olhar mais para esse lado.

Nesta versão nova, tive dificuldades em fazer a validação apenas para alguns métodos das minhas actions e em usar o Tiles. Então acabei fazendo a validação dentro de um método específico da action (implementando uma interface do framework) e retirando o tiles para usar includes nos JSPs.

P

Olá alexandremlima, você poderia colocar o exemplo de uma action sua antes e depois da migração? Estão usando o que no lugar dos seus antigos DynaActions?

A

Atendendo ao seu pedido, vou colocar aqui um exemplo de como se transformaram as minhas Actions.

Antes gostaria de explicar que na minha aplicação, o Model e o Façade são uma única peça. Os métodos get e set funcionam como todos já sabemos e os métodos estáticos funcionam como serviços para a aplicação relativos ao assunto daquele model. Portanto, a aplicação tem a seguinte estrutura: JSP+Action -&gt Model (método estático) -&gt DAO e o Model (métodos get e set) transitando nas 3 camadas.

Meu struts-config.xml (Struts 1) estava assim anteriormente:

<struts-config>

	<form-beans>
		<form-bean name="formTabelasAtividades" type="org.apache.struts.validator.DynaValidatorForm">
			<form-property name="act" type="java.lang.String" />
			<form-property name="actGrid" type="java.lang.String" />
			<form-property name="pagRegPorPagina" type="java.lang.Long" />
			<form-property name="pagRegAtual" type="java.lang.Long" />
			<form-property name="pagRegQtdTotal" type="java.lang.Long" />
			<form-property name="gridRegistros" type="java.util.List" />
			<form-property name="gridSelecao" type="java.lang.String" />
			<form-property name="campoDescricao" type="java.lang.String" />
			<form-property name="campoTipo" type="java.lang.String" />
			<form-property name="todosTipos" type="java.util.List" />
			<form-property name="filtroDescricao" type="java.lang.String" />
			<form-property name="filtroTipo" type="java.lang.String" />
		</form-bean>
	</form-beans>
	
	<global-exceptions>
		<exception type="java.lang.Exception" 
				key="errors.detail" path="/Erro.do" />
	</global-exceptions>
	
	<global-forwards>
		<forward name="irParaLogin" path="/ActLogin.do?act=visualizar" />
	</global-forwards>
	
	<action-mappings>
		<action path="/Erro"
				type="org.apache.struts.actions.ForwardAction" parameter="erro" />

		<action path="/Login"
				type="org.apache.struts.actions.ForwardAction" parameter="login" />
				
		<action path="/ActLogin" scope="request"
				type="embasa.jsime.view.action.LoginConsultaAction" 
				name="formLogin" validate="true"
				input="/Erro.do" parameter="act">
			<forward name="concluirVisualizar" path="/Login.do" />
			<forward name="concluirProcessarPesquisar" path="/ActHome.do?act=visualizar" />
			<forward name="concluirDesconectar" path="/Login.do" />
		</action>
		
		<action path="/TabelasAtividades"
			type="org.apache.struts.actions.ForwardAction" parameter="tabelasAtividades" />
			
		<action path="/TabelasAtividadesCadastro"
			type="org.apache.struts.actions.ForwardAction" parameter="tabelasAtividadesCadastro" />
			
		<action path="/TabelasAtividadesDetalhes"
			type="org.apache.struts.actions.ForwardAction" parameter="tabelasAtividadesDetalhes" />
			
		<action path="/ActTabelasAtividades" scope="request"
			type="embasa.jsime.view.action.tabelas.TabelasAtividadesConsultaAction"
			name="formTabelasAtividades" validate="true"
			input="/Erro.do" parameter="act">
			<forward name="concluirVisualizar" path="/TabelasAtividades.do" />
			<forward name="concluirProcessarPesquisar" path="/TabelasAtividades.do" />
			<forward name="concluirProcessarDetalhes" path="/TabelasAtividadesDetalhes.do" />
		</action>
		
		<action path="/ActTabelasAtividadesCadastro" scope="request"
			type="embasa.jsime.view.action.tabelas.TabelasAtividadesCadastroAction"
			name="formTabelasAtividades" validate="true"
			input="/Erro.do" parameter="act">
			<forward name="concluirIniciarNovo" path="/TabelasAtividadesCadastro.do" />
			<forward name="concluirProcessarNovo" path="/ActTabelasAtividades.do?act=visualizar" />
			<forward name="concluirIniciarEditar" path="/TabelasAtividadesCadastro.do" />
			<forward name="concluirProcessarEditar" path="/ActTabelasAtividades.do?act=visualizar" />
			<forward name="concluirProcessarExcluir" path="/ActTabelasAtividades.do?act=visualizar" />
		</action>
	</action-mappings>
	
</struts-config>

Todos os meus DynaForms tem as propriedades pag* para realizar a paginação dos registros na tela (a nível de banco de dados). A propriedade act é para execução dinâmica de métodos nas Actions do tipo DispatchAction.
As Actions do tipo ForwardAction são para integração com o Tiles.
As demais Actions que são descendentes de DispatchAction agrupam funcionalidades semelhantes em dois grupos separados. *ConsultaAction são os métodos para visualizar a tela, processar pesquisa (filtragem) e ver detalhes de um registro. *CadastroAction são os métodos para iniciar a inclusão de um registro, processar a inclusão do registro, iniciar a edição do registro, processar a edição do registro e processar a exclusão do registro.

Meu validation.xml estava assim:

<form-validation>
	<formset>
		<form name="formTabelasAtividades">
			<field property="act" depends="required">
				<arg key="App.VariavelAct" />
			</field>
			<field property="gridSelecao" depends="validwhen">
				<arg key="App.GridSelecao" />
				<var>
					<var-name>test</var-name>
					<var-value>
						( ( ((act != "iniciarEditar") and (act != "processarExcluir")) and (act != "processarDetalhes") ) or (*this* != null) )
					</var-value>
				</var>
			</field>
			<field property="campoDescricao" depends="validwhen,maxlength">
				<arg0 key="Tabelas.Atividades.CampoDescricao" />
				<arg1 name="maxlength" key="${var:maxlength}" resource="false" />
				<var>
					<var-name>test</var-name>
					<var-value>
						( ( (act != "processarNovo") and (act != "processarEditar") ) or (*this* != null) )
					</var-value>
				</var>
				<var>
        			<var-name>maxlength</var-name>
        			<var-value>100</var-value>
        		</var>
			</field>
			<field property="campoTipo" depends="validwhen">
				<arg key="Tabelas.Atividades.CampoTipo" />
				<var>
					<var-name>test</var-name>
					<var-value>
						( ( (act != "processarNovo") and (act != "processarEditar") ) or ( (*this* != null) and (*this* != "-1") ) )
					</var-value>
				</var>
			</field>
		</form>
	</formset>
</form-validation>

Meu tiles-defs.xml estava assim:

<tiles-definitions>
	<definition name="template_geral" path="/pages/TemplateGeral.jsp">
		<put name="processando" value="/pages/Processando.jsp" />
		<put name="cabecalho" value="/pages/Cabecalho.jsp" />
		<put name="menu" value="/pages/Menu.jsp" />
		<put name="conteudo" value="" />
	</definition>
	
	<definition name="erro" extends="template_reduzido">
		<put name="conteudo"   value="/pages/Erro.jsp" />
    </definition>
    
	<definition name="login" extends="template_reduzido">
		<put name="conteudo" value="/pages/Login.jsp" />
	</definition>
	
	<definition name="tabelasAtividades" extends="template_geral">
		<put name="conteudo" value="/pages/TabelasAtividades.jsp" />
	</definition>
	<definition name="tabelasAtividadesCadastro" extends="template_geral">
		<put name="conteudo" value="/pages/TabelasAtividadesCadastro.jsp" />
	</definition>
	<definition name="tabelasAtividadesDetalhes" extends="template_geral">
		<put name="conteudo" value="/pages/TabelasAtividadesDetalhes.jsp" />
	</definition>
	
</tiles-definitions>

Agora vou começar a mostrar como estavam os JSP’s da aplicação. As páginas são sempre em grupos de 3: uma para visualizar e pesquisar registros (exibindo uma grid), uma para visualizar os detalhes de um registro, e outra para visualizar o formulário de cadastro (inclusão e edição).

TabelasAtividades.jsp

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<h1><bean:message key="App.TituloSistema"/></h1>
<h3><bean:message key="Tabelas.Atividades.CaminhoTela"/></h3>

<html:form action="ActTabelasAtividades.do" onsubmit="javascript: return false;">
<html:hidden property="act"/>
<html:hidden property="actGrid"/>
<table class="grid" cellpadding="0" cellspacing="0">
<tr>
	<td class="gridFiltro">
		<span class="gridCampo">
			<bean:message key="Tabelas.Atividades.CampoDescricao"/>: 
			<html:text property="filtroDescricao" size="30"/>
		</span>
		<span class="gridCampo">
			<bean:message key="Tabelas.Atividades.CampoTipo"/>: 
			<html:select property="filtroTipo">
				<html:option value="-1"> </html:option>
				<logic:notEmpty name="formTabelasAtividades" property="todosTipos">
				<html:optionsCollection property="todosTipos" label="descricao" value="id"/>
				</logic:notEmpty>
			</html:select>
		</span>
		<span class="gridCampo">
			<html:image src="images/ico_atualizar.gif" altKey="App.BotaoRecarregarTabela" onclick="javascript:processando(true);this.form.pagRegAtual.value=1;submitFormTo(this.form,'ActTabelasAtividades.do','processarPesquisar');"/>
		</span>
	</td>
</tr>
<tr>
	<td class="gridTopo">
		<html:hidden property="pagRegPorPagina" />
		<html:hidden property="pagRegAtual" />
		<html:hidden property="pagRegQtdTotal" />
		<bean:define id="regPorPagina" name="formTabelasAtividades" property="pagRegPorPagina" type="java.lang.Long"/>
		<bean:define id="regAtual" name="formTabelasAtividades" property="pagRegAtual" type="java.lang.Long"/>
		<bean:define id="regQtdTotal" name="formTabelasAtividades" property="pagRegQtdTotal" type="java.lang.Long"/>
		<logic:notEmpty name="formTabelasAtividades" property="gridRegistros">
			<c:if test="${regAtual > regPorPagina}">
				<html:image src="images/grid_primeiro.gif" altKey="App.Paginador.BotaoPrimeiro" onclick="javascript:processando(true);this.form.pagRegAtual.value=1;submitFormTo(this.form,'ActTabelasAtividades.do',this.form.actGrid.value);"/>
				 
				<html:image src="images/grid_anterior.gif" altKey="App.Paginador.BotaoAnterior" onclick="javascript:processando(true);this.form.pagRegAtual.value=pagRegAtual.value-pagRegPorPagina.value;submitFormTo(this.form,'ActTabelasAtividades.do',this.form.actGrid.value);"/>
				 
			</c:if>
			<c:out value="${regQtdTotal}"/> <bean:message key="App.Paginador.RegistrosEncontrados"/>
			<c:if test="${regAtual <= regQtdTotal-regPorPagina}">
				 
				<html:image src="images/grid_proximo.gif" altKey="App.Paginador.BotaoProximo" onclick="javascript:processando(true);this.form.pagRegAtual.value=parseInt(pagRegAtual.value)+parseInt(pagRegPorPagina.value);submitFormTo(this.form,'ActTabelasAtividades.do',this.form.actGrid.value);"/>
				 
				<c:if test="${regQtdTotal%regPorPagina != 0}">
				<html:image src="images/grid_ultimo.gif" altKey="App.Paginador.BotaoUltimo" onclick="javascript:processando(true);this.form.pagRegAtual.value=pagRegQtdTotal.value-(pagRegQtdTotal.value%pagRegPorPagina.value)+1;submitFormTo(this.form,'ActTabelasAtividades.do',this.form.actGrid.value);"/>
				</c:if>
				<c:if test="${regQtdTotal%regPorPagina == 0}">
				<html:image src="images/grid_ultimo.gif" altKey="App.Paginador.BotaoUltimo" onclick="javascript:processando(true);this.form.pagRegAtual.value=pagRegQtdTotal.value-(pagRegPorPagina.value)+1;submitFormTo(this.form,'ActTabelasAtividades.do',this.form.actGrid.value);"/>
				</c:if>
			</c:if>
		</logic:notEmpty>
	</td>
</tr>
<tr>
	<td>
		<table class="gridConteudo">
		<tr>
			<th width="20"> </th>
			<th><bean:message key="Tabelas.Atividades.CampoDescricao"/></th>
			<th width="20%"><bean:message key="Tabelas.Atividades.CampoTipo"/></th>
		</tr>
		<logic:notEmpty name="formTabelasAtividades" property="gridRegistros">
		<logic:iterate id="reg" name="formTabelasAtividades" property="gridRegistros" indexId="n">
		<tr class="linha<%=(n.intValue()%2==0)?"1":"2"%>"&gt
			<bean:define id="idReg" name="reg" property="id" type="java.lang.Long"/>
			<td><html:radio property="gridSelecao" value="<%=idReg.toString()%>"/></td>
			<td><bean:write name="reg" property="descricao"/></td>
			<td><bean:write name="reg" property="tipo.descricao"/></td>
		</tr>
		</logic:iterate>
		</logic:notEmpty>
		<logic:empty name="formTabelasAtividades" property="gridRegistros">
		<tr class="linha1">
			<td colspan="3" align="center"><bean:message key="App.SemRegistros"/></td>
		</tr>
		</logic:empty>
		</table>
	</td>
</tr>
<tr>
	<td class="gridRodape">
		<html:image src="images/ico_novo.gif" altKey="App.BotaoNovo" onclick="javascript:processando(true);submitFormTo(this.form,'ActTabelasAtividadesCadastro.do','iniciarNovo');"/>
		<logic:notEmpty name="formTabelasAtividades" property="gridRegistros">
		 
		<html:image src="images/ico_alterar.gif" altKey="App.BotaoAlterar" onclick="javascript:processando(true);submitFormTo(this.form,'ActTabelasAtividadesCadastro.do','iniciarEditar');"/>
		 
		<html:image src="images/ico_excluir.gif" altKey="App.BotaoExcluir" onclick="javascript:processando(true);submitFormTo(this.form,'ActTabelasAtividadesCadastro.do','processarExcluir');"/>
		 
		<html:image src="images/ico_detalhes.gif" altKey="App.BotaoDetalhes" onclick="javascript:processando(true);submitFormTo(this.form,'ActTabelasAtividades.do','processarDetalhes');"/>
		</logic:notEmpty>
	</td>
</tr>
</table>
</html:form>

TabelasAtividadesCadastro.jsp

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<h1><bean:message key="App.TituloSistema"/></h1>
<h3><bean:message key="Tabelas.Atividades.CaminhoTela"/></h3>

<html:form action="ActTabelasAtividadesCadastro.do" onsubmit="javascript: return false;">
<logic:equal name="formTabelasAtividades" property="act" value="iniciarNovo">
	<html:hidden property="act" value="processarNovo"/>
</logic:equal>
<logic:equal name="formTabelasAtividades" property="act" value="iniciarEditar">
	<html:hidden property="act" value="processarEditar"/>
</logic:equal>
<html:hidden property="gridSelecao"/>
<table class="formulario" cellpadding="0" cellspacing="0">
<tr>
	<td class="formularioTopo">
		<bean:message key="Tabelas.Atividades.CadastroTexto"/>
	</td>
</tr>
<tr>
	<td class="formularioConteudo">
		<span class="formularioCampo">
			&lt;bean:message key="Tabelas.Atividades.CampoDescricao"/&gt;: <br />
			&lt;html:text property="campoDescricao" size="80"/&gt;
		&lt;/span&gt;
		&lt;span class="formularioCampo"&gt;
			&lt;bean:message key="Tabelas.Atividades.CampoTipo"/&gt;: <br />
			&lt;html:select property="campoTipo"&gt;
				&lt;html:option value="-1"&gt;&nbsp;&lt;/html:option&gt;
				&lt;html:optionsCollection property="todosTipos" label="descricao" value="id"/&gt;
			&lt;/html:select&gt;
		&lt;/span&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="formularioRodape"&gt;
		&lt;html:image src="images/ico_salvar.gif" altKey="App.BotaoSalvar" onclick="javascript:processando(true);submitFormTo(this.form,'ActTabelasAtividadesCadastro.do',this.form.act.value);"/&gt;
		&nbsp;
		&lt;html:image src="images/ico_cancelar.gif" altKey="App.BotaoCancelar" onclick="javascript:processando(true);this.form.reset();submitFormTo(this.form,'ActTabelasAtividades.do','visualizar');"/&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/html:form&gt;

TabelasAtividadesDetalhes.jsp

&lt;%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %&gt;
&lt;%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %&gt;
&lt;%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %&gt;
&lt;%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %&gt;

&lt;h1&gt;&lt;bean:message key="App.TituloSistema"/&gt;&lt;/h1&gt;
&lt;h3&gt;&lt;bean:message key="Tabelas.Atividades.CaminhoTela"/&gt;&lt;/h3&gt;

&lt;html:form action="ActTabelasAtividades.do" onsubmit="javascript: return false;"&gt;
&lt;html:hidden property="act"/&gt;
&lt;html:hidden property="gridSelecao"/&gt;
&lt;table class="registro" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
	&lt;td class="registroTopo"&gt;
		&lt;bean:message key="Tabelas.Atividades.CadastroTexto"/&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="registroConteudo"&gt;
		<p>
			&lt;span class="registroLabel"&gt;
			&lt;bean:message key="Tabelas.Atividades.CampoDescricao"/&gt;:
			&lt;/span&gt;
			<br />
			&lt;span class="registroDado"&gt;
			&lt;bean:write name="formTabelasAtividades" property="campoDescricao"/&gt;
			&lt;/span&gt;
		</p>
		<p>
			&lt;span class="registroLabel"&gt;
			&lt;bean:message key="Tabelas.Atividades.CampoTipo"/&gt;:
			&lt;/span&gt;
			<br />
			&lt;span class="registroDado"&gt;
			&lt;logic:iterate id="tipo" name="formTabelasAtividades" property="todosTipos"&gt;
				&lt;bean:define id="regTipoId" name="formTabelasAtividades" property="campoTipo"/&gt;
				&lt;c:if test="${regTipoId == tipo.id}"&gt;
					&lt;bean:write name="tipo" property="descricao"/&gt;
				&lt;/c:if&gt;
			&lt;/logic:iterate&gt;
			&lt;/span&gt;
		</p>
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="registroRodape"&gt;
		&lt;html:image src="images/ico_voltar.gif" altKey="App.BotaoRetornar" onclick="javascript:processando(true);submitFormTo(this.form,'ActTabelasAtividades.do','visualizar');"/&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/html:form&gt;

Como citei anteriormente, as minhas Actions combinam dois grupos de funcionalidades. Para este grupos eu tenho duas classes genéricas de Actions. E estas duas ainda extendem de uma mais genérica ainda.

GenericAction.java

package embasa.jsime.view.action;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.actions.DispatchAction;

import embasa.jsime.model.Usuario;
import embasa.jsime.view.util.IAction;
import embasa.jsime.view.util.RecursosSessao;

/**
 * Classe pai de todas as Actions do sistema, possui todos os métodos úteis para
 * as Actions trabalharem com segurança e integridade.
 * 
 * @author Alexandre Mendonça Lima
 * 
 */
public class GenericAction extends DispatchAction implements IAction {

	protected Usuario __usuarioAutenticado;

	protected Long __qtdRegistrosEncontrados;

	protected static String FWD_IR_PARA_LOGIN = "irParaLogin";

	/**
	 * Verifica se o usuário está autenticado na sessão.
	 * 
	 * @param request
	 *            O request vindo da tela, para acessar a sessão do visitante.
	 * @return <i>true</i> se o usuário está autenticado, <i>false</i> caso
	 *         contrário.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected boolean verificarUsuarioAutenticado(HttpServletRequest request)
			throws Exception {
		__usuarioAutenticado = (Usuario) request.getSession().getAttribute(
				RecursosSessao.USUARIO_LOGADO);
		if (__usuarioAutenticado == null) {
			return false;
		} else {
			return true;
		}
	}
	
	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.view.util.IAction#setQtdRegistrosEncontrados(java.lang.Long)
	 */
	public void setQtdRegistrosEncontrados(Long qtd) {
		__qtdRegistrosEncontrados = qtd;
	}
}

GenericConsultaAction.java

package embasa.jsime.view.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

/**
 * Classe que apresenta as ações básicas para visualização de uma tela, para uma
 * tela de busca com grid e filtro e para uma tela de visualização de detalhes
 * de um registro (tela ou impressora).
 * 
 * @author Alexandre Mendonça Lima
 * 
 */
public abstract class GenericConsultaAction extends GenericAction {

	public static String FWD_VISUALIZAR = "concluirVisualizar";

	public static String FWD_PROCESSAR_PESQUISAR = "concluirProcessarPesquisar";

	public static String FWD_PROCESSAR_DETALHES = "concluirProcessarDetalhes";

	public static String FWD_PROCESSAR_IMPRESSAO = "concluirProcessarImpressao";

	/**
	 * Ação executada para visualizar a tela de busca com filtro.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward visualizar(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		String direcao = interceptarVisualizar(mapping, form, request, response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_VISUALIZAR);
	}

	/**
	 * Este método intercepta a execução de visualizar(), executa tarefas
	 * específicas e retorna a execução de visualizar().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarVisualizar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	/**
	 * Ação executada para processar a pesquisa de registros a partir de um
	 * filtro.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward processarPesquisar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String direcao = interceptarProcessarPesquisar(mapping, form, request,
				response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_PROCESSAR_PESQUISAR);
	}

	/**
	 * Este método intercepta a execução de processarPesquisar(), executa
	 * tarefas específicas e retorna a execução de processarPesquisar().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarProcessarPesquisar(
			ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	/**
	 * Ação executada para processar a visualização de detalhes de um registro
	 * específico.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward processarDetalhes(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String direcao = interceptarProcessarDetalhes(mapping, form, request,
				response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_PROCESSAR_DETALHES);
	}

	/**
	 * Este método intercepta a execução de processarDetalhes(), executa tarefas
	 * específicas e retorna a execução de processarDetalhes().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarProcessarDetalhes(
			ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	/**
	 * Ação executada para processar a impressão de um relatório sobre o
	 * registro específico.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward processarImpressao(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String direcao = interceptarProcessarImpressao(mapping, form, request,
				response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_PROCESSAR_IMPRESSAO);
	}

	/**
	 * Este método intercepta a execução de processarImpressao(), executa
	 * tarefas específicas e retorna a execução de processarImpressao().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarProcessarImpressao(
			ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;
}

TabelasAtividadesConsultaAction.java

package embasa.jsime.view.action.tabelas;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

import embasa.jsime.model.Atividade;
import embasa.jsime.util.RecursosMensagens;
import embasa.jsime.util.RecursosSetup;
import embasa.jsime.view.action.GenericConsultaAction;

/**
 * @author Alexandre Mendonça Lima
 * 
 */
public class TabelasAtividadesConsultaAction extends GenericConsultaAction {

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericConsultaAction#interceptarVisualizar(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarVisualizar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!verificarUsuarioAutenticado(request)) {
			return FWD_IR_PARA_LOGIN;
		}
		Long pagRegPorPagina = RecursosSetup.getPagRegPorPagina();
		DynaActionForm dadosForm = (DynaActionForm) form;
		String act = dadosForm.getString("act");

		Long pagRegAtual = (Long) dadosForm.get("pagRegAtual");
		if (pagRegAtual == null || pagRegAtual.longValue() &lt= 0) {
			pagRegAtual = new Long(1);
		}

		// inicializando os campos do formulário com os valores default
		dadosForm.initialize(mapping);

		Atividade.registrarObservadorQtdRegistrosEncontrados(this);
		List gridRegistros = Atividade.obterTodos(__usuarioAutenticado,
				pagRegAtual, pagRegPorPagina);

		dadosForm.set("gridRegistros", gridRegistros);

		List todosTipos = Atividade.Tipo.obterTodos(__usuarioAutenticado);
		dadosForm.set("todosTipos", todosTipos);

		dadosForm.set("pagRegPorPagina", pagRegPorPagina);
		dadosForm.set("pagRegAtual", pagRegAtual);
		dadosForm.set("pagRegQtdTotal", __qtdRegistrosEncontrados);
		dadosForm.set("actGrid", act);
		dadosForm.set("act", act);
		return null; // redireciona para o default
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericConsultaAction#interceptarProcessarPesquisar(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarProcessarPesquisar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!verificarUsuarioAutenticado(request)) {
			return FWD_IR_PARA_LOGIN;
		}
		Long pagRegPorPagina = RecursosSetup.getPagRegPorPagina();
		DynaActionForm dadosForm = (DynaActionForm) form;
		String act = dadosForm.getString("act");

		String filtroDescricao = dadosForm.getString("filtroDescricao");
		String filtroTipo = dadosForm.getString("filtroTipo");

		Long pagRegAtual = (Long) dadosForm.get("pagRegAtual");
		if (pagRegAtual == null || pagRegAtual.longValue() &lt= 0) {
			pagRegAtual = new Long(1);
		}

		// inicializando os campos do formulário com os valores default
		dadosForm.initialize(mapping);

		List gridRegistros = null;
		Atividade.registrarObservadorQtdRegistrosEncontrados(this);
		if ((filtroDescricao != null && !filtroDescricao.equals(""))
				|| (filtroTipo != null && !filtroTipo.equals("-1"))) {
			gridRegistros = Atividade.obterPorDescricaoOuTipoId(
					filtroDescricao, filtroTipo, __usuarioAutenticado,
					pagRegAtual, pagRegPorPagina);
		} else {
			gridRegistros = Atividade.obterTodos(__usuarioAutenticado,
					pagRegAtual, pagRegPorPagina);
		}
		dadosForm.set("gridRegistros", gridRegistros);

		List todosTipos = Atividade.Tipo.obterTodos(__usuarioAutenticado);
		dadosForm.set("todosTipos", todosTipos);

		dadosForm.set("filtroDescricao", filtroDescricao);
		dadosForm.set("filtroTipo", filtroTipo);

		dadosForm.set("pagRegPorPagina", pagRegPorPagina);
		dadosForm.set("pagRegAtual", pagRegAtual);
		dadosForm.set("pagRegQtdTotal", __qtdRegistrosEncontrados);
		dadosForm.set("actGrid", act);
		dadosForm.set("act", act);
		return null; // redireciona para o default
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericConsultaAction#interceptarProcessarDetalhes(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarProcessarDetalhes(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!verificarUsuarioAutenticado(request)) {
			return FWD_IR_PARA_LOGIN;
		}
		DynaActionForm dadosForm = (DynaActionForm) form;
		String act = dadosForm.getString("act");
		String regId = dadosForm.getString("gridSelecao");
		// inicializando os campos do formulário com os valores default
		dadosForm.initialize(mapping);

		Atividade reg = Atividade.obterPorId(new Long(regId),
				__usuarioAutenticado);
		if (reg != null) {
			dadosForm.set("campoDescricao", reg.getDescricao());
			dadosForm.set("campoTipo", reg.getTipo().getId());
		}

		dadosForm.set("gridSelecao", regId);

		List todosTipos = Atividade.Tipo.obterTodos(__usuarioAutenticado);
		dadosForm.set("todosTipos", todosTipos);

		dadosForm.set("act", act);
		return null; // redireciona para o default
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericConsultaAction#interceptarProcessarImpressao(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarProcessarImpressao(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		// Este método não é utilizado na tela correspondente a esta action.
		throw new Exception(RecursosMensagens
				.getMensagem("Exception.MetodoNaoImplementado"));
	}

}

GenericCadastroAction.java

package embasa.jsime.view.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

/**
 * Classe que apresenta as ações básicas para um cadastro com inclusão, edição e
 * exclusão.
 * 
 * @author Alexandre Mendonça Lima
 * 
 */
public abstract class GenericCadastroAction extends GenericAction {

	public static String FWD_CONCLUIR_INICIAR_NOVO = "concluirIniciarNovo";

	public static String FWD_CONCLUIR_PROCESSAR_NOVO = "concluirProcessarNovo";

	public static String FWD_CONCLUIR_INICIAR_EDITAR = "concluirIniciarEditar";

	public static String FWD_CONCLUIR_PROCESSAR_EDITAR = "concluirProcessarEditar";

	public static String FWD_CONCLUIR_PROCESSAR_EXCLUIR = "concluirProcessarExcluir";

	/**
	 * Ação executada ao iniciar o procedimento de inclusão de um registro.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward iniciarNovo(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		String direcao = interceptarIniciarNovo(mapping, form, request,
				response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_CONCLUIR_INICIAR_NOVO);
	}

	/**
	 * Este método intercepta a execução de iniciarNovo(), executa tarefas
	 * específicas e retorna a execução de iniciarNovo().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarIniciarNovo(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	/**
	 * Ação executada para processar a inclusão de um registro.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward processarNovo(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		String direcao = interceptarProcessarNovo(mapping, form, request,
				response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_CONCLUIR_PROCESSAR_NOVO);
	}

	/**
	 * Este método intercepta a execução de processarNovo(), executa tarefas
	 * específicas e retorna a execução de processarNovo().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarProcessarNovo(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	/**
	 * Ação executada ao iniciar o procedimento de edição de um registro.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward iniciarEditar(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		String direcao = interceptarIniciarEditar(mapping, form, request,
				response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_CONCLUIR_INICIAR_EDITAR);
	}

	/**
	 * Este método intercepta a execução de iniciarEditar(), executa tarefas
	 * específicas e retorna a execução de iniciarEditar().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarIniciarEditar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	/**
	 * Ação executada para processar a edição de um registro.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward processarEditar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String direcao = interceptarProcessarEditar(mapping, form, request,
				response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_CONCLUIR_PROCESSAR_EDITAR);
	}

	/**
	 * Este método intercepta a execução de processarEditar(), executa tarefas
	 * específicas e retorna a execução de processarEditar().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarProcessarEditar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

	/**
	 * Ação executada para processar a exclusão de um registro.
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return ActionForward
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	public ActionForward processarExcluir(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		String direcao = interceptarProcessarExcluir(mapping, form, request,
				response);
		if (direcao != null && !direcao.equals(""))
			return mapping.findForward(direcao);
		else
			return mapping.findForward(FWD_CONCLUIR_PROCESSAR_EXCLUIR);
	}

	/**
	 * Este método intercepta a execução de processarExcluir(), executa tarefas
	 * específicas e retorna a execução de processarExcluir().
	 * 
	 * @param mapping
	 * @param form
	 * @param request
	 * @param response
	 * @return O direcionamento que se deseja dar depois da execução. Se for
	 *         nulo ou branco, usará o direcionamento default.
	 * @throws AplicacaoException
	 * @throws AmbienteException
	 */
	protected abstract String interceptarProcessarExcluir(
			ActionMapping mapping, ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception;

}

TabelasAtividadesCadastroAction.java

package embasa.jsime.view.action.tabelas;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.DynaActionForm;

import embasa.jsime.model.Atividade;
import embasa.jsime.view.action.GenericCadastroAction;

/**
 * @author Alexandre Mendonça Lima
 * 
 */
public class TabelasAtividadesCadastroAction extends GenericCadastroAction {

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericCadastroAction#interceptarIniciarNovo(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarIniciarNovo(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!verificarUsuarioAutenticado(request)) {
			return FWD_IR_PARA_LOGIN;
		}
		DynaActionForm dadosForm = (DynaActionForm) form;
		String act = dadosForm.getString("act");
		// inicializando os campos do formulário com os valores default
		dadosForm.initialize(mapping);
		List todosTipos = Atividade.Tipo.obterTodos(__usuarioAutenticado);
		dadosForm.set("todosTipos", todosTipos);
		dadosForm.set("act", act);
		return null; // redireciona para o default
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericCadastroAction#interceptarProcessarNovo(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarProcessarNovo(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!verificarUsuarioAutenticado(request)) {
			return FWD_IR_PARA_LOGIN;
		}
		DynaActionForm dadosForm = (DynaActionForm) form;
		String act = dadosForm.getString("act");
		String campoDescricao = dadosForm.getString("campoDescricao");
		String campoTipo = dadosForm.getString("campoTipo");
		Atividade.inserirNovo(campoDescricao, campoTipo, __usuarioAutenticado);
		// inicializando os campos do formulário com os valores default
		dadosForm.initialize(mapping);
		dadosForm.set("act", act);
		return null; // redireciona para o default
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericCadastroAction#interceptarIniciarEditar(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarIniciarEditar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!verificarUsuarioAutenticado(request)) {
			return FWD_IR_PARA_LOGIN;
		}
		DynaActionForm dadosForm = (DynaActionForm) form;
		String act = dadosForm.getString("act");
		String regId = dadosForm.getString("gridSelecao");
		// inicializando os campos do formulário com os valores default
		dadosForm.initialize(mapping);

		Atividade reg = Atividade.obterPorId(new Long(regId),
				__usuarioAutenticado);
		if (reg != null) {
			dadosForm.set("campoDescricao", reg.getDescricao());
			dadosForm.set("campoTipo", reg.getTipo().getId());
		}

		dadosForm.set("gridSelecao", regId);

		List todosTipos = Atividade.Tipo.obterTodos(__usuarioAutenticado);
		dadosForm.set("todosTipos", todosTipos);
		dadosForm.set("act", act);
		return null; // redireciona para o default
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericCadastroAction#interceptarProcessarEditar(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarProcessarEditar(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!verificarUsuarioAutenticado(request)) {
			return FWD_IR_PARA_LOGIN;
		}
		DynaActionForm dadosForm = (DynaActionForm) form;
		String act = dadosForm.getString("act");
		String regId = dadosForm.getString("gridSelecao");
		String campoDescricao = dadosForm.getString("campoDescricao");
		String campoTipo = dadosForm.getString("campoTipo");
		Atividade.atualizarPorId(new Long(regId), campoDescricao, campoTipo,
				__usuarioAutenticado);
		// inicializando os campos do formulário com os valores default
		dadosForm.initialize(mapping);
		dadosForm.set("act", act);
		return null; // redireciona para o default
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see embasa.jsime.mvc.action.GenericCadastroAction#interceptarProcessarExcluir(org.apache.struts.action.ActionMapping,
	 *      org.apache.struts.action.ActionForm,
	 *      javax.servlet.http.HttpServletRequest,
	 *      javax.servlet.http.HttpServletResponse)
	 */
	protected String interceptarProcessarExcluir(ActionMapping mapping,
			ActionForm form, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		if (!verificarUsuarioAutenticado(request)) {
			return FWD_IR_PARA_LOGIN;
		}
		DynaActionForm dadosForm = (DynaActionForm) form;
		String act = dadosForm.getString("act");
		String regId = dadosForm.getString("gridSelecao");
		Atividade.excluirPorId(new Long(regId), __usuarioAutenticado);
		// inicializando os campos do formulário com os valores default
		dadosForm.initialize(mapping);
		dadosForm.set("act", act);
		return null; // redireciona para o default
	}

}

Este é um exemplo para ter uma idéia de como estava o meu código com o Struts 1.
No próximo post eu vou colocar como ficou o código como Struts 2.

A

Convertendo para o Struts 2, a aplicação manteve a mesma estrutura: JSP+Action -&gt Model (método estático) -&gt DAO e o Model (métodos get e set) transitando nas 3 camadas. Esta estrutura já havia sido pensada assim para poder trocar o framework no nível JSP+Action no futuro.

Reaproveitei todos os Models e DAO’s, sem mexer em nenhuma linha de código destes. Reaproveitei também os JSP’s mas estes tiveram que ser reajustados para as novas tags do Struts 2.

Meu struts.xml agora ficou assim:

&lt;struts&gt;

	&lt;package name="jsime-default" extends="struts-default" abstract="true"&gt;
	
		&lt;interceptors&gt;
		
			&lt;interceptor name="autenticacao" class="embasa.jsime.view.interceptor.AutenticacaoInterceptor"/&gt;
			
			&lt;interceptor-stack name="stackReduzido"&gt;
				&lt;interceptor-ref name="defaultStack"/&gt;
			&lt;/interceptor-stack&gt;
			
			&lt;interceptor-stack name="stackGeral"&gt;
                &lt;interceptor-ref name="stackReduzido"/&gt;
                &lt;interceptor-ref name="autenticacao"/&gt;
            &lt;/interceptor-stack&gt;
			
		&lt;/interceptors&gt;
		
		&lt;default-interceptor-ref name="stackGeral"/&gt;
		
		&lt;global-results&gt;
			&lt;result name="login" type="redirect-action"&gt;Login_visualizar&lt;/result&gt;
			&lt;result name="error"&gt;/pages/Erro.jsp&lt;/result&gt;
			&lt;result name="input"&gt;/pages/Erro.jsp&lt;/result&gt;
			&lt;result name="rootException"&gt;/pages/Erro.jsp&lt;/result&gt;
		&lt;/global-results&gt;
		
		&lt;global-exception-mappings&gt;
			&lt;exception-mapping exception="java.lang.Exception" result="rootException"/&gt;
		&lt;/global-exception-mappings&gt;

	&lt;/package&gt;
	
	&lt;package name="tabelas" extends="jsime-default"&gt;

		&lt;action name="Atividade_*" class="embasa.jsime.view.action.tabelas.AtividadeAction" method="{1}"&gt;
			&lt;result name="visualizar"&gt;/pages/TabelasAtividades.jsp&lt;/result&gt;
			&lt;result name="detalhes"&gt;/pages/TabelasAtividadesDetalhes.jsp&lt;/result&gt;
			&lt;result name="cadastro"&gt;/pages/TabelasAtividadesCadastro.jsp&lt;/result&gt;
		&lt;/action&gt;
		
	&lt;/package&gt;
	
&lt;/struts&gt;

Como falei antes, não consegui fazer o Tiles funcionar no Struts 2 apesar do que está escrito na documentação. Pode ser um bug que seja resolvido na próxima versão beta. Então resolvi voltar a fazer includes nos JSP’s com a tag <s:include/> do novo framework.
Consegui também fazer o código de paginação ficar isolado e genérico num JSP separado e funcionar em todas as telas sem precisar reescrever nada.

Paginacao.jsp

&lt;%@ taglib uri="/struts-tags" prefix="s" %&gt;
&lt;s:hidden name="pagRegPorPagina" /&gt;
&lt;s:hidden name="pagRegAtual" /&gt;
&lt;s:hidden name="pagRegQtdTotal" /&gt;
&lt;s:if test="%{gridRegistros != null && !gridRegistros.isEmpty()}"&gt;
	&nbsp;
	&lt;s:if test="%{pagRegAtual &gt; pagRegPorPagina}"&gt;
		&lt;s:url id="icoPrimeiro" value="/pages/images/grid_primeiro.gif"/&gt;
		&lt;s:submit type="image"
			src="%{icoPrimeiro}"
			label="%{getText('App.Paginador.BotaoPrimeiro')}" 
			onclick="javascript:processando(true);this.form.pagRegAtual.value=1;submitFormTo(this.form,'%{actionName}');"/&gt;
		&nbsp;
		&lt;s:url id="icoAnterior" value="/pages/images/grid_anterior.gif"/&gt;
		&lt;s:submit type="image"
			src="%{icoAnterior}"
			label="%{getText('App.Paginador.BotaoAnterior')}" 
			onclick="javascript:processando(true);this.form.pagRegAtual.value=pagRegAtual.value-pagRegPorPagina.value;submitFormTo(this.form,'%{actionName}');"/&gt;
		&nbsp;
	&lt;/s:if&gt;
	&lt;s:property value="pagRegQtdTotal"/&gt; &lt;s:text name="App.Paginador.RegistrosEncontrados"/&gt;
	&lt;s:if test="%{pagRegAtual &lt;= pagRegQtdTotal-pagRegPorPagina}"&gt;
		&nbsp;
		&lt;s:url id="icoProximo" value="/pages/images/grid_proximo.gif"/&gt;
		&lt;s:submit type="image"
			src="%{icoProximo}"
			label="%{getText('App.Paginador.BotaoProximo')}" 
			onclick="javascript:processando(true);this.form.pagRegAtual.value=parseInt(pagRegAtual.value)+parseInt(pagRegPorPagina.value);submitFormTo(this.form,'%{actionName}');"/&gt;
		&nbsp;
		&lt;s:url id="icoUltimo" value="/pages/images/grid_ultimo.gif"/&gt;
		&lt;s:if test="%{regQtdTotal%regPorPagina == 0}"&gt;
			&lt;s:submit type="image"
				src="%{icoUltimo}"
				label="%{getText('App.Paginador.BotaoUltimo')}" 
				onclick="javascript:processando(true);this.form.pagRegAtual.value=pagRegQtdTotal.value-(pagRegPorPagina.value)+1;submitFormTo(this.form,'%{actionName}');"/&gt;
		&lt;/s:if&gt;
		&lt;s:else&gt;
			&lt;s:submit type="image"
				src="%{icoUltimo}"
				label="%{getText('App.Paginador.BotaoUltimo')}" 
				onclick="javascript:processando(true);this.form.pagRegAtual.value=pagRegQtdTotal.value-(pagRegQtdTotal.value%pagRegPorPagina.value)+1;submitFormTo(this.form,'%{actionName}');"/&gt;
		&lt;/s:else&gt;
	&lt;/s:if&gt;
&lt;/s:if&gt;
&lt;s:else&gt;
&nbsp;
&lt;/s:else&gt;

TabelasAtividades.jsp

&lt;%@ taglib uri="/struts-tags" prefix="s" %&gt;

&lt;s:include value="TemplateGeralHeader.jsp"/&gt;

&lt;h3&gt;&lt;s:text name="Tabelas.Atividades.CaminhoTela"/&gt;&lt;/h3&gt;

&lt;s:form onsubmit="javascript: return false;"&gt;
&lt;table class="grid" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
	&lt;td class="gridFiltro"&gt;
		&lt;span class="gridCampo"&gt;
			&lt;s:text name="Tabelas.Atividades.CampoDescricao"/&gt;: 
			&lt;s:textfield name="filtroDescricao" size="30"/&gt;
		&lt;/span&gt;
		&lt;span class="gridCampo"&gt;
			&lt;s:text name="Tabelas.Atividades.CampoTipo"/&gt;: 
			&lt;s:select name="filtroTipo" 
				list="todosTipos" 
				listKey="id" listValue="descricao" 
				headerKey="-1" headerValue=" "/&gt;
		&lt;/span&gt;
		&lt;span class="gridCampo"&gt;
			&lt;s:url id="icoAtualizar" value="/pages/images/ico_atualizar.gif"/&gt;
			&lt;s:submit type="image"
				src="%{icoAtualizar}"
				label="%{getText('App.BotaoRecarregarTabela')}" 
				onclick="javascript:processando(true);submitFormTo(this.form,'%{actionName}');"/&gt;
		&lt;/span&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="gridTopo"&gt;
		&lt;s:include value="Paginacao.jsp"/&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td&gt;
		&lt;table class="gridConteudo"&gt;
		&lt;tr&gt;
			&lt;th width="20"&gt;&nbsp;&lt;/th&gt;
			&lt;th&gt;&lt;s:text name="Tabelas.Atividades.CampoDescricao"/&gt;&lt;/th&gt;
			&lt;th width="20%"&gt;&lt;s:text name="Tabelas.Atividades.CampoTipo"/&gt;&lt;/th&gt;
		&lt;/tr&gt;
		&lt;s:if test="%{gridRegistros != null && !gridRegistros.isEmpty()}"&gt;
		&lt;s:iterator id="reg" value="gridRegistros" status="gridStatus"&gt;
			&lt;tr class="linha&lt;s:if test="#gridStatus.odd == true"&gt;1&lt;/s:if&gt;&lt;s:else&gt;2&lt;/s:else&gt;"&gt
				&lt;td&gt;&lt;input type="radio" name="gridSelecao" value="&lt;s:property value='id'/&gt;"&gt;&lt;/td&gt;
				&lt;td&gt;&lt;s:property value="descricao"/&gt;&lt;/td&gt;
				&lt;td&gt;&lt;s:property value="tipo.descricao"/&gt;&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/s:iterator&gt;
		&lt;/s:if&gt;
		&lt;s:else&gt;
			&lt;tr class="linha1"&gt;
				&lt;td colspan="3" align="center"&gt;&lt;s:text name="App.SemRegistros"/&gt;&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/s:else&gt;
		&lt;/table&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="gridRodape"&gt;
		&lt;s:url id="icoNovo" value="/pages/images/ico_novo.gif"/&gt;
		&lt;s:submit type="image"
				src="%{icoNovo}"
				label="%{getText('App.BotaoNovo')}" 
				onclick="javascript:processando(true);submitFormTo(this.form,'Atividade','iniciarNovo');"/&gt;
		&lt;s:if test="%{gridRegistros != null && !gridRegistros.isEmpty()}"&gt;
			&lt;s:url id="icoAlterar" value="/pages/images/ico_alterar.gif"/&gt;
			&lt;s:submit type="image"
				src="%{icoAlterar}"
				label="%{getText('App.BotaoAlterar')}" 
				onclick="javascript:processando(true);submitFormTo(this.form,'Atividade','iniciarEditar');"/&gt;
			&lt;s:url id="icoExcluir" value="/pages/images/ico_excluir.gif"/&gt;
			&lt;s:submit type="image"
				src="%{icoExcluir}"
				label="%{getText('App.BotaoExcluir')}" 
				onclick="javascript:processando(true);submitFormTo(this.form,'Atividade','processarExcluir');"/&gt;
			&lt;s:url id="icoDetalhes" value="/pages/images/ico_detalhes.gif"/&gt;
			&lt;s:submit type="image"
				src="%{icoDetalhes}"
				label="%{getText('App.BotaoDetalhes')}" 
				onclick="javascript:processando(true);submitFormTo(this.form,'Atividade','processarDetalhes');"/&gt;
		&lt;/s:if&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/s:form&gt;

&lt;s:include value="TemplateGeralFooter.jsp"/&gt;

TabelasAtividadesCadastro.jsp

&lt;%@ taglib uri="/struts-tags" prefix="s" %&gt;

&lt;s:include value="TemplateGeralHeader.jsp"/&gt;

&lt;h3&gt;&lt;s:text name="Tabelas.Atividades.CaminhoTela"/&gt;&lt;/h3&gt;

&lt;s:form onsubmit="javascript: return false;"&gt;
&lt;table class="formulario" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
	&lt;td class="formularioTopo"&gt;
		&lt;s:text name="Tabelas.Atividades.CadastroTexto"/&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="formularioConteudo"&gt;
		&lt;s:hidden name="gridSelecao"/&gt;
		&lt;span class="formularioCampo"&gt;
			&lt;s:text name="Tabelas.Atividades.CampoDescricao"/&gt;: <br />
			&lt;s:textfield name="atividade.descricao" size="80"/&gt;
		&lt;/span&gt;
		&lt;span class="formularioCampo"&gt;
			&lt;s:text name="Tabelas.Atividades.CampoTipo"/&gt;: <br />
			&lt;s:select name="atividade.tipo.id" 
				list="todosTipos" 
				listKey="id" listValue="descricao" 
				headerKey="-1" headerValue=" "/&gt;
		&lt;/span&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="formularioRodape"&gt;
		&lt;s:if test="%{actionName == 'Atividade_iniciarNovo'}"&gt;
			&lt;s:set name="metodoDestino" value="%{'processarNovo'}"/&gt;
		&lt;/s:if&gt;
		&lt;s:if test="%{actionName == 'Atividade_iniciarEditar'}"&gt;
			&lt;s:set name="metodoDestino" value="%{'processarEditar'}"/&gt;
		&lt;/s:if&gt;
		&lt;s:url id="icoSalvar" value="/pages/images/ico_salvar.gif"/&gt;
		&lt;s:submit type="image"
				src="%{icoSalvar}"
				label="%{getText('App.BotaoSalvar')}" 
				onclick="javascript:processando(true);submitFormTo(this.form,'Atividade','%{metodoDestino}');"/&gt;
		&nbsp;
		<a >
			<img /pages/images/ico_cancelar.gif"/>" border="0" align="absmiddle" alt="&lt;s:text name="App.BotaoCancelar"/&gt;"/&gt
		</a>
	&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/s:form&gt;

&lt;s:include value="TemplateGeralFooter.jsp"/&gt;

TabelasAtividadesDetalhes.jsp

&lt;%@ taglib uri="/struts-tags" prefix="s" %&gt;

&lt;s:include value="TemplateGeralHeader.jsp"/&gt;

&lt;h3&gt;&lt;s:text name="Tabelas.Atividades.CaminhoTela"/&gt;&lt;/h3&gt;

&lt;s:form onsubmit="javascript: return false;"&gt;
&lt;table class="registro" cellpadding="0" cellspacing="0"&gt;
&lt;tr&gt;
	&lt;td class="registroTopo"&gt;
		&lt;s:text name="Tabelas.Atividades.CadastroTexto"/&gt;
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="registroConteudo"&gt;
		<p>
			&lt;span class="registroLabel"&gt;
			&lt;s:text name="Tabelas.Atividades.CampoDescricao"/&gt;:
			&lt;/span&gt;
			<br />
			&lt;span class="registroDado"&gt;
			&lt;s:property value="atividade.descricao"/&gt;
			&lt;/span&gt;
		</p>
		<p>
			&lt;span class="registroLabel"&gt;
			&lt;s:text name="Tabelas.Atividades.CampoTipo"/&gt;:
			&lt;/span&gt;
			<br />
			&lt;span class="registroDado"&gt;
			&lt;s:property value="atividade.tipo.descricao"/&gt;
			&lt;/span&gt;
		</p>
	&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
	&lt;td class="registroRodape"&gt;
		<a >
			<img /pages/images/ico_voltar.gif"/>" border="0" align="absmiddle" alt="&lt;s:text name="App.BotaoRetornar"/&gt;"/&gt
		</a>
	&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;/s:form&gt;

&lt;s:include value="TemplateGeralFooter.jsp"/&gt;

Antes, para saber se um usuário estava logado no sistema, eu tinha que ter um if em cada método das Actions. Agora o Struts já vem com o conceito de interceptador e eu aproveitei ele para fazer isso.

AutenticacaoInterceptor.java

package embasa.jsime.view.interceptor;

import java.util.Map;

import org.apache.struts2.ResultNames;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;

import embasa.jsime.model.Usuario;
import embasa.jsime.view.util.ActionUtil;

/**
 * @author Alexandre Mendonça Lima
 * 
 */
public class AutenticacaoInterceptor implements Interceptor {

	public void destroy() {

	}

	public void init() {

	}

	public String intercept(ActionInvocation invocation) throws Exception {
		ActionContext contexto = invocation.getInvocationContext();
		Map sessao = contexto.getSession();
		Usuario usuarioLogado = (Usuario) sessao.get(ActionUtil.USUARIO_LOGADO);
		if (usuarioLogado == null) {
			return ResultNames.LOGIN;
		}

		return invocation.invoke();
	}

}

Minha GenericAction ficou assim:

package embasa.jsime.view.util;

import java.util.Map;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;

import embasa.jsime.model.Usuario;

/**
 * Classe pai de todos as Actions da aplicação. Extende a classe
 * com.opensymphony.xwork2.ActionSupport do framework Struts.
 * 
 * @author Alexandre Mendonça Lima
 * 
 */
public abstract class GenericAction extends ActionSupport {

	/**
	 * Obtém do objeto com.opensymphony.xwork2.ActionContext o nome da Action
	 * atualmente em uso.
	 * 
	 * @return O nome da Action em uso no ciclo de vida de execução do
	 *         framework.
	 */
	public String getActionName() {
		return ActionContext.getContext().getName();
	}

	/**
	 * Obtém o usuário atualmente autenticado na aplicação.
	 * 
	 * @return Um objeto da classe Usuario ou nulo se não tiver nenhum usuário
	 *         autenticado no momento.
	 */
	protected Usuario getUsuarioLogado() {
		Map session = (Map) ActionContext.getContext().get("session");
		Usuario usuarioLogado = (Usuario) session
				.get(ActionUtil.USUARIO_LOGADO);
		return usuarioLogado;
	}

	private Long pagRegPorPagina;

	private Long pagRegAtual;

	private Long pagRegQtdTotal;

	public Long getPagRegAtual() {
		return pagRegAtual;
	}

	public void setPagRegAtual(Long pagRegAtual) {
		this.pagRegAtual = pagRegAtual;
	}

	public Long getPagRegPorPagina() {
		return pagRegPorPagina;
	}

	public void setPagRegPorPagina(Long pagRegPorPagina) {
		this.pagRegPorPagina = pagRegPorPagina;
	}

	public Long getPagRegQtdTotal() {
		return pagRegQtdTotal;
	}

	public void setPagRegQtdTotal(Long pagRegQtdTotal) {
		this.pagRegQtdTotal = pagRegQtdTotal;
	}
}

Criei uma classe para auxiliar as Actions:

package embasa.jsime.view.util;

/**
 * Esta classe auxilia as Actions do sistema, as quais são extendidas do
 * framework Struts.
 * 
 * @author Alexandre Mendonça Lima
 * 
 */
public abstract class ActionUtil {

	/**
	 * Constante que define a chave da sessão em que está guardado o usuário
	 * autenticado na aplicação.
	 */
	public static final String USUARIO_LOGADO = "usuarioLogado";

	/**
	 * Constante que define o nome do Result para a visualização da tela de
	 * entrada em uma funcionalidade da aplicação.
	 */
	public static final String VISUALIZAR = "visualizar";

	/**
	 * Constante que define o nome do Result para a visualização da tela de
	 * detalhes de um registro de uma funcionalidade da aplicação.
	 */
	public static final String DETALHES = "detalhes";

	/**
	 * Constante que define o nome do Result para a visualização da tela de
	 * cadastro de registro de uma funcionalidade da aplicação.
	 */
	public static final String CADASTRO = "cadastro";

}

E finalmente, assim ficou minha AtividadeAction.java:

package embasa.jsime.view.action.tabelas;

import java.util.List;

import embasa.jsime.model.Atividade;
import embasa.jsime.model.Atividade.Tipo;
import embasa.jsime.util.RecursosSetup;
import embasa.jsime.view.util.ActionUtil;
import embasa.jsime.view.util.GenericAction;

/**
 * @author Alexandre Mendonça Lima
 * 
 */
public class AtividadeAction extends GenericAction {

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.opensymphony.xwork2.Validateable#validate()
	 */
	public void validate() {

		if (getActionName().equals("Atividade_processarDetalhes")
				|| getActionName().equals("Atividade_iniciarEditar")
				|| getActionName().equals("Atividade_processarExcluir")) {

			if (getGridSelecao() == null) {
				String msg = getText("Validation.Obrigatorio",
						new String[] { getText("App.GridSelecao") });
				addFieldError("gridSelecao", msg);
			}

		}

		if (getActionName().equals("Atividade_processarNovo")
				|| getActionName().equals("Atividade_processarEditar")) {

			if (getAtividade().getDescricao() == null
					|| getAtividade().getDescricao().trim().equals("")) {
				String msg = getText(
						"Validation.Obrigatorio",
						new String[] { getText("Tabelas.Atividades.CampoDescricao") });
				addFieldError("atividade.descricao", msg);
			}

			if (getAtividade().getTipo() == null
					|| getAtividade().getTipo().getId() == null
					|| getAtividade().getTipo().getId().equals("-1")) {
				String msg = getText(
						"Validation.Obrigatorio",
						new String[] { getText("Tabelas.Atividades.CampoTipo") });
				addFieldError("atividade.tipo", msg);
			}

		}
	}

	public void prepararListas() throws Exception {
		setTodosTipos(Tipo.obterTodos(getUsuarioLogado()));
	}

	public String visualizar() throws Exception {
		if (getPagRegAtual() == null || getPagRegAtual().longValue() &lt= 0) {
			setPagRegAtual(new Long(1));
		}
		setPagRegPorPagina(RecursosSetup.getPagRegPorPagina());

		prepararListas();

		List registros = null;
		if ((getFiltroDescricao() != null && !getFiltroDescricao().equals(""))
				|| (getFiltroTipo() != null && !getFiltroTipo().equals("-1"))) {
			registros = Atividade.obterPorDescricaoOuTipoId(
					getFiltroDescricao(), getFiltroTipo(), getUsuarioLogado(),
					getPagRegAtual(), getPagRegPorPagina());
		} else {
			registros = Atividade.obterTodos(getUsuarioLogado(),
					getPagRegAtual(), getPagRegPorPagina());
		}
		setGridRegistros(registros);

		setPagRegQtdTotal(Atividade.getQtdRegistrosEncontrados());

		return ActionUtil.VISUALIZAR;
	}

	public String processarDetalhes() throws Exception {
		setAtividade(Atividade.obterPorId(getGridSelecao(), getUsuarioLogado()));
		return ActionUtil.DETALHES;
	}

	public String iniciarNovo() throws Exception {
		prepararListas();
		setAtividade(new Atividade());
		return ActionUtil.CADASTRO;
	}

	public String processarNovo() throws Exception {
		Atividade.inserirNovo(getAtividade().getDescricao(), getAtividade()
				.getTipo().getId(), getUsuarioLogado());
		return visualizar();
	}

	public String iniciarEditar() throws Exception {
		prepararListas();
		setAtividade(Atividade.obterPorId(getGridSelecao(), getUsuarioLogado()));
		return ActionUtil.CADASTRO;
	}

	public String processarEditar() throws Exception {
		Atividade.atualizarPorId(getGridSelecao(), getAtividade()
				.getDescricao(), getAtividade().getTipo().getId(),
				getUsuarioLogado());
		return visualizar();
	}

	public String processarExcluir() throws Exception {
		Atividade.excluirPorId(getGridSelecao(), getUsuarioLogado());
		return visualizar();
	}

	private List gridRegistros;

	private Long gridSelecao;

	private Atividade atividade;

	private List todosTipos;

	private String filtroDescricao;

	private String filtroTipo;

	public List getGridRegistros() {
		return gridRegistros;
	}

	public void setGridRegistros(List gridRegistros) {
		this.gridRegistros = gridRegistros;
	}

	public Long getGridSelecao() {
		return gridSelecao;
	}

	public void setGridSelecao(Long gridSelecao) {
		this.gridSelecao = gridSelecao;
	}

	public Atividade getAtividade() {
		return atividade;
	}

	public void setAtividade(Atividade atividade) {
		this.atividade = atividade;
	}

	public List getTodosTipos() {
		return todosTipos;
	}

	public void setTodosTipos(List todosTipos) {
		this.todosTipos = todosTipos;
	}

	public String getFiltroDescricao() {
		return filtroDescricao;
	}

	public void setFiltroDescricao(String filtroDescricao) {
		this.filtroDescricao = filtroDescricao;
	}

	public String getFiltroTipo() {
		return filtroTipo;
	}

	public void setFiltroTipo(String filtroTipo) {
		this.filtroTipo = filtroTipo;
	}

}

Também não consegui fazer a validação funcionar para os métodos separadamente, então optei por não usar a validação em XML e sim na action. Com isso ganhei debug mas tô tendo um pouco mais de copy-paste.

Qualquer dúvida, é só perguntar.

W

Olá alexandremlima ,
Muito legal a sua explicação acho que já deu para tirar uma conclusão só mais uma pergunta pessoal com relação a IDE, qual delas vc. está usando e os auto completar, code-editor ,help e demais recursos funcionam de acordo pois pelo que vi ainda não temos plugins para o Struts 2.
Mais uma vez obrigado.
att.
William Silva
[email removido]

A

Eu uso o Eclipse 3.1.2 com o plugin WTP 1.0.2 e com o plugin Tomcat Launcher da Sysdeo. Fazemos todos os sistemas somente com esse ambiente.
Estou aprendendo o Struts 2 somente com a documentação do website da Apache e pesquisando nos fóruns usando o Google.

W

Beleza… 8)

T

Olá alexandremlima !

Me explica uma questão, por favor. Qual a razão do action genérico ?
Há tempos à atrás, pensei em algo para uso de polimorfismo, para criar dinamismo na condução das ações, mas não consegui uma conclusão coesa.

Bye !!

T

Ah !! Queria agradecê-lo pelo material. Estou fazendo testes com struts2 e vai me ajudar muito.

Obrigado !

A

A GenericAction é apenas para diminuição de código. Todas as minhas Actions tem os gets e sets da paginação e um get para obter o usuário logado na aplicação. Então, deixei isso numa action genérica e todas as actions herdam dela estes métodos.

R

Estou utilizando o Struts 2 e estou achando bem mais "“organizado” doque o anterior.

Quanto ao Tiles? Como anda isso? Já funciona para a versão 2 ? Estava verificando que já existe um tal de Tiles 2.

T+

A

Sim, o Tiles não estava funcionando muito bem na versão 2.0.1 mas a partir da 2.0.2 está ok.
Sugiro que baixem no momento a versão 2.0.3 em http://people.apache.org/builds/struts/2.0.3/ . É uma versão mais estável do Struts 2 e quase foi promovida a versão GA (produção). Existe já uma versão 2.0.4 em andamento para ser lançada nos próximos dias.

W

Opá…

Existe já uma versão 2.0.4 em andamento para ser lançada nos próximos dias.
Agora vai…rs…rs…

R

Peguei uma aplicação que estava funcionando com a versão do Struts 2.0.1, baixei o pacote para a versão 2.0.3… atualizei a aplicação e BINGO… parou de funcionar… :frowning:

Dá um erro no web.xml !!! voltei os pacotes da versão 2.0.1 tá funcionando novamente !!! Que coisa heim !!!

Segue o meu web.xml

<web-app>
    <display-name>appStruts2.x</display-name>
    <filter>
        <filter-name>filtroStruts</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filtroStruts</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <welcome-file-list>
        <welcome-file>/pages/index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

Estou utilizando o JBOSS, e no log, quando da o erro diz que é na linha 6, neste caso reclama que a tag: não existe !!!

Alguma sugestão !!?!?

t+

R

alexandremlima

Conforme o exemplo que vc. mostrou acima queria saber se tem como chamar o método de uma action via url, até agora só consigo chamar um método chamado INPUT, criei outros métodos (ex. listaRegistros) e não consigo chamar via URL.

Apresenta o seguinte erro : [Dispatcher] Could not find action or result

mas o método esta lá !!!

Será que pode ser uma implementação futura?

t+

A

Versão 2.05 Quentinha…
http://people.apache.org/repo/m2-snapshot-repository/org/apache/struts/struts2-core/2.0.5-SNAPSHOT/

R

Baixei a versão 2.0.5 e ainda não consigo chamar um método de uma action.

ex: http://localhost:8080/appStruts2x/Setor_visualizar.action

Será que isso é “bug” da versão ainda !?!?!?!

A

rodrigo_ctba:
Baixei a versão 2.0.5 e ainda não consigo chamar um método de uma action.
ex: http://localhost:8080/appStruts2x/Setor_visualizar.action
Será que isso é “bug” da versão ainda !?!?!?!

Como está o seu struts.xml?

R

O problema é o seguinte, quando eu tenho o tal NomeAction-validation.xml da erro quando tento chamar um método que esteja dentro dessa action (NomeAction). No entanto se for chamado o método via POST, funciona !!!

Agora se eu ter uma OutraAction , e eu chamo um método que esteja dentro dela não da erro !!! o método é executado !!!

PORQUE acontece isso? Tem alguma lógica ?

t+

K

Tenta excluir a Action de listar no validation deve funcionar.

Boa sorte! :thumbup:

W

Beta Releases do Struts 2.0.5 em.:
http://struts.apache.org/2.0.5/
http://struts.apache.org/2.x/docs/release-notes-205.html

sds
William Silva.

R
  • Criei um Action só para fazer o POST do formulário e uma outra que chamei de GenericAction :?

Estou utilizando a versão 2.0.5 !!!

Que por sinal já está oficialmente no site para download

http://struts.apache.org/download.cgi#struts201

É beta, mas já esta quase, eu acho !!!

Por falar nisso… Alguém sabe se existe uma previsão para o lançamento da versão final ?

S

Comecei recentemente a trabalhar com J2EE e há alguns dias com struts 1.3.5 (nunca mexi no 2).

Minha questao e a seguinte:

como fazer para evitar a super população de classes e o tamanho gigante do struts.xml?

Pra cada insert/update/delete de cada tabela eu tinha uma classe e um action no xml.

Já consegui reduzir para um action pra cada tabela, porem ainda sofro com o excesso de classes. Existe alguma solucao obvia para isto?

W

Olá,
Aqui dois bons artigos sobre Struts 1.xx .:
www.powerlogic.com.br/ecp/files.do?evento=download&urlArqPlc=tirando_max_struts_parte1.pdf

www.powerlogic.com.br/ecp/files.do?evento=download&urlArqPlc=tirando_max_struts_parte2.pdf
Tem um artigo “Struts: Melhores Práticas” na revista Java Magazine num.34 e vc. pode baixar os fontes do exemplo no site da revista .

E um tutorial muito bom no site da JEEBrasil .:
http://www.j2eebrasil.com.br/mostrar/32
E aqui…:
http://www.learntechnology.net/content/struts/struts_lesson1.jsp
http://www.learntechnology.net/content/struts/struts_lesson2.jsp
http://www.learntechnology.net/content/struts/struts_lesson3.jsp
http://www.learntechnology.net/content/struts/struts_crud.jsp

sds.
William Silva.

S

William, era exatamente disso que eu precisava. Muito obrigado mesmo!

C

Olá pessoal,

Achei muito útil esta discussão de vocês. Só fiquei com uma dúvida:

  1. Não existe nenhuma versão do webwork sendo desenvolvida em paralelo com o Struts 2, certo?

Desculpem a pergunta meio leiga, mas é que no site do webwork não fala nada sobre isso e como essa fusão dos frameworks é meio recente eu estou apenas querendo confirmar com quem já está mais por dentro.

Outra dúvida simples:

  1. Vale a pena usar o Struts 2 com o Spring? Já há uma integração confiável?

Obrigado!!!

T+

W

Olá ccalixto,

2. Vale a pena usar o Struts 2 com o Spring? Já há uma integração confiável?
Sim vala a pena vc. usa-lo basta olhar esse link e tirar as suas conclusões ok.:
http://cwiki.apache.org/S2WIKI/struts-2-spring-jpa-ajax.html

sds
William Silva

C

Olá Willian,

Muito bom este tutorial que você me indicou.

Muito obrigado!!!

L

Boa tarde a todos,

estou com o seguinte problema:

criei uma aplicação com Struts2, no entanto não estou conseguindo obter
os valores passados via querystring. Os valores dos forms são "injetados"
no Action beleza, porém quando passo algum valor via querystring, não consigo obter o mesmo. Meu action está mapeado da seguinte forma:
"

def.manter.advogado

"
Ele implementa ServletRequestAware para ter acesso ao request. No entanto,
o objeto request que tenho acesso dentro do action não consegue obter o valor dos parâmetros via quesrystring.

Por exemplo, se acesso a url "http://10.1.0.154:8988/push/manterAdvogado!editar.action?identificador2=43"
não sei como obter o valor do parâmetro identificador2 dentro do action.

Alguém tem alguma sugestão?

M

tenta criar na action uma variavel inteira com o nome de “identificador2”

e cria os gets e sets pra ela, deve funcionar!

L

Já havia feito isto, mas não funcionou. :frowning:

M

estranho, tenho feito isso em um projeto e funcionou bem…
:?

L

Apenas para que outros não percam uma semana ( como eu perdi ), o problema que eu relatei anteriormente ocorria por causa de um bug no OC4J, o container da Oracle. Caso alguém esteja utilizando a versão 10.1.3 do Jdeveloper passará pelo mesmo problema. É necessário aplicar um patch.
De qualquer maneira, agradeço a ajuda.
Agora estou com outro probleminha:

estou usando Struts2 + Tiles2. Tentei adicionar validação, mas não estou conseguindo progredir. Tenho uma action chamado “AdvogadoAction” com um alias “manterAdvogado”. Se chamo a url "manterAdvogado!limpar.action"
chama o método limpar beleza. Agora, a partir do momento que eu adiciono um arquivo AdvogadoAction-validation.xml, ele tenta renderizar a página antes de cair no método e também não cai mais no método. Preciso que caia antes no action pois seto alguns parâmetros dinâmicos.

Alguem tem alguma sugestão?

Valeu.

B

Engraçado ver esse post!!!
Dá a impressão q o struts 2 é uma coisa, totalmente nova!

Só uma pergunta que não foi respondida!
Alguém sabe se o Webwork 2 está ativo?

Pq eu nunca confiei mto no Struts, não sei se continuo com o bom e velho WW2 ou passo para o Struts 2 (acho q todo mundo já sabe que cada vez que sobe uma aplicação nova com struts morre um bebê foca)

Pq vem na minha cabeça uma questão obvia: Por que usar uma cópia do WW se eu posso usar o original?

Bem pessoal, é isso!
Abraço pra todos

W

Olá,

Alguém sabe se o Webwork 2 está ativo?
Veja o comentário .:
April 14, 2007
[b]This 2.2.5 release, 6 months after WebWork 2.2.4, marks the final chapter for the WebWork framework.

Struts 2, its successor, had its first GA release, and in a final push, the WebWork team wanted to do a big effort to bring in as many optimizations and bug fixes as possible before shifting developer focus.

* Release notes
* Changelog
* Download here

This release is fully backwards compatible with WebWork 2.2.4. You can just replace the existing WebWork and XWork jars with the news ones from 2.2.5.

Like always, we would like to thank both regular users and contributors, for helping out, submitting patches, testing, and providing general feedback.

The development of WebWork 2 and XWork 1 slowly grinds to a halt, so if you’re looking for bleeding edge technologies or new features, you are more than welcome to try Struts 2.

The WebWork Development Team[/b]
Acho que isso responde as suas dúvidas.
sds.
William Silva

W

Ps.
Link referência:
http://www.opensymphony.com/webwork/

[s]

H

isso mesmo .

M

Boa tarde pessoal,

sou novo no struts e nunca mexi na versao 1, resolvi partir logo pro struts2, só que estou com um problema estranho, fiz um tutorial dele e no arquivo jsp diz q eu deveria por: <%@ taglib prefix=“s” uri="/struts-tags"%> porém está dando erro dizendo que nao encontrou o arquivo.

Estou usando o eclipse 3.3 ou netbeans 5.5.1 com o struts 2.0.9

alguem ja teve esse problema?

desde ja obrigado!

W

http://www.blogjava.net/max/archive/2006/10/10/74353.aspx
e vamo que vamo…

W

e tem a ultima…
http://www.guj.com.br/posts/list/55805.java

W


R

Alexandre,

Como é possível formatar valores e datas em um <s:textfield … />?

Obrigado

R

Eu utilizo o jstl, coloco no cabeçalho

e dpois no value do textfield

R

Rafoli, muito obrigado pela sua ajuda…

Contudo consegui resolver assim:

No arquivo properties declarei
format.number = {0,number,#,##0.00}

E para utilizar no formulario:
<s:textfield name=“peca.valor” id=“peca.valor” cssStyle=“text-align:right” cssClass=“form” value="%{getText(‘format.number’,{peca.valor})}" />

Nesse caso do arquivo properties é utilizado para Internacionalização (i18N)…

Funcionou direitinho…

R

Tenho um problema agora onde preciso enviar um List para a Action, mas quendo chega lá, ocorre um erro do tipo ognl.NoConversionPossible… Nem imagino o que é isso…

Estou tentando o seguinte: vou incluido um item por vez e adicionando na List<> que está na Action…

Obrigado…

Criado 6 de novembro de 2006
Ultima resposta 31 de ago. de 2008
Respostas 47
Participantes 16