Bloque de conocimiento
Imprimir

Bloque de Conocimiento de Struts2

Tabla de contenidos

Introducción

Struts 2 es un framework de presentación, basado en el patron MVC. Se distingue su amplia capacidad de configuración y extensibilidad. Permite el uso de plugins de componentes e integracion con otros frameworks.

Contenidos

Arquitectura



Arquitectura Struts2

Principales componentes

Los principles componentes de framework son:

  • DispatcherFilter
  • Interceptors
  • Actions
  • Results

DispatcherFilter

Es el punto de entrada del framework. A partir de el se lanza la ejecución del procesamiento para cada request que involucre al framework.

Sus principales responsabilidades son:

  • Ejecutar los Actions (handlers para los request)
  • Comenzar la ejecución de la cadena de interceptors (interceptors chain) asociados al request
  • Limpiar el ActionContext? (para evitar memory leaks). El ActionContext? es el contexto sobre el cual se ejecuta un Action.

Interceptors

Son clases que siguen el patron interceptor, realizan tareas muy similares a los advice de AOP. Se encargan de interceptar la invacación a un Action. Permiten realizar operaciones antes y despues de la invocacion de un Action. Tambien permiten evitar que un Action se ejecuto. Nos sirve para retilizar cierta funcionalidad que queremos aplicar a un conjunto de Actions.

Struts2 trae definidos un conjunto de interceptors por defecto, que le permite realizar un conjunto de acciones sobre los Actions. el Request y Response. Estas acciones son, por ejemplo: validaciones de los parámetros de entrada, inyección de dependencia, logueo, etc.

Actions

Los Actions seran lo encargados de ejecutar la logica necearia para manejar un request determinado. A diferencia de versiones anteriores de struts, los Actions no estan obligados a implementar o heredar de una interfaz o clase ya definida. Pueden ser POJOs. Igualmente, struts2 posee una interfaz Action. Esta interfaz permite definir el método por defecto que se ejecutará sobre el Action para que no tengamos que definirlo por otro medio (Existen varias formas de indicarle a Struts2 el método a invocar sobre un action). Tambien existe una implementación de esta interfaz, denominada ActionSupport?, que nos provee funcionalidad de gran utilidad necesaria por un conjunto de Interceptors para poder manipular el Action a invocar.

Results

Los Results son Objetos que encapsulan el resultado de un Action. Los Actions de la aplicación simplemente devolveran un String en sus métodos. Un Action puede devolver diferentes resultados luego de su ejecución. Cada uno de estos resultados se corresponde con un Result, previamente configurado en Struts2. La configuración de cada Result determina principalmente: el tipo de vista a mostrar (JSP, Velocity Templates, FreeMarker?, entre otros), el recurso asociado a dicha vista, el nombre asociado al Result (mediante este y el resultado del Action se determina el Result a utilizar).

Put it all together (Preliminar)

Para no dejar los componentes definidos y no relacionados, y para mejorar el entendimiento del framework, vamos a explicar como funciona todo junto.

  1. Llega un Request a la aplicación.
  2. El Request es interpretador por el DispatcherFilter? y determina que Action y que conjunto de Interceptors invocar.
  3. Cada Interceptor ejecuta sus acciones previas a la ejecución del método de Action a invocar
  4. Es invocado el método del Action.
  5. Cada Interceptor ejecuta sus acciones posteriores a la ejecución del método de Action a invocar
  6. Se examina el resultado obtenido del Action y se determina el Result correspondiente.
  7. Mediante el Result determinado se genera la vista, y según la configuración definida sobre el se invoca el proceso de generación de la vista.
  8. La vista generada retorna al cliente.

Configuración del framework

Ahora explicaremos la configuración del framework, ondaremos en aspectos mas especificos de cada componente.

Struts2 posee varios archivos de configuración:

  • struts.xml: Es el principal archivo de configuración del framework. Aqui definimos los ActionMapping? de nuestra aplicacion, su división en Package, la registración de los Interceptors, la asignación de los Interceptors a los Package, entre otras cosas.
  • struts-default.xml: Este archivo define una configuración básica de un Package del cual es conveniente que el resto de nuestro Packages hereden para obtener los beneficios del framework. Podemos redefinir esta configuración ubicando un archivo propio con el mismo nombre en el classpath.
  • struts.properties: Este es un archivo de properties que contiene un conjunto de pares key - valor que nos permiten definir un conjunto de parametros del framework. Este archivo es cargado por defecto por el framework (obteniendolo de struts-core.jar), pero podemos redefinir los parametros ubicando el mismo en el classpath de la aplicación

Debemos recordar también que debemos registrar el DispatcherFilter?

<filter>
	<filter-name>action2</filter-name>
	<filter-class>
		org.apache.struts2.dispatcher.FilterDispatcher
	</filter-class>
</filter>
<filter-mapping>
	<filter-name>action2</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>

web.xml

De ahora en mas, nos referiremos a configuración mediante struts.xml a menos que indiquemos lo contrario.

Beans, inyección de dependencias.

Struts2 utiliza el patrón DI (dependency Injection) para configuración del framework. Definir mediante el elemento <bean> un conjunto de objetos para reemplazar, extender y eliminar funcionalidad. Mediante el elemento <bean> y sus atributos indicamos que funcionalidad reemplazar y la implementacion de la misma.

<struts>
...
    <bean class="com.opensymphony.xwork2.ObjectFactory" name="xwork" />
    <bean type="com.opensymphony.xwork2.ObjectFactory" name="struts" class="org.apache.struts2.impl.StrutsObjectFactory" />

    <bean type="com.opensymphony.xwork2.ActionProxyFactory" name="xwork" class="com.opensymphony.xwork2.DefaultActionProxyFactory"/>
    <bean type="com.opensymphony.xwork2.ActionProxyFactory" name="struts" class="org.apache.struts2.impl.StrutsActionProxyFactory"/>
...
</struts>

Fragmento de la configuración definida por el framework en struts-default.xml

Constantes

Se pueden definir atributos del framework a través del elemento <constant>.

<struts>
...
    <constant name="struts.devMode" value="true" />
...
</struts>

Por ejemplo, podemos darle a conocer a struts2 que nos encontramos en tiempo de desarrollo, y el nos proveera caracteristicas, como recarga automatica de los archivos de configuración en tiempo de ejecución

Muchos de estos atributos pueden definirse también en struts.properties:

struts.devMode = true

struts.properties

O en el descriptor de la aplicación web:

<filter>
	<filter-name>struts</filter-name>
	<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
	<init-param>
        	<param-name>struts.devMode</param-name>
        	<param-value>true</param-value>
        </init-param>
 </filter>

web.xml

Include

Se puede dividir la configuración de strtus en varios archivos, para modularizar mejor la configuración.

<include file="administracion.xml"/>

El formato del archivo de incluir debe tener el mismo que struts.xml.

Package

Mediante los Packages podemos agrupar un conjunto de ActionMapping? que compartan configuración. Por ejemplo, podemos definir los interceptors a aplicar sobre ellos, Results comunes, manejo de excepcioens unificado, entre otras cosas.

En forma mas general los Packages permite definir unidades reutilizables y sobreescribibles que agrupan interceptors, interceptor-stacks, action, results, result types. Se puede definir una jerarquia entre los Packages para reutilizar configuración, pueden existir package abstractos para luego reutilizar.

Las principales ventajas que proveen son:

  • Reutilización de configuración.
  • Modularización de la aplicación.

ActionMapping

Un ActionMapping? es un objeto que contiene la información de configuración para el manejo de un conjunto de request. Se corresponde con el elemento <action>. En el se define: El/los handler/s del request, el metodo a invocar. Tambien mantiene referencia a los Results definidos. A partir del atributo namespace del Package en que esta definido, su atributo name, y el postfijo utilizado (por default .action) podemos identificar la expresion regular que debe cumplir el path del Request para que el framework decida su ejecución.

Namespace

A los Package se les puede asignar un namespace que indica un subcontexto de la aplicación web. El namespace define un prefijo para identificar al Package. Por ejemplo, dada la aplicación "pruebaStruts", definiendo un package con el atributo "namespace='/package1'", todas las urls del tipo "http://ip:puerto/pruebaStruts/package1/*" serán mapeadas a este package (o a todos los que tengan este namespace) en busca del action correspondiente.

Los namespace permiten evitar conflicto de nombres entre actions y modularizar nuestra aplicación.

Los Tags de Struts2 conocen los namespaces, asi que no es necesario incluirlos en los elementos de las paginas.

Default Namespace

El namespace por defecto (default namespace) es "". El framework al querer ubicar un action, primero buscara dentro del namespace correspondiente, y en caso de no encontrarlo ira a buscarlo a los actions del namespace por defecto. Es una estrategia local/global, que permite definir actions globales.

Root Namespace

También existe el Root Namespace "/". El package con este namespace será utilizado al recibir un request directamente al context path de la aplicación. Al no encontrar un action bajo este namespace ira a buscarlo al default namespace.

Nota:

Los namespace no constituye una estructura jerárquica. Puede intuirse que al definir un namespace "/package1" y otro namespace "/package1/package2", al no encontrar un action en el package con el namespace "/package1/package2" se iría a buscar al package con el namespace "/package1". Esto no es así. Solo se busca en el package con el namespace indicado. En caso de no encontrarse un action, se buscara en el package con el default namespace.

Action

Wildcard Method

Una nueva característica de struts2 es "Wildcard Method". Esto nos permite utilizar wildcards en la definición del ActionMapping?, para definir actions menos específicos que pueden servir para englobar un conjunto de Actions.

<action name=”*/*/*” method=”{3}” class=”example.actions.{1}.{2}Action”>
	<result name=”view”>/{1}/update{2}.jsp</result>
	<result name=”list”>/{1}/list.jsp</result>
</action>

Los fragmentos de la url que machean con cada wildcard (*) pueden ser referenciados utilizando {número_de _wildcard}. La asignación de números es de izquierda a derecha, comenzando por 1. Dado el Action definido, si invocamos a la url http://ip:puerto/admin/User/add.action , struts invocara el método add del Action example.actions.admin.User.

Nota:

Es conveniente tratar todos los handlers a través de un Action, dado que para que los tags de struts2 funcionen correctamente, los jsp a ser rendereados deben tener previamente invocado el filter de struts2.

<action name="*" class="example.ExampleSupport">
	<result>/example/{1}.jsp</result>
</action>

Un ActionMapping? definido de esta manera, implica que, cuando llegue un request que no machea contra ningún otro ActionMapping? configurado, la respuesta debe ser derivada a un JSP matcheando al request enviado, si dicho JSP existe. Por ejemplo si el request fue http://ip:puerto/pruebaStruts/prueba.action , se intentara renderear la pagina jsp "/pruebaStruts/prueba.jsp"

Dynamic Method Invocation

Nos permite especificar el nombre del método a ejecutar utilizando el caracter "!". Dado el siguiente ActionMapping:

<action name="user" class="example.UserAction">
	<result>/example/userList.jsp</result>
</action>

Si llamamos al ActionMapping? con user!create, se llamara al método create del Action example.UserAction. Esto puede traer un problema de seguridad evidente. Cualquiera podría llamar a ejecutar un método del Action especificando el texto siguiente a "!". Muchas veces se definen los Action implementando la interfase Action. Dicha interfase provee un método execute, el cual será llamado por defecto en caso de no especificar ningún método. Si implementamos dicha interfaz, y deseamos llamar otro método del Action utilizando DMI, entonces struts2 actuara "como Si" se llamara al método execute, pero en su lugar llamara al método definido utilizando DMI. Al decir "como si" nos referimos a que utilizara para la llamada del método la misma configuración que posee el método execute, por ejemplo, configuración de validaciones. Esto no sucede si usamos "Wildcard Method".

Default ActionMapping?

Se puede especificar un ActionMapping? por defecto para cada namespace de la aplicación. En caso de que Struts2 no encuentre ningún ActionMapping? que machee con el request recibido, llamara al default ActionMapping?.

<package name="Hello" extends="action-default">
<default-action-ref name="UnderConstruction">

<action name="UnderConstruction">
<result>/UnderConstruction.jsp</result>
	</action>
</package>

Nota:

Debería existir solo un default action por namespace definido. En caso contrario, no podemos asegurarnos cual action será invocado.

ActionSupport Default

Por defecto, si no especificamos la clase handler del action, se invocara a la clase com.opensymphony.xwork.ActionSupport. Los métodos input (este método sirve para el proceso de validaciones, lo veremos mas adelante) y execute de esta clase devuelven "success".

ActionMapping? definidos sin clase, pueden utilizarse para acceder directamente a las vistas de la aplicación, cuando no es necesario realizar ninguna lógica previa. Recordemos que para que las tag libraries de struts funcionen correctamente es conveniente pasar por el filter de struts antes de renderear la vsita.

<action name="prueba2Redirect">
        <result name="success">/WEB-INF/jsp/login.jsp</result>
</action>

Podemos modificar el Action por default utilizando el elemento "default-action-ref" del elemento "Package" del archivo struts.xml.

Lifecycle Callbacks

Existen tres métodos que están atados a la vida de un Action. Estos métodos nos permiten realizar acciones durante la ejecución de un Action. A diferencia de los interceptors, no se aplicación a un conjunto de Actions, sino a un Action en particular. Para acceder a esta funcionalidad el Action debe ser Interceptado por AnnotationWorkflowInterceptor?.

Los métodos que podemos implementar para realizar acciones durante el ciclo de vida de un Action se definen por sus momentos de ejecución y mediante annotations:

  • Before: Los métodos con esta anotación serán ejecutados antes de la ejecución de la lógica del Action
  • BefoteResult: Los métodos con esta anotación serán ejecutados después de la ejecución de la lógica del Action pero antes de invocar a la ejecución del Result correspondiente.
  • After: Los métodos con esta anotación serán ejecutados después de invocar al Result, pero antes que el resultado sea devuelto al usuario.
Modelo de datos

Luego de realizar sus tareas, el Action debe proveer un conjunto de objetos que deben ser utilizados por la vista. Una de las formas que provee struts2 para realizar esto es a través de una interfaz “ModelDriven” .

public interface ModelDriven {
        java.lang.Object getModel();
    }

Mediante el método getModel struts obtendrá un objeto con los datos a utilizar por la vista, quien los podrá acceder desde la pila de objetos (value stack), dado que struts se encargara de ubicar dicho objeto en la pila. Para poder llevar a cabo estas acciones, el Action debe ser configurado de forma tal que, dentro del conjunto de interceptors que están atados a el se encuentre en particular el interceptor ModelDrivenInterceptor?.

Interceptors

Stuts2 permite utilizar interceptors para los Actions. Mediante estos podemos ejecutar código antes y después de la ejecución de un Action. Esto nos permite agregar funcionalidad útil para todos los Actions de nuestra aplicación.

Struts2 trae definidos un conjunto de interceptors por defecto, que le permite realizar un conjunto de acciones sobre los Action, el Request y el Response. Estas acciones son, por ejemplo: validaciones de los parámetros de entrada, inyección de dependencias, logueo, etc.

Todos los Interceptor deben implementar la interfaz Interceptor

public interface Interceptor extends Serializable {

    void destroy();

    void init();

    String intercept(ActionInvocation invocation) throws Exception;
}

  • Método init: Es llamado luego de que Interceptor sea creado.
  • Método destroy: Es utilizado para que el Interceptor libere los recursos que ha alocado.
  • Método intercept: Es el que debe contener la lógica a ejecutar antes y despues de la llamada de un método.
Registración de Interceptors

<struts>
...
    <package>
   ...
        <interceptors>
            <interceptor name="security" class="com.company.security.SecurityInterceptor"/>
        </interceptors>
    ...
    </package>
...
</struts>

registración de un Interceptor
Interceptor stacks.

Los Interceptor Stacks, nos permiten agrupar un conjunto de interceptors, en un solo paquete para ser utilizados en conjunto. (dentro de un stack podemos incluir otro stack).

Registración de Interceptor Stacks

<struts>
...
    <package>
   ...
        <interceptors>
 	    <interceptor name="security" class="example.interceptor.SecurityInterceptor"/>
    	    <interceptor name=”logueo” class=”example.interceptor.LoguerInterceptor”/>
	    <interceptor-stack name="secureStack">
	        <interceptor-ref name="security"/>
	        <interceptor-ref name="logueo"/>
	    </interceptor-stack>
        </interceptors>
    ...
    </package>
...
</struts>

Registración de un interceptor stack

Cada interceptor será llamado en el orden en que fue definido.

Utilización de Interceptors

Para utilizar los interceptors definidos, podemos:

Definirlos en el package como default interceptor

<struts>
...
    <package>
   ...
        <default-interceptor-ref name="secureStack"/>
    ...
    </package>
...
</struts>

Definirlos en cada Action

<struts>
...
    <package>
   ...
        <action name="loging" class="example.action.Login">
	    <result name="success">...</result>
	    <interceptor-ref name="secureStack"/>
        </action>
    ...
    </package>
...
</struts>

Validaciones

Hay 2 maneras de aplicar validaciones en struts2, programaticamente o de forma declarativa.

Validaciones programáticas

El Action debe implementar dos interfaces, Validateable y ValidationAware?. Podemos extender de la clase ActionSupport? que provee implementaciones basicas para las interfaces. Conviene usar validaciones programáticas, solo en los casos en que las validaciones son extremadamente complejas. En todos los demás casos conviene utilizar validaciones declarativas.

Validaciones Declarativas

Para utilizar validaciones declarativas, los actions deben estar interceptados por:

  • Validation: responsable de realizar las validaciones.
  • Workflow: responsable de retornar el result “input” del action en caso de que la validación haya fallado.
Configurando con XML

Las validaciones de los Actions se realizan de forma declarativa, siguiendo la convención de un archivo xml denominado "clase_del_action-validation.xml" en el mismo package en que se encuentra Action, conteniendo las validaciones a realizar sobre los campos. Struts trae un completo conjunto de validaciones, pero además podemos extender este conjunto con validaciones customizadas.

Antes de llamar al Action, se realizan las validaciones. Si no pasaron todas las validaciones, no se ejecuta el Action, y se llama al result con atributo name="input" para ubicar la vista a renderear.

public class ValidacionXMLAction extends BaseAction{

	private static final long serialVersionUID = -1791204092969485444L;	
	private String nombre;
	private String apellido;
	private String password;
	
	public void setApellido(String apellido) {
		this.apellido = apellido;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public void setPassword(String password) {
		this.password = password;
	}
	
	public String getApellido() {
		return apellido;
	}

	public String getNombre() {
		return nombre;
	}

	public String getPassword() {
		return password;
	}

	public String haceAlgo() {
		return SUCCESS;
	}
}

ValidacionXMLAction.java

<validators>
    <field name="nombre">
        <field-validator type="requiredstring">
			<message>Ingrese su nombre.</message>
        </field-validator>
    </field>
    <field name="apellido">
        <field-validator type="requiredstring">
			<message>Ingrese su apellido.</message>
        </field-validator>
    </field>
    <field name="password">
        <field-validator type="requiredstring">
			<message>Ingrese la password.</message>
        </field-validator>
    </field>
</validators>

ValidacionXML-validation.xml
Validaciones usando annotations

Para realizar validaciones utilizando annotations debemos anotar las propiedades del Action que queramos validar.

@Validation
public class ValidacionAnnotationsAction extends ActionSupport{

	private static final long serialVersionUID = -5065885795907160199L;	
	private User user;
	
	//No se pone mensaje porque esta definido en la clase User
	@VisitorFieldValidator(message="")
	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}

	public String haceAlgoMas(){
		return SUCCESS;
	}
	
	@SkipValidation
	public String redirect() {
		return SUCCESS;
	}	
}

ValidacionAnnotationsAction.java

Nota: Si deseamos que no se ejecuten validaciones para cierto método del action, podemos anotar dicho metodo con @SkipValidation

@Validation
public class User {

	private String nombre;
	private String apellido;
	private String sexo;
	private String [] roles;
	
	@RequiredStringValidator(message="", key="validation.fieldRequeried")
	public String getApellido() {
		return apellido;
	}
	public void setApellido(String apellido) {
		this.apellido = apellido;
	}
		
	@RequiredStringValidator(message="Debe ingresar los roles.")
	public String[] getRoles() {
		return roles;
	}
	public void setRoles(String[] roles) {
		this.roles = roles;
	}
	@RequiredStringValidator(message="Debe ingresar el sexo.")
	public String getSexo() {
		return sexo;
	}
	public void setSexo(String sexo) {
		this.sexo = sexo;
	}	
	@RequiredStringValidator(message="Debe ingresar el nombre.")
	public String getNombre() {
		return nombre;
	}
	public void setNombre(String nombre) {
		this.nombre = nombre;
	}
}

User.java

Value Stack / OGNL

Para acceder a los objetos necesarios para los jsp, struts provee una pila de objetos que denominado value stack. Ligada a la pila de objeto se encuentra OGNL, que significa lenguaje de navegación de grafos de objetos (Object Graph Navigational Language). Es un lenguaje estándar que define como acceder a los objetos dentro de la pila. Los objetos que struts2 pública en esta pila son:

  1. Objetos temporarios: son los objetos creados durante la ejecución de un jsp, por ejemplo, al iterar una colección mediante un tag se crea una referencia al objeto de la iteración actual.
  2. El Modelo de Objeto (The model object): Si el action define un modelo de objetos entonces este es publicado en la pila.
  3. El Action: El Action que se esta ejecutando.
  4. Named Objects: son los objetos que se refieren a los diferentes scopes de servlet (#application, #session, #request, #attr, #parameters).

Es importante conocer el orden, debido a que al querer acceder a uno de estos objetos utilizando OGNL, primero se buscara desde el grupo de menor índice al de mayor índice (como esta enumerado más arriba).

El propósito del Value Stack es definir una manera estándar de acceder a los objetos necesarios para renderear las vistas para cualquier tipo de vista que utilicemos (Velocity, FreeMarker?, JSP, etc).

La pila de objetos puede ser accedida de diferentes formas, la más común es mediante tags. También existen algunas directivas para manipular la pila, por ejemplo, para hacer un push de un objeto sobre la pila.

La pila de objetos nos abstrae de los scope de la aplicación. Supongamos que deseamos imprimir del action, la propiedad “name”. Al pedirle a la pila que nos devuelva el valor de dicha propiedad, comenzará a intentar invocar sobre cada objeto de la pila esta propiedad mediante el método getName, hasta encontrar un objeto nos satisfaga el pedido. Como mencionamos anteriormente, por esta cuestión, debemos conocer el orden en que struts inserta los objetos en la pila.

Ahora, supongamos que tenemos que pedir una propiedad de un objeto, pero existen 2 objetos en la pila con la misma propiedad. Para solucionar esto, OGNL permite indicar la profundidad del objeto en la pila, podríamos hacer “2.name”.

OGNL permite realizar las mismas operaciones que un expresión language y más. Permite llamar métodos, llamar propiedades anidadas, conversión de tipos, manipulación de colecciones y más.

Internacionalización

Para utilizar I18N, debemos definir en el archivo de configuración struts.properties, donde debe localizar struts2 los archivos de mensajes.

struts.custom.i18n.resources=messages

struts.properties

De esta manera struts2 ubicara los mensajes desde el archivo messages.properties. Si configuramos struts para que funcione en modo desarrollo (struts.devMode = true), cada vez que tenga que utilizar un mensajes, recargara los archivos de recursos, permitiendo modificar los archivos sin necesidad de bajar y levantar la aplicación para que tome los cambios.

Implementación en las validaciones

Utilizando validaciones por XML

<validators>
    <field name="nombre">
        <field-validator type="requiredstring">
			<message key="validation.fieldRequeried"/>
        </field-validator>
    </field>
</validators>

Utilizando validaciones por annotations

...
	@RequiredStringValidator(message=" ", key="validation.fieldRequeried")
	public String getNombre() {
		return nombre;
	}
...

El atributo key define la propiedad a utilizar.

Implementación en jsp

Para imprimir texto:

...
        <s:text name="login.title"/>
...

Put it all toguether

Ahora que hemos visto las principales caracterisiticas del framework, como se configuran e implementan, veamos, en detalle, la organización del trabajo del framework para un Request.

  1. Llega un Request a la aplicación.
  2. El Request es interpretador por el DispatcherFilter? y determina que Action y que conjunto de Interceptors invocar.
  3. Cada Interceptor ejecuta sus acciones previas a la ejecución del método de Action a invocar
    • Si el Interceptor I18nInterceptor? intercepta el Action: Se ubicara en la session del usuario un objeto Locale para utilizar i18n.
    • Si el Interceptor ValidationInterceptor? intercepta el Action: Se ejecutan la reglas de validación definidas sobre el Action
    • Si el Interceptor AnnotationValidationInterceptor? intercepta el Action: Se chequea en el método a invocar del Action si tiene la anotación @SkipValidation, en cuyo caso no se realizan validaciones
  4. Es ejecutado el método anotado con @Before en el Action
  5. Es invocado el método del Action.
  6. Es ejecutado el método anotado con @After en el Action
  7. Es ejecutado el método anotado con @BeforeResult en el Action
  8. Cada Interceptor ejecuta sus acciones posteriores a la ejecución del método de Action a invocar
    • Si el Interceptor ModelDrivenInterceptor? intercepta el Action: Luego de la ejecución del Action se ubicara en el value stack el modelo que provee el Action.
    • Si el Interceptor ParametersInterceptor? intercepta elAction: Los parametros provenientes del Request se ubican en el value stack
  9. Se examina el resultado obtenido del Action y se determina el Result correspondiente.
  10. Mediante el Result determinado se genera la vista, y según la configuración definida sober el se invoca el proceso de generación de la vista.
  11. La vista generada retorna al cliente.

Solo se exponen algunos Interceptors a modo de ejemplo.

Otras Fuentes de Información

Proyectos en los que se usó

  • Prototype de cliente de Workflow - La Ley

Documentación existente

Documentación existente en Epidata debidamente comentada. La documentación puede ser, file Explorer, biblioteca interna etc.

Bibliografía

Referente

The Greek

Otras páginas de interés


Contribuyentes a esta página: The Greek .
Page last modified on Viernes 25 de Enero, 2008 09:18:07 EST by The Greek.
El contenido de esta página esta licenciado bajo los términos del http://creativecommons.org/licenses/by-sa/2.5/legalcode.

Usuarios en línea

57 usuarios en línea