Problema: vi chiedono di scrivere dei portlet per Liferay che leggono dei dati da un database esistente.
Soluzione "sporca": vi fate il vostro accesso ai dati e integrate il database esterno alla vostra portlet.
Soluzione"pulita": istruite il service builder adeguatamente e gli fate wrappare le tabelle dell'altro database, così avrete la stessa modalità d'accesso ai dati che avete quando andate sul database di Liferay e chi usa la vostra API non dovrà impazzire per comprenderla!:)
Vediamo un po' nel dettaglio questa soluzione!
Per prima cosa, istruiamo il Service Builder ad utilizzare il database esterno.
Prima un concetto chiave: su Liferay è possibile specificare per singola entity il datasource da utilizzare. Quindi il grosso del lavoro viene fatto dal framework del Service Builder -e dalle classi che saranno generate-; ora vediamo nel dettaglio un po' di codice.
Creiamo una entity che mappi una tabella esistente nel database target -esterno al database di Liferay-. Di seguito evidenzio i pezzi "importanti", quelli che permettono la magia.. :)
<entity name="TimeSheet" table="public.time_sheet"
local-service="true" remote-service="false"
data-source="intranetDataSource"
session-factory="intranetSessionFactory"
tx-manager="intranetTxManager">
...
</entity>
Come vedete, nel nostro file service.xml
, specifichiamo quale dev'essere il data-source
da utilizzare, quale il session-factory
e quale transaction manager
.
È ovvio che chi conosce bene Spring ha già chiaro di che cosa stiamo parlando.
Per gli altri, invece, il concetto è molto semplice: Liferay farà in modo che, per l'entità in questione, siano utilizzate connessioni, persistenza e transazioni su un db diverso e non quelle "dirette" che creerebbe verso il suo database.
Una volta creato il nostro file service.xml
dobbiamo buildarlo, in modo da farci generare gli oggetti che ci serviranno dopo.
Per farlo, dal build file del vostro portlet, eseguite il task build-service
.
Dopo che il Service Builder avrà generato le classi e gli oggetti a partire dal nostro file, dovremo istruire il framework Spring a creare ed utilizzare gli oggetti che, per ora, abbiamo solo referenziato nel service.xml
.
Per farlo, nella META-INF del nostro source folder (quindi docroot/WEB-INF/src/META-INF/), creiamo un file chiamato ext-spring.xml
Dentro a questo file, mettiamoci questo codice:
<?xml version="1.0"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- Qui specifichiamo il JNDI name da utilizzare
per la nostra connessione. La risorsa JNDI va messa all'interno
del file <liferay_dir>/<tomcat_dir>/conf/context.xml -->
<bean id="intranetDataSourceTarget"
class="com.liferay.portal.spring.jndi.JndiObjectFactoryBean"
lazy-init="true">
<property name="jndiName">
<value>jdbc/intranetDB</value>
</property>
</bean>
<!-- Qui creiamo il nostro data source collegato alla connessione
JNDI che abbiamo referenziato poco sopra. -->
<bean id="intranetDataSource"
class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource">
<ref bean="intranetDataSourceTarget" />
</property>
</bean>
<bean id="intranetHibernateSessionFactory"
class="com.liferay.portal.spring.hibernate.PortletHibernateConfiguration">
<property name="dataSource">
<ref bean="intranetDataSource" />
</property>
</bean>
<!-- Qui specifichiamo la nostra SessionFactory -->
<bean id="intranetSessionFactory"
class="com.liferay.portal.dao.orm.hibernate.SessionFactoryImpl">
<property name="sessionFactoryImplementor">
<ref bean="intranetHibernateSessionFactory" />
</property>
</bean>
<!-- E qui creiamo il TransactionManager -->
<bean id="intranetTxManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="dataSource">
<ref bean="intranetDataSource" />
</property>
<property name="sessionFactory">
<ref bean="intranetHibernateSessionFactory" />
</property>
</bean>
</beans>
Una volta che abbiamo creato questo file il gioco è fatto!
Ci basterà deployare il nostro portlet e usare la nostra APILiferay per accedere anche alle tabelle del secondo database!
Spero d'esservi stato d'aiuto!
Alla prossima!:)