Spring WebFlow con JSP

En el articulo anterior http://www.profesor-p.com/2018/10/29/spring-webflow-con-jsp-configuracion/ explicaba como configurar el programa para que Spring WebFlow funcionara. En este articulo explicare como hacer el flujo en si.

La página principal del programa no esta dentro de ningún flujo y sus peticiones son respondidas por Spring MVC, en la clase MyController, la cual podemos encontrar en el paquete profesorp.webflow.controller. Esta clase anotada con la etiqueta @Controller responde en la función indice1 a las peticiones de los recursos “/” e “index”

Aquí podéis ver el código:

Como veis devuelve un objeto **ModelAndView **donde guarda el objeto cliente, la cual es una @entity de la tabla Clientes, que ya vimos en la entrada anterior. La vista devuelta es “index.jsp” que esta en el directorio webapp/WEB-INF/jsp/

En “index.jsp” encontramos la etiqueta <sec:authorize access=”isAuthenticated()”> que esta dentro del paquete spring-security-taglibs. Si el usuario no esta autentificado mostrara la pantalla de login, en caso contrario saludara al usuario  y permitirá realizar el traspaso de dinero.

Al usar el  paquete security, y para evitar ataques CSRF,  Spring solo permite realizar peticiones tipo POST,  al recurso /logout. Por ello uso la librería JQuery con la cual creo esa petición en la función de javascript function post(path, parameters)

En todas las peticiones tipo POST debemos incluir la variable _csrf.parameterName  con el valor _csrf.token para evitar estos mismos ataques CSRF. Si no  las ponemos Spring Security no aceptara nuestras peticiones, pues entenderá que es un posible ataque.

Esta es la pantalla de entrada , solicitando las credenciales.

Y está, la pantalla de entrada , una vez el usuario esta registrado.

Si pulsamos el enlace “Transferencia” iremos al recurso “traspaso” que estará ubicado en la URL http://localhost:8080/webflow/traspaso. Este recurso es tratado por Spring Webflow, por lo cual se cargara el fichero  WEB-INF/flows/traspaso/traspaso.xml pues así lo definimos en la clase WebFlowConfig anteriormente vista.

Todo fichero XML que defina un webflow deberá empezar con las siguientes lineas.

A continuación defino la variable traspasoBean con una nueva instancia del objeto profesorp.webflow.controller.TraspasoBean.

Esta sentencia seria el equivalente al código java <strong>traspasoBean  = new profesorp.webflow.controller.TraspasoBean()</strong>

Seguidamente. indico que al cargar el flujo de trabajo debe evaluar la expresión logicaService.getCliente() cuyo resultado debe guardar en la variable cliente, la cual sera  de ámbito flow (flowScope.cliente). Una explicación de los ámbitos la tenéis en la pagina oficial de Spring (en ingles me temo). Baste decir, de momento que una variable definida dentro del ámbito flowscope es accesible en todas las paginas que estén definidas en nuestro flujo.

Tener en cuenta que para poder acceder al objeto logicaService  lo hemos tenido que definir como un Bean en nuestro programa. En este ejemplo lo tenéis en la clase LogicaService, que muestro a continuación.

A continuación indico la primera vista que se debe cargar, que sera el fichero cuentaOrigen.jsp

Con el parámetro model especifico  las variables que reciba de la vista, deberán ser puestas en el objeto traspasoBean.

Como en la vista  definimos la variable cuentaOrigen (en un campo tipo select),y  el bean profesorp.webflow.controller.TraspasoBean tiene a su vez la variable cuentaOrigen definida, se llamara a la función setCuentaOrigen() de esa clase, con el valor introducido , por el usuario en la vista.

Si tuviéramos más variables en el formulario que coincidieran con sus correspondientes setters, también serian llamadas.

La vista, que detallo a continuación, es un formulario bastante simple donde se pide el numero de cuenta origen:

Así se ve la vista en el navegador

![](/img/2018/10/Captura-25.png(

Lo primero es ver como la URL a llamar por el formulario es el resultado de la variable ${flowExecutionUrl}. Esta variable es puesta automáticamente por Spring WebFlow y apuntara  a la dirección donde continuara el flujo actual.

La variable “_eventId”  es la que Spring WebFlow buscara para decidir que acción llevar a cabo. En este caso le asigno el valor “activate” que coincide con  el valor de la etiqueta transition <transition on="activate" to="importe"/> 

Con esto lo que hacemos es configurar que cuando la variable _eventId tenga el valor “activate” el flujo vaya al ID importe. Por supuesto, el ID deberá existir en nuestro flujo.

Aclarar que “activate” es un literal libre, que igual podria ser ‘MI_SALIDA‘ o ‘SEGUIR‘.

Lo normal, en una vista, es que pueda devolver diferentes valores. Así en  la ultima linea donde declaramos un enlace (<a href…”>) vemos como se llama a **${flowExecutionUrl} **pasando el parámetro _eventId=cancel . En el caso de que pulsemos ese enlace lo que se ejecutara sera el siguiente código que esta al final del fichero traspaso.xml

Esto es así porque hemos definido que cualquier evento tipo “cancel” dentro del flujo, llame al ID cancel del que luego hablare.

La etiqueta hace que lo que haya dentro se ejecute justo antes de renderizar la vista. En este caso llamara a la función logicaService.getCuentasByCliente()y el valor devuelto lo almacenara en flowScope.cuentas

Este objeto cuentas que es un Array de strings que se usa en la vista para crear el desplegable  con las cuentas de origen disponibles, en el código <c:forEach items.....>

Lo siguiente define la vista con ID importe, que es donde ira el usuario cuando pulse el botón siguiente, como hemos definido con las etiquetas <transition on="activate" to="importe"/> anteriores.

Como en la anterior vista, los valores introducidos en el formulario serán introducidos en traspasoBean, al incluirse la etiqueta model.

Antes de mostrar la vista se llama a la función traspasoBean.puestoPeriodico() con el valor false debido a la etiqueta on-render.

Si el valor de la variable “_eventId” es “salir” el flujo sera dirigido al ID comprobarImporte, pero antes de ir se llamara a la función logicaService.hasCredit(traspasoBean). Si esa función devuelve true se realizara el salto a comprobarImporte en caso contrario se volvera a mostrar la vista actual, es decir importe.

La vista importe esta definida en el fichero importe.jsp del cual pongo un extracto a continuación

Resaltar que como la variable periodico esta en un campo checkbox solo sera mandada cuando el usuario seleccione esa opción, por lo cual si no es marcada, la funcion setPeriodico() no sera llamada, pero no se pondrá a false la correspondiente variable en el Bean. Es por ello que antes de mostrar la vista, con la etiqueta <on-render> se pone a false una variable auxiliar que utilizara el programa para saber que no se ha seleccionado la opción “Traspaso Periódico

Una imagen de como se muestra la vista en el navegador.

El id comprobarImporte se define a continuación,

En este estado que es tipo decisión, se llama a la función checkImporte(traspasoBean) del objeto logicaService en caso de que devuelva true se ira al ID periocidad, en caso contrario se volverá al ID importe . Esta función comprueba que el cliente tenga suficiente dinero en la cuenta.

El ID periocidad es otro estado tipo decisión que dependiendo del resultado de la función isPeriodico, la cual comprueba si se ha selecionado la opción “Traspaso Periodico” en la vista, ira a periodico o a confirmar

El ID periodico es una llamada al flujo traspaso_time, al cual se saltara pasándole el objeto traspasoBean debido a la etiqueta input.

Si ese flujo sale con el ID salir se saltara al ID confirmar

A continuación detallo el contenido del flujo traspaso_time que esta definido en el fichero traspaso_time.xml

Lo primero que declaramos es que debemos recibir un objeto traspasoBean . Si no lo recibieramos el programa fallara.

Es decir el flujo lo podríamos llamar con la URL: http://localhost:8080/webflow/traspaso_time pero si lo hacemos al no recibir el objeto  **traspasoBean ** fallara.

En el flujo mostramos la vista tiempo y si el event_id es **salir **se saltara al ID salir.

Este ID es tipo end-state por lo cual  se volverá  al anterior  flujo con el ID salir. En el flujo traspaso entonces  se saltara al ID confirmar, como esta definido por la etiqueta: <transition on="salir" to="confirmar"> 

Si el event_id es cancelar también volverá al flujo anterior, pero  a través del ID cancel y por lo tanto se saltara al ID cancel , como se definió con las etiquetas anteriormente mostradas.

La vista tiempo se muestra así en el navegador.

Por último la vista confirmar, muestra todos los datos introducidos y solicita la confirmación. En caso de darla se ira al ID salir con lo cual saldremos del flujo redirigiendonos al recurso index pasando la variable **transferencia ** con el valor “1”. En caso de que en algún momento hayamos cancelado la transferencia se saldrá del flujo dirigiéndonos a index pero la variable transferencia tendrá el valor “0”

Esto se nos mostrara en pantalla una vez hayamos confirmado la transferencia

Y con esto termino esta entrada tan larga, pero donde creo que he explicado bastantes conceptos de WebFlow.

Como siempre, espero vuestros comentarios y mejoras, con la esperanza de haberme explicado bien.

¡¡ Hasta otra, alumnos!!