Outils pour utilisateurs

Outils du site


issue76:tutoriel_-_spring_integration

Table des matières

1

Some time ago, I began a new job in a big corporation. My first task was to reimplement / reimport their C# tcp client to Java. Existing convertors sucked, so I did it manually. After a week or so, the new Java tcp client and server simulator were written and waiting for further use. Having met the client’s requirements, we found that Java’s implementation lacked important features such as failover and auto-reconnection. Adding such functionality required us to add some untested code, which might be unable to handle the business logic. One of our guys said, Aha, what if…? We can replace the Java implementation with another one, for instance - Spring Integration. The rest of us smiled, thinking what the heck? Anyway, he is a good chap, trying to use the best technologies available. We got the green light to do research and learn something exciting. To simplify our requirements, I am going to discuss a simulator (aka server) and a client. Before delving deeper, let me explain what Spring Integration is intended for. As their site suggests: “it provides an extension of the Spring programming model to support the well-known Enterprise Integration Patterns”. Rephrasing, to design good enterprise applications one could use messaging (more precisely asynchronous messaging) that enables diverse applications to be integrated with each other – without nightmares or pain. A wise guy named Martin Fowler has written a famous book: “Enterprise Integration Patterns”. Folks from Spring probably one day decided to materialize a theory into practice. Very pragmatic approach, isn’t it? Later, you will see how wonderful it is for regular tasks. The main concept of SI is: Endpoint, Channel and Message.

Il y a quelque temps, j'ai commencé un nouveau boulot dans une grande société. Ma première tâche était de réimplémenter/porter leur client tcp de C# en Java. Les convertisseurs existants fonctionnant mal, je l'ai fait manuellement. Après environ une semaine, le nouveau client tcp et le nouveau simulateur de serveur étaient écrits en Java et prêts à être utilisés. Après avoir répondu aux exigences du client, nous avons constaté que l'implémentation en Java manquait de caractéristiques importantes telles que la gestion de panne et l'auto-reconnexion. Ajouter ces fonctionnalités nécessitait l'ajout de code non testé, qui risquait de ne pas gérer la logique métier. Un de nos collègues a dit : Aha, et si… ? Nous pourrions remplacer l'implémentation en Java par une autre, par exemple - Spring Integration. Nous avons rigolé en pensant : mais qu'est-ce qu'il raconte ? Quoi qu'il en soit, c'est un bon garçon, qui essaie d'utiliser les meilleures technologies disponibles. Nous avons eu le feu vert pour faire des recherches et apprendre quelque chose de passionnant. Pour simplifier nos besoins, je vais parler d'un simulateur (c'est-à-dire, un serveur) et d'un client.   Avant d'y plonger plus profondément, laissez-moi vous expliquer pour quelle fonction Spring Integration est conçu. Comme leur site l'indique : « cela fournit une extension du modèle de programmation Spring qui supporte les modèles bien connus d'intégration de l'entreprise (Enterprise Integration Patterns) ». Pour reformuler, cela permet de concevoir de bonnes applications d'entreprise en utilisant des messages (plus précisément une messagerie asynchrone) qui permet à diverses applications de s'intégrer les unes aux autres, sans cauchemar ni douleur. Un sage du nom de Martin Fowler a écrit un livre célèbre : Enterprise Integration Patterns. Les gens de Spring ont sans doute décidé un jour de transformer une théorie en pratique. Approche très pragmatique, n'est-ce pas ? Plus tard, vous verrez combien c'est merveilleux pour des tâches récurrentes. Les concepts principaux du SI sont : Endpoint, Channel et Message (nœud d'échange, canal et message).

2

Endpoint is a component which actually does something with a message. A message is a container consisting of header and payload. The header contains data that’s relevant to the messaging system where the payload contains the actual data. Channel connects two or more endpoints, it’s similar to Unix pipes. Two endpoints can exchange messages if they’re connected through a channel. Pretty easy, isn’t it? The following diagram shows this. The next step to our crash course will be defining the requirements. I would say, we need a server (tcp) and tcp client. We will write a simple application that will exchange a couple of messages with each other. An important thing with SI is a configuration file which contains all the necessary components we’re going to use. Here is the “server” part of the configuration. Simplifying a model and SI lifecycle, Spring creates objects that are defined in the configuration xml. More generally, such a concept is called declarative programming. You define a business object in the xml, and a framework generates appropriate classes for you, and injects and initializes dependencies. The mantra says: you should be concentrated only on the business and not on the implementation.

Le nœud d'échange est un composant qui agit sur un message. Un message est un contenant composé d'en-tête et d'une charge utile. L'en-tête contient des données qui sont pertinentes pour le système de messagerie et la charge utile contient les données réelles. Un canal relie deux ou plusieurs nœuds d'échange ; il est semblable à des « tubes » (pipes) Unix. Deux nœuds peuvent échanger des messages s'ils sont reliés par un canal. Assez facile, n'est-ce pas ? Le schéma suivant montre cela.

La prochaine étape pour notre cours intensif sera de définir les exigences. Je dirais que nous avons besoin d'un serveur (tcp) et d'un client tcp. Nous allons écrire une application simple qui va échanger quelques messages entre les deux.

Une chose importante dans le SI est un fichier de configuration qui contient tous les composants que nous allons utiliser. Voici la partie « serveur » de la configuration. Pour simplifier le modèle et le cycle de vie du SI, Spring crée des objets qui sont définis dans le fichier xml de configuration. Plus généralement, un tel concept est appelé programmation déclarative. Vous définissez un objet métier dans le xml et un outil (« framework ») génère les classes appropriées à votre place, puis injecte et initialise les dépendances. Le mantra dit : vous devez être concentré uniquement sur le travail et non sur la mise en œuvre.

3

Let’s define a part of the configuration xml (next page, top left), the server part: http://pastebin.com/6AHQWPse Important things are: A factory (tcp-connection-factory) - creates tcp server using a byte array length serializer. A Serializer is needed for “packaging” our message in some way or to encode it in order to transmit it over a wire. On the other hand, a Deserializer is needed for “unpackaging” our message or to decode it. Spring Integration has two factories – one for the client and another for the server. The difference is the Type [server or client]. A Port listens for incoming messages. An IP address is not mentioned here because a server runs as a localhost. We also defined two channels: serverIn (for incoming messages) and serverOut (for outgoing messages). So that our server can send and receive messages, we define inbound and outbound adapters which are associated with the factory and channels. In our case they define the endpoints. So, when a message arrives, something should take care of it. This responsibility requires a service, i.e. file sender service. If it accepts a message, then it will send a file in the background, line by line, to the client. Basically, when a server starts, it listens for incoming messages. However, only specific messages will be accepted, and, when accepted, than the server sends a file line-by-line. If an error occurs, it’s routed to the error channel. It’s done using interceptor.

Nous allons définir une partie du fichier xml de configuration (page suivante, en haut à gauche), la partie serveur : http://pastebin.com/6AHQWPse

Les choses importantes sont : une usine (tcp-connection-factory) crée un serveur TCP en utilisant un tableau sérialiseur d'une longueur d'un octet. Un sérialiseur est nécessaire pour « emballer » notre message, c-à-d l'encoder afin de le transmettre par un câble. D'autre part, un désérialiseur est nécessaire pour « déballer » notre message, autrement dit, le décoder. Spring Integration possède deux usines : une pour le client et l'autre pour le serveur. La différence est le type [serveur ou client]. Un port écoute les messages entrants. Une adresse IP n'est pas mentionnée ici, car le serveur s'exécute en tant que localhost (serveur local).

Nous avons également défini deux canaux : serverIn (pour les messages entrants) et serverOut (pour les messages sortants). Pour que notre serveur puisse envoyer et recevoir des messages, nous définissons des adaptateurs entrants et sortants qui sont associés à l'usine et aux canaux. Dans notre cas, ils définissent les nœuds d'échange. Donc, quand un message arrive, quelque chose doit s'en occuper. Cette responsabilité exige un service, à savoir le service d'envoi de fichier. S'il accepte un message, il envoie un fichier en tâche de fond, ligne par ligne, vers le client. En gros, quand un serveur démarre, il écoute les messages entrants. Cependant, seuls des messages spécifiques seront acceptés et, lorsqu'il sont acceptés, le serveur envoie un fichier ligne par ligne. Si une erreur se produit, elle est acheminée vers le canal d'erreur. On utilise pour cela un intercepteur.

4

I would say a couple of words about the SI lifecycle. Spring framework has two “main” packages: org.springframework.beans and org.springframework.context that build up the core utility of the dependency injection of the component. The org.springframework.beans.factory.BeanFactory interface provides basic lifecycle methods (start and stop) for bean initialization/destruction. The org.springframework.context.ApplicationContext offers AOP integration, message resource handling, and even more. Our server is ready… I mean, completely ready. To run the example, follow the below steps: cd /tcpserver mvn clean install mvn dependency:copy-dependencies mvn exec:java -Dexec.mainClass=“org.example.tcpserver.ServerRunner” -Dexec.args=“–file=”/file_to_be_sent.txt““

Je voudrais dire quelques mots sur le cycle de vie du SI. Le framework Spring a deux paquets « principaux » : org.springframework.beans et org.springframework.context qui construisent l'important utilitaire d'injection de dépendances du composant. L'interface org.springframework.beans.factory.BeanFactory fournit des méthodes de base de cycle de vie (démarrage et arrêt) pour l'initialisation et la destruction du bean. org.springframework.context.ApplicationContext offre une intégration AOP, la gestion des ressources du message et plus encore.

Notre serveur est prêt… Je veux dire, tout à fait prêt. Pour exécuter l'exemple, suivez les étapes ci-dessous :

cd /tcpserver

mvn clean install

mvn dependency:copy-dependencies

mvn exec:java -Dexec.mainClass=“org.example.tcpserver.ServerRunner” -Dexec.args=”–file=”/file_to_be_sent.txt“”

5

Our main class expresses as shown in the box below. The source code can be found here http://pastebin.com/6PMpWTfX Also we define a file-send service. This is shown on the next page, top left. The code is at: http://pastebin.com/icHRdQS3 Next, denote a business runner. That code is shown on the next page, bottom left. The code can be seen at: http://pastebin.com/LZRdZ3Tg Finally, for the server, write an error handler which logs the errors which is shown above. Code is at: http://pastebin.com/2EQvbVR8 At this point, we’re done with our server.

Notre classe principale s'exprime comme dans l'encadré ci-dessous.

Le code source peut être trouvé ici : http://pastebin.com/6PMpWTfX

Nous définissons également un service d'envoi de fichier. Ceci est illustré à la page suivante, en haut à gauche. Le code est ici : http://pastebin.com/icHRdQS3

Ensuite, voici un exécuteur du boulot. Ce code-là est montré sur la page suivante, en bas à gauche. Le code peut être récupéré ici : http://pastebin.com/LZRdZ3Tg

Enfin, pour le serveur, nous écrivons un gestionnaire d'erreur, qui enregistre les erreurs et que l'on voit ci-dessus. Le code est là : http://pastebin.com/2EQvbVR8

À ce stade, nous en avons terminé avec notre serveur.

6

Now, let’s define a tcp client which connects to the server, sends an accept message, and gets a file sent from the server. Our configuration file looks as follows: http://pastebin.com/egquzq5q Here’s how to run a client: Open a new terminal: cd /tcpclient mvn clean install mvn dependency:copy-dependencies mvn exec:java -Dexec.mainClass=“org.example.tcpclient.ClientTcp” Almost the same logic applies here. Have a look. A main class has the lines shown in the code on the next page, top left.

Maintenant, nous allons définir un client TCP qui se connecte au serveur, envoie un message d'acceptation et obtient un fichier envoyé par le serveur.

Notre fichier de configuration se présente comme suit : http://pastebin.com/egquzq5q

Voici comment faire fonctionner un client :

Ouvrez un nouveau terminal :

cd /tcpclient

mvn clean install

mvn dependency:copy-dependencies

mvn exec:java -Dexec.mainClass=“org.example.tcpclient.ClientTcp”

C'est presque la même logique qui s'applique ici. Jetez un œil. Une classe principale contient les lignes figurant dans le code sur la page suivante, en haut à gauche.

7

In addition, define a client service: void send(String txt); Next, a message handler: public void handle(byte[] s) { String ss = new String(s); LOG.info(“r:” + ss); } And the last one is an interceptor, which will inform your application about: i. Message sent; ii. A connection closed; iii. A new connection added. That’s it! To play with the code, see here: http://www.4shared.com/zip/eF4q7l0k/spring_integration_example.html.

En outre, on définit un service client :

void send(String txt);

Ensuite, un gestionnaire de messages :

public void handle(byte[] s) {

 String ss = new String(s);
 
 LOG.info("r:" + ss);

}

Et le dernier est un intercepteur, qui informera votre application sur : i. Message envoyé ; ii. Une connexion est fermée ; iii. Une nouvelle connexion est ajoutée.

C'est tout !

Pour vous amuser avec le code, voir ici : http://www.4shared.com/zip/eF4q7l0k/spring_integration_example.html.

8

Prerequisites: • Java 1.6 or above; • Maven 3 or above; • Desire to learn something new and thrilling; Pros: • A lot of features • Tested • Good and friendly community • If you have questions, the people reply really quickly • There are tons of examples • API is easy and comprehensive Cons: • Takes time to learn and understand how to work with it. • If you get problems, sometime it is difficult to debug it.

Pré-requis : • Java 1.6 ou supérieur ; • Maven 3 ou supérieur ; • le désir d'apprendre quelque chose de nouveau et passionnant.

Avantages : • un grand nombre de fonctionnalités ; • testé ; • communauté amicale et agréable ; • si vous avez des questions, les gens répondent très rapidement ; • il y a des tonnes d'exemples ; • API simple et complète.

Inconvénients : • il faut du temps pour apprendre et comprendre comment l'utiliser ; • si vous avez des problèmes, il est parfois difficile de déboguer.

issue76/tutoriel_-_spring_integration.txt · Dernière modification : 2014/02/11 14:50 de auntiee