Spring Web Flow

Post on 25-May-2015

3.500 views 0 download

Transcript of Spring Web Flow

Spring Web Flow

Colin Fairless

Agenda

• Motivación

• Solución Spring Web Flow

• Implementando procesos

• Reuso de procesos

• Pruebas

• Demo

Motivación

• La mayoría de aplicaciones web tienen estado• Cualquier aplicación donde el usuario ingresa

toda la data requerida por una única transacción de negocio mediante varias páginas– Checkout de carrito de compras– Reservando un vuelo online

• Data parcial de las páginas anteriores está guardada en sesión HTTP o en base de datos– Manejado explícitamente por la aplicación.

Desafíos de Web Apps con estado

• HTTP es un protocolo sin estado– Cada request es un evento aislado

• Frameworks tradicionales son request driven– Cada página hace submit a un controller

distinto– Cada controller es responsable sólo por un

único paso en el proceso completo

Desafíos de Web Apps con estado

• Muchos caminos de navegación pueden ser dificiles de manejar– Sin un lugar central para manejar navegación

• Los scopes de Request y Session a veces no son suficientes– Redirect del lado del cliente limpia el scope

del Request– Problema de double post y botón regresar

• Difícil probar

Aplicaciones Web tradicionales con estado

Agenda

• Motivación

• Solución Spring Web Flow

• Implementando procesos

• Reuso de procesos

• Pruebas

• Demo

Process Driven Application

• Define toda la navegación en un lugar central

• Maneja la interacción completa como una entidad única

• Deja al framework decidir qué hacer y adónde ir dependiendo de los eventos invocados por el usuario

Process Driven Application

Diagrama de Flujo

Modelando Proceso

• Flow execution = nuevas conversaciones del usuario con el servidor• Pasos en el flujo se llaman estado• Cada estado tiene una o más transiciones que son usadas para

mover a otro estado• Una transición es disparada por un evento

Estados

• View State– Hacer una pausa en una ejecución y hacer un render

de la vista para obtener input del usuario

• Action State– Ejecutar código Java– Se puede hacer transición a estados diferentes

dependiendo del resultado

• Decision State– Ramas de la lógica

Estados

• Subflow State– Transferir ejecución a un flujo diferente– Ejecución volverá a este estado cuando el

subflujo termine

• End State– Estado final del flujo– Puede o no definir una vista para presentar

Variables

• Web Flow te permite definir variables como parte del proceso del modelo

• Se puede guardar variables en uno de los scopes diferentes– Conversation, Flow, Flash, View, Request

Conversational y Flow Scopes

• Conversation scope disponible a todos los flujos

• Flow scope limitado solamente a un flujo individual

Flash Scope

• Limpiado una vez que se presentó la vista

• Útil para guardar resultados temporales de los Action States

• Sobrevive los redirects del cliente

View Scope

• Creado una vez que entra al View State

• Destruido cuando sale de la vista

• Útil en páginas que submiten muchos requests AJAX

Request y Session Scopes

• El Request Scope tradicional todavía está disponible– El mismo lapso de vida que siempre– No sobrevive redirects del cliente

• Session Scope no es fácil de acceder– Es más grande que el Conversation Scope– No tiene sentido desde WebFlow– Interactúa con sesión via atributos de input y

output del flujo

Agenda

• Motivación

• Solución Spring Web Flow

• Implementando procesos

• Reuso de procesos

• Pruebas

• Demo

Modelando el proceso

• Domain Specific Language (DSL) disponible de la caja– XML

• Se puede definir un flujo programáticamente

• Implementa FlowAssembler y FlowBuilder para crear tu própio flow definition language

– Poco impacto cuando es introducido a proyectos existentes

– Puntos de entrada a otros frameworks son consistentes

• Spring Webflow es autocontenido

Integración

Definición del Flujo

<flow xmlns=“…”>

<input name="cart“

required="true“

type=“com.mycomp…" />

<decision-state id=“hasItems">

<if test="cart.empty" then="goShopping“

else="enterAddresses"/>

</decision-state>

Definición del Flujo

<view-state id="enterAddresses“><transition

on="next“to="shipMethod" />

</view-state>

<view-state id="shipMethod"><transition

on="back“

to="enterAddresses" /><transition

on="next“to="calculateTax" />

</view-state>

Definición del Flujo

<action-state id="calculateTax">

<evaluate expression=“basketService.calcTax(cart)" />

<transition to="ccInfo" />

</action-state>

<view-state id="ccInfo">…

</view-state>

Evaluate

• El punto de conección primario entre WebFlow y servicios de backend

• Expresión dentro del evaluate tag es Unified EL– El mismo lenguaje de expresión usado en

JSP 2.1– Se puede referenciar a los spring beans

directamente por nombre– Acceso a variables del scope

• flashScope.foo

Evaluate

• Usar en Action States• Usar en View States

– on-entry– on-render– on-exit

• Usar en Flow– on-start– on-end

• Usar en Transicion

Definición del Flujo

<action-state id="validateCC">

<evaluate

expression=“basketService.validateCC(cart)" />

<transition on=“yes" to="confirm" />

<transition on=“no" to="ccInfo" />

</action-state>

Definición del Flujo

<action-state id="processOrder">

<evaluate expression=“…”/>

<transition to="thankYou" />

</action-state>

<end-state id="thankYou“ view=“thankYou”>

<output name=“confirmationNumber”

value=“cart.confirmationNumber” />

</end-state>

<end-state id="goShopping" view="externalRedirect:servletRelative:/home"/>

Codificando la Vista

• Forms de HTML estándar

• Se puede usar form tags de Spring MVC

• Variables de todos los scopes disponibles en expresiones EL como request scoped variables

• Siempre envia POST al flow controller– EL Variable: ${flowExecutionUrl}

Invocando Evento

<input type=“submit” name=“_eventId_back”

value=“Back” />

<input type=“submit” name=“_eventId_next”

value=“Next” />

<a href=“${flowExecutionUrl}&_eventId=next”>

Next</a>

• Enlace

• Botón nombrado

Agenda

• Motivación

• Solución Spring Webflow

• Implementando procesos

• Reuso de procesos

• Pruebas

• Demo

Subflujos

• Igual a un flujo normal

• Llama a un flujo desde otro flujo

• Tiene su propio namespace de variables– Flow scope no compartido entre flujos– Conversational scope es compartido entre

flujos

• Análogo a una llamada al método en código Java

Diagrama de Flujo

Diagrama de Flujo

Subflujo

Definición de Subflujo

<view-state id="enterAddresses">

<transition on="next" to="shipMethod" />

<transition on="addrBook" to="addrBook" />

</view-state>

<subflow-state id="addrBook“

subflow="addressBookFlow">

<attribute name="user" value="cart.user" />

<transition to=“enterAddresses” />

</subflow-state>

Aplicando seguridad a Web Flow

<view-state id="enterAddresses"><transition on="next" to="shipMethod" /><transition on="addrBook" to="addrBook" />

</view-state>

<subflow-state id="addrBook“subflow="addressBookFlow">

<secured attributes=“ROLE_AUTHENTICATED” /><attribute name="user" value="cart.user" /><transition to=“enterAddresses” />

</subflow-state>

Aplicando seguridad a Web Flow

• Integra con Spring Security

• Se puede aplicar el tag <secured> a– States– Transitions– Flows

• AccessDeniedException lanzado– Manejado por Spring Security según su

própia configuración

Agenda

• Motivación

• Spring Webflow

• Implementando procesos

• Reuso de procesos

• Pruebas

• Demo

Probando WebFlow

• Probando un proceso web de múltiples páginas puede ser muy difícil– Normalmente involucra la preparación de un

servidor de pruebas y la ejecución de la aplicación

– Difícil aislar la definición del flujo desde la ejecución

– Difícil probar los pasos en el medio sin ejecutar todos los pasos previos

Probando WebFlow

• WebFlow viene con la clase AbstractXmlFlowExecutionTest– Prueba de JUnit– Todas las pruebas corren dentro de un contenedor

Spring, con todos los objetos conectados

• Al mínimo, especificar la ubicación de tu definición XML del flujo

• Se dan puntos de extensión útiles– Registrar stubs y mocks con el contenedor Spring– Especificar ubicación de la definición del flujo padre si

es necesario

AbstractXmlFlowExecutionTest

• Maneja ejecución del flujo– startFlow(), setCurrentState(), resumeFlow()

• Afirmaciones– assertCurrentStateEquals()– assertFlowExecutionEnded()– más

• Acceso a Scoped Variables– Get y set

MockExternalContext

• Usar esta clase para poblar cualquier estado externo esperado para el pedazo de flujo en prueba– setCurrentUser()– setEventId()– getRequestParameterMap().put(“name”,

“value”)

Prueba de ejemplo: Haciendo transiciones

public void testSomething() throws Exception {

setCurrentState(“enterAddresses”);

MockExternalContext context =

new MockExternalContext(); context.setEventId(“next”);

resumeFlow(context);

assertCurrentStateEquals(“shipMethod”);

}

Agenda

• Motivación

• Solución Spring Webflow

• Implementando procesos

• Reuso de procesos

• Pruebas

• Demo

Demo

Resumen

• Desarrollo de aplicaciones web con estado– Abordaje Process Driven es muy diferente al

abordaje Request Driven usado en aplicaciones MVC tradicionales

• Modelar proceso de negocio como unidad única– WebFlow usa un Domain Specific Language

(DSL) análogo a un diagrama de flujo para modelar el proceso en un archivo único

Resumen

• Procesos son reutilizables por áreas distintas de la aplicación– Flujos pueden ser invocados desde otros

fllujos. Flujos pueden recibir parámetros de input y devolver valores de output.

• Fácil probar– AbstractXmlFlowExecutionTests y

MockExecutionContext permiten probar definiciones de flujos en aislamiento de la lógica de la aplicación