Symposium Liferay France 2014 : la roadmap Liferay

A l’occasion du symposium France 2014, Liferay à présenté les dernières évolution du produit, celles en cours et la vision future. En voici un bref résumé:

La Roadmap présentée :

  • Déjà fait ou en cours :
    • Accélération des release : un service pack tous les mois (déjà en cours)
    • Plus de publications sur le store (déjà en cours)
    • Nouvelle version social office (déjà déployé)
    • Nouveau Developper Studio (2.0) semaine prochaine : support Maven, debugger Freemarker, Intégration IvyIDE.
    • Alloy UI 2.5 / Liferay Faces 3.2 (déjà déployé)
    • Portlet Sandbox (espace isolé pour les tests – déjà déployé)
    • Sens de lecture droite – gauche (déjà déployé)
    • Nouvelle version du Sharepoint Connector (déjà déployé)
    • Mobile SDK (déjà déployé) pour iOS et Android
    • Liferay Cloud Services (déjà déployé) : connecter le serveur local au cloud et il donne des statistiques d’utilisation techniques (pools, portlets, …), état du serveur local, niveau de mise à jour des portlets, … Ces services sont amenés à se développer.
  • En cours de développement (déployés en SP de la 6.2 ou pour la 7)
      • Personnalisation : content targeting : gestion des segments, de campagnes, mesure du retour. Applicable pour les contenus, users, apps, thèmes, …
      • Amélioration de la gestion de contenu :
        • Comparaison de versions de contenus
        • Autocomplete sur le CKeditor
        • Système de mention (si utilisateur mentionné dans un texte, il en est informé)
        • Refonte de plusieurs fonctions annexes (breadcrumb, …)
  • Amélioration de l’ergonomie
  • Support des Single Page Application : notion de « surfaces » dans lequelles on pose des portlets. Ne sont chargées que les surfaces visibles au fur et à mesure du scroll.
  • Geolocalisation des utilisateurs, contenus, fonction et personnalisation par rapport à cette information (sous forme de tags)
  • Intégration Bootstrap 3, ElasticSearch (à la place du simple Lucene), Arquillian
  • Le futur :
    • Amélioration de la developper experience :
      • Modularité (OSGI, …)
      • Amélioration des APIs :  NodeJS, Angular, …
      • MEAP
  • Amélioration end user experience :
    • Amélioration des analytics
    • Amélioration du test utilisateur (A/B, …)
  • Amélioration de la « power user » experience :
    • Collaboration

Liferay restera sur un rythme d’une version majeure par an. La version 7 est donc prévue pour décembre 2014 / début 2015.

{lang: 'fr'}

Utiliser l’héritage de thèmes de Liferay

Dans un projet Liferay, le thème contient généralement l’ensemble des fichiers constituant le thème (template, css, images).

Ce principe oblige la reprise du thème complet lors d’une montée de version et ne permet pas d’avoir une vision claire des modifications effectuées.

Afin d’éviter cela, il est préférable de mettre en place l’héritage de thème.

Pour se faire, on utilise la configuration maven suivante :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<groupId>com.liferay.maven.plugins</groupId>
<artifactId>liferay-maven-plugin</artifactId>
<executions>
	<execution>
		<phase>generate-sources</phase>
		<goals>
			<goal>theme-merge</goal>
			<goal>build-css</goal>
			<goal>build-thumbail</goal>
		</goals>
	<execution>
</executions>
<configuration>
	<pluginType>theme</pluginType>
	<themeType>vm</themeType>
	<parentTheme>classic</parentTheme>
</configuration>

Ce paramétrage est standard et fait partie des bonnes pratiques usuelles.

Mais il est souvent requis de produire un nouveau thème, celui-ci n’étant qu’une variante du premier.

Idéalement, il faudrait hériter de celui-ci et seulement implémenter les différences. Or au premier abord il est seulement possible d’hériter de _unstyled, _styled, classic ou control_panel.

Mais, il est également possible d’hériter de n’importe quel thème ! Pour cela, il faut utiliser la syntaxe groupId:artifactId:version

Par exemple:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<groupId>com.liferay.maven.plugins</groupId>
<artifactId>liferay-maven-plugin</artifactId>
<executions>
	<execution>
		<phase>generate-sources</phase>
		<goals>
			<goal>theme-merge</goal>
			<goal>build-css</goal>
			<goal>build-thumbail</goal>
		</goals>
	<execution>
</executions>
<configuration>
	<pluginType>theme</pluginType>
	<themeType>vm</themeType>
	<parentTheme>com.mycompany.liferay:core-theme:1.0.0</parentTheme>
</configuration>

L’héritage entre les deux thèmes du projet est alors actif.

{lang: 'fr'}

Intégrer Liferay et Alfresco

Dans cet article, nous proposons d’étudier les moyens existants pour l’intégration de Liferay et Alfreco. Le but est de permettre l’utilisation de documents stockés dans Alfresco dans les fonctions de publication proposées par Liferay.

Liferay propose en standard deux modes d’intégration :

  • L’intégration des documents via le protocole CMIS
  • Le déploiement de portlets pour l’affichage des documents.

 

1. Intégration par CMIS

a. Présentation

Liferay propose en standard un module d’intégration de référentiel CMIS.
CMIS permet de connecter des applications comme Sharepoint, Documentum ou Alfresco en utilisant ce protocole.
- Création du repository Alfresco dans Liferay :

Une fois connecté le repository affiche alors les dossiers et documents présent dans Alfresco :

Les documents publiés dans Alfresco sont alors directement accessible dans Liferay. Il est également possible (en fonction des permissions) de créer ou de mettre à jour des documents à partir de Liferay.
L’utilisation d’un « repository » permet d’utiliser la fonctionnalité standard de Liferay vis-à-vis des documents : lien dans un contenu web, liste de documents.

b. Limitations

i. Gestion d’identité

Une des problématiques de l’interconnexion de deux outils est le transfert de l’identité de l’utilisateur consultant/modifiant les documents.

En standard Liferay propose d’utiliser l’identifiant et le mot de passe lors de la connexion à Alfresco via CMIS. Cela présente 3 points négatifs :
- Il faut activer l’authentification par screenname
- Il faut stocker le mot de passe utilisateur dans la session utilisateur (risque de sécurité).
- Il faut disposer des mêmes informations d’authentification (identifiant/mot de passe dans les deux systèmes).

Il sera donc préférable de mettre en place un tiers de confiance (Active Directory, NTML, SSO).

ii. Métadonnées

Une des fonctionnalités majeurs d’Alfresco est la possibilité de définir un méta modèle spécifiques et ainsi de caractériser les documents publiés par l’ajout de méta données (exemple : client lié à un contrat).

Actuellement l’implémentation standard CMIS ne permet pas d’extraire les métadonnées du document. Celles-ci ne pourront pas être véhiculées et réutilisées dans Liferay.

Alfresco propose une extension à CMIS afin de permettre l’extraction des métadonnées. Il conviendra d’étendre le fonctionnement du repository Liferay pour y ajouter la gestion de l’extension Alfresco. Ces métadonnées pourraient alors être utilisées dans l’affichage des documents.

iii. AssetPublisher

Les documents accessibles via un repository CMIS ne sont pas accessibles via la portlet standard Asset Publisher.

Cette portlet permet l’affichage dynamique de contenus Liferay (Documents, Dossiers, Contenus Web) en fonction de critères de filtre.

Il conviendrait d’étendre le fonctionnement du repository CMIS pour ajouter les documents en tant qu’Asset dans Liferay.

 

2. Portlets

a. Présentation

Alfresco propose en standard un mode portlet de l’interface Share. Par exemple : http://www.liferay.com/web/navin.agarwal11/blog/-/blogs/integration-with-alfresco-4-x-and-liferay-6-1

Ce mode permet d’avoir à l’ensemble des capacités d’Alfresco tout en restant dans le contexte Liferay.

b. Limitations

i. SSO

Pour assurer l’intégration d’Alfresco dans Liferay par le mode portlet, la mise en place d’un outil de SSO est nécessaire.

ii. Installation

Le déploiement requiert beaucoup de configuration pour assurer le fonctionnement du Share Alfresco au sein de Liferay puisque le fonctionnement repose sur ce dernier. Il est donc nécessaire de reporter toute la configuration du share dans le contexte Liferay.

iii. Cloisonnement

Les documents gérés dans Alfresco et affichés via la portlet Share ne peuvent pas être réutilisés dans les fonctionnalités Liferay (Contenus web,…). La portlet permet uniquement la gestion du référentiel de document Alfresco.

 

3. Conclusion

Il n’existe pas aujourd’hui de solution technique permettant de fournir une intégration complète entre ces 2 outils.

Le mode le plus aboutit passe par l’utilisation du protocole CMIS qu’il est possible d’étendre et compléter avec des fonctionnalités complémentaires (Asset, Tags, Catégorie) mais cela nécessitera un développement complémentaire au module existant (cf module Sharepoint pour Liferay).

{lang: 'fr'}

Optimiser les performances de Liferay 6.1 par paramétrage

Plusieurs paramètres de Liferay 6.1 (CE ou EE) peuvent influer de manière significatives sur les performances du serveur.

Il est par exemple indispensable de positionner le paramètre « direct.servlet.context.reload » à false .

D’autres optimisations sont possibles:

  • Désactiver les filtres non utilisés, par exemple:
1
2
3
4
5
6
7
8
9
com.liferay.portal.servlet.filters.sso.cas.CASFilter=false
com.liferay.portal.servlet.filters.audit.AuditFilter=false
com.liferay.portal.servlet.filters.sso.opensso.OpenSSOFilter=false
com.liferay.portal.servlet.filters.strip.StripFilter=false
com.liferay.portal.servlet.filters.validhtml.ValidHtmlFilter=false
com.liferay.portal.servlet.filters.monitoring.MonitoringFilter=false
com.liferay.portal.servlet.filters.sso.ntlm.NtlmFilter=false
com.liferay.portal.servlet.filters.sso.ntlm.NtlmPostFilter=false
com.liferay.portal.sharepoint.SharepointFilter=false
  • Utiliser la compression GZip Apache plutôt que Liferay:
1
com.liferay.portal.servlet.filters.gzip.GZipFilter=false
  • Si elle n’est pas utilisée, désactiver la fonction « view counter » sur les documents et les assets:
1
2
3
4
5
#Document library
dl.file.rank.enabled=false
dl.file.entry.read.count.enabled=false
#Asset
asset.entry.increment.view.counter.enabled=false

 

{lang: 'fr'}

Outil de migration de dépendances ant vers maven

Un rapide post pour présenter un petit outil très pratique : Provenance

Marre de devoir écrire à la main les balises dependency dans votre pom.xml ?
Vous avez un répertoire rempli de jar à inscrire dans votre pom.xml ? (pour une migration depuis Ant par exemple)

Cet outil est fait pour vous ! : )

Téléchargez les sources, packager le projet (maven package) puis exécuter simplement :

1
java -jar Provenance.jar lib_dir > dep.xml

Cela créera le xml correspondant aux librairies trouvées dans le ‘lib-dir’.

Cet outil se base sur le checksum des jar et le service REST de recherche de chez Sonatype, peu de chance de se tromper sur le résultat !

{lang: 'fr'}

Introduction aux EIPs (suite) : mise en pratique avec Spring Integration

Passons à la mise en pratique avec Spring Integration !

Comme nous l’avons vu dans l’article précédent, Camel prends quelques libertés vis-à-vis des concepts des EIPs, les channels sont implicites et l’implémentation des routes modélisées par EIPs peuvent se révéler assez différentes. Spring Integration au contraire, est à la base une pure implémentation des EIPs, chaque élément retrouvé dans notre modélisation va être retranscrite point par point et enrichie :

Ainsi chaque endpoint et channel (aller comme retour) sont retranscrits dans Spring Integration, nous aurons donc :

  • Un endpoint http d’entrée
  • Un endpoint s’occupant de l’appel http au service Google
  • 2 endpoints transformant les messages
  • 4 channels liant les endpoints

Chacun de ces composants seront définis comme bean spring, on retrouvera donc une configuration et une architecture classique des applications spring, très modulaire facilitant la réutilisation.

Toute la configuration se fait par fichier spring XML, les endpoints et channels développés peuvent néanmoins être intégrés et configurés dans le conteneur Spring à l’aide d’annotations.

Les Channels

Contrairement à Camel, les channels sont explicites, ils peuvent être de type publish/subscribe, queue, direct… Nous allons utiliser seulement les directs dans notre exemple :

1
2
3
4
5
<!-- Inbound/Outbound Channels -->
<int:channel id="spellJsonRequest" />
<int:channel id="spellXmlRequest" />
<int:channel id="spellXmlResponse" />
<int:channel id="spellJsonResponse" />

Endpoint http : inbound-gateway

Afin de réaliser notre endpoint http, Spring Integration propose le endpoint http inbound gateway. C’est un endpoint producteur de messages. Evidemment, Spring se base sur Spring MVC pour créer ce endpoint :

1
2
3
4
5
6
7
<int-http:inbound-gateway id="inboundEmployeeSearchRequestGateway"
	supported-methods="GET" request-channel="spellJsonRequest"
	reply-channel="spellJsonResponse" mapped-request-headers="null"
	mapped-response-headers="Return-Status, Return-Status-Msg, HTTP_RESPONSE_HEADERS"
	path="/spell/{word}" reply-timeout="50000">
 <int-http:header name="word" expression="#pathVariables.word" />
</int-http:inbound-gateway>

Cette configuration créé un endpoint à l’adresse /spell qui est rajouté à la DispatcherServlet de Spring MVC. Le mapped-request-headers permet de spécifier quel headers http sont mappés sur les headers du message du flux. Les request et reply channel permettent de brancher le endpoint aux channels. Le header est enrichi du pathVariable pour la suite.

Template velocity

Afin de garder la même logique que pour l’implémentation Camel, la requête XML est générée à l’aide d’un template Velocity. Il n’existe pas de Transformer velocity natif sous Spring Integration, mais il est simple d’en implémenter un :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Component("velocityTransformer")
public class VelocityTransformer {
	@Value("request.vm")
	private String templateLocation;
 
	@Autowired
	private VelocityEngine velocityEngine;
 
	@Transformer
	public String transform(@Header("word") String word)
			throws VelocityException, IOException {
		Map map = new HashedMap();
		map.put("word", word);
		return VelocityEngineUtils.mergeTemplateIntoString(velocityEngine,
				templateLocation, map);
	}
}

A noter l’utilisation des Annotations, la méthode @Transformer permet d’injecter directement dans ses paramètres d’appel des valeurs du header « word ».
Le transformer est ensuite branché sur la route :

1
2
<int:transformer input-channel="spellJsonRequest"
		output-channel="spellXmlRequest" ref="velocityTransformer" />

Endpoint http : outbound-gateway

Un endpoint permettant les appels http est disponible, il est basé sur le RestTemplate de Spring :

1
2
3
<int-http:outbound-gateway request-channel="spellXmlRequest"
		expected-response-type="com.sedona.simple.SpellResult" reply-channel="spellXmlResponse"
		url="http://www.google.com/tbproxy/spell?lang=en" http-method="POST" />

L’url cible est simplement précisée avec la méthode http utilisée. L’expected-response-type permet de convertir directement la réponse XML en objet Java grâce à un mapping JaxB. Aucune configuration supplémentaire est nécessaire, seule la classe SpellResult est développée :

1
2
3
4
5
6
7
8
9
10
11
12
@XmlRootElement(name = "spellresult")
public class SpellResult {
	private String c;
 
	public String getC() {
		return c;
	}
 
	public void setC(String c) {
		this.c = c;
	}
}

 Transformation Objet vers Json

Un transformer natif est disponible à partir du moment où la librairie Jackson est disponible dans le classpath. Il suffit ensuite de le déclarer :

1
2
<int:object-to-json-transformer
	input-channel="spellXmlResponse" output-channel="spellJsonResponse" content-type="application/json" />

Les headers de réponse du service google étant par défaut mappés, attention à bien changer le content-type de xml à json.

Configuration et déploiement

La solution se basant sur du spring MVC, une configuration spring classique (ContextLoaderListener dans le web.xml) et un déploiement dans un conteneur de servlet (tomcat) sont nécessaires.

Conclusion

Comme déjà précisé, Spring Integration est plus fidèle aux EIPs, la route configurée correspond exactement à la conception de notre flux, l’implémentation est donc plus implicite et demande moins de connaissance du framework et de ses composants, on profite en plus des forces de ce framework (Spring MVC, système de conversion etc…).
Néanmoins Camel est plus pragmatique, ses composants sont plus riches et le développement et la configuration a été plus rapide qu’avec Spring.

{lang: 'fr'}

Introduction aux EIPs (suite) : mise en pratique avec Apache Camel

Suite de l’article précédent, la mise en pratique des EIPs se fera avec une mise en bouche de deux frameworks d’intégrations : Apache Camel et Spring Integration

Pour rappel, l’exemple de flux simple a été modélisé ainsi :

Deux implémentations vont être réalisées afin de présenter les deux frameworks, voici la première avec Apache Camel.

Apache Camel

Directement basé sur les EIPs, Camel permet de créer des routes et des règles de médiations. Nous verrons que ce framework comme Spring Integration, ne suit pas forcément à la lettre les design et modélisations des EIPs, certaines simplifications et extensions sont mises en place. Une des particularités de Camel est qu’il propose plusieurs moyen de définir des routes, comme par exemple par l’intermédiaire d’une API Java de type DSL ou par fichier de configuration Spring XML.

L’implémentations des EIPs se fait par l’utilisation de composants (qui peuvent être des endpoints comme des simple transformer) et de data format afin de faciliter la conversion de données.

Chaque composant possède sa propre URI,  qui déterminer à la fois le transport utilisé et des paramètres propres au composant. Par exemple, un endpoint http en entrée relié à un endpoint http de sortie donne en Java DSL :

1
from("jetty:http://localhost:9000/test").to("http://www.google.com");

Cette route indique que le composant Camel jetty est utilisé en entrée, écoute sur le port 9000 et transmet les requêtes en entrée vers google grâce au composant http de camel.
La liste des composants est disponibles ici. Ainsi le composant file permet de lire ou écrire un fichier, le composant cxf de faire appel à un web service cxf etc…
Un exemple de route en xml :

1
2
3
4
<route>
	<from uri="jetty:http://localhost:9000/test" />
	<to uri="http://www.google.com" />
</route>

Implémentation de la route

Implémenter notre route d’exemple se résume donc à choisir les composants camel à utiliser ou à en créer de nouveaux. L’implémentation choisie a finalement été :

  • Utilisation d’un web service rest CXF comme endpoint d’entrée
  • Utilisation d’un template velocity pour construire la requête XML nécessaire
  • Utilisation du composant http pour le endpoint vers google
  • Une transformation standard du xml vers json grâce à un data-format
L’exemple ayant été implémenté sous maven, chaque composant est une dépendance maven à rajouter pour pouvoir l’utiliser, soient CXF, velocity, http et xmljson.
La route a été définie ainsi :
1
2
3
4
5
6
from("cxfrs:bean:spellCheckEndpoint")
		.to("velocity:request.xml")
		.setHeader(Exchange.HTTP_URI,
			simple("http://www.google.com/tbproxy/spell?lang=en"))
		.setHeader(Exchange.HTTP_METHOD, constant("POST"))
		.to("http://googleSpellCheck").marshal().xmljson();
L’équivalent en xml :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<route>
    <from uri="cxfrs:bean:spellCheckEndpoint"/>
    <to uri="velocity:request.xml"/>
    <setHeader headerName="CamelHttpUri">
        <simple>http://www.google.com/tbproxy/spell?lang=en</simple>
    </setHeader>
    <setHeader headerName="CamelHttpMethod">
        <constant>POST</constant>
    </setHeader>
    <to uri="http://googleSpellCheck"/>
    <marshal>
        <xmljson/>
    </marshal>
</route>

La route va être détaillée point par point.

CXF

Le endpoint d’entrée utilise le composant CXFRS. L’URI précise le bean spring à utiliser, son implémentation (JAX-RS) est simple :

1
2
3
4
5
6
7
8
9
@Path("/")
public class SpellCheck {
	@GET
	@Path("/{word}")
	@Produces("text/json")
	public String getSpellCheck(@PathParam("word") String word) {
		return word;
	}
}

Il retourne simplement le path param ‘word’ qui constituera donc le corps du message de la route.
Il est ensuite déclaré en tant que bean spring grâce à une notation spécifique afin de créer simplement le connecteur jetty associé :

1
2
<cxf:rsServer id="spellCheckEndpoint" address="http://0.0.0.0:9001/spell/"
		serviceClass="com.sedona.simple.SpellCheck" />

Template Velocity

Le composant velocity est ensuite utilisé pour dynamiser le requête xml qui sera envoyée à google :

1
2
3
4
<?xml version="1.0" encoding="utf-8" ?>
<spellrequest textalreadyclipped="0" ignoredups="0" ignoredigits="1" ignoreallcaps="1">
    <text>${body[0]}</text>
</spellrequest>

Le path param précédemment récupéré par le service JAX-RS est donc inséré dans la balise text et le xml constitue désormais le payload du message.

Http

L’envoi de la requête http vers google se fait par le composant http. Comme précisé dans le précédent article les messages routés sont composés de headers et d’un payload. Afin de spécifier la destination réel du message et la méthode utilisée pour le requête (un Post), des headers sont précisés avant de faire appel au composant.

Réponse json

Enfin, la réponse est convertie grâce aux système data format de Camel, grâce à xmljson.
Par défaut, une route Camel est de type request/reply, le retour vers le endpoint d’entrée est implicite.

Dernières configurations

Si la notation java DSL est utilisée, le code java doit être dans la méthode configure() d’un classe héritant de RouteBuilder. Le fichier spring doit ensuite contenir une référence vers cette dernière :

1
2
3
4
5
6
7
8
9
10
11
<beans xmlns="http://www.springframework.org/schema/beans"
	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.xsd
	http://camel.apache.org/schema/spring
	http://camel.apache.org/schema/spring/camel-spring.xsd">
 
	<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
		<package>com.sedona.simple</package>
	</camelContext>
</beans>

Pour la notation XML, il faut rajouter la définition dans la balise camelContext.
Pour tester, une classe Main standard camel est utilisée, se basant sur spring, elle charge automatiquement les fichiers spring positionnés dans le classpath dans META-INF/spring.

Une fois démarré, un simple test : http://localhost:9001/spell/herllo nous retourne un json avec des propositions de correction :

1
{"@error":"0","@clipped":"0","@charschecked":"6","@suggestedlang":"en","c":{"@o":"0","@l":"6","@s":"0","#text":"hello\tHelli\thell\tHeall\thallo"}}

Conclusion

Ce petit exemple a permis de présenter un aperçu de Camel, une page présente comment les différents EIPs sont intégrés mais c’est surtout la richesse de ses composants et connecteurs qui font la force de Camel, il a était simple de réaliser cette route avec un minimum de développement.

Prochain article : même exercice avec Spring Integration !

{lang: 'fr'}

Introduction aux Entreprise Integration Patterns

Les design patterns, on en connaît à la pelle ! Mais ce billet est une petite introduction à ces patterns particuliers que sont les Entreprise Integration Patterns ou EIP.

 

Les EIPs ? Qu’est ce que c’est ?

Nous connaissons tous les patterns Gof, les MVC, les IOC qui concernent la programmation orientée objet, mais les EIPs, comment leur nom l’indique, concernent une toute autre problématique, l’intégration d’entreprise ou plus simplement les flux de données dans un système d’information. La moindre application faisant partie d’un SI est amenée à échanger des informations avec d’autres applications, par transfert de fichier, partage de base de données, web services, système de messaging… Les EIPs proposent de modéliser ces échanges et d’identifier les patterns les plus courants utilisés lors de ces flux, ne se basant pas sur des diagrammes de classes, ils proposent une toute autre représentation graphique. Principalement orientés autour de systèmes de messaging, nous verront que leur application peut être plus large et plus simple et que même l’intégration d’un fichier plat peut être modélisé sous forme d’échange de message.

Car c’est bien là la base des EIPs, elles modélisent tout échange d’information comme un transfert de message entre deux Endpoints par l’intermédiaire d’un channel. Un message est composé d’un header (qui contient des informations liées à l’infrastructure et le mode de transfert) et d’un payload, la données en elle même, qui peut être de n’importe quelle nature.

Le channel est tout simplement la tuyauterie et la manière dont est transféré de le message (direct point à point, publish/subscribe, message bus). Un Endpoint est un producteur et/ou un consommateur de messages, comme un connecteur à votre application ou un système.

Enfin à cela peut se rajouter :

  • Un traducteur / convertisseur du message (message translator ou transformer)
  • Un routeur, comme un choix sur le channel à emprunter selon le contenu du message
  • Un filtre…
Par exemple, un échange entre deux systèmes (endpoints), demandant une transformation selon le type de données peut être modélisé simplement :
A partir de ces éléments de base, tout une série de patterns peuvent créée, comme par exemple, le normalizer, qui selon le message en entrée, procédera à une ou l’autre des transformations disponibles grâce à un router :
Qui possède son propre schema :
Ce billet n’a pas vocation de présenter tous les patterns, vous pouvez en avoir un aperçu ici (En effet, cette notation et ces patterns sont tirés du livre Entreprise Integration Patterns), mais plusieurs seront présentés au cours de la petite série de billets sur le sujet.

Essayons de mettre en pratique cette notation afin de modéliser un traitement simple, la mise en place d’un web service Rest/Json à partir d’un web service Rest/XML hébergé chez google. Les deux aspects fondamentaux sont :

  1.  Nous avons affaire à un flux request/reply, en effet le endpoint producteur (de type http/rest donc) du message a besoin de retourner une réponse
  2. Le traitement du flux est essentiellement une conversion du message de la request d’entrée et de la réponse de retour du service google.
C’est tout simplement un aller retour avec une transformation de message comme vu précédemment, soit :
Voilà pour une rapide introduction à cette notation et les premiers patterns, suite au prochain article, avec deux exemples d’implémentations de cette échange suivant deux frameworks, Apache Camel et Spring Integration.
{lang: 'fr'}

JSoup

Vous connaissez JSoup ?
Il s’agit d’une librairie très utile. Elle vous permettra de lire et surtout de parcourir, manipuler, traverser un DOM et son contenu avec des sélecteurs html/css. Elle est en plus compatible Html 5.
Un exemple:

1
2
Document doc = Jsoup.connect("http://en.wikipedia.org/").get(); 
Elements newsHeadlines = doc.select("#mp-itn b a");

ou à partir d’un fichier:

1
2
File input = new File("/tmp/input.html"); 
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");

La configuration Maven:

1
2
3
4
5
<dependency>
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.7.2</version>
</dependency>

JSoup.org

{lang: 'fr'}