Sviluppare su OSGi con Camel e GWT

Post on 13-May-2015

367 views 1 download

description

Slides per l'incontro "Aperitivo tecnologico" del GDG Firenze http://www.gdg-firenze.info/ del 16 dicembre 2013. Argomenti: Introduzione ad OSGi e ServiceMix Introduzione ad Apache Camel Utilizzare GWT su ServiceMix SensorMix: Architettura di esempio Cool Facts: perchè ci piace questa architettura

Transcript of Sviluppare su OSGi con Camel e GWT

Sviluppare su OSGIcon Camel e GWTAperitivo tecnologico del GDG Firenzehttp://www.gdg-firenze.info/

Cristiano Costantini - Giuseppe Gerla - Michele Ficarra - Sergio Ciampi - Stefano Cigheri

Chi Siamo

Cristiano

Giuseppe

Michele

Sergio

Stefano

Aperitivo Osgi, Camel e GWT 3/108

Sommario

Aperitivo Osgi, Camel e GWT

Introduzione ad OSGi e ServiceMix

Introduzione ad Apache Camel

Utilizzare GWT su ServiceMix

SensorMix: Architettura di esempio

Cool Facts: perchè ci piace questa architettura

·

·

·

·

·

4/108

Introduzione a OSGi e ServiceMixOvvero un approccio modulare per backend SOA

OSGi: questo sconosciuto

Il nucleo delle specifiche definisce la gestione del modello del ciclo di vita delsoftware, i moduli (chiamati bundles), un service registry e un ambiente diesecuzione.

Aperitivo Osgi, Camel e GWT

OSGi: Open Service Gateway initiative

OSGi Alliance: organizzazione fondata nel 1999 da Ericsson, IBM, Oracle e altri

OSGi Framework: è un layer di modularità per la piattaforma Java

·

·

·

6/108

Una Metafora:Pensate ai servizi di Windows o demoni Unix ma completamente Java

Aperitivo Osgi, Camel e GWT 7/108

Perchè nasce OSGi

OSGi nasce con lo scopo di creare sistemi embedded per mercati residenziali,automotive e M2M. In questi contesti è spesso necessario comunicare con idevices attraverso protocolli differenti.

Il fine, quindi, era quello di fornire un modello di programmazione capace direalizzare servizi end-to-end creando uno strato di astrazione che unificasse idifferenti protocolli.

Aperitivo Osgi, Camel e GWT 8/108

Perchè si espande

We’ve all used development platforms in the past,such as Java Enterprise Edition (JEE), and eventhough there have been great advances in thisindustry, we’re still building large complex systems,which are hard to develop, maintain, and extend.Alexandre de Castro AlvesOSGi in Depth - Manning, pagina 1, riga 1

Aperitivo Osgi, Camel e GWT

9/108

Implementazioni OSGi

Esistono diverse implementazioni di OSGi. Quelle più complete sono:

Aperitivo Osgi, Camel e GWT

Apache Felix

Eclipse Equinox

Knopflerfish

·

·

·

10/108

Service

Lifecycle

Module

Come è fatto un framework OSGi

Il framework può essere rappresentato con trelayer:

Aperitivo Osgi, Camel e GWT

Il module layer definisce il concetto di moduloOSGi: il Bundle

Il lifecycle layer definisce come i bundles sonodinamicamente installati e gestiti nelframework OSGi

Il service layer supporta e promuove unmodello di sviluppo di applicazioni flessibileche incapsula concetti resi di uso comune dalservice-oriented programming

·

·

·

11/108

Il “Module layer”

Il cuore del module layer è il Bundle.

Un Bundle è un JAR che contiene metadati extra(manifest).

A differenza dei JAR il bundle ha:

Grazie al manifest è possibile estendere lavisibilità del classpath dichiarando esplicitamentele proprie dipendenze

Aperitivo Osgi, Camel e GWT

un classpath “ristretto” al solo bundle

un manifest più ricco

·

·

12/108

Il manifest OSGi

Nel manifest viene specificato anche:

Esempi:

Aperitivo Osgi, Camel e GWT

L’identificazione e la descrizione

Il classloading

L’attivazione

·

·

·

13/108

Il manifest OSGiManifest di un semplice JAR compilato con maven

Aperitivo Osgi, Camel e GWT

Manifest-Version: 1.0Build-Jdk: 1.7.0_40Built-By: gdg-firenzeCreated-By: Apache Maven

MANIFEST.MF

14/108

Il manifest OSGiManifest di un Bundle

Aperitivo Osgi, Camel e GWT

Manifest-Version: 1.0Bnd-LastModified: 1386750447262Build-Jdk: 1.7.0_40Built-By: gdg-firenzeBundle-ManifestVersion: 2Bundle-Name: GDG Firenze :: Sensormix :: Example BundleBundle-SymbolicName: example-bundleBundle-Vendor: GDG Firenze :: Sensormix TeamBundle-Version: 1.0.0.SNAPSHOTBundle-Activator: com.google.developers.gdgfirenze.dataservice.ActivatorCreated-By: Apache Maven Bundle PluginExport-Package: com.google.developers.gdgfirenze.model;version="1.0.0.SNAPSHOT", com.google.developers.gdgfirenze.osgi;version="1.0.0.SNAPSHOT", com.google.developers.gdgfirenze.service;version="1.0.0.SNAPSHOT"Import-Package: javax.jws,javax.jws.soap,javax.xml.bind.annotation,javax.xml.wsTool: Bnd-1.50.0

MANIFEST.MF

15/108

Il “Lifecycle layer”Il lifecycle layer ha due scopi:

Esternamente gestisce il ciclo di vita del bundle.

Aperitivo Osgi, Camel e GWT 16/108

Il “Lifecycle layer”Il lifecycle layer ha due scopi:

Internamente definisce Bundle Activator

= public static void main(String[] args)

Aperitivo Osgi, Camel e GWT 17/108

Il “Service layer”

L’OSGi service layer promuove l’approccio basato su interface ed in particolarela separazione tra interfacce e implementazioni.

I Servizi OSGi sono interfacce Java che rappresentano un contratto tra il serviceprovider e i service clients.

Aperitivo Osgi, Camel e GWT 18/108

OSGi: la Service Platform

L’OSGi definisce un set minimo di servizi peragevolare lo sviluppo di applicazioni modulari

Aperitivo Osgi, Camel e GWT

Cofiguration Admin (hot configuration)

Event Admin

Console Admin

Log Service

Blueprint component framework

·

·

·

·

·

19/108

Karaf: un OSGi container

Karaf è un OSGi container in cui sono deployati bundles (e servizi) aggiuntivi perfornire ulteriori funzionalità tra cui Hot deployment, Dynamic configuration,Logging System, Extensible Shell console (SSH)

Karaf è un chiaro esempio di architettura basata su OSGi

Aperitivo Osgi, Camel e GWT 20/108

ServiceMix: un ESB su OSGi

ServiceMix estende ulteriormente Karaf con funzionalità perimplementare un Enterprise Service Bus.

Le principali funzionalità di ServiceMix sono:

Altre funzionalità offerte da ServiceMix:

Aperitivo Osgi, Camel e GWT

reliable messaging with Apache ActiveMQ

messaging, routing and Enterprise Integration Patterns withApache Camel

WS-\* and RESTful web services with Apache CXF

OSGi-based server runtime powered by Apache Karaf

·

·

·

·

loosely coupled integration between all the other components with Apache ServiceMix NMR includingrich Event, Messaging and Audit API

complete WS-BPEL engine with Apache ODE

·

·

21/108

OSGi e SpringUso di Spring dentro a Karaf/ServiceMix

Lo springframework fornisce molte features interessanti (dependency injection, ORM, AOP,...)

Lo Spring Deployer riconosce i file Spring all'interno del folder META-INF/spring di un Jar, e ne istanzia ibean che vi sono definiti, senza necessità di utilizzare le API OSGi

Aperitivo Osgi, Camel e GWT

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

<bean id="consumer" class="com.myapplication.HelloWorldConsumer" destroy-method="osgiDestroy" init-method="osgiInit"/> </beans>

SPRING

22/108

OSGi e SpringSpring DM

Spring DM permette di utilizzare servizi OSGi da Spring in modo trasparente.

Aperitivo Osgi, Camel e GWT

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:util="http://www.springframework.org/schema/util" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">

<osgi:service ref="eventService" interface="com.myapplication.HelloWorldService" />

</beans>

SPRING DM

23/108

Introduzione ad Apache CamelOvvero un modo agile per integrare sistemi eterogenei

“Integrare”

Cosa si intende quando parliamo di integrazione?

Trovare una soluzione al seguente problema:

Come posso far funzionare insieme molteplici

applicazioni attraverso lo scambio di

informazioni?

Aperitivo Osgi, Camel e GWT

25/108

Enterprise Integration Patterns

Gli Enterprise Integration Patters offrono soluzioni per affrontare il precedenteproblema.

Cosa sono gli EIP?

Aperitivo Osgi, Camel e GWT 26/108

Un libro!

Gregor Hohpe and Bobby WoolfAddison-Wesley 2003

EIP Importanti

Aperitivo Osgi, Camel e GWT

Message Channel:How does one application communicate with another using messaging?

Message:How can two applications connected by a message channel exchange a piece of information?

Message Router:How can you decouple individual processing steps so that messages can be passed to different filters depending on a set of conditions?

Message Translator:How can systems using different data formats communicate with each other using messaging?

Message Endpoint:How does an application connect to a messaging channel to send and receive messages?

Dead Letter Channel:What will the messaging system do with a message it cannot deliver?

Message Bus:What is an architecture that enables separate applications to work together, but in a decoupled fashion such that applications can be easily added or removed without affectingthe others?

Command Message:How can messaging be used to invoke a procedure in another application?

Document Message:How can messaging be used to transfer data between applications?

Event Message:How can messaging be used to transmit events from one application to another?

Request-Reply:When an application sends a message, how can it get a response from the receiver?

Canonical Data Model:How can you minimize dependencies when integrating applications that use different data formats?

28/108

Come si può fare integrazione?

I principali metodi tramite cui avviene integrazione sono:

Gli EIP si focalizzano sulla integrazione via “messaging” e definiscono unanotazione per rappresentare le soluzioni di integrazione.

Aperitivo Osgi, Camel e GWT

Scambio di file

Database condiviso

Remote Procedure Invocation

Messaging

·

·

·

·

29/108

Notazione EIP

http://www.eaipatterns.com/toc.html

Soluzioni con EIP

Aperitivo Osgi, Camel e GWT 31/108

Soluzioni con EIP

Aperitivo Osgi, Camel e GWT 32/108

Soluzioni con EIP

Attenti a questa qui!

Aperitivo Osgi, Camel e GWT 33/108

Come implementare facilmente EIP?(domanda retorica)

Integrare è però difficile perchè esiste una vasta eterogeneità di protocolli,interfacce e formati.

Come si possono implementare su una piattaforma Java gli EnterpriseIntegration Pattern?

con

Apache CamelConcise Application Messaging Exchange Language

Aperitivo Osgi, Camel e GWT

“ ”

34/108

Apache Camel

Apache Camel è un framework di integrazione open-sorce versatile basato sugliEnterprise Integration Patterns del libro di Hohpe e Woolf.

Include un vasto insieme di componenti per funzionare con molti protocolli ditrasporto e formati dati e permette di definire regole di instradamento eintermediazione attraverso l’uso di domain-specific language.

...si presta talmente bene alla integrazione che ServiceMix, dalla versione 3 alla4, ha abbandonato la tecnologia JBI per adottare un nuovo approccio allaintegrazione basato su Camel e OSGi.

Aperitivo Osgi, Camel e GWT 35/108

Esempio: Content Based Router

from newOrder choice when isWidget to widget otherwise to gadget

Aperitivo Osgi, Camel e GWT 36/108

from newOrder choice when isWidget to widget otherwise to gadget

Content Based Router in Java DSL

Aperitivo Osgi, Camel e GWT

public class MyRoute extends RouteBuilder {

public void configure() throws Exception { from("activemq:queue:newOrder") .choice() .when(xpath("/order/product = 'widget'")) .to("activemq:queue:widget") .otherwise() .to("activemq:queue:gadget") .end(); }}

JAVA DSL

37/108

from newOrder choice when isWidget to widget otherwise to gadget

Content Based Router in Spring XML

Aperitivo Osgi, Camel e GWT

<camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="activemq:queue:newOrder"/> <choice> <when> <xpath>/order/product = 'widget'</xpath> <to uri="activemq:queue:widget"/> </when> <otherwise> <to uri="activemq:queue:gadget"/> </otherwise> </choice> </route></camelContext>

SPRING XML

38/108

Una applicazione Camel completa:

Aperitivo Osgi, Camel e GWT

import org.apache.camel.CamelContext;import org.apache.camel.builder.RouteBuilder;import org.apache.camel.impl.DefaultCamelContext;

public class CamelExample { public static void main(String[] args) throws Exception {

CamelContext context = new DefaultCamelContext();

context.addRoutes(new RouteBuilder() { public void configure() { from("jetty:http://0.0.0.0:8080/tellMeSomething") .transform(simple("You say ${in.body}")) .to("velocity:response.vm"); } });

context.start(); System.out.println("Press ENTER to exit"); System.in.read();

context.stop(); }}

SPRING XML

39/108

Camel in ServiceMix

Una volta attivati i bundle di Camel su Karaf-ServiceMix...

Aperitivo Osgi, Camel e GWT 40/108

Camel in ServiceMix

...è possibile definire rotte direttamente nei file Spring XML, oppure utilizzare dei RouteBuilder in Java peravviare delle applicazioni che usano Camel all’interno di ServiceMix.

Aperitivo Osgi, Camel e GWT

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans">

<camelContext xmlns="http://camel.apache.org/schema/spring"> <route> <from uri="jetty:http://0.0.0.0:8080/tellMeSomething"/> <convertBodyTo type="java.lang.String"/> <transform> <simple>You say ${in.body}</simple> </transform> <to uri="velocity:response.vm" /> </route>

</camelContext>

</beans>

SPRING XML

41/108

Camel: componenti162 componenti elencati su camel.apache.org/components.html

ActiveMQ ActiveMQBroker Activiti AHC AMQP APNS Atom Avro

AWS-CW AWS-DDB AWS-S3 AWS-SDB AWS-SES AWS-SNS AWS-SQS Bean

Bean Validation Browse Cache Class CMIS Cometd Context ControlBus

CouchDB Crypto CXF CXF Bean CXFRS DataFormat DataSet Db4o

Direct Direct-VM Disruptor DNS EJB ElasticSearch Esper EventAdmin

Exec Facebook File Flatpack FOP FreeMarker FTP FTPS

GAuth Geocoder GHttp GLogin GMail GTask GuavaEventBus Hazelcast

HBase HDFS Hibernate HL7 HTTP HTTP4 iBATIS IMAP

IMAPS Infinispan IRC JavaSpace JBI JCIFS jclouds JCR

JDBC Jetty JGroups JMS JMX JPA Jsch JT/400

Kestrel Krati Language LDAP Log Lucene MINA MINA2

Mock MongoDB MQTT MSV Mustache MVEL MyBatis Nagios

Netty Netty HTTP NMR OptaPlanner Pax-Logging POP3 POP3S Printer

Properties Quartz Quartz2 Quickfix RabbitMQ RCode Ref Restlet

Aperitivo Osgi, Camel e GWT 42/108

Camel: data format25+ data format elencati su camel.apache.org/data-format.html

Avro Base64 BeanIO Bindy Castor

Crypto CSV EDI Flatpack DataFormat GZip data format

HL7 DataFormat JAXB JiBX JSON PGP

Protobuf Serialization SOAP String XmlBeans

XmlJson XMLSecurity DataFormat XStream Zip DataFormat Zip File DataFormat

Aperitivo Osgi, Camel e GWT 43/108

Utilizzare GWT su ServiceMixOvvero un modo diverso per fare Web Application

SOA e SOFEA

Aperitivo Osgi, Camel e GWT

http://raibledesigns.com/

45/108

Framework Web per SOFEA

Aperitivo Osgi, Camel e GWT

http://raibledesigns.com/

46/108

ServiceMix e le Web Application

ServiceMix non nasce come Web Container ma permette lo stesso di deployaredelle web application.

In particolare risulta molto interessante qualora l’applicazione segua l’approccioprecedente.

Aperitivo Osgi, Camel e GWT 47/108

La nostra SOFEA

Aperitivo Osgi, Camel e GWT 48/108

Deploy di WAR sotto Karaf/ServiceMixWAR Deployer

Il WAR Deployer è un bundle che si occupa del deploy di Web Application suKaraf/ServiceMix

Cosa fa?

Ma basta?

Aperitivo Osgi, Camel e GWT

Cerca il file /WEB-INF/web.xml

Se lo trova, pubblica i file statici e le Servlet definite nel web.xml via HTTP

·

·

49/108

Deploy di WAR sotto Karaf/ServiceMixIl WAR ha bisogno di modifiche

É raccomandato fare uno Skinny war e usare dipendenze di Bundle (usando ilmaven-war-plugin e il maven-bundle-plugin)

Abbiamo Finito?

Aperitivo Osgi, Camel e GWT

Deve avere un file /META-INF/MANIFEST.MF nella root del JAR

Il MANIFEST.MF deve contenere:

·

·

L'header Web-ContextPath (l'applicazione verrà pubblicata al contextpath specificato da questo header)

L'header Bundle-ClassPath: .,WEB-INF/classes (informaKaraf/ServiceMix dove sono i bytecode)

-

-

50/108

Applicazioni GWT sotto Karaf/ServiceMix

Aperitivo Osgi, Camel e GWT

...anche gwt-servlet.jar ha bisogno di modifiche!

GWT non è predisposto per essere usato in OSGi.

Non è un bundle perchè al manifest della gwt-servlet.jar mancano gli header OSGi.

E allora?

51/108

Come usare GWT con OSGiQuattro strade:

Ci sono 4 strade per ottenere un gwt-servlet.jar OSGi compliant e poterlo deployare su Karaf/ServiceMix.

Aperitivo Osgi, Camel e GWT

Caso 1:

Compilarsi a mano il gwt-servlet.jar con gli header OSGi necessari

Caso 2:

Deployare il Jar non-OSGi configurandolo al momento della installazione su Karaf/ServiceMixpassando come parametro le informazioni che dovrebbero essere contenute nel MANIFEST.MF

Caso 3:

Aspettare che il ServiceMix Team rilasci il Bundle per GWT-Servlet con gli header OSGi per laversione 2.6.0

Caso 4:

Sperare che il GWT Project Team accetti la patch, che abbiamo proposto, nella versione GWT2.6.0 o successive.

52/108

Come usare GWT con OSGiChe cosa significa?

Aperitivo Osgi, Camel e GWT

Caso 1:git fetch https://gwt.googlesource.com/gwt refs/changes/51/5351/7git checkout FETCH_HEADant distinstall -s mvn:com.google.gwt/gwt-servlet/2.6.0

Caso 2:install -s wrap:mvn:com.google.gwt/gwt-servlet/2.6.0$Bundle-Name=GWT-Servlet&Bundle-SymbolicName=com.google.gwt.gwt-servlet&Bundle-Version=2.6.0&Export-Package=com.google.gwt.user.client.rpc.*,org.hibernate.validator.engine,com.google.web.bindery.requestfactory.vm.impl.*,!javax.validation,!org.hibernate.validator.*,!*.client.*,!*.impl.*,*&Import-Package=javax.servlet.*,javax.validation;resolution:=optional,org.json;resolution:=optional,javax.validation.*;resolution:=optional,org.json.*;resolution:=optional,!com.google.gwt.*,*;resolution:=optional

Caso 3:install -s mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.gwt-servlet/2.6.0_1

Caso 4:install -s mvn:com.google.gwt/gwt-servlet/2.6.0

53/108

Esempi GWT su ServiceMix

Abbiamo adattato alcuni esempi della distribuzione GWT per funzionare suKaraf/ServiceMix:

https://github.com/cristcost/gwt-karaf-examples

Tra poco faremo vedere un esempio che mette insieme tutte le tecnologieraccontate fino ad ora.

Aperitivo Osgi, Camel e GWT 54/108

SensorMixEsempio di architettura basata su ServiceMix, Camel e GWT

Come è composto SensorMixArchitettura esterna

Aperitivo Osgi, Camel e GWT 56/108

Come è composto SensorMixArchitettura interna

Aperitivo Osgi, Camel e GWT 57/108

DemoAperitivo Osgi, Camel e GWT 58/108

Aperitivo Osgi, Camel e GWT

Data Model Bundle

59/108

Il Canonical Data Model EIP

Dal libro EIP:

“I am designing several applications to work together through Messaging. Eachapplication has its own internal data format.”

“How can you minimize dependencies when integrating applications that usedifferent data formats?”

Aperitivo Osgi, Camel e GWT 60/108

Il Canonical Data Model EIP

Aperitivo Osgi, Camel e GWT 61/108

Il nostro approccio al CDM

A noi piace l’approccio Java first:

Usiamo annotazioni JaxB e JaxWS per generare dal nostro modello gli XMLSchema e WSDL.

Troviamo che cominciare dagli oggetti sia più naturale, lineare e agile:

Aperitivo Osgi, Camel e GWT

Modello dati: POJO

Modello servizi: Interfacce Java

·

·

Lo XML Schema finale risulta più pulito

Si può fare a meno della validazione XML

Lavorare sulle classi Java è più veloce (per noi che siamo sviluppatori)

·

·

eccezioni Java = XML non valido-

·

62/108

Binding Java-XML Schema

Aperitivo Osgi, Camel e GWT

@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "SampleReport")public class SampleReport implements Serializable {

@XmlAttribute(required = true, name = "sensorId") @XmlSchemaType(name = "anyURI") private String sensorId;

@XmlAttribute(required = false, name = "sampleType") private String sampleType;

@XmlElement(required = false, name = "dailySampleReport") private List<DailySampleReport> dailySampleReports;

JAVA

<xs:complexType name="SampleReport"> <xs:attribute name="sensorId" type="xs:anyURI" use="required"/> <xs:attribute name="sampleType" type="xs:string"/> <xs:sequence> <xs:element name="dailySampleReport" type="tns:DailySampleReport" maxOccurs="unbounded" minOccurs="0" /> </xs:sequence></xs:complexType>

XML SCHEMA

63/108

POJO annotati JaxB

Aperitivo Osgi, Camel e GWT

@XmlAccessorType(XmlAccessType.FIELD)@XmlType(name = "SampleReport")public class SampleReport implements Serializable {

/** The sensor id. */ @XmlAttribute(required = true, name = "sensorId") @XmlSchemaType(name = "anyURI") private String sensorId;

/** The sample type. */ @XmlAttribute(required = false, name = "sampleType") private String sampleType;

/** The daily sample reports. */ @XmlElement(required = false, name = "dailySampleReport") private List<DailySampleReport> dailySampleReports;

// ...

JAVA

64/108

Interfaccia annotata JaxWS

Aperitivo Osgi, Camel e GWT

@WebService(name = "SensormixService", targetNamespace = "http://developers.google.com/gdgfirenze/ns/service")@SOAPBinding(parameterStyle = ParameterStyle.WRAPPED, style = Style.DOCUMENT, use = Use.LITERAL)public interface SensormixService {

@WebMethod(action = "urn:#listSensorsIds") @RequestWrapper(localName = "listSensorsIdsIn", targetNamespace = "http://developers.google.com/gdgfirenze/ns/service") @ResponseWrapper(localName = "listSensorsIdsOut", targetNamespace = "http://developers.google.com/gdgfirenze/ns/service") @WebResult(name = "sensorId") List<String> listSensorsIds();

@WebMethod(action = "urn:#listSamplesTypes") @RequestWrapper(localName = "listSamplesTypesIn", targetNamespace = "http://developers.google.com/gdgfirenze/ns/service") @ResponseWrapper(localName = "listSamplesTypesOut", targetNamespace = "http://developers.google.com/gdgfirenze/ns/service") @WebResult(name = "sampleType") List<String> listSamplesTypes();

// ...

JAVA

65/108

Utilizzo del CDM su GWT

Infine, se si vuole usare il data model anche dentro un progetto GWT, bastaaggiungere un modulo .gwt.xml:

Aperitivo Osgi, Camel e GWT

<?xml version="1.0" encoding="UTF-8"?><!-- When updating your version of GWT, you should also update this DTD reference, so that your app can take advantage of the latest GWT module capabilities. --><!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.5.1//EN" "http://google-web-toolkit.googlecode.com/svn/tags /2.5.1/distro-source/core/src/gwt-module.dtd"><module>

<!-- Specify the paths for translatable code --> <source path='model' /> <source path='service' />

</module>

GWT XML

66/108

Aperitivo Osgi, Camel e GWT

Data Service Bundle

67/108

Il bundle dataservice

Contiene un servizio che espone funzionalità di memorizzazione e recupero diinformazioni

Il servizio viene registrato in OSGi tramite Spring DM

Aperitivo Osgi, Camel e GWT 68/108

La registrazione del servizio

Aperitivo Osgi, Camel e GWT

<osgix:cm-properties id="dataSourceProperties" persistent-id="sensormix.jpa.persistenceunit"> <prop key="sensormix_db.driverClassName">org.hsqldb.jdbcDriver</prop> <prop key="sensormix_db.url">jdbc:hsqldb:mem:sensormix_db</prop> <prop key="sensormix_db.username">sa</prop> <prop key="sensormix_db.password"></prop></osgix:cm-properties>

<osgi:service ref="sensormixService"> <osgi:interfaces> <value>com.google.developers.gdgfirenze.service.SensormixService</value> <value>com.google.developers.gdgfirenze.osgi.SensormixAdminInterface</value> </osgi:interfaces></osgi:service>

SPRING DM

69/108

Il servizio in java

Aperitivo Osgi, Camel e GWT

public class SensormixServiceJpaImpl implements SensormixService, SensormixAdminInterface {

private EntityManagerFactory entityManagerFactory;

@Override public List<String> listSensorsIds() { List<String> result = new ArrayList<String>();

try { EntityManager em = entityManagerFactory.createEntityManager(); TypedQuery<String> q = em.createQuery("SELECT s.id FROM JpaSensor s", String.class);

result.addAll(q.getResultList());

em.close(); } catch (Exception e) { logger.log(Level.SEVERE, "Error during sensors list retrieving", e); }

return result; }

JAVA

70/108

Spring ORM

Aperitivo Osgi, Camel e GWT

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceUnitName" value="sensormix_db" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"> <property name="showSql" value="true" /> </bean> </property> <property name="jpaProperties"> <props> <prop key="eclipselink.ddl-generation">create-tables</prop> <prop key="eclipselink.logging.level">INFO</prop> <prop key="eclipselink.weaving">false</prop> <prop key="javax.persistence.jdbc.driver">${sensormix_db.driverClassName}</prop> <prop key="javax.persistence.jdbc.url">${sensormix_db.url}</prop> <prop key="javax.persistence.jdbc.user">${sensormix_db.username}</prop> <prop key="javax.persistence.jdbc.password">${sensormix_db.password}</prop> </props> </property></bean>

<bean id="sensormixService" class="com.google.developers.gdgfirenze.dataservice.SensormixServiceJpaImpl"> <property name="entityManagerFactory" ref="emf" /></bean>

SPRING DM

71/108

Aperitivo Osgi, Camel e GWT

Integration Bundle

72/108

Il bundle di integrazione

Definisce le rotte Camel per l'ingresso dei campioni da Android, Arduino e iOS

Utilizza quasi esclusivamente configurazione via Spring XML

Unica eccezione: la classe SampleAdapter che trasforma da protocol buffer alnostro data model tramite codice java

Aperitivo Osgi, Camel e GWT 73/108

Rivediamo le interfacce SensorMix

Aperitivo Osgi, Camel e GWT 74/108

Le rotte di ingresso UDP e HTTPUsate da Android e da Arduino

Aperitivo Osgi, Camel e GWT

<route> <from uri="mina2:udp://0.0.0.0:10081" /> <to uri="seda:jsonEntry" /></route>

SPRING XML

<route> <from uri="jetty:http://0.0.0.0:10080/sensormixSamplesEndpoint" /> <to uri="seda:jsonEntry" />

<setHeader headerName="Content-Type"> <constant>application/json</constant> </setHeader> <to uri="velocity:vm_templates/json_response_template.vm" /></route>

SPRING XML

75/108

La rotta di trasformazione del JSON

Aperitivo Osgi, Camel e GWT

<route> <from uri="seda:jsonEntry" /> <convertBodyTo type="java.lang.String" />

<unmarshal> <xmljson elementName="item" arrayName="list" rootName="root" /> </unmarshal>

<to uri="xslt:xslt_adapters/raw2cdm_adapter.xsl" />

<unmarshal> <jaxb contextPath="com.google.developers.gdgfirenze.service" /> </unmarshal>

<to uri="seda:serviceEntry" /></route>

SPRING XML

76/108

La rotta TCP + ProtoBuf

Aperitivo Osgi, Camel e GWT

<route> <from uri="netty:tcp://0.0.0.0:10082/?decoders=#length-decoder&amp;sync=false" /> <unmarshal> <protobuf instanceClass="com.google.developers .gdgfirenze.protobuf.SensormixProtos$SampleMessage" /> </unmarshal> <bean ref="sampleAdapter" method="transform" /> <to uri="seda:serviceEntry" /></route>

<bean id="sampleAdapter" class="com.google.developers.gdgfirenze.integration.SampleAdapter" />

SPRING XML

package com.google.developers.gdgfirenze.integration;

public class SampleAdapter { public SamplesPayload transform(SampleMessage message) { SamplesPayload ret = new SamplesPayload(); // process 'SampleMessage' and return the adapted 'SamplesPayload' return ret; }}

JAVA

77/108

L'output verso il servizio OSGi

Aperitivo Osgi, Camel e GWT

<osgi:reference id="sensormixService" interface="com.google.developers.gdgfirenze.service.SensormixService" timeout="30000" cardinality="1..1" />

<route> <from uri="seda:serviceEntry" /> <to uri="bean:sensormixService?method=recordSamples(${body.samples})" /></route>

SPRING XML

78/108

Aperitivo Osgi, Camel e GWT

Admin WebApp Bundle

79/108

SensorMix GWT Web Application

Abbiamo visto che per il deploy di una Web Application GWT suKaraf/ServiceMix dobbiamo garantire che:

Noi cosa abbiamo fatto?

Aperitivo Osgi, Camel e GWT

Il WAR sia un bundle OSGi compliant

Che gwt-servlet.jar sia stata correttamente installata come bundle.

·

·

80/108

Configuriamo il maven-bundle-plugin

Aperitivo Osgi, Camel e GWT

<instructions> <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> <Bundle-Description>${project.description}</Bundle-Description>

<Web-ContextPath>/${project.artifactId}</Web-ContextPath>

<Bundle-ClassPath>.,WEB-INF/classes</Bundle-ClassPath>

<Import-Package> com.google.gwt.user.client.rpc.*, com.google.gwt.user.client.rpc.core.com.google.gwt.core.shared, com.google.gwt.user.client.rpc.core.java.lang, com.google.gwt.user.client.rpc.core.java.math, com.google.gwt.user.client.rpc.core.java.sql, com.google.gwt.user.client.rpc.core.java.util, com.google.gwt.user.client.rpc.core.java.util.logging, com.google.gwt.user.server.rpc.core.java.lang, com.google.gwt.user.server.rpc.core.java.util, !com.google.gwt.*.client.*, * </Import-Package></instructions>

POM.XML

81/108

Configuriamo il maven-war-pluginRicordate lo skinny war?

Si tolgono le dipendenze dalla lib:

Si istruisce Maven di copiare il Manifest al posto giusto:

Aperitivo Osgi, Camel e GWT

<packagingExcludes>WEB-INF/lib/, WEB-INF/classes/META-INF/</packagingExcludes>

POM.XML

<archive> <manifestFile> ${project.build.outputDirectory}/META-INF/MANIFEST.MF </manifestFile></archive>

POM.XML

82/108

Importiamo il Canonical Data Model

Nel file SensormixAdminApp.gwt.xml:

Nel pom.xml:

Aperitivo Osgi, Camel e GWT

<inherits name='com.google.developers.gdgfirenze.Sensormix' /> .GWT.XML

<dependency> <groupId>com.google.developers.gdgfirenze</groupId> <artifactId>sensormix-datamodel-api</artifactId> <version>${project.version}</version></dependency><dependency> <groupId>com.google.developers.gdgfirenze</groupId> <artifactId>sensormix-datamodel-api</artifactId> <version>${project.version}</version> <classifier>sources</classifier></dependency>

POM.XML

83/108

GWT RPC Plumbing diagramSiamo partiti da qui...

Aperitivo Osgi, Camel e GWT 84/108

Sensormix RPC Plumbing diagram...per arrivare qui

Aperitivo Osgi, Camel e GWT 85/108

GWT RPC in SensormixLato Client

Instanziare la service interface usando GWT.create():

Fare la chiamata al servizio:

Aperitivo Osgi, Camel e GWT

GwtSensormixServiceAsync sensormixService = GWT.create(GwtSensormixService.class);

JAVA

sensormixService.listSensorsIds(new AsyncCallback() { @Override public void onFailure(Throwable caught) { // handle the request failure }

@Override public void onSuccess(List result) { // handle the response from the service }});

JAVA

86/108

GWT RPC in SensormixLato Server

SensormixServiceProxy.java è un servizio GWT che usa un servizio OSGi. Nella inizializazione ottiene deiriferimenti al servizio utilizzando le API del Framework.

Come viene usata l’istanza del servizio OSGi?

Aperitivo Osgi, Camel e GWT

public void init() throws ServletException {

final BundleContext context = FrameworkUtil.getBundle(this.getClass()).getBundleContext(); tracker = new ServiceTracker(context, SensormixService.class.getName(), null); tracker.open();}

JAVA

private SensormixService getService() { return (SensormixService) tracker.waitForService(10000);}

public List<String> listSensorsIds() { return getService().listSensorsIds();}

JAVA

87/108

Cool FactsOvvero perchè ci piace questa architettura

Integrazione di Arduino

Aperitivo Osgi, Camel e GWT 89/108

Integrazione di Arduino

Aperitivo Osgi, Camel e GWT 90/108

Integrazione di Android

Aperitivo Osgi, Camel e GWT

HttpPost httppost = new HttpPost(url.toString()); httppost.setHeader("Content-type", "application/json");

StringEntity se = new StringEntity(bodyForHttpPostRequest); se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json")); httppost.setEntity(se);

HttpResponse response = httpclient.execute(httppost); String temp = EntityUtils.toString(response.getEntity()); logger.info("JSON post response: " + temp);

JAVA

91/108

Integrazione di Android - NFC

Aperitivo Osgi, Camel e GWT

Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG); StringBuilder id = new StringBuilder(); byte[] data = tag.getId(); for (int i = 0; i < data.length; i++) { id.append(String.format("%02x", data[i])); if (i < data.length - 1) { id.append(":"); } } JSONObject jsonSamplePacket = new JSONObject(); JSONObject obj = new JSONObject(); jsonSamplePacket.put("sample", obj); obj.put("device_id", "the device id"); obj.put("time", dateFormat.format(new Date())); obj.put("nfc", id); Intent intent = new Intent(this, DataSenderService.class); intent.putExtra(DataSenderService.INTENT_EXTRA, jsonSamplePacket.toString()); startService(intent);

JAVA

92/108

Installiamo ServiceMix

Aperitivo Osgi, Camel e GWT 93/108

Creare una distribuzione della applicazione

Aperitivo Osgi, Camel e GWT 94/108

Le Karaf Features

Aperitivo Osgi, Camel e GWT

<features name='sensormix-1.0.0'> <feature name="sensormix-core" version="1.0.0"> <bundle>mvn:com.google.developers.gdgfirenze/sensormix-datamodel-api/1.0.0</bundle> </feature>

<feature name="sensormix-dataservice" version="1.0.0"> <feature version="1.0.0">sensormix-core</feature> <feature>spring-orm</feature> <!-- ... --> <bundle>mvn:mysql/mysql-connector-java/5.1.26</bundle> <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-dbcp/1.4_3</bundle> <bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.javax-inject/1_2</bundle> <bundle>mvn:org.eclipse.persistence/javax.persistence/2.1.0</bundle> <bundle>mvn:org.eclipse.persistence/org.eclipse.persistence.jpa/2.5.0</bundle> <!-- ... --> <bundle>mvn:com.google.developers.gdgfirenze/sensormix-dataservice-bundle/1.0.0</bundle> </feature>

<feature name="sensormix" version="1.0.0"> <feature version="1.0.0">sensormix-dataservice</feature> <feature version="1.0.0">sensormix-webservice</feature> </feature></features>

FEATURES.XML

95/108

Il Features Maven Plugin di Karaf

Aperitivo Osgi, Camel e GWT

<plugin> <groupId>org.apache.karaf.tooling</groupId> <artifactId>features-maven-plugin</artifactId> <version>${features.plugin.version}</version> <executions> <execution> <id>add-features-to-repo</id> <phase>package</phase> <goals> <goal>add-features-to-repo</goal> </goals> <configuration> <descriptors> <descriptor>com.google.developers.gdgfirenze /sensormix-deploy-features/1.0.0/xml/features</descriptor> </descriptors> <features> <feature>sensormix/1.0.0</feature> </features> <repository>target/local-repo</repository> </configuration> </execution> </executions></plugin>

FEATURES.XML

96/108

Installiamo SensorMix

Aperitivo Osgi, Camel e GWT 97/108

Kryo e Benchmark

Si è scelto di utilizzare un’unica classe per tutti i sample (con un campobyte[] che contiene la serializzazione (Kryo) del sample).

Sfruttando l’astrazione di JPA sono stati fatti benchmark di occupazione eperformance per supportare le scelte e validare la soluzione.

Aperitivo Osgi, Camel e GWT 98/108

ServiceMix: Quanto overhead?Il pacchetto ServiceMix occupa circa 65MB sul filesystem

Aperitivo Osgi, Camel e GWT 99/108

Maven ed Eclipse

SensorMix è stato sviluppato in Team utilizzando Maven ed Eclipse.

In particolare:

Aperitivo Osgi, Camel e GWT

Sviluppo GWT integrato nello stesso Java IDE

Distribuzione tramite Karaf's Features Maven Plugin

Checkstyle e PMD per migliorare la cooperazione del Team

·

·

·

100/108

ConclusioniConsiderazioni finali e riferimenti bibliografici

Issue su GWT

Serve GWT 2.6.0 che sia reso OSGi ready:per favore aiutateci, votate lo issue sulla Osgify di GWT:

oppure lo issue su Jira per avere il bundle rilasciato da ServiceMix il primapossibile:

·

http://goo.gl/GEuVBR-

·

http://goo.gl/jFsVcP-

Materiali

Aperitivo Osgi, Camel e GWT

Slides:

http://cristcost.github.io/sensormix/

Sensormix:

https://github.com/cristcost/sensormix/

Sensormix Android:

https://github.com/cristcost/sensormix-android/

Sensormix Arduino:

https://github.com/michelefi/sensormix-arduino/

103/108

Libri

Camel in Action

C. Ibsen, J. Anstey - Manning

Enterprise Integration Patterns

G. Hohpe, B. Woolf - Addison Wesley

Spring DM in Action

A. Cogoluègnes, T. Templier, A. Piper - Manning

OSGi in Action

R. S. Hall, K. Pauls, S. McCulloch, D. Savage - Manning

OSGi In depth

Alexandre de Castro Alves - Manning

Links

Aperitivo Osgi, Camel e GWT

Apache Camel:

http://camel.apache.org/

Apache ServiceMix:

http://servicemix.apache.org/

Apache Karaf:

http://karaf.apache.org/

GWT:

http://www.gwtproject.org/

105/108

Q&AAperitivo Osgi, Camel e GWT 106/108

<Thank You!>

Cristiano Costantini cristiano.costantini@gmail.com

Giuseppe Gerla giuseppe.gerla@gmail.com

Michele Ficarra miche.ficarra@gmail.com

Sergio Ciampi sergio.ciampi@gmail.com

Stefano Cigheri stefano.cigheri@gmail.com