Herramienta de Generación de Código Framework ATLAS Versión 1.8 Arquitectura de Software Framework Atlas Manual Usuario Generador de Código Hoja de Control Título Manual de Usuario de la Herramienta de Generación de Código de ATLAS Documento de Referencia NORMATIVA ATLAS Responsable ICM Versión 1.8 Fecha Versión Fecha 1 Revisado/Validado por: 2 01/02/2016 Revisión/Validación Aprobado por: Fecha Aprobación Registro de Cambios Versión Causa del Cambio Fecha del Cambio 1.0 Versión inicial del documento 23/02/2012 1.1 Nueva versión de la herramienta que incluye generación de pantallas. Listado de ficheros modificados y/o creados por la herramienta Documentada incrementalidad parcial. Documentado alcance y funcionalidades futuras 12/06/2012 1.2 Modificada Introducción e incluido apartado Descripción de código que se genera 26/10/2012 1.3 La herramienta pregunta por las capas de la aplicación que se desea generar 26/02/2013 1.4 1.5 1.6 - Añadido un aviso de configurar la BBDD de la aplicación además de la del generador - Nuevos filtros para la pantalla de búsqueda. - Añadido soporte para vistas y campos LOB. - Modificada la ingeniería inversa en las tablas sin PK y creado fichero de propiedades de ingeniería inversa. - Eliminado apartado 5 de alcance de la herramienta. - Indica que se crea al fichero hibernate.reveng.log - Añadida la opción de mostrar el formulario detalle en un pop-up - Inclusión de las instrucciones para comprobar con CheckStyle y PMD el código una vez generado, formateado y limpiado. 1.7 3.6.1 Comprobación de los ficheros de configuración de Spring en los test 1.8 Añadido apartado: Tablas con relación N:M Página 2 de 40 5/06/2013 27/11/2013 29/04/2014 4/12/2014 Framework Atlas Manual Usuario Generador de Código Índice 1 INTRODUCCIÓN ................................................................................................................................................................ 4 1.1 1.2 2 DESCRIPCION DEL CODIGO QUE SE GENERA ........................................................................................................ 5 2.1 2.2 2.3 2.4 3 ACCESO A DATOS ....................................................................................................................................................... 5 SERVICIOS DE NEGOCIO ........................................................................................................................................... 6 PRESENTACION........................................................................................................................................................... 9 PRUEBAS .................................................................................................................................................................... 15 USO DE LA HERRAMIENTA ......................................................................................................................................... 17 3.1 3.2 3.3 3.4 3.5 3.6 3.6.1 3.7 3.8 3.8.1 3.9 4 AUDIENCIA OBJETIVO .............................................................................................................................................. 4 CONOCIMIENTOS PREVIOS ...................................................................................................................................... 4 CONFIGURACIÓN DE LA CONSOLA DE HIBERNATE ........................................................................................ 18 CONFIGURACIÓN DEL PAQUETE JAVA ............................................................................................................... 19 CONFIGURACIÓN DE LA CONEXIÓN A BASE DE DATOS ................................................................................. 20 SELECCIÓN DE LAS TABLAS .................................................................................................................................. 21 EJECUCIÓN ................................................................................................................................................................. 22 COMPROBACIÓN DE CÓDIGO GENERADO ......................................................................................................... 27 COMPROBACIÓN DE LOS FICHEROS DE CONFIGURACIÓN DE SPRING EN LOS TEST ...................................................... 31 COMPROBACION DE FORMATO DEL CÓDIGO GENERADO. ............................................................................ 31 TABLAS CON RELACIÓN N:M................................................................................................................................. 36 CAMBIOS EN EL MAPEO GENERADO ........................................................................................................................... 36 EJECUCIÓN DE LA APLICACIÓN ............................................................................................................................ 39 USO INCREMENTAL DE LA HERRAMIENTA .......................................................................................................... 40 Página 3 de 40 Framework Atlas Manual Usuario Generador de Código Contenido 1 INTRODUCCIÓN A partir de la versión 1.2.0 del framework de desarrollo de aplicaciones ATLAS, se incluye una herramienta de generación automática de código. Esta herramienta permite, a partir de un modelo de datos, generar código para gestionar las operaciones básicas (alta, baja, modificación y consulta) de ese modelo de datos de acuerdo a la normativa del framework Atlas en las distintas capas de la aplicación. La herramienta nos permite seleccionar las tablas de las que queremos generar el código, y a partir de ellas realiza una ingeniería inversa del modelo de datos y genera el código en la aplicación. También detecta las vistas si su nombre cumple la normativa de base de datos. Para el desarrollo de la herramienta se ha tomado como punto de partida el plugin JBoss Hibernate Tools, y se ha personalizado su configuración para adaptarlo a las necesidades propias de ATLAS. Atención El código fuente generado es un punto de partida para el desarrollo. Lo generado se debe evolucionar para adaptarlo a las necesidades y requisitos específicos del proyecto. En este documento se describe el código generado, cómo configurar la herramienta y cómo utilizarla. 1.1 AUDIENCIA OBJETIVO Este documento está orientado a toda aquella persona que desee desarrollar una aplicación con el framework ATLAS y para ello requiera interaccionar con un modelo de datos. 1.2 CONOCIMIENTOS PREVIOS Para un completo entendimiento del documento, el lector deberá tener conocimientos previos sobre las siguientes tecnologías: Lenguaje Java Spring JSF Hibernate Framework de desarrollo de aplicaciones ATLAS Página 4 de 40 Framework Atlas Manual Usuario Generador de Código 2 DESCRIPCION DEL CODIGO QUE SE GENERA En este apartado se muestra para cada una de las capas del framework Atlas los diagramas de clases del código que se genera y la descripción de cada uno de los elementos creados y/o modificados para cada una de las capas de la aplicación. Se ha tomado como ejemplo una entidad de base de datos llamada Expediente. 2.1 ACCESO A DATOS En los desarrollos con framework Atlas nos vamos a encontrar con que una gran parte del desarrollo implica la capa de acceso a base de datos. En el framework Atlas se ha definido que dicho acceso sea con Hibernate y con implementaciones de clases de dominio y dao. La herramienta va a generar las clases que la normativa del framework Atlas determina (Clases de dominio y DAOS) para las operaciones básicas de consulta, alta, baja y modificación. Además se a van a realizar las correspondientes actualizaciones en los ficheros de configuración de Spring para que estas clases puedan ser usadas desde los servicios de negocio. A continuación se indican los elementos que se van a generar o modificar para cada una de las entidades/tablas de las cuales se solicita la generación de código: Fichero src/main/java/xxxx/domain/YYYY.java Creación / Descripción Modificación Creación, sólo si no existe Entidad de dominio asociada a una tabla. Está mapeada con anotaciones de Hibernate a dicha tabla y sus campos. Ejemplo: Expediente.java Interfaz e implementación de base para todos los DAOS. Se incluyen las operaciones básicas de alta, baja, modificación y consulta de forma genérica para src/main/java/xxxx/dao/BaseDAO.java Creación, cualquier dao. Todos los DAOs deberán heredar de src/main/java/xxxx/dao/BaseDAOImpl.java sólo si no existe ellas para así heredar estas operaciones básicas. Si en el desarrollo de la aplicación se identifica una necesidad común para todos los DAOS se ha de incluir en estas clases. Interfaz e implementación del DAO que permite gestionar las distintas operaciones de base de datos para la entidad. Heredan de BaseDAO y src/main/java/xxxx/dao/YYYYDAO.java Creación, src/main/java/xxxx/dao/YYYYDAOImpl.java sólo si no existe BaseDAOImpl respectivamente. En la generación estas clases se quedan vacías. Las nuevas operaciones de acceso a base de datos relacionadas con las entidad se han de implementar en estas clases. Ejemplo: ExpedienteDAO.java y ExpedienteDAIMpl.java Página 5 de 40 Framework Atlas Manual Usuario Generador de Código Se incluye el paquete de las clases de dominio src/main/resources/conf/applicationContextdatabase.xml Modificación generadas en la entrada “packagesToScan” para que las reconozca Hibernate. Se incluye la definición de un bean para el DAO generado en el fichero de contexto de Spring para src/main/resources/conf/applicationContextdao.xml Modificación que pueda ser usado desde los servicios de negocio. La nomenclatura del bean es yyyyDAO donde yyyy corresponde con el nombre la entidad. Ejemplo: expedienteDAO Clases generadas para la capa de acceso a datos class Acceso a Datos «interface» dao::BaseDAO + + + + + + + + + + + + + + findAll() : List<T> countAll() : Long findAllDistinct() : List<T> countAllDistinct() : Long find(PK) : T find(int, int, AtlasOrder[], AtlasQuery) : List<T> count(AtlasQuery) : int exists(PK) : boolean insert(T) : T insertOrUpdate(T) : void update(T) : void delete(PK) : void delete(T) : void findByNamedQuery(String, Map<String, Object>) : List<T> java.io.Serializable «interface» dao:: ExpedienteDAO T PK:extends Serializable HibernateDaoSupport dao::BaseDAOImpl - logger: Log = LogFactory.getL... {readOnly} persistentClass: Class<T> + + + + + + + + + + + + + + + + # BaseDAOImpl(Class<T>) BaseDAOImpl(Class<T>, SessionFactory) findAll() : List<T> countAll() : Long findAllDistinct() : List<T> countAllDistinct() : Long find(PK) : T find(int, int, AtlasOrder[], AtlasQuery) : List<T> count(AtlasQuery) : int findInternal(AtlasOrder[], AtlasQuery, boolean) : Criteria exists(PK) : boolean insert(T) : T insertOrUpdate(T) : void update(T) : void delete(PK) : void delete(T) : void findByNamedQuery(String, Map<String, Object>) : List<T> getLog() : Log dao::ExpedienteDAOImpl + ExpedienteDAOImpl() expedienteDAO : ExpedienteDAOImpl Bean de Spring para utilizar desde los servicios de negocio. 2.2 domain::Expediente - serialVersionUID: long = 1L {readOnly} idExpediente: Integer oficina: Oficina cdExpediente: String dsExpediente: String itEstado: String fcAlta: Date fcModif: Date clDsExtendida: Clob nmCdUadmin: Integer expeInteresados: Set<ExpeInteresado> = new HashSet<Exp... expeArchivos: Set<ExpeArchivo> = new HashSet<Exp... + + + Expediente() Expediente(Integer) Expediente(Integer, Oficina, String, String, String, Date, Date, Clob, Integer, Set<ExpeInteresado>, Set<ExpeArchivo>) getIdExpediente() : Integer setIdExpediente(Integer) : void getPKAsString() : String getPKFromString(String) : Integer getOficina() : Oficina setOficina(Oficina) : void getCdExpediente() : String setCdExpediente(String) : void getTextoListaValores() : String getDsExpediente() : String setDsExpediente(String) : void getItEstado() : String setItEstado(String) : void getFcAlta() : Date setFcAlta(Date) : void getFcModif() : Date setFcModif(Date) : void getClDsExtendida() : Clob setClDsExtendida(Clob) : void getNmCdUadmin() : Integer setNmCdUadmin(Integer) : void getExpeInteresados() : Set<ExpeInteresado> setExpeInteresados(Set<ExpeInteresado>) : void getExpeArchivos() : Set<ExpeArchivo> setExpeArchivos(Set<ExpeArchivo>) : void toString() : String equals(Object) : boolean hashCode() : int + + + + + + + + + + + + + + + + + + + + + + + + + + + + SERVICIOS DE NEGOCIO En la capa de servicios de negocio la herramienta se van a generar las clases que la normativa del framework Atlas determina (Fachada y Servicios) para las operaciones básicas de consulta, alta, baja y modificación invocando para su ejecución a los DAOs de la capa de acceso a datos. Además va a realizar las correspondientes configuraciones para incluir objetos de estos servicios en el contexto de Spring.. Página 6 de 40 Framework Atlas Manual Usuario Generador de Código A continuación se indican los elementos que se van a generar o modificar para cada una de las entidades/tablas de las cuales se solicita la generación de código: Creación / Fichero Descripción Modificación Interfaz e implementación de base para todos los Servicios. Se incluyen las operaciones básicas de alta, baja, modificación y consulta de forma genérica src/main/java/xxxx/services/BaseService.java src/main/java/xxxx/services/BaseServiceImpl.java Creación o para cualquier servicio. Todos los modificación si Servicios deberán heredar de ellas para ya existe. así heredar estas operaciones básicas. Si en el desarrollo de la aplicación se identifica una necesidad común para todos los Servicios se ha de incluir en estas clases. Interfaz e implementación del Servicio que permite gestionar las distintas operaciones que se pueden realizar con la entidad. Heredan de BaseService y src/main/java/xxxx/services/YYYYService.java Creación, src/main/java/xxxx/services/YYYYServiceImpl.java sólo si no existe BaseServiceImpl respectivamente. En la generación estas clases se quedan vacías ya que heredan la operativa básica. Las nuevas operaciones de este servicio se han de implementar en estas clases. Ejemplo: ExpedienteService.java y ExpedienteServiceIMpl.java Creación o src/main/java/xxxx/services/facade/XxxxFacade.java src/main/java/xxxx/services/facade/XxxxFacadeImpl.java modificación si ya existe. Página 7 de 40 Clases con la fachada y la implementación para el paquete xxxx. Ejemplo PruebasFacade.java y PruebasFacadeImpl.java Framework Atlas Manual Usuario Generador de Código Se incluye la definición de un bean para el servicio generado al cual se le inyecta el bean del dao correspondiente. La nomenclatura del bean del servicio es yyyyService donde yyyy corresponde con el nombre la entidad. Ejemplo: expedienteService src/main/resources/conf/applicationContextservices.xml Modificación Además se crea y/o modifica el bean de la fachada para inyectar el servicio. La nomenclatura del bean de la fachada es xxxxFacade donde xxxx corresponde con el nombre del paquete donde se han generado las clases. Ejemplo: expedienteFacade. A continuación se muestra un diagrama que incluye las clases generadas para la capa de servicio de negocio para una entidad de ejemplo llamada Expediente: Código generado para la capa de servicio de negocio class Serv icio «interface» serv ices::BaseServ ice + + + + + + + + + + + + + + + + setDao(D) : void getDao() : D findAll() : List<T> countAll() : Long findAllDistinct() : List<T> countAllDistinct() : Long find(PK) : T find(int, int, AtlasOrder[], AtlasQuery) : List<T> count(AtlasQuery) : int exists(PK) : boolean insert(T) : T insertOrUpdate(T) : void update(T) : void delete(PK) : void delete(T) : void findByNamedQuery(String, Map<String, Object>) : List<T> facade::PruebasFacadeImpl «interface» serv ices:: ExpedienteServ ice -expedienteService - expedienteService: ExpedienteService + + setExpedienteService(ExpedienteService) : void findExpediente(int, int, AtlasOrder[], AtlasQuery) : List<Expediente> findExpediente(Integer) : Expediente countExpediente(AtlasQuery) : int insertExpediente(Expediente) : void updateExpediente(Expediente) : void insertOrUpdateExpediente(Expediente) : void deleteExpediente(Expediente) : void deleteExpediente(Integer) : void + + + + + + + «interface» facade::PruebasFacade T PK:extends Serializable D:extends BaseDAO<T, PK> + serv ices::BaseServ iceImpl - logger: Log = LogFactory.getL... {readOnly} dao: D + + + + + + + + + + + + + + + + setDao(D) : void getDao() : D findAll() : List<T> countAll() : Long findAllDistinct() : List<T> countAllDistinct() : Long find(PK) : T find(int, int, AtlasOrder[], AtlasQuery) : List<T> count(AtlasQuery) : int exists(PK) : boolean insert(T) : T insertOrUpdate(T) : void update(T) : void delete(PK) : void delete(T) : void findByNamedQuery(String, Map<String, Object>) : List<T> expedienteDAO : ExpedienteDAOImpl expediente : Expediente + + + + + + + findExpediente(int, int, AtlasOrder[], AtlasQuery) : List<Expediente> findExpediente(Integer) : Expediente countExpediente(AtlasQuery) : int insertExpediente(Expediente) : void updateExpediente(Expediente) : void insertOrUpdateExpediente(Expediente) : void deleteExpediente(Expediente) : void deleteExpediente(Integer) : void serv ices:: ExpedienteServ iceImpl expedienteServ ice : ExpedienteServ iceImpl pruebasFacade : PruebasFacadeImpl Bean de Spring para ser usado desde los beans de respaldo de JSF Página 8 de 40 Framework Atlas Manual Usuario Generador de Código 2.3 PRESENTACION En la capa de presentación se generan para cada una de las entidades/tablas unas pantallas que nos permitan realizar el mantenimiento básico de dicha tabla. La generación de la parte de presentación está pensada como una solución para generar el código asociado al mantenimiento de catálogos que típicamente podemos encontrar en las aplicaciones. En el caso de las vistas no se generan las acciones de eliminar ni editar en el listado, ni el formulario de edición, y es posible especificar si se quieren tratar todas las tablas como vistas. Se generan los siguientes elementos de código: Fichero Creación / Modificación Descripción Clase del bean de respaldo de JSF para la gestión de operaciones de la entidad. src/main/java/xxxx/jsf/YYYYBean.java Creación, sólo si no existe Incluye las operaciones que se van a hacer desde las distintas pantallas. Este bean interactua con los servicios de negocio invocando a través de la fachada. Ejemplo: ExpedienteBean Página principal de administración de src/main/webapp/secure/catalogos.xhtml Creación si no existe catálogos. Se trata de una página inicial de ejemplo que se puede personalizar para cada aplicación. Página JSF que muestra un tabla paginada con los elementos de la entidad y filtros para cada uno de los campos que src/main/webapp/secure/listaYYYY.xhtml Creación si no existe permitan realizar busquedas. Más adelante se muestra como es gráficamente esta página. Ejemplo: listaExpediente.xhtml Página JSF que muestra un formulario src/main/webapp/secure/formularioYYYY.xhtml Creación si no existe con los campos de la entidad. Esta misma (no se genera en el página se utilizar para dar de alta un caso de vistas o nuevo elemento y para editar uno ya entidades de sólo existente. Más adelante se muestra como lectura) es gráficamente esta página. Ejemplo: formularioExpediente.xhtml. Página 9 de 40 Framework Atlas Manual Usuario Generador de Código Incluye una nueva opción de menú dentro src/main/resources/menu.xml Modificación de la opción Mantenimiento de Catálogos para acceder a la pantalla listaYYYY. Incluye la declaración del bean de respaldo para que pueda ser usado desde las páginas JSF. Este bean se declara en src/main/webapp/WEB-INF/faces-managedbeans.xml Modificación ambito request. La nomenclatura es es yyyyBean donde yyyy corresponde con el nombre la entidad. Ejemplo: expedienteBean Incluye las reglas de navegación para las src/main/webapp/WEB-INF/faces-navigation.xml Modificación distintas pantallas. Ver gráfico facesnavigation más abajo. src/main/java/xxxx/jsf/NavigationResults.java Modificación (si no existen ya los cambios) Resultados de navegación de las distintas páginas JSF, que se utilizan en facesnavigation.xml Todos los textos mostrados en las src/main/resources/msg/messages_es.properties Modificación pantallas se incluyen en el ficheros de mensajes. Cualquier modificación de los textos se ha de hacer en este fichero. Página 10 de 40 Framework Atlas Manual Usuario Generador de Código A continuación se muestra el código generado en la capa de presentación: Código generado: Presentación class Presentacion listaExpediente.xhtml formularioExpediente.xhtml expedienteBean : ExpedienteBean expedienteBean : ExpedienteBean Managed Bean para ser usado desde las páginas JSF j sf::ExpedienteBean - serialVersionUID: long = 1L {readOnly} facade: PruebasFacade orderAndFilter: OrderAndFilterBean = null entidad: Expediente = null listaValoresOficina: ListaValores textoOficina: String oficinaFilter: String cdExpedienteFilter: String dsExpedienteFilter: String itEstadoFilter: String fcAltaFilter: Date fcModifFilter: Date scroller: UIDataScroller = new UIDataScroller() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ExpedienteBean() getEntidad() : Expediente setEntidad(Expediente) : void getFacade() : PruebasFacade setFacade(PruebasFacade) : void getTimeZone() : TimeZone getOrderAndFilter() : OrderAndFilterBean setOrderAndFilter(OrderAndFilterBean) : void obtener(int, int, Object, Object) : List<Expediente> obtenerTotal(Object) : int cargar() : String cargar(ActionEvent) : void eliminar() : String eliminar(ActionEvent) : void confirmarEliminar() : String confirmarEliminar(AjaxBehaviorEvent) : void guardar() : String nuevo() : String volver() : String getListaValoresOficina() : ListaValores setListaValoresOficina(ListaValores) : void setTextoOficina(String) : void getTextoOficina() : String obtenerListaOficina(int, int, Object, Object) : List<AtlasHashMap> obtenerTotalOficina(Object) : int getOficinaFilter() : String setOficinaFilter(String) : void getCdExpedienteFilter() : String setCdExpedienteFilter(String) : void getDsExpedienteFilter() : String setDsExpedienteFilter(String) : void getItEstadoFilter() : String setItEstadoFilter(String) : void getFcAltaFilter() : Date setFcAltaFilter(Date) : void getFcModifFilter() : Date setFcModifFilter(Date) : void getScroller() : UIDataScroller setScroller(UIDataScroller) : void filtrar() : String setIdOficina(String) : void getRequiredMessage() : String «interface» facade::PruebasFacade + + -facade + + Página 11 de 40 + + + + -entidad countExpediente(AtlasQuery) : int insertExpediente(Expediente) : void updateExpediente(Expediente) : void findExpediente(int, int, AtlasOrder[], AtlasQuery) : List<Expediente> findExpediente(Integer) : Expediente insertOrUpdateExpediente(Expediente) : void deleteExpediente(Expediente) : void deleteExpediente(Integer) : void java.io.Serializable domain::Expediente Framework Atlas Manual Usuario Generador de Código A continuación se muestra un gráfico que muestra la navegación entre las páginas JSF generadas: faces-navigation A continuación se muestran ejemplos de pantallas generadas para el mantenimiento de la entidad Expediente. Ejemplo de página xhtml generada Listado: listaExpediente.xhtml Desde esta pantalla nos permite realizar las siguientes operaciones: Búsqueda basada en filtros Borrar los filtros para realizar una nueva búsqueda Página 12 de 40 Framework Atlas Manual Usuario Generador de Código Nuevo elemento: Accede a la pantalla de alta Eliminación: Borra un registro (no aparece en vistas y entidades de sólo lectura) Edición: Accede a la pantalla de edición (no aparece en vistas y entidades de sólo lectura) Características de esta pantalla: Filtros: o Para cada campo de la tabla de tipo String se genera un <inputText> para buscar por ese campo. o En el caso de que un campo sea una foreign key de una tabla se genera un <inputText> para buscar en el primer campo de tipo texto de la tabla foránea. o En el caso de un campo fecha se genera un campo que nos permite filtrar por una fecha, rango de fechas, antes/después de una fecha o registro nulo. o En el caso de campos numéricos se genera un campo que nos permite filtrar por criterios de igualdad, mayor/menor, intervalo o registro nulo. Tabla de resultados: o Ordenación por columnas o Paginación por ajax o Exportación a Excel o PDF (Pudiendo seleccionar columnas y modificar el orden en el documento de salida). o Para los campos de tipo LOB se genera un icono de descarga. Ejemplo de página xhtml generada Página de alta y edición: formularioExpediente.xhtml Página 13 de 40 Framework Atlas Manual Usuario Generador de Código Características de esta pantalla: Campos que son foreign key de otra tabla se genera un <inputText> asociado a una lista de valores Campos de tipo Date: se genera un campo de tipo Calendario Campos de tipo String: se genera un <inputText> limitado al tamaño máximo de la columna en base de datos Campos numéricos: se genera un <inputText> con validadores asociados para que el contenido no exceda el tamaño máximo permitido en base de datos Campos de tipo BLOB: se genera un <inputText> de sólo lectura que muestra el tamaño en bytes del contenido e iconos de acción para sustituir el contenido (mediante un componente fileUpload), descargarlo o eliminarlo (estos dos últimos sólo se muestran si hay contenido) File upload para añadir contenido a un campo BLOB Campos de tipo CLOB: se genera un <inputText> de sólo lectura que muestra los primeros caracteres del campo. Pinchando sobre el inputText se abre un panel modal para editar el contenido. Además, se generan los mismos iconos de acción que en el caso de los campos de tipo BLOB (subida mediante file upload, descarga y eliminación de contenido) Panel modal de edición de campo CLOB Página 14 de 40 Framework Atlas Manual Usuario Generador de Código Resto de campos se genera un <inputText> Cada campo lleva asociado un enlace a una ayuda de contexto Se marcan en amarillo los campos obligatorios y se muestra un mensaje si no se rellenan El siguiente diagrama muestra como interactúan entre sí los distintos elementos de código generados. Se ha realizado para la operación de “guardar” pero el resto de operaciones siguen el mismo patrón: Diagrama de secuencia para guardar un expediente sd Class Model expedienteBean :ExpedienteBean pruebasFacade :PruebasFacadeImpl expedienteService :ExpedienteServiceImpl expedienteDAO :ExpedienteDAOImpl formularioExpediente Hibernate guardar() :String insertOrUpdateExpediente(Expediente) insertOrUpdate(T) insertOrUpdate(T) 2.4 PRUEBAS Además se generan pruebas unitarias para la clase del Servicio, salvo en el caso de vista o tablas de sólo lectura. Creación / Fichero Modificación src/test/java/xxxx/services/YYYYServiceTest.java Creación, sólo si no Clase JUnit para testear la clase del existe servicio de negocio generada. Modificación del fichero para declarar los src/main/resources/conf/applicationContextservices.xml Descripción Modificación Beans de Spring correspondientes a fachada y/o servicios Clase generada para Test JUnit Página 15 de 40 Framework Atlas Manual Usuario Generador de Código class Pruebas AbstractTransactionalJUnit4SpringContextTests serv ices::ExpedienteServ iceTest - log: Logger = Logger.getLogge... facade: PruebasFacade sessionFactory: SessionFactory + + + + + + + + + + + + + setFacade(PruebasFacade) : void setSessionFactory(SessionFactory) : void beforeTransaction() : void afterTransaction() : void setUp() : void tearDown() : void testFind1Expediente() : void testFind2Expediente() : void testCountExpediente() : void testUpdateExpediente() : void testInsertOrUpdateExpediente() : void testDelete1Expediente() : void testDelete2Expediente() : void Página 16 de 40 Framework Atlas Manual Usuario Generador de Código 3 USO DE LA HERRAMIENTA Este documento toma como punto de partida un Arquetipo Web recién generado, y asume que se dispone del entorno Eclipse correctamente configurado y con el plugin JBoss Hibernate Tools instalado. Si no se dispone del arquetipo o el entorno, puede descargarse el DVD con el entorno de desarrollo ATLAS de la web de ArquitecturaSw (http://www.madrid.org/arquitecturasw ). En los ejemplos mostrados en este documento se ha utilizado un arquetipo web generado con los siguientes parámetros: Para configurar el entorno de desarrollo para utilizar la herramienta, y posteriormente utilizarla es necesario realizar los pasos descritos en los siguientes apartados. Página 17 de 40 Framework Atlas Manual Usuario Generador de Código 3.1 CONFIGURACIÓN DE LA CONSOLA DE HIBERNATE Antes de poder utilizar la ingeniería inversa, es necesario crear una Consola de Hibernate. Para ello, pulsamos con el botón derecho sobre la carpeta “generador”, seleccionamos “New -> Other -> Hibernate Console Configuration”: Pulsamos sobre “Next” y aparece la pantalla para crear una nueva consola. Página 18 de 40 Framework Atlas Manual Usuario Generador de Código En este pantalla, pulsamos sobre “Finish” y la consola ya estará creada. 3.2 CONFIGURACIÓN DEL PAQUETE JAVA Las clases que generará la herramienta estarán dentro de un paquete que puede ser configurado a través de la variable “generador.paquete” del fichero “web/src/main/resources/environment.properties”. Se deberá modificar el valor de esta variable para configurar el paquete en el que deseamos generar las clases Java: Página 19 de 40 Framework Atlas Manual Usuario Generador de Código 3.3 CONFIGURACIÓN DE LA CONEXIÓN A BASE DE DATOS Para que la herramienta pueda conectarse a la base de datos, debemos modificar el fichero de configuración del arquetipo situado en “web/generador/hibernate.cfg.xml”, y modificar las siguientes propiedades: hibernate.connection.url: Cadena de conexión JDBC. - Ej: jdbc:oracle:thin:@icm21:1521:denivel2 hibernate.connection.username: Usuario de conexión a la base de datos. - Ej: DBA_EJPL hibernate.connection.password: Contraseña de conexión. hibernate.default_schema: Schema de conexión (igual que el usuario). - Ej: DBA_EJPL ¡ATENCIÓN! Además de configurar la Base de Datos para el generador de código, no hay que olvidar configurar la Base de Datos de la aplicación como habitualmente. Es decir, modificar en el fichero enviroment.properties las variables jdbc.username=dba_ejpl jdb.password=sis Página 20 de 40 Framework Atlas Manual Usuario Generador de Código 3.4 SELECCIÓN DE LAS TABLAS Antes de ejecutar la herramienta tenemos que seleccionar las tablas para las que queremos realizar la generación. Para ello, debemos abrir el fichero “generador/hibernate.reveng.xml”, y seleccionar la pestaña “Table Filters”: Aquí, pulsamos sobre el botón “Refresh”, y aparecerá un desplegable en el que debemos seleccionar consola de hibernate que ya habíamos creado: En ese momento es posible que aparezca el siguiente mensaje: Página 21 de 40 Framework Atlas Manual Usuario Generador de Código Pulsamos sobre “Yes”, y ya podemos desplegar en la zona “Database Schema” todas las tablas del esquema. Debemos seleccionar las tablas que queramos, y pulsar sobre “Include…”, para pasarlas a la zona de la izquierda y que así sean utilizadas para la generación de código. Cuando hayamos terminado de seleccionar las tablas, pulsaremos sobre “Save” para guardar el fichero: 3.5 EJECUCIÓN Una vez que ya hemos terminado de configurar la herramienta, podemos proceder a su ejecución para generar el código. La ejecución de la herramienta se realiza mediante Maven, para ello pulsamos con el botón derecho sobre el proyecto “XXXX_web”, y seleccionamos “Run As… -> Maven build”: Página 22 de 40 Framework Atlas Manual Usuario Generador de Código En la pantalla que aparece, deberemos rellenar los siguientes valores: - Goal: generate-resources - Profiles: generador Posteriormente pulsamos sobre el botón “Run” para ejecutar Maven con esos valores: Página 23 de 40 Framework Atlas Manual Usuario Generador de Código Comenzará entonces la ejecución de la herramienta, que mostrará todo el log por la consola. Nota 1 Durante la ejecución, la herramienta hará preguntas para afinar algunos detalles del modelo, estas preguntas sólo se harán la primera vez, y las respuestas se guardarán en el fichero de propiedades hibernate.reveng.properties, ubicado en el directorio generador del módulo web, este fichero puede editarse para modificar o eliminar propiedades, en este último caso en la siguiente ejecución la herramienta volvería a hacer las preguntas. Si se ha seleccionado alguna tabla que no contenga definida una PRIMARY KEY, la herramienta de generación de código preguntará si se desea usar la lista de columna no nulas como clave primaria, mostrando en pantalla la lista de estas columnas que pueden identificar unívocamente los elementos de esa tabla: La respuesta debe ser “S” o “N” (mayúscula o minúscula). Si la respuesta es “N” se solicitará la lista de columnas para la clave primaria. Si la tabla no tuviera columnas no nulas no se hace la pregunta anterior, pasando directamente a solicitar los nombres de las columnas para la clave primaria. Debemos introducirlos EN MAYÚSCULA y separados por coma (si pulsamos “Enter” sin introducir ningún nombre de columna, utilizará todas las columnas de la tabla como clave única): Si alguna de las tablas tiene campos de tipo BLOB, la herramienta de generación de código preguntará si se desea especificar una extensión para el contenido de ese campo: Página 24 de 40 Framework Atlas Manual Usuario Generador de Código Si se especifica una extensión, se utilizará para añadirla al nombre del fichero de descarga en las pantallas de consulta y mantenimiento, asociando además un mime type adecuado. En caso de no especificarla el nombre del fichero de descarga no llevará extensión. A continuación se pregunta si se desea tratar todas las tablas como entidades de sólo lectura, es decir, como si fueran vistas, a lo que habrá que responder “S” o “N”. Nota 2 La herramienta identificará aquellas entidades cuyo nombre cumpla la normativa de Erwin 7 de identificadores para vistas, y para esas entidades no generará las acciones de eliminar ni editar en el listado, el formulario de edición ni los tests unitarios. Lo siguiente será que la herramienta pregunte si deseamos generar cada una de las distintas capas de la aplicación, preguntas a las que tendremos que responder pulsando la letra “S” o “N” (mayúsculas o minúsculas indistintamente): - Generar Entidades de Dominio S/N - Generar los DAOs S/N - Generar los Servicios S/N - Generar la Fachada S/N Página 25 de 40 Framework Atlas Manual Usuario Generador de Código - Generar las pantallas JSF S/N - Mostrar los formularios en pop-ups (ver Nota 3) - Generar los Tests de JUnit S/N Nota 3 Si indica „N‟ en la opción “ ATENCIÓN: INDIQUE SI DESEA QUE LOS FORMULARIOS SE MUESTREN EN POPUPS (S/N)", el formulario se mostrará en su propia página JSF, como ha ocurrido hasta la versión 1.5. Por otro lado, si indica „S‟, el formulario detalle se mostrará en un pop-up, tanto para las acciones de editar como nuevo. El código generado difiere mínimamente al indicar esta opción. Caben destacar los siguiente cambios: Todas las acciones usadas en las páginas JSF son Ajax y se encuentran dentro de un único formulario (<h:form> en listaXXX.xhtml) Se creará un pop-up en cada página JSF de listado (popupFormulario en listaXXX.xhtml) para mostrar el detalle de cada registro (formularioXXX.xhtml) en la acciones de Nuevo y Modificar Página 26 de 40 Framework Atlas Manual Usuario Generador de Código Después de seleccionar las opciones deseadas, la herramienta comienza a generar todos los ficheros, mostrando al final el resultado de la generación, así como un listado de todos los ficheros generados y/o modificados: Nota 4 Es importante revisar el log de la consola, porque en ocasiones se muestran advertencias sobre ficheros que no se han creado porque ya existían, o modificaciones que no se ha podido realizar. Fichero de Log de la generación de código En el directorio /generador se crea automáticamente un fichero llamado hibernate.reveng.log que contiene un log con todas las ejecuciones del generador de código. A leerlo asegurarse de estar leyendo la última ejecución ya que el log guarda todas. 3.6 COMPROBACIÓN DE CÓDIGO GENERADO Una vez ejecutada la herramienta, sólo queda comprobar que el código se ha generado correctamente. Para ello, debemos pulsar con el botón derecho sobre el proyecto “XXXX_Web”, y seleccionar la opción “Refresh”: Página 27 de 40 Framework Atlas Manual Usuario Generador de Código Podemos comprobar entonces que se han generado los ficheros indicados en el apartado Descripción del código que se genera, tanto Java como xhtml dentro de las carpetas correspondientes del arquetipo. Nota 1 En casos excepcionales es posible que algunos de los tests de JUnit no se ejecuten correctamente, en ese caso será necesario revisar los logs de ejecución para identificar los posibles errores y corregirlos. En tablas con Primary Key única y numérica, el generador de código asume que se cumple la normativa de Base de Datos y ERWIN V7, por lo que asume que existe una secuencia con la nomenclatura XXXX_S_NOMBRETABLA, que utilizan las entidades para crear nuevos objetos. Un fallo típico en los tests de JUnit es al tratar de insertar un objeto de algún tipo de datos para el cuál no existe la secuencia. Página 28 de 40 Framework Atlas Manual Usuario Generador de Código Nota 2 En tablas con foreign keys no nulas a otras entidades de dominio , la herramienta de generación de código genera el código de los Tests de JUnit, pero deja comentada la anotación @Test, y por tanto el test no se ejecuta. En estos casos deberá modificarse el test manualmente, y posteriormente descomentar la anotación para que se ejecute el test. Para saber dónde hay que modificar el test, la herramienta deja un comentario “// TODO: “ en las líneas concretas: Página 29 de 40 Framework Atlas Manual Usuario Generador de Código Nota 3 Puede observarse que para poder tratar las entidades de manera genérica en las pantallas de administración de catálogos, la herramienta de generación de código crea tres métodos anotados como @Transient en las entidades de dominio. Estos métodos son: - getPKAsString y getPKFromString: necesarios para identificar una entidad a través de una cadena de texto. - getTextoListaValores: Utilizado para mostrar un texto descriptivo de la entidad cuando se muestra dentro de una lista de valores y para buscar sobre ese campo en los formularios de búsqueda. Esta anotación indica que ese método no tiene que ser persistente. Página 30 de 40 Framework Atlas Manual Usuario Generador de Código 3.6.1 Comprobación de los ficheros de configuración de Spring en los test Los test generados por la herramienta de generación de código hay que revisarlos, sólo si se está generando código para una aplicación Batch o Librería. De elos test se tienen que quitar del @ContextConfiguration los ficheros marcados ficheros de /src/test/java/… @ContextConfiguration(locations = { "classpath:/conf/applicationContext-general.xml", "classpath:/conf/applicationContext-database.xml", "classpath:/conf/applicationContext-dao.xml", "classpath:/conf/applicationContext-services.xml", "classpath:/conf/applicationContext-security.xml", "classpath:/conf/applicationContext-security-hostPolitica.xml", "classpath:/conf/applicationContext-componentes.xml", "classpath:/conf/atlas-trazas-application-context.xml", "classpath:/conf/applicationContext-database-test.xml" }) public class ClienteServiceTest extends AbstractTransactionalJUnit4SpringContextTests { … … 3.7 COMPROBACION DE FORMATO DEL CÓDIGO GENERADO. Una vez generado todo el código y comprobado que se ha realizado correctamente debemos comprobar el formato de este. Para hacerlo, debemos ejecutasr el validador de Checkstyle y PMD de eclipse, para hacerlo, lo primero que debemos comprobar es que tenemos configurado eclipse con las los fichero de configuración de Checkstyle y PMD de ATLAS (Ver manual de configuración del entorno de desarrollo). Una vez comprobado esto, ejecutar la validación se realiza siguiendoestos pasos: 1. Ejecución de la validación de Checkstyle: botón derecho del ratón sobre el proyecto en la vista “Project Explorer” / “Package Explorer”, accediendo al menu “Checkstyle” y en este clickando en la opción “Check Code With Checkstyle” Página 31 de 40 Framework Atlas Manual Usuario Generador de Código 2. Ejecución de la validación de PMD: botón derecho en el proyecto, seleccionamos el menu “PMD” y la opción “Check Code With PMD”. 3. Comprobación del resultado de las validaciones: al realizar estas validaciones, siempre que se encuentren errores, aparecen en las clases que tienen errores un indicador de error, indicador que se muestra tanto a nivel de paquete como de clase. 4. Página 32 de 40 Framework Atlas Manual Usuario Generador de Código Además de estos indicadores en la vista de “Project Explorer”/”Package Explorer”, se puede abrir la vista “Checkstyle violations” donde se muestra una lista con los problemas encontrados en el código. Para PMD no tenemos ninguna vista especifica para comprobar los errores. 5. Corrección automatica de errores: los errores encontrados con las validaciones de Checkstyle y PMD, en la mayoria de ocasiones se solucionan con el formateador de código de eclipse. a. Antes de utilizar el formateador hay que comprobar que tenemos configurado el fichero de ATLAS para el formateador: i. Comprobación de la configuración del formateador de código de eclipse: entramos en la configuración de Java (Window>Preferences). En esta configuración accedemos a Java>Code Style>Formatter y comprobamos que tenemos en al Active profile el formateador de ICM. ii. iii. Comprobación de la configuración del cleaner de eclipse: accedemos a la configuración de Java (Window>Preference) En esta navegamos a Java>Code Style>Clean Up y comprobamos que tenemos en al Active profile el limpiador de ICM.. Página 33 de 40 Framework Atlas Manual Usuario Generador de Código b. Una vez comprobado que el “formateador” y el “limpiador” están correctamente configurados, accediendo a cada una de las clases en las que tengamos marcados errores de Checkstyle o PMD, debemos pulsar el botón derecho del ratón en el editor de código y seleccionar en el menu “Source” las opciones Format y Clean Up. Página 34 de 40 Framework Atlas Manual Usuario Generador de Código 6. Una vez ejecutadas estas dos herramientas, debemos actualizar la información de Checkstyle y PMD repitiendo los pasos 1 y 2. Normalmente no debería quedar ningún error, pero en algunos casos es posible que queden errores. Si al realizar esta comprobación siguen apareciendo errores de Checkstyle o PMD, estos deben solucionarse manualmente. Página 35 de 40 Framework Atlas Manual Usuario Generador de Código 3.8 TABLAS CON RELACIÓN N:M Cuando se genera código mediante el generador de Atlas, este crea todos los mapeos correspondientes a las tablas seleccionadas por el usuario, generando objetos de dominio para cada tabla (entidad). Además, el generador relaciona las entidades entre sí, por lo que las relaciones se mapean como objetos dentro de cada una de ellas, es decir: Si dos tablas A y B tienen relación 1:1, como resultado se obtendrá una entidad A que tendrá un atributo de tipo B y una entidad B con un atributo de tipo A. En el caso de una relación 1:N, el resultado es una entidad de tipo A con un Set de objetos tipo B y una de tipo B con un atributo de tipo A. Si la relación es de N:M, en el esquema de BD existe una tabla intermedia, AB, que el generador de código mapea, con lo que se obtienen tres entidades con relaciones 1:N, de forma que el objeto A tiene un atributo Set<AB>, el objeto B tiene un atributo Set<AB> y el objeto AB contiene un atributo tipo A y uno tipo B. Es en este tercer punto,en las relaciones N:M es donde el mapeo puede no resultar del todo correcto, y hay que distinguir dos casos: a) La tabla AB contiene alguna otra columna además de los IDs de las tablas que relaciona. En este caso, el mapeo es correcto, ya que es necesario que exista esta entidad con datos extra referentes a la relación. b) La tabla AB no tiene más columnas que los IDs de las tablas que relaciona. En este caso, hay que actuar de forma manual ya que en la aplicación la entidad AB carece de sentido funcional, y lo adecuado es tener una relación N:M en lugar de dos 1:N. Esta actuación se describe a continuación. 3.8.1 Cambios en el mapeo generado Para corregir el error del generador en las relaciones N:M, hay que actuar en todas las capas que se hayan generado. Para su explicación utilizaremos como ejemplo las tablas Alumno, AsignaturaCurso y AlumnoAsignatura (entidad relación entre Alumno y AsignaturaCurso). Este es el esquema de Oracle relacionado con las clases: Página 36 de 40 Framework Atlas Manual Usuario Generador de Código Cambios en la tablas de dominio: En primer lugar hay que modificar las entidades eliminando en Alumno y AsignaturaCurso todas las referencias a AlumnoAsignatura, ya que esta será eliminada. 1.- En Alumno Sustituir: private Set<AlumnoAsignatura> alumnoAsignaturas = new HashSet<AlumnoAsignatura>(0); Por: private List<AsignaturaCurso> asignaturas = new ArrayList<AsignaturaCurso>(0); El getter y el setter de la propiedad habrá que editarlo, también. Para el getter hay que modificar las anotaciones de Hibernate e indicarle cuál es la tabla de relación e identificar las columnas de unión. Sutituir @OneToMany(fetch = FetchType.LAZY, mappedBy = "alumno") public Set<AlumnoAsignatura> getAlumnoAsignaturas() { return this.alumnoAsignaturas; } public void setAlumnoAsignaturas(Set<AlumnoAsignatura> alumnoAsignaturas) { this.alumnoAsignaturas = alumnoAsignaturas; } Por: @ManyToMany @JoinTable(name = "EJPL_ALUMNO_ASIGNATURA ", joinColumns = { @JoinColumn(name = "ID_ALUMNO", nullable = false, updatable = false), inverseJoinColumns = { @JoinColumn(name = "ID_ASIGNATURA_CURSO",nullable = false, updatable = false) } ) public List<AsignaturaCurso> getAsignaturas() { return asignaturas; } public void setAsignaturas(List<AsignaturaCurso> asignaturas) { this.asignaturas = asignaturas; } 2.- En AsignaturaCurso: Sustituir: private Set<AlumnoAsignatura> alumnoAsignaturas = new HashSet<AlumnoAsignatura>(0); Por: private List<Alumno> alumnos = new ArrayList<Alumno>(0); Página 37 de 40 Framework Atlas Manual Usuario Generador de Código El getter y setter hay que adaptarlos y modificar las anotaciones de Hibernate. Sustituir: @OneToMany(fetch = FetchType.LAZY, mappedBy = "asignaturaCurso") public Set<AlumnoAsignatura> getAlumnoAsignaturas() { return this.alumnoAsignaturas; } public void setAlumnoAsignaturas(Set<AlumnoAsignatura> alumnoAsignaturas) { this.alumnoAsignaturas = alumnoAsignaturas; } Por: @ManyToMany @JoinTable(name = "EJPL_ALUMNO_ASIGNATURA", joinColumns = { @JoinColumn(name = "ID_ASIGNATURA_CURSO", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "ID_ALUMNO", nullable = false, updatable = false) }) public List<Alumno> getAlumnos() { return this.alumnos; } public void setAlumnos (List<Alumno> setAlumnos) { this. setAlumnos = setAlumnos; } 3.- En AlumnoAsignatura: Eliminar la clase que representa la tabla de relación y también la que representa su identificador, AlumnoAsignaturaId.java Cambios en la clases de DAO: Hay que eliminar los DAOs correspondientes a las entidades eliminadas, en este caso AlumnoAsignaturaDAO.java y AlumnoAsignaturaDAOImpl.java. Cambios en la clases de Servicio: Hay que eliminar los servicios asociados a las entidades eliminadas, en este caso AlumnoAsignaturaService.java y AlumnoAsignaturaServiceImpl.java Cambios en la clases de Fachada: Hay que eliminar los métodos que referencian a los servicios eliminados, si los hay. Cambios en la clases de Vista: Hay que eliminar los métodos que referencian a los servicios eliminados, si los hay. Cambios en la configuración: Hay que eliminar de todos los applicationContext las referencias a los beans de las clases eliminadas. Página 38 de 40 Framework Atlas Manual Usuario Generador de Código 3.9 EJECUCIÓN DE LA APLICACIÓN Por último, debemos de ejecutar Maven para compilar el proyecto (goals “clean install”), y comprobar que los tests de JUnit generados se ejecutan correctamente. Después, procederemos a ejecutar la aplicación para comprobar que efectivamente se han generado las pantallas de mantenimiento de catálogos. La herramienta de generación automática de código genera una sub-opción de menú por cada catálogo, en la opción “Mantenimiento de Catálogos”: Página 39 de 40 Framework Atlas Manual Usuario Generador de Código 4 USO INCREMENTAL DE LA HERRAMIENTA La herramienta está pensada para poderse ejecutar incrementalmente, de manera que se puedan generar las pantallas correspondientes a una serie de tablas, y en el futuro cuando se añadan tablas nuevas volverse a ejecutar con las nuevas. Así, antes de introducir una modificación en el código, la herramienta comprueba que dicha modificación no exista ya, de forma que no realiza ninguna modificación dos veces. Nota La incrementalidad de la herramienta de generación de código es incrementalidad a nivel de tabla, no a nivel de campo. Si se modifican las columnas de una tabla para la que ya se generó el código, es necesario eliminar primero manualmente el código anterior para que vuelva a generarse el código con los campos modificados, del mismo modo si se elimina alguna propiedad del fichero hibernate.reveng.properties, la herramienta volverá a solicitar la información, pero sólo se modificarán el código si los ficheros afectados han sido eliminados previamente. Página 40 de 40