Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Liferay 6.1 Service Builder

2,361 views

Published on

Published in: Technology
  • Be the first to comment

Liferay 6.1 Service Builder

  1. 1. Liferay 6.1 Service Builder
  2. 2. Service Builder Preparado por Jesús Salinas Revelles Índice de contenidos ‣ Introducción. ‣ Fichero service.xml. ‣ Ejercicio.
  3. 3. Service Builder Preparado por Jesús Salinas Revelles Introducción ‣ Es una herramienta desarrollada por Liferay para la creación automática de interfaces y clases que son usadas por el portal o portlets, es decir, nos permite crear servicios Java. ‣ Se puede acceder a estos servicios de diferentes formas: ‣ Acceso local mediante código Java. ‣ Acceso remoto mediante servicios web. ‣ La generación de estas clases e interfaces pasa por construir adecuadamente un fichero xml llamado service.xml, siguiendo una sintaxis específica. ‣ Se pasan a describir a continuación las reglas a seguir para su correcta construcción.
  4. 4. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Este fichero permite definir el código que posteriormente va a generar Service builder. ‣ Ejemplo: <?xml version="1.0"?> <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 5.2.0//EN" "http://www.liferay.com/dtd/ liferay-service-builder_5_2_0.dtd"> <service-builder package-path="com.ext.portlet.reports"> <namespace>Reports</namespace> <entity name="ReportsEntry" local-service="true" remote- service="false" ... > <column name="entryId" type="String" primary="true" /> <column name="companyId" type="String" /> <column name="userId" type="String" /> ... </entity> </service-builder>
  5. 5. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ El fichero service.xml debe incluir la dtd correspondiente al Service builder adecuado: ‣ Una vez incluida la DTD se deben incluir los elementos XML necesarios: ‣ Elemento service-builder. ‣ Elemento namespace. ‣ Elemento entity ‣ ... <?xml version="1.0"?> <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 5.2.0//EN" "http://www.liferay.com/dtd/ liferay-service-builder_5_2_0.dtd"> <service-builder package-path="com.ext.portlet.reports"> ... </service-builder>
  6. 6. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento service-builder: ‣ Es el elemento raíz del fichero, todos los elementos que se definan posteriormente son elementos hijo de este: ‣ Ejemplo: <?xml version="1.0"?> <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 5.2.0//EN" "http://www.liferay.com/dtd/liferay- service-builder_5_2_0.dtd"> <service-builder package-path="com.ext.portlet.reports"> ... </service-builder> <!ELEMENT service-builder (author?, namespace, entity+, exceptions?)>
  7. 7. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento service-builder: ‣ Atributo package-path: ‣ Ruta del paquete donde se almacena el código fuente: <?xml version="1.0"?> <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 5.2.0//EN" "http://www.liferay.com/dtd/liferay- service-builder_5_2_0.dtd"> <service-builder package-path="com.ext.portlet.reports"> ... </service-builder>
  8. 8. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento entity: ‣ Una entidad habitualmente representa una fachada de negocio y una tabla en la base de datos. Si la entidad no tiene columnas sólo representa una fachada. ‣ Si la entidad tiene columnas, se generan el value object, el POJO que se mapea a la base de datos, y otras utilidades basadas en la definición de órdenes y finders. ‣ Sus elementos hijo son: <!ELEMENT entity (column*, order?, finder*, reference*, tx- required*)>
  9. 9. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento entity: ‣ Sus atributos son: <!ATTLIST entity ! name CDATA #REQUIRED ! table CDATA #IMPLIED ! uuid CDATA #IMPLIED ! local-service CDATA #IMPLIED ! remote-service CDATA #IMPLIED ! persistence-class CDATA #IMPLIED ! data-source CDATA #IMPLIED ! session-factory CDATA #IMPLIED ! tx-manager CDATA #IMPLIED ! cache-enabled CDATA #IMPLIED >
  10. 10. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento entity: ‣ Atributo name: nombre de la entidad. ‣ Atributo table: nombre de la tabla donde se mapea la entidad. ‣ Atributo uuid: si el valor está a true, el servicio genera una columna UUID. Por defecto, a false. ‣ Atributo local-service: si está a true, se genera un servicio con interfaces locales. ‣ Atributo remote-service: si está a true, se genera un servicio con interfaces remotas. ‣ Atributo persistence-class: nombre de la clase persistente que se genera.
  11. 11. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento column: ‣ Representa una columna en la tabla de una base de datos. ‣ No tiene elementos hijo: ‣ Ejemplo: <!ELEMENT column (#PCDATA)> <column name="entryId" type="String" primary="true" /> <column name="companyId" type="String" />
  12. 12. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento column: ‣ Atributos del elemento: <!ATTLIST column ! name CDATA #REQUIRED ! db-name CDATA #IMPLIED ! type CDATA #REQUIRED ! primary CDATA #IMPLIED ! entity CDATA #IMPLIED ! mapping-key CDATA #IMPLIED ! mapping-table CDATA #IMPLIED ! id-type CDATA #IMPLIED ! id-param CDATA #IMPLIED ! convert-null CDATA #IMPLIED ! localized CDATA #IMPLIED >
  13. 13. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento column: ‣ Atributo name: nombre de la columna, especifica el nombre de los getter y setter en la entidad ‣ type: especifica el tipo de la columna. ‣ Ejemplo: ‣ La entidad tiene un método getNombre que devuelve como valor de retorno una cadena de caracteres. <column name="nombre" type="String" />
  14. 14. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento column: ‣ Nota, tipos en el service builder: ‣ boolean => BOOLEAN. ‣ int, Integer, short => INTEGER. ‣ long => LONG. ‣ float, double => DOUBLE. ‣ String => VARCHAR (<4000), STRING (=4000), TEXT (>4000). ‣ Date => DATE.
  15. 15. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento column: ‣ primary: si es true, la columna es parte de la clave primaria de la entidad. Si varias columnas tienen este atributo a true, implica que la clave es compuesta. ‣ Ejemplo: <column name="entryId" type="String" primary="true" />
  16. 16. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento column: ‣ entity: nombre de la entidad que se relaciona con este atributo. ‣ mapping-key: clave de mapeo. ‣ mapping-table: tabla de mapeo.
  17. 17. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento column: ‣ Los atributos id-type y id-param se utilizan para crear claves primarias que se generan automáticamente cuando se insertan registros en la tabla. ‣ Se pueden implementar de cuatro formas diferentes.
  18. 18. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml <entity name="Account" local-service="true" remote-service="true"> ! <!-- PK fields --> ! <column name="accountId" type="long" primary="true" /> ! <!-- Audit fields --> ! <column name="companyId" type="long" /> ! <column name="userId" type="long" /> ! <column name="userName" type="String" /> ! <column name="createDate" type="Date" /> ! <column name="modifiedDate" type="Date" /> ! <!-- Other fields --> ! ... ! <column name="type" type="String" /> ! <column name="size" type="String" /> </entity>
  19. 19. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento finder: ‣ Representa métodos finder que se generarán automáticamente. ‣ Tiene un elemento hijo llamado finder-column: ‣ Ejemplo: <!ELEMENT finder (finder-column+)> <finder name="CompanyId" return-type="Collection"> <finder-column name="companyId" /> </finder>
  20. 20. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento finder: ‣ Atributos: <!ATTLIST finder ! name CDATA #REQUIRED ! return-type CDATA #REQUIRED ! unique CDATA #IMPLIED ! where CDATA #IMPLIED ! db-index CDATA #IMPLIED >
  21. 21. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento finder: ‣ Atributos: ‣ name: nombre del método ‣ return-type: tipo del valor de retorno. Los valores válidos son Collection o el nombre de una entidad. ‣ unique: si es true, el método debe devolver una única entidad. ‣ db-index: si es true, el servicio genera automáticamente un índice SQL para el método. Por defecto el valor es true. ‣ Ejemplo: <finder name="CompanyId" return-type="Collection"> ... </finder>
  22. 22. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento finder-column: ‣ Representa una columna a partir de la cuál se busca. ‣ No tiene elementos hijo: ‣ Ejemplo: <finder name="CompanyId" return-type="Collection"> <finder-column name="companyId" /> </finder> <!ELEMENT finder-column (#PCDATA)>
  23. 23. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento finder-column: ‣ Atributos: <!ATTLIST finder-column ! name CDATA #REQUIRED ! case-sensitive CDATA #IMPLIED ! comparator CDATA #IMPLIED >
  24. 24. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento finder-column: ‣ Atributos: ‣ name: nombre de la columna. ‣ case-sensitive: valor booleano utilizado si la columna es de tipo String. ‣ comparator: puede tomar como valor =, !=, <, <=, >, >=, o LIKE y es usado para comparar la columna. ‣ Ejemplo: <finder name="CompanyId" return-type="Collection"> ... </finder>
  25. 25. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Ejemplo: <finder name="CompanyId" return-type="Collection"> ! <finder-column name="companyId" /> </finder> <finder name="UserId" return-type="Collection"> ! <finder-column name="userId" /> </finder> <finder name="C_C" return-type="Collection"> ! <finder-column name="companyId" /> ! <finder-column name="classNameId" /> </finder>
  26. 26. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento order: ‣ Representa la ordenación por defecto que se aplica a las entidades cuando se envían desde la base de datos. ‣ Tiene un elemento hijo order-column: ‣ Ejemplo: <order by="asc"> <order-column name="parentLayoutId" /> <order-column name="priority" /> </order> <!ELEMENT order (order-column+)>
  27. 27. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento order: ‣ Atributos: ‣ El atributo by toma dos valores: ‣ asc o desc: ordenación ascendente o descendente. <!ATTLIST order ! by CDATA #IMPLIED >
  28. 28. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento order-column: ‣ Representa la ordenación por defecto que se aplica a las entidades cuando se envían desde la base de datos. ‣ No tiene elementos hijo: ‣ Ejemplo: <!ELEMENT order-column (#PCDATA)> <order by="asc"> <order-column name="parentLayoutId" /> <order-column name="priority" /> </order>
  29. 29. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ Elemento order-column: ‣ Atributos: ‣ El atributo order-by toma dos valores: ‣ asc o desc: ordenación ascendente o descendente. <!ATTLIST order-column ! name CDATA #REQUIRED ! case-sensitive CDATA #IMPLIED ! order-by CDATA #IMPLIED > <order> <order-column name="articleId" order-by="asc" /> <order-column name="version" order-by="desc" /> </order>
  30. 30. Service Builder Preparado por Jesús Salinas Revelles Ejercicio ‣ Introducción. ‣ Fichero service.xml. ‣ Generación del servicio. ‣ Código generado. ‣ Asociaciones.
  31. 31. Service Builder Preparado por Jesús Salinas Revelles Introducción ‣ Se describe a continuación el proceso de utilización de Service builder en el entorno Ext. ‣ Creación del fichero service.xml. ‣ Generación del servicio. ‣ Código generado. ‣ Vamos a crear un servicio que nos permite manejar entidades de tipo Factura.
  32. 32. Service Builder Preparado por Jesús Salinas Revelles Introducción ‣ La tabla sobre la que se quiere trabajar es: create table Factura ( id_ VARCHAR(75) not null primary key, razonSocial VARCHAR(75) null, cif VARCHAR(75) null, nombreCliente VARCHAR(75) null, fechaServicio DATE null,importe DOUBLE )
  33. 33. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml ‣ El fichero service.xml debe crearse en el directorio ext-impl. ‣ Se crea, para nuestro ejemplo, en el directorio: ‣ src/com/ext/portlet/PortletPrueba
  34. 34. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml <?xml version="1.0"?> <!DOCTYPE service-builder PUBLIC "-//Liferay//DTD Service Builder 5.2.0//EN" "http://www.liferay.com/dtd/liferay- service-builder_5_2_0.dtd"> <service-builder package- path="com.ext.portlet.PortletPrueba"> <namespace>Prueba</namespace> <entity name="Factura" local-service="true" remote- service="false"persistence-class="com.ext.portlet. PortletPrueba.FacturaEntryPersistenceImpl"> <column name="id" type="String" primary="true" /> <column name="razonSocial" type="String" /> <column name="cif" type="String" /> <column name="nombreCliente" type="String" /> <column name="fechaServicio" type="Date" /> <column name="importe" type="Double" /> ...
  35. 35. Service Builder Preparado por Jesús Salinas Revelles Fichero service.xml <order by="asc"> <order-column name="nombreCliente" case- sensitive="false" /> </order> <finder name="nombreCliente" return-type="Collection"> <finder-column name="nombreCliente" /> </finder> <finder name="cif" return-type="Collection"> <finder-column name="cif" /> </finder> </entity> </service-builder>
  36. 36. Service Builder Preparado por Jesús Salinas Revelles Generación del servicio ‣ Una vez construido correctamente el fichero service.xml, la generación del servicio se realiza mediante la herramienta Eclipse:
  37. 37. Service Builder Preparado por Jesús Salinas Revelles Código generado ‣ Introducción. ‣ Modelo. ‣ Servicio de persistencia. ‣ Servicio de negocio. ‣ Ficheros de configuración.
  38. 38. Service Builder Preparado por Jesús Salinas Revelles Introducción ‣ Éste se puede clasificar de varias formas. ‣ Si pensamos en los distintos niveles de la aplicación: ‣ Código asociado al modelo. ‣ Código asociado al servicio de persistencia. ‣ Código asociado al servicio de negocio. ‣ Si pensamos en clases e interfaces: ‣ Implementaciones de los servicios. ‣ Especificaciones de los servicios. ‣ En principio, vamos a utilizar la primera para describir el código generado.
  39. 39. Service Builder Preparado por Jesús Salinas Revelles Modelo ‣ Para el problema planteado, básicamente el código generado podría resumirse mediante el siguiente esquema:
  40. 40. Service Builder Preparado por Jesús Salinas Revelles Modelo ‣ La interface FacturaModel: ‣ Define todos los métodos set y get necesarios. public interface FacturaModel extends BaseModel<Factura> { ... } NUNCA DEBE MODIFICARSE O REFERENCIARSE DIRECTAMENTE.
  41. 41. Service Builder Preparado por Jesús Salinas Revelles Modelo ‣ La interface Factura: ‣ Hereda de FacturaModel. ... public interface Factura extends FacturaModel { } Esta interface DEBE utilizarse SIEMPRE que se desea referenciar una entidad que conceptualmente representa una factura. NUNCA DEBE MODIFICARSE DIRECTAMENTE.
  42. 42. Service Builder Preparado por Jesús Salinas Revelles Modelo ‣ La clase FacturaModelImpl: ‣ Esta clase implementa la interface FacturaModel implementando todos los métodos get y set. public class FacturaModelImpl extends BaseModelImpl<Factura> ! implements FacturaModel { ! public static final String TABLE_NAME = "Factura"; ! public static final Object[][] TABLE_COLUMNS = { ! ! ! { "facturaId", new Integer(Types.BIGINT) }, ! ! ! { "companyId", new Integer(Types.BIGINT) }, ! ! ! { "cliente", new Integer(Types.VARCHAR) }, ! ! ! { "razonSocial", new Integer(Types.VARCHAR) }, ! ! ! { "fechaEmision", new Integer(Types.TIMESTAMP) }, ! ! ! { "importe", new Integer(Types.DOUBLE) } ! }; NUNCA DEBE MODIFICARSE O REFERENCIARSE DIRECTAMENTE.
  43. 43. Service Builder Preparado por Jesús Salinas Revelles Modelo ‣ La clase FacturaImpl: ‣ Esta clase es la implementación del modelo. Hereda de FacturaModelImpl e implementa Factura: ... public class FacturaImpl extends FacturaModelImpl implements Factura { ! public FacturaImpl() { ! } } NUNCA DEBE REFERENCIARSE DIRECTAMENTE.
  44. 44. Service Builder Preparado por Jesús Salinas Revelles Modelo ¿Cómo? ¿Por qué se trabaja con un conjunto de clases e interfaces para resolver un problema teóricamente más simple? ¿Puedo modificar el código generado por el service builder?
  45. 45. Service Builder Preparado por Jesús Salinas Revelles Modelo ‣ Service Builder, mediante su fichero service.xml, nos permite crear de forma totalmente automática el modelo del servicio que queremos definir. ‣ Pero si, por la razón que sea, necesitamos modificar y adaptar el modelo de forma manual, será posible gracias a la arquitectura que propone Liferay. ‣ Cualquier modificación que necesitemos hacer se llevará a cabo en la clase FacturaImpl.
  46. 46. Service Builder Preparado por Jesús Salinas Revelles Servicio de persistencia ‣ Para el problema planteado, básicamente el código generado podría resumirse mediante el siguiente esquema:
  47. 47. Service Builder Preparado por Jesús Salinas Revelles Servicio de persistencia ‣ La interface FacturaPersistence: define todos los métodos que proporciona el servicio de persistencia para el concepto Factura. ... public interface FacturaPersistence extends BasePersistence<Factura> { NUNCA DEBE MODIFICARSE O REFERENCIARSE DIRECTAMENTE.
  48. 48. Service Builder Preparado por Jesús Salinas Revelles Servicio de persistencia ‣ La clase FacturaPersistenceImpl: es la implementación de todos los métodos definidos en la interface FacturaPersistence. ... public class FacturaPersistenceImpl extends BasePersistenceImpl<Factura> ! implements FacturaPersistence { NUNCA DEBE MODIFICARSE O REFERENCIARSE DIRECTAMENTE.
  49. 49. Service Builder Preparado por Jesús Salinas Revelles Servicio de persistencia ‣ La clase FacturaUtil: mediante Spring Framework se inyecta la implementación del servicio de persistencia asociado a Facturas y mediante métodos estáticos se proporciona el servicio. ... public class FacturaUtil { private static FacturaPersistence _persistence; public void setPersistence(FacturaPersistence persistence) { ! ! _persistence = persistence; } public static void clearCache() { getPersistence().clearCache(); } ... NUNCA DEBE MODIFICARSE DIRECTAMENTE.
  50. 50. Service Builder Preparado por Jesús Salinas Revelles Servicio de persistencia ‣ Las clases e interfaces del servicio de persistencia se crean de forma automática. ‣ La clase utility para el servicio de Facturas envuelve la implementación del servicio de persistencia y proporciona acceso a las operaciones CRUD del modelo. ‣ Esta utilidad SÓLO debe ser utilizada por el servicio de negocio asociado y siempre dentro de una transacción. Nunca debemos utilizarlo desde una página jsp, un controlador, etc.
  51. 51. Service Builder Preparado por Jesús Salinas Revelles Servicio de negocio ‣ Para el problema planteado, básicamente el código generado podría resumirse mediante el siguiente esquema:
  52. 52. Service Builder Preparado por Jesús Salinas Revelles Servicio de negocio ‣ La interface FacturaLocalService: ‣ Define todos los métodos proporcionados por el servicio de negocio que posteriormente tendrán que ser implementados. ... @Transactional(isolation = Isolation.PORTAL, rollbackFor={PortalException.class, SystemException.class}) public interface FacturaLocalService { ... public es.ematiz.model.Factura addFactura(Factura factura) throws SystemException; ... NUNCA DEBE MODIFICARSE O REFERENCIARSE DIRECTAMENTE.
  53. 53. Service Builder Preparado por Jesús Salinas Revelles Servicio de negocio ‣ La clase FacturaLocalServiceBaseImpl: ‣ Esta clase implementa todos los métodos definidos en la interface FacturaLocalService. ‣ Mediante Spring Framework, el servicio de persistencia de Facturas es inyectado en esta clase para poder implementar los servicios necesarios: public abstract class FacturaLocalServiceBaseImpl implements FacturaLocalService { protected FacturaPersistence facturaPersistence; public Factura addFactura(Factura factura) throws SystemException { factura.setNew(true); return facturaPersistence.update(factura, false); } NUNCA DEBE MODIFICARSE O REFERENCIARSE DIRECTAMENTE.
  54. 54. Service Builder Preparado por Jesús Salinas Revelles Servicio de negocio ‣ La clase FacturaLocalServiceImpl: ‣ Esta clase hereda de FacturaLocalServiceBaseImpl. ... public class FacturaLocalServiceImpl extends FacturaLocalServiceBaseImpl { } Todos los métodos que se quieren añadir en el servicio DEBEN incluirse aquí. NUNCA DEBE REFERENCIARSE DIRECTAMENTE.
  55. 55. Service Builder Preparado por Jesús Salinas Revelles Servicio de negocio ‣ La clase FacturaLocalServiceUtil: ‣ Define todos los métodos que expone el servicio de negocio mediante métodos estáticos. ‣ Esta es la clase que debe utilizar el programador cuando quiere utilizar el servicio de negocio. ... public class FacturaLocalServiceUtil { public static Factura addFactura(Factura factura) throws SystemException { return getService().addFactura(factura); } ... NUNCA DEBE MODIFICARSE DIRECTAMENTE.
  56. 56. Service Builder Preparado por Jesús Salinas Revelles Ficheros de configuración ‣ Como ya se ha comentado anteriormente, Liferay maneja sus servicios apoyándose básicamente en dos tecnologías: ‣ Spring Framework. ‣ Hibernate Framework. ‣ El uso de estas tecnologías implica la incorporación de un conjunto de ficheros de configuración. Se pasan a describir a continuación: ‣ base-spring.xml. ‣ cluster-spring.xml. ‣ dynamic-data-source-spring.xml. ‣ hibernate-spring.xml. ‣ infraestructure-spring.xml. ‣ ...
  57. 57. Service Builder Preparado por Jesús Salinas Revelles Ficheros de configuración ‣ base-spring.xml: ‣ Es un fichero de configuración de Spring Framework que define diferentes advice de programación orientada a aspectos. ... <bean id="basePersistence" abstract="true"> <property name="dataSource" ref="liferayDataSource" /> <property name="sessionFactory" ref="liferaySessionFactory" /> </bean> <bean id="serviceAdvice" class="com.liferay.portal.monitoring.statistics.service.ServiceM onitorAdvice" factory-method="getInstance"> <property name="monitoringDestinationName" value="liferay/monitoring" /> <property name="nextMethodInterceptor" ref="asyncAdvice" /> </bean>
  58. 58. Service Builder Preparado por Jesús Salinas Revelles Ficheros de configuración ‣ base-spring.xml: ‣ Es interesante hacer énfasis en el advice para la gestión de transacciones: ... <bean id="transactionAdvice" class= "com.liferay.portal.spring.transaction.TransactionInterceptor"> <property name="transactionManager" ref="liferayTransactionManager" /> <property name="transactionAttributeSource"> <bean class="com.liferay.portal.spring.transaction. AnnotationTransactionAttributeSource" /> </property> </bean>
  59. 59. Service Builder Preparado por Jesús Salinas Revelles Ficheros de configuración ‣ dynamic-data-source-spring.xml: ... <bean id="transactionAdvice" class="com.liferay.portal.dao.jdbc .aop.DynamicDataSourceTransactionInterceptor"> <property name="transactionManager" ref="liferayTransactionManager" /> <property name="transactionAttributeSource"> <bean class="org.springframework.transaction.annotation. AnnotationTransactionAttributeSource"> <constructor-arg> ! <bean class="com.liferay.portal.spring.annotation. PortalTransactionAnnotationParser" /> </constructor-arg> </bean> </property> </bean>
  60. 60. Service Builder Preparado por Jesús Salinas Revelles Ficheros de configuración ‣ hibernate-spring.xml: ‣ Define la forma en que Spring Framework maneja Hibernate en la capa de datos: <bean id="liferayHibernateSessionFactory" class="com.liferay.portal.spring.hibernate. PortletHibernateConfiguration"> ! <property name="dataSource" ref="liferayDataSource" /> </bean> <bean id="liferaySessionFactory" class="com.liferay.portal.dao.orm.hibernate. SessionFactoryImpl"> ! <property name="sessionFactoryClassLoader" ref="portletClassLoader" /> ! <property name="sessionFactoryImplementor" ref="liferayHibernateSessionFactory" /> </bean> <bean id="liferayTransactionManager" class="com.liferay.portal.kernel.util.InfrastructureUtil" factory-method="getTransactionManager" />
  61. 61. Service Builder Preparado por Jesús Salinas Revelles Ficheros de configuración ‣ infraestructure-spring.xml: ‣ Se define la fuente de datos para Liferay: <bean id="liferayDataSource" class="org.springframework.jdbc.datasource. LazyConnectionDataSourceProxy"> <property name="targetDataSource"> <bean class="com.liferay.portal.kernel.util. InfrastructureUtil" factory-method="getDataSource" /> </property> </bean>
  62. 62. Service Builder Preparado por Jesús Salinas Revelles Ficheros de configuración ‣ portlet-spring.xml: ‣ Las inyecciones de dependencias necesarias para el correcto funcionamiento de los servicios se define aquí: <bean id="es.ematiz.service.FacturaLocalService" class="es.ematiz.service.impl.FacturaLocalServiceImpl" /> <bean id="es.ematiz.service.FacturaLocalServiceUtil" class="es.ematiz.service.FacturaLocalServiceUtil"> ! <property name="service" ref="es.ematiz.service.FacturaLocalService" /> </bean> <bean id="es.ematiz.service.persistence.FacturaPersistence" class="es.ematiz.service.persistence.FacturaPersistenceImpl" parent="basePersistence" />
  63. 63. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Desde un punto de vista teórico una asociación queda definida por la direccionalidad que indica cómo se navega en dicha asociación y la cardinalidad que indica el número de objetos de cada extremo que intervienen en la relación. ‣ Según la direccionalidad tenemos dos tipos: ‣ Unidireccional: la asociación sólo es navegable en un sentido, por lo que desde uno de sus extremos no se podrá llegar a los objetos del otro extremo. ‣ Bidireccional: la asociación es navegable en ambos sentidos. Por lo que desde cualquiera de sus extremos se puede acceder a los objetos del otro extremo.
  64. 64. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Hibernate propone un modelo muy interesante que mediante ficheros de mapeo permite manejar asociaciones de todo tipo. ‣ Ejemplo: ... <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> ... </class> <class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses"> <key column="personId" not-null="true"/> <one-to-many class="Address"/> </set> </class>
  65. 65. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ El Service Builder de Liferay, en cambio, propone un modelo diferente. ‣ El concepto de asociación se va a ilustrar a partir de un ejemplo de Liferay: ‣ Las entidades User y Role: Role User
  66. 66. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ El fichero service.xml que define estas entidades se encuentra en portal- impl/src/com/portal:
  67. 67. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Entidad Role: <entity name="Role" local-service="true" remote- service="true"> <!-- PK fields --> <column name="roleId" type="long" primary="true" /> <!-- Audit fields --> <column name="companyId" type="long" /> <!-- Other fields --> <column name="classNameId" type="long" /> <column name="classPK" type="long" /> <column name="name" type="String" /> <column name="title" type="String" /> <column name="description" type="String" /> <column name="type" type="int" /> <column name="subtype" type="String" />
  68. 68. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Entidad Role: Se define la relación con la entidad User ... <!-- Relationships --> <column name="groups" type="Collection" entity="Group" mapping-table="Groups_Roles" /> <column name="permissions" type="Collection" entity="Permission" mapping- table="Roles_Permissions" /> <column name="users" type="Collection" entity="User" mapping-table="Users_Roles" /> ...
  69. 69. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ One to many: ‣ Se define mediante el elemento column. ‣ Los atributos entity y mapping-key se utilizan y el atributo mapping-table NO. ‣ Ejemplo: ‣ La columna especifica que habrá un método getter llamado getShoppingItemPrices() que devuelve una colección. Mapeará una columna llamada itemId en la tabla que mapea a la entidad ShoppingItemPrice. ... <column name="shoppingItemPrices" type="Collection" entity="ShoppingItemPrice" mapping-key="itemId" /> ...
  70. 70. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Many to many: ‣ Se define mediante el elemento column. ‣ Los atributos entity y mapping-table se utilizan y el atributo mapping-key NO. ‣ Ejemplo: ... <column name="roles" type="Collection" entity="Role" mapping-table="Groups_Roles" /> ...
  71. 71. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Clases de utilidad: ‣ RoleLocalServiceUtil. ‣ UserLocalServiceUtil. ‣ Fachada de Servicios: ‣ UserLocalService y UserLocalServiceImpl. ‣ RoleLocalService y RoleLocalServiceImpl. ‣ Servicios persistentes: ‣ UserPersistence y UserPersistenceImpl. ‣ RolePersistence y RolePersistenceImpl.
  72. 72. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Ejemplo 1. Método getUserRoles: ‣ La relación entre ambas entidades puede percibirse en el método getUserRoles de la clase RoleLocalServiceUtil. ‣ Se pasa como parámetro el identificador de un usuario y se devuelve la lista de roles asociados a dicho usuario: ‣ El método que implementa esta funcionalidad se llama getUserRoles que se encuentra definido en el servicio. public static java.util.List<com.liferay.portal.model.Role> getUserRoles( long userId) throws com.liferay.portal.SystemException { return getService().getUserRoles(userId); }
  73. 73. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Este método se encuentra en la clase RoleLocalServiceImpl: ‣ Se apoya en el servicio persistente de la Entidad User para llevar a cabo la operación. public List<Role> getUserRoles(long userId) throws SystemException { return userPersistence.getRoles(userId); }
  74. 74. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Ejemplo 2. Método addUserRoles: ‣ Se encuentra en la clase RoleLocalServiceUtil. ‣ Este método asocia un usuario a una lista de roles. ‣ Como es lógico, las entidades se crean primero y posteriormente se conectan. public static void addUserRoles(long userId, long[] roleIds) throws com.liferay.portal.SystemException { getService().addUserRoles(userId, roleIds); }
  75. 75. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Ejemplo 2. Método addUserRoles: ‣ El método addUserRoles de la implementación del servicio se apoya en el servicio de Usuarios: ... public void addUserRoles(long userId, long[] roleIds) throws SystemException { userPersistence.addRoles(userId, roleIds); userLocalService.reIndex(userId); PermissionCacheUtil.clearCache(); } ...
  76. 76. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Ejemplo 2. Método addUserRoles: ‣ La entidad persistente del usuario proporciona el acceso correcto: ... public void addRoles(long pk, long[] rolePKs) throws SystemException { try { for (long rolePK : rolePKs) { addRole.add(pk, rolePK); } } catch (Exception e) { throw processException(e); } finally { FinderCacheUtil.clearCache("Users_Roles"); } } ...
  77. 77. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Ejemplo 2. Método addUserRoles: ‣ El objeto addRole es el elemento que realmente define la asociación entre ambas entidades. ‣ En el código de la clase se puede encontrar: ‣ La clase AddRole es una clase interna dentro de UserPersistenceImpl: ... protected class AddRole { ... addRole = new AddRole(this);
  78. 78. Service Builder Preparado por Jesús Salinas Revelles Asociaciones ‣ Ejemplo 2. Método addUserRoles: ‣ La clase interna AddRole tiene un método que asocia Role y Usuario: _sqlUpdate = SqlUpdateFactoryUtil.getSqlUpdate( getDataSource(), "INSERT INTO Users_Roles (userId, roleId) VALUES (?, ?)", new int[] { Types.BIGINT, Types.BIGINT }); protected void add(long userId, long roleId) throws SystemException { ... _sqlUpdate.update(new Object[] {new Long(userId), new Long (roleId)}); ...

×