Las novedades del arquetipo en su versión 0.0.7 se enumeran en los siguientes apartados.
La plantilla de diseño esta basada en Bootstrap 3.3. Los ficheros están en la ruta src/main/web_resources/resources del módulo Web. Donde están los ficheros de fuentes, JS, CSS, etc. que utiliza bootstrap.
Recordaros que en la carpeta src/main/web_resources es donde se ponen los ficheros JS, CSS, etc. que ya están minimizados y no queremos que pasen por el plugin Yui Compressor Maven Plugin, que tenemos configurado para el módulo Web. Que minimiza los ficheros JS y CSS para los entornos de pre-producción y producción.
Ahora vamos a describir el mecanismo de carga de estilos en la nueva plantilla.
En la nueva plantilla de la páginas (/layout/template.xhtml) se ha añadido un sistema de ordenación en la carga de recursos JS y CSS en la cabecera (<h:head>).
<h:head> <f:facet name="first"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title><h:outputText value="#{messages['application.title']}" /></title> <link rel="shortcut icon" href="#{request.contextPath}/resources/img/favicon.ico" /> <ui:insert name="head-first" /> </f:facet> <f:facet name="middle"> <ui:insert name="head-middle" /> </f:facet> <f:facet name="last"> <!--h:outputScript library="fundeweb" name="primefaces/js/primefaces_fix.js" /--> <h:outputScript library="fundeweb" name="primefaces/js/locales.js"/> <h:outputScript library="js" name="bootstrap.min.js" /> <h:outputScript library="fundeweb" name="js/fundeweb.js"/> <h:outputScript library="js" name="menu.js" /> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.5.3/less.min.js"></script> <!-- Personalizacion de la aplicacion --> <fdw:outputStylesheet library="css" name="bootstrap.min.css" /> <fdw:outputStylesheet library="css" name="font.css" /> <fdw:outputStylesheet library="css" name="layout.css" /> <fdw:outputStylesheet library="css" name="layout_primefaces.css" /> <fdw:outputStylesheet library="css" name="less.css" /> <fdw:outputStylesheet library="css" name="custom.css" /> <ui:insert name="head-last" /> </f:facet> <ui:insert name="head" /> </h:head>
Como podemos ver, tenemos dividida la cabecera en tres secciones definidas mediante <f:facet>: first, middle y last. Como su nombre indica, representan la posición donde se cargan los elementos definidos en ella.
A su vez, al final de cada una de estas tres secciones, tenemos un elemento <ui:insert>, que es el que nos permite en nuestra página añadir elementos a las secciones de la cabecera. Si por ejemplo, quiero añadir un fichero JS o CSS en la sección last, tendré que añadir en mi página lo siguiente:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:s="http://jboss.org/schema/seam/taglib" xmlns:p="http://primefaces.org/ui"> <ui:composition template="/layout/template.xhtml"> <ui:define name="head-last"> <h:outputScript library="js" name="my_custom_js.js" /> <fdw:outputStylesheet library="css" name="my_custom_css.css" /> </ui:define> <ui:define name="body"> ... </ui:define> </ui:composition> </html>
Como se puede observar, para cargar ficheros CSS mediante JSF utilizamos el componente <fdw:outputStylesheet> en lugar de <h:outputStylesheet>. Este cambio es importante, porque sino, la ordenación de los CSS no funcionara correctamente.
Antes de cerrar la cabecera (</h:head>), también disponemos de un lugar donde añadir ficheros de recursos identificado con head. Es por retro-compatibilidad con las anteriores plantillas, pero que sería igual que utilizar la sección head-last.
Dentro de la carpeta layout se han añadido nuevas plantillas para poder utilizar facilmente bootstrap y el grid responsive.
<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:s="http://jboss.org/schema/seam/taglib"> <ui:composition> <div id="#{clientId}" class="form-group #{styleClass == null ? '' : styleClass} #{ invalid ? 'has-error' : ''}" style="#{style == null ? '' : style}"> <ui:insert/> </div> </ui:composition> </html>
<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:s="http://jboss.org/schema/seam/taglib" xmlns:fdw="http://www.um.es/atica/fundeweb"> <ui:composition> <s:label styleClass="control-label #{labelStyleClass == null ? '' : labelStyleClass}" style="#{labelStyle == null ? '' : labelStyle}"> <ui:insert name="label"/> <s:span styleClass="required" rendered="#{required}">*</s:span> </s:label> <span class="#{valueStyleClass == null ? '' : valueStyleClass}" style="#{valueStyle == null ? '' : valueStyle}"> <s:validateAll> <ui:insert name="value"/> </s:validateAll> </span> <s:span styleClass="has-error #{messageStyleClass == null ? 'hidden-lg hidden-md hidden-sm hidden-xs' : messageStyleClass}" rendered="#{invalid}" style="#{messageStyle == null ? 'margin-top: 0.2em;' : messageStyle}"> <fdw:message /> </s:span> </ui:composition> </html>
Veamos un ejemplo:
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:s="http://jboss.org/schema/seam/taglib" xmlns:p="http://primefaces.org/ui"> <div class="container-fluid"> <h:form id="crearObjetivosForm" styleClass="form-horizontal editFundeweb"> <p:focus context="codigoRow" for="codigoInput" /> <s:decorate id="codigoRow" template="/layout/editLineBs.xhtml" enclose="false"> <s:decorate id="codigoCell" template="/layout/editCellBs.xhtml" enclose="false"> <ui:param name="labelStyleClass" value="col-lg-1 col-md-1 col-sm-2 col-xs-2" /> <ui:param name="valueStyleClass" value="col-lg-3 col-md-3 col-sm-5 col-xs-5" /> <ui:param name="messageStyleClass" value="col-lg-8 col-md-8 col-sm-12 col-xs-12" /> <ui:define name="label">#{messages['tabla.header.codigo']}</ui:define> <ui:define name="value"> <p:inputText id="codigoInput" styleClass="form-control" value="#{manejadorAutorizacion.idObjetivo}" required="true" requiredMessage="#{messages['required.field']}" maxlength="20"/> </ui:define> </s:decorate> </s:decorate> <s:decorate id="descripcionRow" template="/layout/editLineBs.xhtml" enclose="false"> <s:decorate id="descripcionCell" template="/layout/editCellBs.xhtml" enclose="false"> <ui:param name="labelStyleClass" value="col-lg-1 col-md-1 col-sm-2 col-xs-2" /> <ui:param name="valueStyleClass" value="col-lg-5 col-md-6 col-sm-9 col-xs-10" /> <ui:param name="messageStyleClass" value="col-lg-6 col-md-5 col-sm-12 col-xs-12" /> <ui:define name="label">#{messages['tabla.header.descripcion']}</ui:define> <ui:define name="value"> <p:inputText id="descripcionInput" styleClass="form-control" value="#{manejadorAutorizacion.descripcionObjetivo}" required="true" requiredMessage="#{messages['required.field']}" maxlength="50"/> </ui:define> </s:decorate> </s:decorate> <s:decorate id="botonesRow" template="/layout/editLineBs.xhtml" enclose="false"> <div class="col-lg-offset-1 col-md-offset-1 col-sm-offset-2 col-xs-offset-2 col-lg-1 col-md-1 col-sm-1 col-xs-1"> <p:commandButton value="#{messages['value.add']}" icon="fa fa-floppy-o" global="true" action="#{manejadorAutorizacion.crearObjetivo}" update="@form, :tabPanel:gestionObjetivosForm:listaObjetivos, :messages" /> </div> </s:decorate> </h:form> <p:separator /> ... </div>
Para tener un grid responsive necesitamos:
Veamos como queda el ejemplo:
Si provocamos un error de validación de datos, obtenemos para una pantalla lg (large) según bootstrap:
{{ :fdw2.0:fundeweb2.0:gt_arquetipo:ejemplo-ii.jpg | Ejemplo de Grid Responsive - Large}
Si provocamos un error de validación de datos, obtenemos para una pantalla md (medium) según bootstrap:
Si provocamos un error de validación de datos, obtenemos para una pantalla sm (small) según bootstrap:
Si provocamos un error de validación de datos, obtenemos para una pantalla xs (extra small) según bootstrap:
Hemos añadido la suplantación de identidad. Podemos hacer búsquedas del usuario por el identificador (DNI) o por el correo.
En cuanto al log, aparecerá lo siguiente en la aplicación:
20 dic 2017 11:17:54,877 DEBUG (SuplantarIdentidadBean.java:88) - Usuario: juanmiguel.bernal@ticarum.es - Cargando identidad. Correo [pedro.delgado@ticarum.es]. 20 dic 2017 11:21:31,825 INFO (SuplantarIdentidadBean.java:106) - Usuario: juanmiguel.bernal@ticarum.es - Suplantando identidad del usuario pedro.delgado@ticarum.es. 20 dic 2017 11:21:31,825 INFO (UmuIdentity.java:218) - Usuario: juanmiguel.bernal@ticarum.es - Suplantando al usuario [pedrody@um.es] por parte de [juanmiguelbg@um.es] 20 dic 2017 11:21:31,826 INFO (LogManagerBean.java:38) - Usuario: juanmiguel.bernal@ticarum.es - Cambiando USERNAME: juanmiguel.bernal@ticarum.es --> pedrody@um.es 20 dic 2017 11:21:31,826 INFO (LogManagerBean.java:38) - Usuario: pedrody@um.es - Cambiando USERNAME: pedrody@um.es --> pedrody@um.es 20 dic 2017 11:21:31,827 INFO (UmuIdentityLoader.java:40) - Usuario: pedrody@um.es - Entra en loadDataLoginSuccessful 20 dic 2017 11:21:31,827 INFO (UmuIdentityLoader.java:51) - Usuario: pedrody@um.es - Usuario conectado: pedrody@um.es 20 dic 2017 11:21:31,828 DEBUG (SqlStatementLogger.java:104) - Usuario: pedrody@um.es - select usuarios0_.LOGIN as LOGIN1_4_ from PORTALFUNDEWEB.USUARIOS usuarios0_ where usuarios0_.LOGIN=? 20 dic 2017 11:21:31,833 DEBUG (SqlStatementLogger.java:104) - Usuario: pedrody@um.es - select rolesusuar0_.LOGIN as LOGIN1_4_1_, rolesusuar0_.ID_ROL as ID_ROL2_5_1_, roles1_.ID_ROL as ID_ROL1_1_0_, roles1_.DESCRIPCION as DESCRIPC2_1_0_, roles1_.ROL_PADRE as ROL_PADR3_1_0_ from PORTALFUNDEWEB.ROLES_USUARIO rolesusuar0_ inner join PORTALFUNDEWEB.ROLES roles1_ on rolesusuar0_.ID_ROL=roles1_.ID_ROL where rolesusuar0_.LOGIN=? 20 dic 2017 11:21:31,837 INFO (UmuIdentityLoader.java:55) - Usuario: pedrody@um.es - ROL CARGADO: ADM 20 dic 2017 11:21:31,837 INFO (UmuIdentityLoader.java:42) - Usuario: pedrody@um.es - pasa a ser el usuario: pedrody@um.es 20 dic 2017 11:21:31,838 INFO (UmuIdentity.java:222) - Usuario: pedrody@um.es - Suplantacion correcta: [juanmiguelbg@um.es] ha suplantado a [pedrody@um.es].
Una vez hecha la suplantación, en la parte superior derecha de la pantalla, junto al nombre del usuario, aparece el botón Restaurar, para deshacer la suplantación.
Si restauramos nuestro usuario, volvemos a aparecer en la parte superior derecha de la pantalla.
En cuanto al log, aparecerá lo siguiente en la aplicación:
20 dic 2017 11:23:50,985 INFO (SuplantarIdentidadBean.java:122) - Usuario: pedrody@um.es - Restaurando identidad del usuario juanmiguelbg@um.es 20 dic 2017 11:23:50,986 INFO (UmuIdentity.java:240) - Usuario: pedrody@um.es - Restaurando la suplantacion del usuario [pedrody@um.es] por parte de [juanmiguelbg@um.es] 20 dic 2017 11:23:50,986 INFO (LogManagerBean.java:38) - Usuario: pedrody@um.es - Cambiando USERNAME: pedrody@um.es --> juanmiguelbg@um.es 20 dic 2017 11:23:50,987 INFO (LogManagerBean.java:38) - Usuario: juanmiguelbg@um.es - Cambiando USERNAME: juanmiguelbg@um.es --> juanmiguelbg@um.es 20 dic 2017 11:23:50,987 INFO (UmuIdentityLoader.java:40) - Usuario: juanmiguelbg@um.es - Entra en loadDataLoginSuccessful 20 dic 2017 11:23:50,988 INFO (UmuIdentityLoader.java:51) - Usuario: juanmiguelbg@um.es - Usuario conectado: juanmiguelbg@um.es 20 dic 2017 11:23:50,988 DEBUG (SqlStatementLogger.java:104) - Usuario: juanmiguelbg@um.es - select usuarios0_.LOGIN as LOGIN1_4_ from PORTALFUNDEWEB.USUARIOS usuarios0_ where usuarios0_.LOGIN=? 20 dic 2017 11:23:50,992 DEBUG (SqlStatementLogger.java:104) - Usuario: juanmiguelbg@um.es - select rolesusuar0_.LOGIN as LOGIN1_4_1_, rolesusuar0_.ID_ROL as ID_ROL2_5_1_, roles1_.ID_ROL as ID_ROL1_1_0_, roles1_.DESCRIPCION as DESCRIPC2_1_0_, roles1_.ROL_PADRE as ROL_PADR3_1_0_ from PORTALFUNDEWEB.ROLES_USUARIO rolesusuar0_ inner join PORTALFUNDEWEB.ROLES roles1_ on rolesusuar0_.ID_ROL=roles1_.ID_ROL where rolesusuar0_.LOGIN=? 20 dic 2017 11:23:50,997 INFO (UmuIdentityLoader.java:55) - Usuario: juanmiguelbg@um.es - ROL CARGADO: ADM 20 dic 2017 11:23:50,997 INFO (UmuIdentityLoader.java:42) - Usuario: juanmiguelbg@um.es - pasa a ser el usuario: juanmiguelbg@um.es 20 dic 2017 11:23:50,998 INFO (UmuIdentity.java:245) - Usuario: juanmiguelbg@um.es - Restauracion de la suplantacion correcta: el usuario [pedrody@um.es] ya no esta suplantado por [juanmiguelbg@um.es].
Las pantallas son responsive, y utilizan las nuevas plantillas para los decoradores. Se pueden usar como guía. Por defecto, este sistema de autorización esta desactivado. Para poder activar dicho sistema, tenemos que:
package es.um.atica.prueba.security.authorization.entities; // Generated 18-jun-2014 10:18:26 by Hibernate Tools 4.0.0 import java.util.ArrayList; import java.util.List; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; import javax.persistence.Table; import javax.persistence.Transient; import org.jboss.seam.annotations.security.management.UserPassword; import org.jboss.seam.annotations.security.management.UserPrincipal; import org.jboss.seam.annotations.security.management.UserRoles; import org.umu.atica.servicios.gesper.gente.entity.Persona; /** * Usuarios generated by hbm2java */ @NamedQueries({ @NamedQuery(name = "Usuarios.obtenerUsuarios", query = "select usuario from Usuarios usuario") }) //@Entity @Table(schema = "PORTALFUNDEWEB", name = "USUARIOS") public class Usuarios implements java.io.Serializable { private static final long serialVersionUID = 5961882811529717090L; ... }
<!-- Gestion de Roles y Usuarios --> <!-- <security:jpa-identity-store user-class="es.um.atica.ArquillianTest.security.entities.Usuarios" role-class="es.um.atica.ArquillianTest.security.entities.Roles" /> <security:persistent-permission-resolver permission-store="#{umuPermissionStore}" /> -->
Con este arquetipo trabajamos con PrimeFaces 6.1 y PrimeFaces Extension 6.1.
Cuando se pone el JIRA a sistemas, hay que indicar que tiene que enlazarse con la versión de las librerías 2.0.1.
— JUAN MIGUEL BERNAL GONZALEZ 19/12/2017 09:44