2. 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)
3. 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
4. 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
5. 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
6. 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
16. 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?
17. 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)
20. Liferay Symposium Italy, Rome 2014
- 21 -
Problematiche risolte
✔Gestire il codice di integrazione con OpenCRX in una libreria riusabile da più plugins
21. 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!
22. 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
23. 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
25. 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
26. 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
27. 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?
28. 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)
29. 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
30. Liferay Symposium Italy, Rome 2014
- 31 -
Problematica – Sovraccarico CRM
Come evitare di sovraccaricare il CRM con troppe richieste contemporanee?
31. 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.
32. 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)
33. 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
34. 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)
35. 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
36. 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
37. 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
38. 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;
39. 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;
}
40. Liferay Symposium Italy, Rome 2014
- 41 -
Caching strato servizi
La configurazione della cache si trova in “portal- impl/src/ehcache”
41. 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)
42. 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
43. 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"
44. 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”
45. 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;
46. 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 chiamare
MethodKey myMethodKey = new MethodKey(
MethodClass.class, "methodName", FirstSerializableArguement.class ...);
●Creo l'handler del metodo
MethodHandler myMethodHandler = new MethodHandler(
myMethodKey, myFirstArguement....);
●Lo invoco
–Metto true su skipLocal per saltare me stesso
ClusterRequest clusterRequest = ClusterRequest.createMulticastRequest(
methodHandler, true);
ClusterExecutorUtil.execute(clusterRequest);
47. 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
48. Liferay Symposium Italy, Rome 2014
- 49 -
MessageBus, Cluster communication and caching on B2B
Mariuzzo Mauro
Liferay Architect, SMC Treviso srl