Suite

Tampon pour les fonctionnalités sélectionnées dans le mapcanvas et écriture dans un fichier csv


J'ai sélectionné certaines entités à l'aide de l'outil "Sélectionner des entités à main levée" dans QGIS et j'essaie de trouver le tampon pour ces entités sélectionnées uniquement et d'écrire les noms de ville et d'état dans le tampon dans un fichier csv. Mon code et mon image sont joints pour une compréhension claire. il écrit un fichier csv à l'emplacement donné mais rien n'est trouvé à l'intérieur du csv.

Et mon code est

import csv selection = layer.selectedFeatures() layer = qgis.utils.iface.activeLayer() column=['name', 'state' ] pour l'entité dans la sélection : mbuf = feature.geometry().buffer (50, 2) iterFeat = layer.getFeatures() pour f dans iterFeat : geom2 = f.geometry() valTest = QgsGeometry.within(geom2, mbuf) lsNearCities = [] if valTest : idx = selection.fieldNameIndex('name') idx1 = selection. fieldNameIndex('state') nearCity = f.attributes()[idx] state = f.attributes()[idx1] state_and_cities = str(state) + "," + nearCity lsNearCities.append(state_and_cities) print lsNearCities

la ligne,

feature = layer.selectedFeatures()

renvoie une liste de QgsFeature. Vous devrez le parcourir pour traiter les sélections individuelles, comme ci-dessous.

layer = qgis.utils.iface.activeLayer() pour la fonctionnalité dans layer.selectedFeatures() : mbuf = feature.geometry().buffer (50, 2) iterFeat = layer.getFeatures() pour f dans iterFeat : geom2 = f. géométrie()

2 réponses 2

Dans l'ensemble, vos données sont simplement mal formatées. Par exemple, plus loin dans la liste, vos dates ressemblent à "3-Mar" qui est interprété comme le 3 mars et non comme mars 2003, comme vous l'aviez prévu. Pour la plupart, ce n'est pas de votre faute, mais Excel formate arbitrairement les données, et vous devez être vigilant pour qu'il ne les interprète pas mal. À cette fin, j'ai réécrit ma réponse pour contourner le mauvais formatage.

Tout d'abord, vos données numériques sont formatées avec des virgules, nous devons donc nous en débarrasser.

Deuxièmement, vos dates, comme je l'ai dit ci-dessus, sont mal formatées. Le code, ci-dessous, divise la date à "-", vérifie si la partie numérique a une longueur 1 et la fait précéder d'un "0" si c'est le cas, trie les deux chaînes par longueur, inverse le tri et les remet ensemble avec "-" entre.


Vous pouvez essayer de supprimer le BufferedWriter et d'utiliser directement le FileWriter. Sur un système moderne, il y a de fortes chances que vous écriviez simplement dans la mémoire cache du lecteur de toute façon.

Il me faut environ 4 à 5 secondes pour écrire 175 Mo (4 millions de chaînes) - c'est sur un Dell à 2,4 GHz double cœur exécutant Windows XP avec un disque Hitachi de 80 Go à 7 200 tr/min.

Pouvez-vous isoler combien de temps est la récupération d'enregistrements et combien de temps est l'écriture de fichiers ?

essayez les fichiers mappés en mémoire (il faut 300 m/s pour écrire 174 Mo dans mon m/c, core 2 duo, 2,5 Go de RAM) :

Uniquement pour des raisons de statistiques :

La machine est un ancien Dell avec un nouveau SSD

Processeur : Intel Pentium D 2,8 Ghz

SSD : Patriot Inferno 120 Go SSD

Comme nous pouvons le voir, la méthode brute est plus lente que la méthode tamponnée.

Votre vitesse de transfert ne sera probablement pas limitée par Java. Au lieu de cela, je soupçonnerais (sans ordre particulier)

Si vous lisez l'ensemble de données complet puis l'écrivez sur le disque, cela prendra plus de temps, car la JVM devra allouer de la mémoire et l'écriture de la base de données/du disque se fera de manière séquentielle. Au lieu de cela, j'écrirais à l'écrivain tamponné pour chaque lecture que vous effectuez à partir de la base de données, et donc l'opération sera plus proche d'une opération simultanée (je ne sais pas si vous le faites ou non)


Création de publicités Instagram à l'aide du gestionnaire de publicités Facebook

Parce que le système publicitaire de Facebook est si complet, nous devons suivre plusieurs étapes pour créer des publicités Instagram. Ils sont assez simples et nous passerons en revue chacun d'eux ci-dessous. Voici les étapes générales :

  • Choisir un objectif marketing
  • Nommez votre campagne publicitaire
  • (Certains objectifs marketing nécessitent des étapes supplémentaires ici, que nous verrons ci-dessous.)
  • Définissez votre audience, vos emplacements, votre budget et votre calendrier
  • Créer l'annonce elle-même ou utiliser une publication existante

Pointe: Bien qu'il n'y ait pas de règle de nommage fixe, vous voudriez utiliser une convention de nommage telle que vous (et votre équipe) puissiez les différencier par le nom. Par exemple, voici la convention de nommage utilisée par HubSpot :

Naviguer vers le gestionnaire de publicités Facebook

Cette méthode a tendance à être la façon dont la plupart des spécialistes du marketing créent des publicités Instagram.

L'utilisation du gestionnaire de publicités Facebook a tendance à être plus facile que la création de publicités dans l'application Instagram, et vous pouvez également faire beaucoup plus grâce au gestionnaire de publicités Facebook.

Note de l'éditeur: Nous allons créer des publicités Instagram dans l'application Instagram ci-dessous. Si vous souhaitez en savoir plus maintenant, n'hésitez pas à passer à cette section.

La création de publicités Instagram est très similaire à la création de publicités Facebook. Tout comme les publicités Facebook, Facebook Ads Manager est l'endroit idéal pour créer, modifier et gérer les publicités Instagram.

Pour accéder à votre gestionnaire de publicités Facebook, cliquez sur la flèche déroulante dans le coin supérieur droit de n'importe quelle page Facebook et sélectionnez « Gérer les publicités » dans la liste déroulante.

Vous pouvez également utiliser ce lien direct : https://www.facebook.com/ads/manager/ pour accéder à votre gestionnaire de publicités Facebook.

Une fois que vous y êtes, cliquez simplement sur le bouton vert bien visible « Créer une annonce » dans le coin supérieur droit pour commencer.

(Si vous avez plusieurs comptes publicitaires, vous devrez peut-être d'abord sélectionner votre compte publicitaire préféré pour vos publicités Instagram.)

Pointe: Pour créer des publicités Instagram à l'aide du gestionnaire de publicités Facebook, il vous suffit d'avoir une page Facebook. Vous n'avez même pas besoin d'un compte Instagram !

Les 8 objectifs différents des publicités Instagram

Alors que Facebook propose 11 objectifs dans le gestionnaire de publicités Facebook, seuls les huit suivants vous permettront de créer des publicités Instagram.

  1. Notoriété de la marque
  2. Atteindre
  3. Trafic
  4. Installations d'applications
  5. Engagement
  6. Vues vidéo
  7. Génération de leads
  8. Conversions

Certains de ces objectifs sont très simples : il vous suffit de choisir l'objectif et de créer votre annonce immédiatement. D'autres, cependant, peuvent nécessiter quelques étapes supplémentaires avant de pouvoir diffuser votre annonce. Voici un bref aperçu de chacun des objectifs (et comment vous les configurez à l'aide de Facebook Ads Manager) :

1. Notoriété de la marque

Avec cet objectif, vous pouvez contribuer à accroître la notoriété de votre marque. Vos publicités Instagram seront diffusées auprès des personnes les plus susceptibles de s'y intéresser.

Aucune étape supplémentaire n'est requise pour cet objectif.

2. Atteindre

Avec cet objectif, vous pouvez maximiser le nombre de personnes qui voient vos publicités Instagram et à quelle fréquence. Contrairement à l'objectif de notoriété de la marque, les personnes qui verront ces publicités pourraient ne pas toutes être intéressées par elles.

Étape supplémentaire :

Après avoir choisi cet objectif et nommé votre campagne publicitaire, vous devrez choisir une page Facebook à associer à cette campagne publicitaire.

Si vous n'avez pas de compte Instagram, cette page Facebook représentera votre entreprise dans vos publicités Instagram. Si vous avez un compte Instagram et préférez l'utiliser, il y aura une option pour connecter votre compte Instagram lorsque vous créez l'annonce elle-même.

Pointe: Pour créer des publicités Instagram Stories, vous ne pouvez utiliser que l'objectif Reach pour le moment.

3. Trafic

Avec cet objectif, vous pouvez envoyer des personnes vers votre site Web ou vers l'App Store de votre application à partir de vos publicités Instagram.

Étape supplémentaire :

Après avoir choisi cet objectif et nommé votre campagne publicitaire, vous devrez choisir où vous souhaitez générer du trafic. Vous pouvez choisir soit :

Vous devrez saisir l'URL de destination lors de la création de l'annonce elle-même.

4. Engagement

Avec cet objectif, vous pouvez amener plus de personnes à voir et à interagir avec votre publication.

Pour cet objectif, vous pouvez choisir le type d'engagement que vous souhaitez, tel que l'engagement de publication, les likes de page, les réponses aux événements et les revendications d'offre. Pour la publicité sur Instagram, vous ne pouvez choisir que « Post engagement ».

Si vous souhaitez promouvoir une publication existante, ce sera l'objectif à atteindre. Mais notez que vous ne pouvez promouvoir qu'un La page Facebook Publier. Pour promouvoir une publication Instagram existante, vous devrez le faire dans l'application Instagram. Cliquez ici pour passer à la section.

5. Installations d'applications

Avec cet objectif, vous pouvez envoyer des personnes vers l'App Store où elles peuvent télécharger votre application.

Pour cet objectif, il existe une fonctionnalité bonus : les tests fractionnés (ou test A/B). Cette fonctionnalité vous permet de tester facilement différentes versions de vos annonces pour découvrir ce qui fonctionne le mieux afin d'améliorer vos futures annonces.

Étape supplémentaire :

Après avoir choisi cet objectif et nommé votre campagne publicitaire, vous devrez choisir l'application que vous souhaitez promouvoir et l'App Store que vous préférez (iTunes ou Google Play pour les applications mobiles ou Facebook Canvas pour les applications de bureau).

Vous ne pouvez promouvoir qu'une seule plateforme à la fois. Si vous souhaitez promouvoir plusieurs plates-formes, vous devrez recréer la même annonce mais sélectionner une autre plate-forme.

6. Vues vidéo

Avec cet objectif, vous pouvez promouvoir une vidéo auprès d'un plus grand nombre de personnes. Cet objectif est très simple et aucune étape supplémentaire n'est requise pour cet objectif.

7. Génération de leads

Avec cet objectif, vous pouvez créer des publicités Instagram de génération de leads pour collecter des informations pertinentes auprès de leads potentiels.

Étape supplémentaire :

Après avoir choisi cet objectif et nommé votre campagne publicitaire, vous devrez choisir une page Facebook à associer à cette campagne publicitaire. Si vous n'avez pas de compte Instagram, cette page Facebook représentera votre entreprise dans vos publicités Instagram.

  • Les publicités à formulaire sur Facebook et Instagram présentent plusieurs différences :
    • Tous les champs pré-remplis ne sont pas pris en charge sur Instagram. Instagram ne prend actuellement en charge que ces champs : E-mail, Nom complet, Numéro de téléphone et Sexe.
    • Les publicités sont différentes. Pour compléter vos publicités Instagram, les utilisateurs devront ouvrir la publicité et cliquer sur quelques pages pour remplir leurs coordonnées. Sur Facebook, les gens n'ont qu'à faire défiler vers le bas et ne pas cliquer.

    8. Conversions

    Avec cet objectif, vous pouvez inciter les gens à prendre des mesures sur votre site Web ou votre application. Semblable à l'objectif d'installations d'applications, vous pouvez effectuer des tests fractionnés de vos annonces avec cet objectif.

    Étape supplémentaire :

    Après avoir choisi cet objectif et nommé votre campagne publicitaire, vous devrez choisir le site Web ou l'application que vous souhaitez promouvoir et un événement de pixel ou d'application Facebook pour aider à suivre les conversions.

    Si vous n'avez pas configuré d'événement de pixel ou d'application Facebook, il existe des instructions à ce stade pour vous aider.


    3 réponses 3

    Tout d'abord, vous devez savoir ce que vous faites à InnoDB lorsque vous insérez des millions de lignes dans une table InnoDB. Jetons un coup d'œil à l'architecture InnoDB.

    Dans le coin supérieur gauche, il y a une illustration du pool de tampons InnoDB. Notez qu'il y a une section dédiée au tampon d'insertion. Qu'est-ce que ça fait ? Il est utilisé pour migrer les modifications apportées aux index secondaires du pool de tampons vers le tampon d'insertion à l'intérieur de l'espace de table système (a.k.a. ibdata1). Par défaut, innodb_change_buffer_max_size est défini sur 25. Cela signifie que jusqu'à 25 % du pool de mémoire tampon peut être utilisé pour le traitement des index secondaires.

    Dans votre cas, vous disposez de 6,935 Go pour le pool de tampons InnoDB. Un maximum de 1,734 Go sera utilisé pour le traitement de vos index secondaires.

    Maintenant, regardez votre table. Vous avez 13 index secondaires. Chaque ligne que vous traitez doit générer une entrée d'index secondaire, la coupler avec la clé primaire de la ligne et les envoyer par paire depuis le tampon d'insertion dans le pool de tampons dans le tampon d'insertion dans ibdata1. Cela se produit 13 fois avec chaque ligne. Multipliez cela par 10 millions et vous pouvez presque sentir un goulot d'étranglement arriver.

    N'oubliez pas que l'importation de 10 millions de lignes en une seule transaction va tout empiler dans un segment d'annulation et remplir l'espace UNDO dans ibdata1.


    Maintenant que vous disposez des packages requis, chargez-les dans la session R actuelle.

    Quand la zone d'enquête CA653 a-t-elle été exportée pour la dernière fois vers SSURGO ?

    Y a-t-il des zones d'enquête qui n'ont pas été mises à jour depuis le 1er janvier 2010 ?

    Quelle est la dernière enquête mise à jour en Californie ?

    Une simple requête à partir de la table des composants, pour une seule unité de carte : mukey = '461958' . Il s'agit d'une clé d'unité de carte SSURGO, les enregistrements STATSGO sont donc implicitement supprimés des résultats.

    mukey cokey comppct_r nom de l'entreprise nomtaxcl
    461958 16893928 85 San Joaquín Durixeralfs abrutiques fins, mixtes, thermiques
    461958 16893929 4 Galt N / A
    461958 16893930 4 Bruella N / A
    461958 16893931 3 Haie N / A
    461958 16893932 3 Kimball N / A
    461958 16893933 1 Anonyme N / A

    Obtenez une liste des unités de carte qui contiennent "Amador" comme composant mineur. Notez que ce type de requête nécessite l'exclusion explicite des enregistrements STATSGO.

    muname mukey cokey nom de l'entreprise comppct_r
    Loam argileux Pentz, pentes de 0 à 8 pour cent 463106 16889616 Amador 5
    Loam argileux Pentz, pentes de 8 à 30 pour cent 463107 16889620 Amador 5
    Loam graveleux Pentz, pentes de 0 à 8 pour cent 463108 16889625 Amador 5
    Loam graveleux Pentz, pentes de 8 à 30 pour cent 463109 16889628 Amador 5
    Loam Pentz, pentes de 0 à 8 pour cent 463110 16889632 Amador 5
    Loam Pentz, pentes de 8 à 30 pour cent 463111 16889636 Amador 5

    Obtenez des données de base sur les unités et les composants de la carte pour une seule zone d'enquête, le comté de Yolo (CA113). Il n'est pas nécessaire d'exclure les enregistrements STATSGO car nous spécifions un symbole de zone SSURGO dans la clause WHERE.

    mukey cokey comppct_r nom de l'entreprise nomtaxcl arrêté fiscal sous-frontalier fiscal taxgrtgroup impôtsubgrp
    765508 16891279 85 Henneke Argixerolls argileux-squelettiques, serpentinitiques, thermiques lithiques Mollisol Xerolls Argixerolls Argixerolls lithiques
    765509 16891280 30 Millsholm Xérochrepts limoneux, mixtes, superactifs, thermiques lithiques Inceptisols Ochreptes Xérochrepts Xérochrepts lithiques
    765509 16891281 20 Lodo Haploxérolls limoneux, mixtes, superactifs, thermiques lithiques Mollisol Xerolls Haploxérolls Haploxérolls lithiques
    765509 16891282 30 Maymen Xérochrepts limoneux, mixtes, actifs, mésiques lithiques dystriques Inceptisols Ochreptes Xérochrepts Xérochrepts lithiques dystriques
    765511 16891283 85 Montara Haploxérolls limoneux, serpentinitiques, thermiques lithiques Mollisols Xerolls Haploxérolls Haploxérolls lithiques
    765512 16891284 100 Affleurement rocheux N / A N / A N / A N / A N / A

    Recoupez l'occurrence des composants nommés "Auburn" et "Dunstone" avec le symbole de zone d'enquête. Notez que ce type de requête nécessite l'exclusion explicite des enregistrements STATSGO.


    3 réponses 3

    Vous ne pouvez pas éliminer totalement les dépendances. Une histoire dépendra d'une autre, une fonctionnalité aura besoin d'une autre fonctionnalité pour être construite en premier, une nouvelle fonctionnalité ne sera souhaitée qu'après avoir vu et interagi avec une fonctionnalité déjà construite, etc. C'est juste la nature des choses.

    Ainsi, l'"Indépendant" dans INVEST ne consiste pas à éliminer les dépendances, il s'agit de minimiser les dépendances.

    Les dépendances sont mauvaises car elles introduisent des problèmes de hiérarchisation des user stories, de planification, d'estimations, peut-être des défis techniques, le travail devient inefficace, etc. Vous devriez donc les avoir aussi indépendantes que possible. Parfois, cela signifie combiner quelques user stories (si elles sont suffisamment petites pour tenir dans un sprint) ou trouver une autre façon d'organiser la fonctionnalité (c'est-à-dire une autre façon de diviser la fonctionnalité en stories).

    Par exemple, vous pouvez n'avoir qu'une seule user story :

    Ou vous pouvez en créer deux sur les trois :

    1. En tant qu'utilisateur, je souhaite filtrer et afficher mes transactions ("Tous" n'est qu'un autre filtre dans ce contexte)
    2. En tant qu'utilisateur, je souhaite exporter les transactions que je sélectionne

    Mais bien sûr, il faut être pragmatique: vous ne voulez pas passer tout votre temps à essayer de trouver la meilleure façon d'écrire des user stories. Si tout le monde est satisfait de la façon dont les user stories sont écrites et que vous pouvez travailler dessus sans difficulté, alors c'est bien de laisser les histoires comme ça. Encore une fois, il s'agit de minimiser les dépendances, pas de les éliminer complètement.

    Votre liste d'histoires est parfaite telle qu'elle est écrite, John ! Les méthodes que nous appelons maintenant « Agile » partagent en commun l'idée de développement itératif, selon l'article fondateur de William Rouse sur la gestion de projets logiciels (1970). Ils supposent que vous allez créer une fonctionnalité de base, puis ajouter des fonctionnalités par-dessus.

    Selon l'excellent point de Bogdan, la plupart des outils que j'ai utilisés ont une fonctionnalité pour identifier les dépendances en série. (Ma pratique consiste à traiter une histoire précédente comme un bloqueur ou un obstacle à l'histoire suivante dans la séquence, empêchant cette dernière de se lancer dans un sprint jusqu'à ce que le prédécesseur soit terminé.) D'après mes lectures, le point sur "l'indépendant" dans INVEST est-ce qu'en fonction de ce qui a déjà été fait, vous pouvez terminer l'histoire sans en terminer une autre en même temps (en parallèle).

    À votre commentaire : Dans Scrum, il n'y a pas de différence pratique entre incrémental et itératif. Selon le Guide Scrum, vous développez des incréments au sein d'un cycle itératif. Voir par exemple https://agility.im/frequent-agile-question/difference-incremental-iterative-development/.


    :! envoie au shell qui l'exécute et affiche sa sortie à l'écran.

    :! envoie les lignes du tampon courant à l'intérieur comme entrée de la programme et les remplace par sa sortie.

    • % est la plage, ce qui signifie : toutes les lignes du tampon courant
      Il peut aussi s'écrire 1,$ (de la première ligne à la dernière)
    • jq est le programme de filtrage

    Voici une page décrivant les différentes manières d'écrire une plage.
    Et sur cette page, vous pouvez trouver d'autres exemples d'utilisation d'un programme de filtrage :

    Le premier remplace un fichier binaire par un vidage hexadécimal (ou l'inverse avec le drapeau -r).
    Le second formate les données du fichier dans une table.
    Le troisième trie les lignes en fonction des premiers caractères.

    Vous pouvez tester le troisième, avec ce simple fichier :

    Après avoir tapé :%! sort , le tampon est remplacé par :

    Si vous aviez tapé :!sort % , la sortie aurait été affichée à l'écran mais n'aurait pas remplacé le tampon.

    Notez que le signe % ne veut pas dire la même chose selon l'endroit où il est placé :

    Avant le bang (et plus généralement avant la plupart des commandes Ex), il est interprété comme une plage (identique à 1,$ ) qui indique à vim quelles lignes doivent être filtrées.

    Après le bang (et plus généralement après la plupart des commandes Ex), il est développé en tant que nom du fichier actuel avant que la commande complète ne soit envoyée au shell.


    Widget-Gadget Corp -- Un exemple

    La meilleure façon de comprendre les solutions d'intégration basées sur les messages est de prendre un exemple concret. Considérons Widgets & Gadgets 'R Us (WGRUS), un détaillant en ligne qui achète des widgets et des gadgets aux fabricants et les revend aux clients.

    Pour cet exemple, nous supposons que la solution doit prendre en charge les exigences suivantes. Naturellement, nous avons un peu simplifié les exigences par souci de concision, mais néanmoins ces types d'exigences se produisent fréquemment dans les entreprises réelles.

    • Prendre des ordres: Les clients peuvent passer des commandes via le Web, par téléphone ou par fax
    • Traiter les commandes: Le traitement d'une commande implique plusieurs étapes, notamment la vérification des stocks, l'expédition des marchandises et la facturation au client
    • Vérifier l'état: Les clients peuvent vérifier l'état de la commande
    • Changement d'adresse: Les clients peuvent utiliser une interface Web pour modifier leur adresse de facturation et de livraison
    • Nouveau catalogue: Les fournisseurs mettent à jour leur catalogue périodiquement. WGRUS doit mettre à jour ses prix et sa disponibilité en fonction des nouveaux catalogues.
    • Annonces: Les clients peuvent s'abonner à des annonces sélectives de WGRUS.
    • Test et surveillance: Le personnel d'exploitation doit être en mesure de surveiller tous les composants individuels et le flux de messages entre eux.

    Nous aborderons chacune de ces exigences séparément et décrirons les solutions alternatives et les compromis en utilisant le langage de modèles présenté dans ce livre.

    Comme dans la plupart des scénarios d'intégration, WGRUS n'est pas une implémentation dite de « champ vert », mais plutôt l'intégration d'une infrastructure informatique existante composée d'une variété d'applications packagées et personnalisées. Le fait que nous devions travailler avec des applications existantes rend souvent le travail d'intégration difficile. Dans notre exemple, WGRUS exécute les systèmes suivants (voir image).


    Infrastructure informatique WGRUS

    WGRUS dispose de quatre canaux différents pour interagir avec les clients. Les clients peuvent visiter le site Web de l'entreprise, appeler le représentant du service clientèle du centre d'appels ou soumettre des commandes par télécopieur. Les clients peuvent également recevoir des notifications par e-mail.

    Les systèmes internes de WGRUS comprennent le système comptable, qui comprend également des fonctions de facturation, le système d'expédition qui calcule les frais d'expédition et interagit avec les compagnies maritimes. Pour des raisons historiques, WGRUS dispose de deux systèmes d'inventaire et de catalogue. WGRUS ne vendait que des widgets, mais a acquis un autre détaillant qui vend des gadgets. WGRUS a décidé qu'il serait moins coûteux d'exploiter des systèmes parallèles que d'essayer de réécrire les deux systèmes en un seul système.

    La première fonction que nous voulons implémenter est la prise de commandes. Prendre des commandes est une bonne chose car elles génèrent des revenus. Cependant, passer des commandes est actuellement un processus manuel fastidieux de sorte que le coût encouru avec chaque commande est élevé. En fait, pour les commandes inférieures à 20 $, WGRUS ne rapporte pratiquement pas d'argent, car tout profit potentiel est absorbé par le coût de la main-d'œuvre pour traiter la commande.

    La première étape pour rationaliser le traitement des commandes consiste à unifier la prise de commandes. Un client peut passer des commandes sur l'un des trois canaux suivants : site Web, centre d'appels ou télécopie. Malheureusement, chaque système est basé sur une technologie différente et stocke les commandes entrantes dans un format de données différent. Le système de centre d'appels est une application packagée tandis que le site Web est une application J2EE personnalisée. Le système de télécopie entrante nécessite la saisie manuelle des données dans une petite application Microsoft Access. Nous voulons traiter toutes les commandes de manière égale, quelle que soit leur source. Par exemple, un client devrait pouvoir passer une commande via le centre d'appels et vérifier l'état de la commande sur le site Web.

    Parce que passer une commande est un processus asynchrone qui connecte de nombreux systèmes, nous décidons de mettre en œuvre une solution middleware orientée message pour rationaliser le processus de saisie des commandes. Étant donné que l'application de centre d'appels packagée n'a pas été développée dans un souci d'intégration, nous la connectons au système de messagerie à l'aide d'un adaptateur de canal . Un adaptateur de canal est un composant qui peut s'attacher à une application et publier des messages sur un canal de message chaque fois qu'un événement se produit dans l'application. Avec certains adaptateurs de canaux, l'application peut même ne pas être consciente de la présence de l'adaptateur. Par exemple, un adaptateur de base de données peut ajouter des déclencheurs à des tables spécifiques afin qu'à chaque fois que l'application insère une ligne de données, un message soit envoyé au canal de message . Les adaptateurs de canal peuvent également fonctionner dans la direction opposée, en consommant des messages d'un canal de message et en déclenchant une action à l'intérieur de l'application en réponse.

    Nous utilisons la même approche pour l'application de fax entrant, en connectant l'adaptateur de canal à la base de données de l'application. Étant donné que l'application Web est personnalisée, nous implémentons le code Endpoint à l'intérieur de l'application. Nous utilisons une passerelle de messagerie pour isoler le code de l'application du code spécifique à la messagerie.


    Prendre des commandes à partir de trois canaux différents

    Étant donné que chaque système utilise un format de données différent pour les commandes entrantes, nous utilisons trois traducteurs de messages pour convertir les différents formats de données en un message de nouvelle commande commun qui suit un modèle de données canonique. Un modèle de données canonique définit des formats de message indépendants de toute application spécifique afin que toutes les applications puissent communiquer entre elles dans ce format commun. Si le format interne d'une application change, seul le traducteur de messages entre l'application concernée et le canal de messages à venir doit changer, tandis que toutes les autres applications et traducteurs de messages restent inchangés. L'utilisation d'un modèle de données canonique signifie que nous traitons deux types de messages : les messages canoniques (publics) et les messages spécifiques à l'application (privés). Les messages spécifiques à l'application ne doivent être consommés par aucun autre composant, à l'exception de l'application associée et du traducteur de messages associé. Pour renforcer cette politique, nous nommons les canaux de messages spécifiques à l'application en commençant par le nom de l'application, par ex. WEB_NEW_ORDER . Les canaux transportant des messages canoniques sont nommés d'après l'intention du message sans aucun préfixe, par ex. NOUVELLE COMMANDE .

    Nous connectons chaque adaptateur de canal au traducteur de messages via un canal point à point car nous voulons être sûrs que chaque message de commande n'est consommé qu'une seule fois. Nous pourrions nous en sortir sans utiliser de traducteur de messages pour l'interface Web si nous programmions la logique de transformation dans la passerelle. Cependant, les fonctions de transformation de codage manuel peuvent être fastidieuses et sujettes aux erreurs et nous préférons utiliser une approche cohérente. Le traducteur de messages supplémentaire nous permet également de protéger le flux de nouvelles commandes contre les modifications mineures du format de données de l'interface Web. Tous les traducteurs de messages publient sur le même canal point à point NEW_ORDER afin que les commandes puissent être traitées à partir de ce canal sans tenir compte de l'origine de la commande.

    Le canal de message NEW_ORDER est ce qu'on appelle un canal de type de données car il transporte des messages d'un seul type, c'est-à-dire les nouvelles commandes. Cela permet aux consommateurs de messages de savoir facilement à quel type de message s'attendre. Le message de nouvelle commande lui-même est conçu comme un message de document. L'intention du message n'est pas de demander au destinataire de prendre une action spécifique, mais plutôt de transmettre un document à tout destinataire intéressé qui est libre de décider comment traiter le document.

    Maintenant que nous avons un message de commande cohérent et indépendant de la source du message, nous devons traiter les commandes. Afin de remplir une commande, nous devons effectuer les étapes suivantes :

    • Vérifiez la solvabilité du client. Si le client a des factures impayées, nous souhaitons rejeter la nouvelle commande.
    • Vérifier l'inventaire. Nous ne pouvons pas honorer les commandes d'articles qui ne sont pas en stock.
    • Si le client est en règle et que nous avons des stocks, nous voulons acheter les marchandises et facturer le client.

    Nous pouvons exprimer cette séquence d'événements à l'aide d'un diagramme d'activité UML. Les diagrammes d'activités ont une sémantique relativement simple et sont un bon outil pour décrire des processus qui incluent des activités parallèles. Les activités suivantes sont reliées par de simples flèches. Les activités parallèles sont reliées par une épaisse barre noire représentant les actions de fourche et de jointure. Une action de fork entraîne le démarrage simultané de toutes les activités connectées, tandis que l'action de jointure ne se poursuit qu'une fois toutes les activités entrantes terminées.

    Le diagramme d'activité exécute la tâche « Vérifier l'inventaire » et la tâche « Vérifier la position du client » en parallèle. La barre de jointure attend que les deux activités soient terminées avant de permettre à la prochaine activité de démarrer. L'activité suivante vérifie les résultats des deux étapes : avons-nous des stocks et le client est-il en règle ? Si les deux conditions sont remplies, le processus se poursuit pour exécuter la commande. Sinon, nous passons à une activité de gestion des exceptions. Par exemple, nous pouvons appeler le client pour lui rappeler de payer la dernière facture ou lui envoyer un e-mail l'informant que la commande sera retardée. Étant donné que ce livre se concentre sur les aspects de conception de l'intégration orientée message plutôt que sur la modélisation du flux de travail, nous laissons de côté les détails du processus de gestion des exceptions pour le moment. Pour une très bonne discussion sur l'architecture de workflow et la modélisation de workflow, nous vous renvoyons à [Leyman] et [Sharp].


    Diagramme d'activité pour le traitement des commandes

    Il s'avère que les activités correspondent relativement bien aux systèmes du service informatique de WGRUS. Le système comptable vérifie la solvabilité du client, les systèmes d'inventaire vérifient l'inventaire et le système d'expédition lance l'expédition physique des marchandises. Le système comptable fait également office de système de facturation et envoie les factures. La fonction de traitement des commandes est une implémentation typique d'un processus métier distribué.

    Pour convertir le diagramme d'activité logique en une conception d'intégration, nous utilisons un canal de publication-abonnement pour implémenter l'action de fourche et un agrégateur pour implémenter l'action de jointure. Un canal de publication-abonnement envoie un message à tous les consommateurs actifs tandis qu'un agrégateur reçoit plusieurs messages entrants et les combine en un seul message sortant (voir image) :


    Implémentation du traitement des commandes à l'aide de la messagerie asynchrone

    L'agrégateur combine les résultats des deux messages et transmet le message résultant à un routeur basé sur le contenu . Un routeur basé sur le contenu est un composant qui consomme un message et le publie sans modification sur un choix d'autres canaux en fonction de règles codées à l'intérieur du routeur. Le Content-Based-Router est équivalent à la branche dans un diagramme d'activité UML. Dans ce cas, si la vérification d'inventaire et la vérification de crédit ont toutes deux été affirmatives, le routeur basé sur le contenu transfère le message au canal VALIDATED_ORDER. Si le client n'est pas en règle ou si nous n'avons pas de stock disponible, il transmet le message au processus INVALID_ORDER. Le processus d'exception (non représenté sur l'image) écoute les messages sur ce canal et informe le client de la commande rejetée.

    Comme nous l'avons appris dans la section des exigences, WGRUS dispose de deux systèmes d'inventaire, un pour les widgets et un pour les gadgets. Par conséquent, nous devons acheminer la demande d'inventaire vers le système approprié. Parce que nous voulons cacher les particularités des systèmes d'inventaire des autres systèmes, nous insérons un routeur basé sur le contenu qui achemine le message vers le bon système en fonction du type d'article commandé (voir image). Par exemple, tous les messages entrants avec un numéro d'article commençant par « W » sont acheminés vers le système d'inventaire des widgets et toutes les commandes avec un numéro d'article commençant par « G » sont acheminées vers le système d'inventaire des gadgets.


    Acheminer la demande d'inventaire

    Notez que l'intention des messages sur les canaux point à point entre le routeur basé sur le contenu et les systèmes d'inventaire est différente de celle du canal précédent. Ces canaux contiennent des messages de commande, des messages qui demandent au système d'exécuter la commande spécifiée, en vérifiant dans ce cas l'inventaire d'un article.

    Étant donné que le système d'inventaire de widgets et le système d'inventaire de gadgets utilisent des formats de données internes différents, nous insérons à nouveau des traducteurs de messages pour convertir le format de message canonique de nouvelle commande en un format spécifique au système. L'utilisation de Message Translator s avec chaque système d'origine (interface Web, centre d'appels, fax entrant) et chaque système cible (inventaire de widgets et inventaire de gadgets) nous permet de découpler les changements entre les systèmes. Par exemple, si nous ajoutions un autre moyen de passer des commandes (par exemple, la commande par e-mail), aucun des autres systèmes ne serait affecté. Le prix que nous payons pour cette flexibilité est le fait que nous traduisons chaque message deux fois, une fois à la source et une fois à destination.

    Que se passe-t-il si le poste de commande ne commence ni par « W » ni par « G » ? Le routeur basé sur le contenu achemine le message vers le canal INVALID_ORDER afin que la commande invalide puisse être traitée en conséquence, par ex. en informant le client. Ce canal est un exemple typique de canal de message invalide . Cet exemple met en évidence le fait que la signification d'un message change selon le canal sur lequel il se trouve. Le canal NEW_ORDER et le canal INVALID_ORDER transportent le même type de message, mais dans un cas une nouvelle commande est en cours de traitement tandis que dans l'autre cas, la commande est considérée comme invalide.

    Jusqu'à présent, nous avons supposé que chaque commande ne peut contenir qu'un seul article. Ce serait assez gênant pour nos clients car ils devraient passer une nouvelle commande pour chaque article. De plus, nous finirions par expédier plusieurs commandes au même client et entraînerions des frais d'expédition inutiles. Cependant, si nous autorisons plusieurs articles dans une commande, quel système d'inventaire doit vérifier l'inventaire de cette commande ? Nous pourrions utiliser un canal de publication-abonnement pour envoyer la commande à chaque système d'inventaire afin de sélectionner les articles qu'il peut traiter. Mais qu'adviendrait-il alors des éléments invalides ? Comment remarquerions-nous qu'aucun système d'inventaire n'a traité l'article ? We want to maintain the central control the Content-Based Router gives us, but we need to be able to route each order item individually.

    Therefore, we insert a Splitter , a component that breaks a single message into multiple individual messages. In our case, the Splitter splits a single Order message into multiple Order Item message. Each Order Item message can then be routed to the correct inventory system using a Content-Based Router (see below).


    Processing Order Items Individually

    Naturally, when the inventory for all items has been verified, we need to recombine the messages into a single message. We already learned that the component that can combine multiple messages into a single message is the Aggregator . Using both a Splitter and an Aggregator , we can logically separate the message flow for order items from that for orders.

    When designing an Aggregator , we have to make three key decisions:

    • Which messages belong together (“correlation”)?
    • How do we determine that all messages are received (the “completeness condition”)?
    • How do we combine the individual messages into one result message (the “aggregation algorithm”)?

    We can’t correlate order items by the customer ID because a customer may place multiple orders in short succession. Therefore, we need a unique order ID for each order. We accomplish this by inserting a Content Enricher into the Taking Orders solution (see picture). A Content Enricher is a component that adds missing data items to an incoming message.


    Taking Orders With Enricher

    Now that we have an order ID to correlate order item messages, we need to define the completeness condition and the aggregation algorithm. Because we route all messages including invalid items to the Aggregator , the Aggregator can simply use the number of items in the order (one of the fields in the order message) to count until all order items arrive. The aggregation algorithm is similarly simple. The Aggregator concatenates all item messages back into a single order message and publishes it to the VALIDATED_ORDER channel.

    The combination of a Splitter , a Router and an Aggregator is fairly common. We refer to it as a Composed Message Processor . To simplify the picture, we insert the symbol for a Composed Message Processor into the original message flow diagram:


    Revised Order Process Implementation

    Despite connecting the systems via messaging channels, fulfilling an order can take some amount of time. For example, we may be out of a certain item and the inventory system may be holding the inventory check message until new items arrive. This is one of the advantages of asynchronous messaging: the communication is designed to happen at the pace of the components. While the inventory system is “holding” the message, the accounting system can still verify the customer’s credit standing. Once both steps are completed, the Aggregator publishes the Validated Order message to initiate shipment and invoicing.

    A long-running business process also means that both customers and managers are likely to want to know the status of a specific order. For example, if certain items are out of inventory, the customer may decide to process just those items that are in stock. Or if the customer has not received the goods it is useful if we can tell him or her that the goods are on their way (including the shipping company’s tracking number) or that there is an internal delay in the warehouse.

    Tracking the status of an order with the current design is not so easy. Related messages flow through multiple systems. In order to ascertain the status of the order in the sequence of steps we would have to know the “last” message related to this order. One of the advantages of a Publish-Subscribe Channel is that we can add additional subscribers without disturbing the flow of messages. We can use this property to listen in to new and validated orders and store them into a Message Store . We could then query the Message Store database for the status (see picture):


    Adding a Message Store To Track Order Status

    In situations where we use a Point-Point-Channel, we cannot simply add a subscriber to the channel because in a Point-to-Point Channel , each message can only be consumer by a single subscriber. However, we can insert a Wire Tap, a simple component that consumes a message off one channel and publishes it to two channels. We can then use the second channel to send messages to the Message Store (see picture).


    Tracking Messages with a Wire Tap

    Storing message data in a central database has another significant advantage. In the original design each message had to carry all relevant data in order to continue processing the message down the line. For example, the ‘Verify Customer Standing’ may have to pass through all sorts of customer data even though it may only require the customer ID. This additional data is necessary so that the resulting message still contains all data from the original order message. Storing the New Order message in a Message Store has the advantage that all subsequent components can refer to the Message Store for important message data without all intermediate steps having to carry the data along (we will later to this function as Claim Check - messages can “check” data for later retrieval).

    Now the Message Store is responsible for maintaining data related to the new message as well as the progress of the message within the process. This data gives us enough information to use the Message Store to determine the next required steps in the process rather than connecting components with fixed Message Channel s. For example, if the database contains reply messages from both the inventory systems and the billing system, we can conclude that the order has been validated and send a message to the Shipping and billing system. Instead of making this decision in a separate Aggregator component, we can do it right in the Message Store . Effectively, we are turning the Message Store into a Process Manager .

    A Process Manager is a central component that manages the flow of messages through the system. The Process Manager provides two main functions:

    • Storing data between messages
    • Keeping track of progress and determining the next step


    Processing Orders With a Process Manager

    This architecture turns the individual systems (e.g. the inventory systems) into Shared Services that can be accessed by any process. This increases reuse and allows for rapid changes and maintenance. The services themselves can still be composed out of multiple steps, wired together via a message flow (for example, using a Composed Message Processor to check inventory status for each order item), or orchestrated via a Process Manager .

    The Process Manager itself uses a persistent store (typically files or a relational database) to store data associated with each process instance. In order to allow the Web Interface to query the status of an order we could send a message to the Process Manager or the order DB. However, checking status is a synchronous process – the customer expects the response right away. Because the Web Interface is a custom application, we decide to access the Order Database directly to query the order status. This form of Shared Database is the simplest and most efficient approach and we are always ensured that the Web Interface displays the most current status. The potential downside of this approach is the fact that the Web Interface is tightly coupled to the database, a trade-off that we are willing to take.

    The new architecture exposes all services to a common services bus so that they can be invoked from any other component. If we add facilities to lookup (“discover”) a service from a service registry, we can turn the WGRUS IT infrastructure into a Service-Oriented Architecture. In order to participate in a Service-Oriented Architecture, each service has to provide additional functions. For example, each service has to expose an interface contract that describes the functions provided by the service. Each request-reply service also needs to support the concept of a Return Address . A Return Address allows the caller (the “service consumer”) to specify the channel where the service should send the reply message. This is important to allow the service to be reused in different contexts, each of which may require its own channel for reply messages.

    One difficulty in enabling these service functions is that many legacy systems were not build with features such as Return Address in mind. Therefore, we “wrap” access to the legacy system with a Smart Proxy . This Smart Proxy enhances the basic system service with additional capability so that it can participate in a Service-Oriented Architecture. To do this, the Smart Proxy intercepts both request and reply messages to and from the basic service (see picture).


    Inserting a Smart Proxy to Turn a Legacy System Into a Shared Service

    The Smart Proxy can store information from the request message (e.g. the Return Address specified by the requestor) and use this information to process the reply message, (e.g. route it to the correct reply channel). A Smart Proxy is also very useful to track quality of service (e.g. response times) of an external service.

    WGRUS needs to deal with a number of addresses. For example, the invoice has to be sent to the customer’s billing address while the goods are shipped to the shipping address. We want to allow the customer to maintain all these addresses through the Web Interface to eliminate unnecessary manual steps.

    We can choose between two basic approaches to get the correct billing and shipping addresses to the billing and shipping systems:

    • Include address data with the New Order message
    • Replicate address data to other systems

    The first option has the advantage that we can use an existing integration channel to transport the additional information. A potential downside is the additional data flowing across the middleware infrastructure. We pass the address data along with every order even though the address may change much less frequently.

    Because the billing and shipping systems are packaged applications they were not designed with integration in mind. As such, they are unlikely to be able to accept addresses with a new order but rather use the address that is stored in their local database. In order to enable the systems to update the address with the New Order message we need to execute two functions in the billing system (and the shipping system): first, we need to update the address, and then we need to send the bill (or ship the goods). Because the order of the two messages matters we insert a simple Process Manager component that receives a New Order message (which includes the current shipping and billing address0 and publishes two separate messages to the billing (or shipping) system (see diagram).


    Including Address Data in the New Order Message

    We update the address directly into the system database using a database Channel Adapter . Sending the goods or producing an invoice has to invoke the applications’ business logic. Therefore, we connect to the applications’ business tiers and invoke the correct API function when a message is received.

    We need to keep in mind that the Channel Adapter s require messages to be formatted in the proprietary formats used by the applications (using so-called private messages). Because the New Order message arrives in the canonical message format we need to perform a translation between the two formats. We could build the transformation into the Process Manager but we actually prefer external Message Translator s so that the logic inside the Process Manager is not affected by the possibly complicated data format required by the applications.

    The second option uses data replication to propagate address changes to all affected systems independently of the New Order process. Whenever the address information changes in the Web interface we propagate the changes to all interested systems using a Publish-Subscribe Channel . The systems store the updated address internally and use it when an order message arrives. This approach reduces message traffic (assuming customers change addresses less frequently than they place orders). It can also reduce coupling between systems. Any system that uses an address can subscribe to the ADDRESS_CHANGE channel without affecting any other systems. The potential downside is that we have to build another interface function for the billing and shipping systems to enable them to consume address change messages.

    Because we are dealing with multiple types of addresses (shipping and billing addresses) we need to make sure that only the right type of address is stored in each system. We need to avoid sending an address change message to the shipping system if the address is a billing address. We accomplish this by using Message Filters that only pass messages matching certain criteria (see diagram).

    We also use Message Translator s to translate the generic Address Change message into the specific message format used by the applications. In this case we do not use a Message Translator for the Web Interface because we define the Canonical Data Model as equal to the format of the Web Interface application. This could limit out flexibility if we want to introduce other ways of changing addresses in the future, but for now it is sufficient.


    Propagating Address Changes via a Separate Publish-Subscribe Channel

    Both the shipping and the billing system store addresses in a relational database so that we use a database Channel Adapter to update the data in each system.

    How do we decide between the two options? In our situation the message traffic is not much of a concern because we only process a few hundred orders a day, so either solution would work well. The main decision driver is going to be the internal structure of the applications. We may not be able to insert the addresses directly into the database, but rather through the applications’ business layer. In this case the applications may perform additional validation steps and record the address change activity. The system may even be programmed to e-mail a confirmation message to the customer every time the address changes. This would get very annoying if the update the address with every order. Such a condition would favor propagating address changes using dedicated messages that are sent only when the customer actually changes the address.

    In general we prefer well-defined, self-contained business actions such as “Change Address” and “Place Order” because they give us more flexibility in orchestrating the businesses processes. It all comes down to a question of granularity and the associated trade-offs. Fine-grained interfaces can lead to sluggish systems due to an excessive number of remote calls being made or messages being sent. For example, imagine an interface that exposes a separate method to change each address field. This approach would be efficient if the communication happens inside a single application – you only update those fields that changed. In an integration scenario sending six or seven messages to update an address would be a significant overhead plus we would have to deal with synchronizing the individual messages. Fine-grained interfaces also lead to tight coupling. If we change the address format, we have to define new message formats and change all other applications to send an additional message.

    Coarse grained interfaces solve these issues. We send fewer messages and are therefore more efficient and less tightly coupled. However, interfaces that are too coarse can limit our flexibility. If Send Invoice and Change Address are combined into one external function, will we never need to change an address without sending a bill? So as always the best answer is the happy medium and depends on the specific trade-offs at work in the real-life scenario.

    In order for customers to place orders they need to see the currently offered items and their prices on-line. WGRUS’ catalog is driven by the offerings from the respective suppliers. However, one of the services that WGRUS provides to its customers is allowing them to view widgets and gadgets on the same site and to order both types of items in a single order. This function is an example of an Information Portal scenario – we combine information from multiple sources into a single view.

    It turns out that both suppliers update their product catalog once every 3 months. Therefore, it makes relatively little sense to create a real-time messaging infrastructure to propagate catalog changes from the suppliers to WGRUS. Instead, we use File Transfer integration to move catalog data from suppliers to WGRUS. The other advantage of using files is that they are easily and efficiently transported across public networks using FTP or similar protocols. In comparison, most asynchronous messaging infrastructures do not work well over the public Internet.

    We still can use Translators and Adapters to transform the data to our internal catalog format. However, these Translators process a whole catalog at once instead of one item at a time. This approach is much more efficient if we are dealing with large amounts of data in the same format.


    Updating Catalog Data via File Transfer

    In order to improve business, we want to announce specials to our customers every once in a while. In order to not annoy the customers, we allow the customer to only receive messages that are of interest to them. We also want to target specific messages to a specific subset of customers. For example, we may announce special deals only to preferred customers. When we need to send information to multiple recipients, a Publish-Subscribe Channel immediately comes to mind. However, a Publish-Subscribe Channel has some disadvantages. First, it allows any subscriber to listen to the published messages without the publisher’s knowledge. For example, we would not want smaller customers to receive special offers intended for high-volume customers. The second downside of Publish-Subscribe Channel s is that they work efficiently only on local networks. If we send data across wide-area networks the Publish-Subscribe Channel we have to send a separate copy of the message to each recipient. If a recipient is not interested in the message we would have incurred unnecessary network traffic.

    Therefore, we should look for a solution that allows subscribers to issue their subscription preferences and then send individual messages only to interested (and authorized) customers. In order to perform this function we use a Dynamic Recipient List. UNE Dynamic Recipient List is the combination of two Message Routing patterns. A Recipient List is a router that propagates a single message to a set of recipients. The main difference between the Recipient List and a Publish-Subscribe Channel is that the Recipient List addresses each recipient specifically and therefore has tight control over who receives messages. A Dynamic Router is a router whose routing algorithm can change based on control messages. These control messages can take the form of subscription preferences issued by the subscribers. Combining these two patterns results in a Dynamic Recipient List.


    Sending Announcements With a Dynamic Recipient List

    If customers receive announcements via e-mail, the implementation of these patterns can use the mailing lists features typically supplied by e-mail systems. Each recipient channel is then identified by an e-mail address. Likewise, if customers prefer to receive announcements via a Web services interface, each recipient channel is implemented by a SOAP request and the channel address is the URI of the Web service. This example illustrates that the patterns we use to describe the solution design are independent of a specific transport technology.

    Testing and Monitoring

    Monitoring the correct execution of messages is a critical operations and support function. The Message Store can provide us with some important business metrics such as the average time to fulfill an order. However, we may need for more detailed information for the successful operation of an integration solution. Let’s assume we enhance our solution to access an external credit agency to better assess our customer’s credit standing. Even if we show no outstanding payments we may want to decline a customer’s order if the customer’s credit ranking is particularly poor. This is especially useful for new customers. Because the service is provided by an outside provider we are being charged for its use. To verify the provider’s invoice we want to track our actual usage and reconcile the two reports. We cannot simply go by the number of orders because the business logic may not request an external credit check for long-standing customers. Also, we have a Quality of Service (QoS) with the external provider. If the response time exceeds a specified time, we do not have to pay for the request.

    To make sure we are being billed correctly we want to track the number of requests we made and the time it takes for the associated response to arrive. We have to be able to deal with two specific situations. The external service can process more than one request at a time, so we need to be able to match up request and reply messages. Second, since we treat the external service as a shared service inside our enterprise we want to allow the service consumer to specify a Return Address , the channel where the service should send the reply message. It could be difficult to match request and reply messages if we don’t know which channel the reply message is on.

    Once again the Smart Proxy is the answer. We insert the Smart Proxy between any service consumer and the external service. We replace the Return Address specified by the service consumer with a fixed reply channel. We store the original Return Address inside the Smart Proxy so that it can forward the reply message to the channel specified by the consumer. The Smart Proxy also measures the time elapsed between request and reply message from the external service. The Smart Proxy publishes this data to the Control Bus . The Control Bus is connected to a management console that collects metrics from many different components.


    Inserting a Smart Proxy to Track Response Times

    We also want to make sure that the external credit service is working correctly. The Smart Proxy can report cases where no reply message is received within a specified time-out period to the management console. Much harder to detect are cases where the external service returns a reply message but the results in the message are incorrect. For example is the external service malfunctions and returns a credit score of zero for every customer we would end up denying every order. There are two mechanisms that can help us protect against such a scenario. First, we can periodically inject a Test Message into the request stream. This Test Message requests the score for a specific person so that the result is known. We can then use a Test Data Verifier to not only check the fact that a reply was received but also the accuracy of the message content. Because the Smart Proxy supports Reply Addresses the Test Data Generator can specify a special reply channel to separate test replies from regular replies (see picture).


    Inserting Test Messages to Verify Accurate Results

    Another effective strategy to detect malfunctioning services that return messages in a valid format but with bad data is to take a statistical sample. For example, we may expect to decline an average of less than one in 10 orders due to the customer’s poor standing. If we decline more than 5 orders in a row this may be an indication that an external service or some business logic is malfunctioning. The management console could e-mail the five orders to an administrator who can then take a quick look at the data to verify whether the rejections were justified.


    InnoDB

    InnoDB is a storage engine for MySQL. MySQL 5.5 and later use it by default. It provides the standard ACID-compliant transaction features, along with foreign key support (Declarative Referential Integrity). It implements both SQL and XA transactions, tablespaces, FULLTEXT indexes, and spatial operations following the OpenGIS standard. It is included as standard in most binaries distributed by MySQL AB, the exception being some OEM versions. The software is dual licensed by the Oracle Corporation it is distributed under the GNU General Public License, but can also be licensed to parties wishing to combine InnoDB in proprietary software.