miércoles, diciembre 10, 2008

Postprocesado con interceptors en struts2

Introducción:
En struts 2 cada acción al ser procesada pasa por una cadena de procesado. En esta cadena se ejecutan una serie de interceptors, posteriormente la acción (si ningun interceptor interrumpe la cadena) y de nuevo los interceptors en orden inverso.
Para quien le suene algo, esto actua como un patron cadena de responsabilidades (Chain of Responsibility)

Situación:
Tenemos un action de nuestra aplicación que despues de ejecutarse y dependiendo de una elección del usuario, ha de comportarse de forma diferente (incluso modificar su result-type).

Posible solución:

  • Creamos un interceptor que se colocará en la interceptors stack en ultimo lugar (de tal manera que se ejecute el ultimo en preprocesado y el primero en postprocesado)
  • Este interceptor en lugar de llamar al metodo invoke() de ActionInvocation, llamará directamente al método execute() de la acción a ejecutar, y si todo ha ido correctamente, hace el postprocesado que necesita hacer y devuelve el result que le corresponde.

Ejemplo:
Este interceptor permite que un action que mostraba por pantalla una lista de VOs, genere un fichero en excel y se lo envie al usuario si este así lo ha marcado:


package es.acore....;

import ...

/*
* This interceptor generates a excel file containing a list of VOs
*/

public class ExcelInterceptor implements Interceptor {

...

public String intercept( ActionInvocation actionInvocation )
throws Exception {

Action action = ( Action ) actionInvocation.getAction();

if (action instanceof ExcelAware) {
System.out.println("Logged in: ExcelInterceptor.java");
if ((((ExcelAware)action).getGenerarExcel() != null)
&& ((ExcelAware)action).getGenerarExcel()){

String result = action.execute();

if (result.equals(Action.ERROR))
return Action.ERROR;

List vos = ((ExcelAware)action).getListaVOs();

...

XlsTable generadorExcel = new XlsTable();
generadorExcel.addTableToSheet(vos,...);

ByteArrayOutputStream out =
new ByteArrayOutputStream();
wb.write(out);
InputStream inputStream =
new ByteArrayInputStream(out.toByteArray());

((ExcelAware)action).setInputStream(inputStream);
return COINConstants.EXCELRESULTCODE;//"excel"
}
}
//if there is nothing to do with excel
//we continue de execution stack as usuall
return actionInvocation.invoke();
}
}