2. Service Builder
Preparado por Jesús Salinas Revelles
Índice de contenidos
‣ Introducción.
‣ Fichero service.xml.
‣ Ejercicio.
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. 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. 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. 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. 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. 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*)>
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. 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" />
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. 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. 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. 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. 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.
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. 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. 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. 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. 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. 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>
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. 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. 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. 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. Service Builder
Preparado por Jesús Salinas Revelles
Ejercicio
‣ Introducción.
‣ Fichero service.xml.
‣ Generación del servicio.
‣ Código generado.
‣ Asociaciones.
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. 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. 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
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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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>
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. 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. 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. 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. 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. 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. 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:
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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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)});
...