Upload
kino2k
View
413
Download
0
Tags:
Embed Size (px)
Citation preview
MessageBus, Cluster communication and caching on B2B
Mariuzzo MauroLiferay Architect, SMC Treviso srl
Liferay Symposium Italy, Rome 2014- 2 -
Requisito
Creare una soluzione B2B per consentire a Partner e Rivenditori di:● vedere il catalogo dei prodotti● effettuare ordini e vederne lo stato di
avanzamento● vedere i propri documenti fiscali (ordini,
fatture)
Liferay Symposium Italy, Rome 2014- 4 -
Prodotti coinvolti - ERP
Fonte aziendale autoritativa per:● Anagrafiche Cliente, Anagrafiche Prodotto, ...● Lavorazioni● Ordini● Fatture● Listini Particolari Cliente e metodi di calcolo del prezzo● Contratti e Promozioni● ....
ERP
Liferay Symposium Italy, Rome 2014- 5 -
Soluzione CRM open source realizzata in Java secondo un paradigma model-driven.
Gestisce le problematiche CRM, SFA, MA.
Implementa diversi meccanismi di integrazione: CalDAV, CardDAV, IMAP, LDAP, ...
Prodotti coinvolti - CRM
OpenCRX
Liferay Symposium Italy, Rome 2014- 6 -
Replica i dati ERP e li arricchisce per i contesti “non fiscali”:● Customer Satisfaction (Help-Desk, TTS, ....)● Sales Force Automation● Marketing Automation● ....
Prodotti coinvolti - CRM
OpenCRX
Liferay Symposium Italy, Rome 2014- 7 -
● Fornisce all'utente una User Interface semplificata che migliora la sua User eXperience– Rispetto a ERP e CRM
● Unico punto di accesso applicativo per gli utenti esterni● Moltiplicatore di accessi
– I CRM non sono pensati per centinaia di utenti contemporanei
● Arricchisce i contenuti per una fruizione “responsiva” e cross-browser
● ....
Prodotti coinvolti - Portale
Liferay-Portal
Liferay Symposium Italy, Rome 2014- 17 -
Problematiche – Integrazione Liferay-CRM
OpenCRX dispone di un ricco set di API REST per accedere alle informazioni ed alle funzionalità
La “soluzione B2B” è composta da diversi plugins (file .war separati)
Come evitare di duplicare il codice di integrazione?
Liferay Symposium Italy, Rome 2014- 18 -
Problematiche – Integrazione Liferay-CRM – plugin shared
Per i servizi SOAP posso generare una “client library” partendo dal wsdl.
Per i servizi REST me la devo costruire.
Con il Liferay Plugins SDK posso realizzare la “client library” come plugin “shared”:● un particolare tipo di plugin che produce “.jar”
invece di “.war”● pensato per codice senza stato (stateless)
Liferay Symposium Italy, Rome 2014- 19 -
Problematiche – Integrazione Liferay–CRM – plugin shared
Esempio: knowledge-base-portlet, knowledge-base-shared
Il file build.xml
<?xml version="1.0"?><!DOCTYPE project>
<project name="knowledge-base-shared" basedir="." default="deploy"><property name="plugin.version" value="1" />
<import file="../build-common-shared.xml" /></project>
Liferay Symposium Italy, Rome 2014- 20 -
Problematiche – Integrazione Liferay–CRM – plugin shared
Il file “build.xml” nel portlet che vuole usare lo shared
<?xml version="1.0"?><!DOCTYPE project>
<project name="knowledge-base-portlet" basedir="." default="deploy"><import file="../build-common-portlet.xml" />
<property name="import.shared" value="knowledge-base-shared" /></project>
Liferay Symposium Italy, Rome 2014- 21 -
Problematiche risolte
✔ Gestire il codice di integrazione con OpenCRX in una libreria riusabile da più plugins
Liferay Symposium Italy, Rome 2014- 22 -
Problematiche – Evitare sovraccarico CRM
Come evitare che tutti i plugin parlino direttamente con il CRM sovraccaricandolo?
Il plugin “shared” non mi aiuta.
Posso usare i service con il required-context!
Liferay Symposium Italy, Rome 2014- 23 -
Liferay Plugins SDK - Required context
● Anche un plugin può dichiarare dei servizi (file service.xml)
● Il servizio si basa su 3 elementi:– L'interfaccia (es: KBArticleService)– La classe di implementazione (es: KBArticleServiceImpl)– La classe singleton (es: KBArticleServiceUtil)
● Interfaccie e singleton finiscono in un file “xxxx-service.jar”
● L'implementazione è caricata in modalità “lazy” tramite Spring
Liferay Symposium Italy, Rome 2014- 24 -
Liferay Plugins SDK - Required context
● Un plugin può dichiarare che vuole usare i servizi usati da un altro plugin– Nel file “liferay-plugin-package.properties”– Proprietà “required-depoyment-contexts”
● A compile-time il file “xxxx-service.jar” viene copiato in “docroot/WEB-INF/lib” e finisce nel .war
● Nella fase di deploy il plugin non viene reso operativo in assenza del contesto richiesto
● Spring crea un tunnel tra i due plugin (i due contesti)● L'infrastruttura Liferay permette di trasferire oggetti
complessi senza ClassCastExcpetion
Liferay Symposium Italy, Rome 2014- 25 -
Liferay Plugins SDK - Required context
● I servizi sono dichiarati nel file “service.xml”● Possono gestire entità reali (tabelle a
database) <entity name="FavoriteSite" local-service="true" remote-service="false"> <column name="favoriteSiteId" type="long" primary="true" /> <column name="groupId" type="long" /> <column name="companyId" type="long" />
● Oppure entità “di servizio” <entity name="SocialOffice" local-service="false" remote-service="true"> <!-- References --> <reference package-path="com.liferay.portal" entity="Group" /> </entity>
Liferay Symposium Italy, Rome 2014- 26 -
Liferay Plugins SDK - Required context
● Dichiaro delle entità di servizio per gli elementi CRM (es: CRMProductService*)
● Sfrutto il required-deployment-contexts per fornire i servizi agli altri plugins
Liferay Symposium Italy, Rome 2014- 27 -
Problematiche risolte
✔ Gestire il codice di integrazione con OpenCRX in una libreria riusabile da più plugins
✔ Concentrare l'accesso al CRM in un unico plugin
Liferay Symposium Italy, Rome 2014- 28 -
Liferay Plugins SDK - Required context
I metodi dei services devono ritornare i dati del CRM
Come evitare che Bean complessi mi sollevino una ClassCastException?
Liferay Symposium Italy, Rome 2014- 29 -
Liferay Plugins SDK - Required context
● I servizi devono ritornare oggetti semplici (int, long, String)– gli oggetti complessi sono JSON
● Ho bisogno di un ulteriore strato che:– Dichiari i POJO delle entità CRM (es: CRMProduct)– Si preoccupi di convertire gli oggetti JSON in POJO
(es: CRMProductUtil)
Liferay Symposium Italy, Rome 2014- 30 -
Problematiche risolte
✔ Gestire il codice di integrazione con OpenCRX in una libreria riusabile da più plugins
✔ Concentrare l'accesso al CRM in un unico plugin
✔ Gestire gli elementi CRM come oggetti complessi
Liferay Symposium Italy, Rome 2014- 31 -
Problematica – Sovraccarico CRM
Come evitare di sovraccaricare il CRM con troppe richieste contemporanee?
Liferay Symposium Italy, Rome 2014- 32 -
Problematica – Sovraccarico CRM
Come evitare di sovraccaricare il CRM con troppe richieste contemporanee?
Creando qualcosa di simile ad un connection-pool.
Uso il MessageBus per creare delle code di elaborazione.
Liferay Symposium Italy, Rome 2014- 33 -
MessageBus
● E' un framework sviluppato da Liferay per gestire code di messaggi.
● E' stato realizzato per essere leggero e flessibile.
● Non si appoggia ad alcun framework esterno● Composto da tre elementi principali
– Il Messaggio– La Destinazione (dove viene recapitato il
messaggio)– Il Listener (l'attore che elabora il Messaggio)
Liferay Symposium Italy, Rome 2014- 34 -
MessageBus
Le Destinazioni sono● Asincrone: utilizzano più worker per elaborare i
messaggi– Seriale: dispacciano il Messaggio ad un Listener alla volta– Parallela: dispacciano il Messaggio su più Listener
contemporaneamente
● Sincrone: utilizzano un singolo worker
com....kernel.messaging.SerialDestination
com....kernel.messaging.ParallelDestination
com....kernel.messaging.SynchronousDestination
Liferay Symposium Italy, Rome 2014- 35 -
MessageBus
L'invio dei messaggi può essere:● Sincrono
– il processo sender rimane appeso in attesa di una risposta– finché non arriva o per un periodo di tempo certo (timeout)
● Asincrono– il processo sender continua– posso indicare un callback su cui ricevere la risposta– Posso “inviare e dimenticare”
MessageBusUtil.sendMessage(destination, payload)
MessageBusUtil.SendSyncronousMessage(destination, payload)
Liferay Symposium Italy, Rome 2014- 36 -
Problematica – Sovraccarico CRM
Il plugin “crm-integration-web”● Implementa il dialogo con il CRM● Tramite il ServiceBuilder gestisce le entità CRM come entità “di
servizio”– Sotto forma di oggetti JSON
● Dichiara delle MessageBus Destination per creare delle code di accesso ai servizi generati dal ServiceBuilder
Il plugin “crm-integration-shared”● Dichiara / Implementa i Bean delle entità CRM● Implementa le classi per interagire con il MessageBus
– Inviare i messaggi– Trasformare le risposte JSON (Payload) in POJO
Liferay Symposium Italy, Rome 2014- 37 -
Problematica – Sovraccarico CRM
Plugin ONE
crm-integration-shared
Plugin TWO
crm-integration-shared
crm-integration-web
Destination
Destination
Service
Destination
Listener
Listener
Listener
CRM
Liferay Symposium Italy, Rome 2014- 38 -
Caching strato servizi
Posso fare di più?
Cache!
Per le entità reali il ServiceBuilder genera la classe xxxPersistenceImpl che sfrutta la MultiVMPoolUtil per gestire la cache dei Model e dei Finder
Liferay Symposium Italy, Rome 2014- 39 -
Caching strato servizi
Per le entità “di servizio” questa classe non c'è.
Ma la posso creare.
Devo creare sia l'interfaccia nella parte service
public interface CrmProductPersistence {
public int countByC_P_D_C_B_TT(
long userId, String customerId, String productNumber,
String description, String categoryId, String brandId,
CrmProductSearchTerms terms)
throws CrmComunicationException, CrmResponseException;
Liferay Symposium Italy, Rome 2014- 40 -
Caching strato servizi
Ed ovviamente la sua implementazione
public class CrmProductPersistenceImpl extends CrmBasePersistenceImpl implements CrmProductPersistence {.... public List<String> findByDescription( long userId, String customerId, String productNumber, String description, String categoryId, String brandId, CrmProductSearchTerms terms, Locale locale, int start, int count) throws CrmComunicationException, CrmResponseException {
Object[] finderArgs = new Object[] { productNumber, description, categoryId, brandId, terms, start, count, locale};
@SuppressWarnings("unchecked") List<String> list = (List<String>)FinderCacheUtil.getResult( FINDER_PATH_FIND_BY_DESCRIPTION, finderArgs, null);
if (list == null) { ... list = crmItemsValuesFromResponse(productsResponse);
if ((list != null) && !list.isEmpty()) { FinderCacheUtil.putResult(FINDER_PATH_FIND_BY_DESCRIPTION, finderArgs, list); } }
return list; }
Liferay Symposium Italy, Rome 2014- 41 -
Caching strato servizi
La configurazione della cache si trova in “portal-impl/src/ehcache”
Liferay Symposium Italy, Rome 2014- 42 -
Problematiche risolte
✔ Gestire il codice di integrazione con OpenCRX in una libreria riusabile da più plugins
✔ Concentrare l'accesso al CRM in un unico plugin
✔ Gestire gli elementi CRM come oggetti complessi
✔ Ridurre sovraccarico CRM (code + cache)
Liferay Symposium Italy, Rome 2014- 43 -
Problematica - cluster
● E se ho una installazione Liferay in Cluster?● La cache di Liferay è di tipo “Invalidante”
– Se un dato non è presente in cache, oppure è scaduto o invalidato
● lo leggo e lo metto nella mia cache
– Se modifico un dato● Lo salvo sul DB● Lo aggiorno nella mia cache● Informo gli altri nodi di invalidarlo nella loro cache
– Se cancello un dato● Lo cancello dal DB● Lo invalido nalla mia cache● Informo gli altri nodi di invalidarlo nella loro cache
Liferay Symposium Italy, Rome 2014- 44 -
Problematica - cluster
Possibilità UNO: dichiaro una specifica cache di replica nel MultiVMPoolUtil
<cache eternal="false" maxElementsInMemory="100000" name="it.smc.....CRMProduct" overflowToDisk="false" timeToIdleSeconds="600"> <cacheEventListenerFactory class="com....ehcache.LiferayCacheEventListenerFactory" properties="replicatePuts=false,replicateUpdatesViaCopy=false" propertySeparator="," /> <bootstrapCacheLoaderFactory class="com....ehcache.LiferayBootstrapCacheLoaderFactory" /></cache>
"replicatePuts=true,replicatePutsViaCopy=true,replicateUpdatesViaCopy=true"
Liferay Symposium Italy, Rome 2014- 45 -
Problematica - cluster
Possibilità DUE: Uso la SingleVMPoolUtil e decido io come propagare la cache tra i nodi.
Per propagarla utilizzo il framework “ClusterExecutor”
Liferay Symposium Italy, Rome 2014- 46 -
Problematica - cluster
com.liferay.portal.kernel.cluster.ClusterExecutorUtil
public List<ClusterNode> getClusterNodes(); public ClusterNode getLocalClusterNode() throws SystemException; public Address getLocalClusterNodeAddress(); public void initialize(); public boolean isClusterNodeAlive(Address address); public boolean isClusterNodeAlive(String clusterNodeId); public boolean isEnabled();
public FutureClusterResponses execute( ClusterRequest clusterRequest) throws SystemException;
Liferay Symposium Italy, Rome 2014- 47 -
Problematica - cluster
Il metodo Execute mi permette di eseguire un metodo di una classe negli altri nodi● Identifico il metodo da chiamareMethodKey myMethodKey = new MethodKey( MethodClass.class, "methodName", FirstSerializableArguement.class ...);
● Creo l'handler del metodoMethodHandler myMethodHandler = new MethodHandler( myMethodKey, myFirstArguement....);
● Lo invoco– Metto true su skipLocal per saltare me stesso
ClusterRequest clusterRequest = ClusterRequest.createMulticastRequest( methodHandler, true);ClusterExecutorUtil.execute(clusterRequest);
Liferay Symposium Italy, Rome 2014- 48 -
Problematiche risolte
✔ Gestire il codice di integrazione con OpenCRX in una libreria riusabile da più plugins
✔ Concentrare l'accesso al CRM in un unico plugin
✔ Gestire gli elementi CRM come oggetti complessi
✔ Ridurre sovraccarico CRM (code + cache)✔ Gestire installazione in Cluster