Liferay 6.1 Service Builder
-
Upload
ematiz-tecnologia-sl -
Category
Technology
-
view
1.280 -
download
8
description
Transcript of Liferay 6.1 Service Builder
Liferay 6.1Service Builder
Service Builder
Preparado por Jesús Salinas Revelles
Índice de contenidos
‣ Introducción.
‣ Fichero service.xml.
‣ Ejercicio.
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.
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>
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>
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?)>
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>
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*)>
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>
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.
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" />
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>
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" />
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.
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" />
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.
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.
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>
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>
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>
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>
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)>
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>
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>
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>
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+)>
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>
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>
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>
Service Builder
Preparado por Jesús Salinas Revelles
Ejercicio
‣ Introducción.
‣ Fichero service.xml.
‣ Generación del servicio.
‣ Código generado.
‣ Asociaciones.
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.
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)
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
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" />...
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>
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:
Service Builder
Preparado por Jesús Salinas Revelles
Código generado
‣ Introducción.
‣ Modelo.
‣ Servicio de persistencia.
‣ Servicio de negocio.
‣ Ficheros de configuración.
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.
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:
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.
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.
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.
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.
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?
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.
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:
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.
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.
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.
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.
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:
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.
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.
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.
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.
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.
‣ ...
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.ServiceMonitorAdvice" factory-method="getInstance"><property name="monitoringDestinationName" value="liferay/monitoring" /><property name="nextMethodInterceptor" ref="asyncAdvice" />
</bean>
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>
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>
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" />
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>
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" />
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.
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>
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
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:
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" />
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" />
...
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" />...
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" />...
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.
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);
}
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);}
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);}
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();}
...
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");}
}...
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);
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)});...