<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Transentia &#187; SOA</title>
	<atom:link href="http://wordpress.transentia.com.au/wordpress/tag/soa/feed/" rel="self" type="application/rss+xml" />
	<link>http://wordpress.transentia.com.au/wordpress</link>
	<description>transentia pty. ltd.; development, consulting, training at the leading-edge of technology</description>
	<lastBuildDate>Tue, 13 Dec 2011 03:01:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2</generator>
		<item>
		<title>In A Whimsical Mood</title>
		<link>http://wordpress.transentia.com.au/wordpress/2011/02/05/in-a-whimsical-mood/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2011/02/05/in-a-whimsical-mood/#comments</comments>
		<pubDate>Sat, 05 Feb 2011 12:06:15 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[Retrospectives]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=1245</guid>
		<description><![CDATA[Good morning Class! Welcome back to the Cervantes School of Software Wrangling! This course is &#8220;Tiliting at Windmills 201.&#8221; I&#8217;m your lecturer Don Quixote. We will begin with a snap quiz. You have two well-established computer systems A and B. In accordance with its original design system B makes use of a small but signifiant [...]]]></description>
			<content:encoded><![CDATA[<p>Good morning Class! Welcome back to the Cervantes School of Software Wrangling!</p>
<p>This course is &#8220;Tiliting at Windmills 201.&#8221;</p>
<p>I&#8217;m your lecturer Don Quixote.</p>
<p>We will begin with a snap quiz.</p>
<p>You have two well-established computer systems A and B. In accordance with its original design system B makes use of a small but signifiant proportion of system A&#8217;s schema. It is proposed that system B should be enhanced, which will require accessing a few additional tables from system A&#8217;s schema. </p>
<p>Do you:</p>
<ol type='A'>
<li>Go ahead and grab the data you need, along the lines of what is already being done?</li>
<li>First espouse the concept of a &#8220;common integration language&#8221; and then promote the idea of linking the two systems together via some to-be-announced-Real-Soon-Now &#8220;integration layer&#8221;?</li>
<li>Place a huge purchase order for the latest silver bullet product espoused in last month&#8217;s &#8220;What&#8217;s Next! A busy CIO&#8217;s guide to the latest trends in ICT&#8221; magazine, mandate that this product is now the &#8220;Enterprise Standard&#8221;, and require systems A &#038; B should use this product for their new &#8220;Enterprise-level Interactions&#8221;?</li>
</ol>
<p>I&#8217;ll give you a few seconds to think about it….</p>
<p>…time&#8217;s up.</p>
<p>Now: those of you who answered &#8216;A&#8217;…</p>
<p>Sigh. Did you learn nothing last year? Don&#8217;t you remember &#8220;Complification 101&#8243;? Don&#8217;t you remember the Three Principles: &#8216;Complicate&#8217;, &#8216;Obfuscate&#8217;, &#8216;Procrastinate&#8217;? I am disappointed in you…you&#8217;ll never get ahead in today&#8217;s enterprise with a can-do attitude like that. </p>
<p>OK. Who answered B?</p>
<p>That&#8217;s more like it!  Glad to see you &#8216;B&#8217;s were paying attention in &#8220;Elementary Enterprise Operations 101&#8243; last year. Remember that this alternative gives you the advantage of being able to wander around the whole organisation declaiming &#8220;Integration Layer&#8221; at every opportunity. This may not constitute a successful approach to building working software but it sure is a great way of building visibility with The Powers That Be…and what&#8217;s more important, after all, eh?</p>
<p>NO, Mr. &#8220;I answered &#8216;A&#8217;…I thought it was all about building software to do something useful&#8221;…it isn&#8217;t. Really! Maybe you should be rethinking your career path while the year is still young? </p>
<p>Did anybody answer C? Ah. you must be from the &#8220;Software and Sales&#8221; double degree. I see bright futures ahead for you guys. This is the way to go! Even you &#8216;B&#8217;s need to take notice here. Maybe even consider taking &#8220;Hype and Hysteria 204&#8243;? There&#8217;s always another silver bullet just around the corner and you don&#8217;t want to miss out on the opportunities. </p>
<p>Who&#8217;s left? You over there…you&#8217;re a &#8220;Software Law&#8221; student aren&#8217;t you? Kibitzing, I see…what are you looking so happy about? Wonderful, just wonderful: &#8220;Looking forward to all those failed implementations.&#8221; This, class, is what you should really be aspiring to if you really want to succeed! The software wrangling business is for mugs&#8230;why do you think that I am standing here in front of you and not sitting in front of a computer!</p>
<p>OK. With all this in mind, let&#8217;s begin, shall we? </p>
<p>Today&#8217;s lecture is entitled &#8220;A Picture Paints A Thousand Words. It Also Consumes Many Megabytes, Gives You RSI And Still Ends Up Less Useful Than A Single Line Of Code.&#8221;  Please open your books to the chapter entitled &#8220;Oracle Service Bus&#8221;…</p>
<p><em>I&#8217;ve got to go now&#8230;some nice men in white coats have come to take me on holiday. How nice of them!</em></p>
<p>Seriously though&#8230;some 2004-vintage food for thought, entitled <a href="http://www.ebpml.org/site_updates.htm#40">Jump off the bus, take a cab!</a>:</p>
<blockquote><p>
&#8230;<br />
A lot of companies have expressed the similarities between SOA and the concept of (hardware) Bus&#8230;.I understand that a bus offers a &#8220;common interface infrastructure&#8221; and components can use the bus to communicate with each other, this is pretty much where the analogy stops for SOA. SOA requires very little in the middle (other than a standard communication infrastructure, that we already have for free) and is inherently point to point and asynchronous, unlike most bus architectures which require some centralized infrastructure and synchronous behavior. I would agree with the OASIS/BCM group that the only shared component in a SOA is a directory service.<br />
&#8230;
</p></blockquote>
<p>Bear this quote in mind the next time some SOA-totin&#8217; salesman attempts to bale up your checkbook with an order for their latest and greatest centralised server-based product.</p>
<p>Also worth an &#8220;honourable mention&#8221; is this oldie-but-a-goodie from InfoQ: <a href="http://www.infoq.com/news/2007/08/esb-oriented-architecture">ESB-Oriented Architectures considered harmful</a>.</p>
<p>A final thought, as directed at the &#8216;real&#8217; Don Quixote:</p>
<blockquote><p>And you, Señor Don Quixote, your head is going to end up a stranger to your neck. </p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2011/02/05/in-a-whimsical-mood/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unit Testing XQuery Using OSB&#8217;s API</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/11/20/unit-testing-xquery-using-osbs-api-2/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/11/20/unit-testing-xquery-using-osbs-api-2/#comments</comments>
		<pubDate>Sat, 20 Nov 2010 04:09:56 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[OSB]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Retrospectives]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[XQuery]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=1183</guid>
		<description><![CDATA[As regular readers (all one[?] of you) will know, I have recently been subjected to the woeful Oracle Service Bus. Concomitant with my attempts to be a good modern developer, one of the first entries on my Fings Wot I Need To Find Out More About list went something like: Given that almost all of [...]]]></description>
			<content:encoded><![CDATA[<p>As regular readers (all one[?] of you) will know, I have <a href="http://wordpress.transentia.com.au/wordpress/2010/11/07/the-emperors-new-service-bus/">recently</a> been subjected to the <a href="http://www.crazymcphee.net/x/2010/07/12/the-ordeal-of-installing-oracle-service-bus-on-a-windows-based-developer-workstation/">woeful</a> Oracle Service Bus.</p>
<p>Concomitant with my attempts to be a good modern developer, one of the first entries on my <em>Fings Wot I Need To Find Out More About</em> list went something like:</p>
<blockquote><p>Given that almost all of the actual &#8216;code&#8217; in my system will be XQuery transformations, how do I unit-test those transformations with JUnit? It is obviously important that I use the weblogic API/Jars, not some external or third-party system.</p></blockquote>
<p><strong>Roughly six months</strong> later I am finally in a position to answer that question!</p>
<p>Took me a few goes (turns out that there are a number of different potential red-herring APIs to filter out and reject, including BEAs <a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.92.2337&amp;rep=rep1&amp;type=pdf">xdbc</a>), a number of visits to <a href="http://www.javamonamour.org/2010/05/xquery-and-unit-tests.html">other</a> <a href="http://biemond.blogspot.com/2008/11/using-xquery-in-jdeveloper-11g-and.html">people</a>&#8216;s <a href="http://blogs.oracle.com/knutvatsendvik/2010/03/unit_testing_framework_for_xquery.html">attempts</a> and about 20 messages on the Oracle forum (gotta say I appreciated the comment &#8220;I just wanted to praise your discipline and devotion to research and investigation. Kudos!&#8221; that I picked up along the way&#8230;) but here I am.</p>
<p>This is the Groovy JUnit4 test class, just to prove that it can be done:</p>
<pre>package transentia.test

import org.junit.*
import transentia.XQueryTransformer

class XQTest {
  def xqt

  @Before
   void setup() {
    xqt = new XQueryTransformer("xqueries/Messier.xq",
                                 src: new File("xml/Messier.xml"),
                                 str: 'hello, world',
                                 n: 42,
                                 b: true,
                                 dt: new Date(),
                                 f: Math.PI,
                                 nd: null as Date)
  }

  @Test
  void testTransform() {
    xqt.withString { str -&gt;
      println str
    }
  }

  @Test
  void testSlurping() {
    xqt.withString { str -&gt;
      def data = new XmlSlurper().parseText(str).declareNamespace(oth: "http://other")
      assert data.'oth:m'.size() == 5
      assert data.'oth:m'[3].text() == 'Scorpius'
    }
  }

  @Test
  void testParsing() {
    xqt.withString { str -&gt;
      def data = new XmlParser().parseText(str)
      assert data.'oth:m'.size() == 5
      assert data.'oth:m'[4].text() == 'Serpens'
    }
  }
}</pre>
<p>Pretty trivial.</p>
<p>This is the XQuery that is under test:</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/11/Messier.xq_.png" alt="" title="Messier.xq" width="600" class="alignnone size-full wp-image-1225" /></p>
<p>(Strangely, wordpress simply <em>refuses</em> to display this file without barfing. Can&#8217;t for the life of me work out why, hence the above is an image. <a href='http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/11/Messier.xq_.txt'>Here&#8217;s the real file</a>)</p>
<p>Notice the &lt;destination:m?&gt; bit? That trailing question mark is a BEA extension to the standard XQuery language: <a href="http://download.oracle.com/docs/cd/E13167_01/aldsp/docs30/xquery/extensions.html">&#8220;Optional Indicator in Direct Element and Attribute Constructors.&#8221;</a> Very useful but not widely advertised/supported (which basically accounts for why it took me 6 months to work out how to handle it).</p>
<p>Next is the XML file:</p>
<pre>&lt;?xml version="1.0" standalone="yes" ?&gt;
&lt;MESSIER xmlns="http://transentia"&gt;
  &lt;M INDEX="1"&gt;
    &lt;CONSTELLATION&gt;Taurus&lt;/CONSTELLATION&gt;
    &lt;DESCRIPTION&gt;Diffuse Nebula&lt;/DESCRIPTION&gt;
  &lt;/M&gt;
  &lt;M INDEX="2"&gt;
    &lt;CONSTELLATION&gt;Aqarius&lt;/CONSTELLATION&gt;
    &lt;DESCRIPTION&gt;Globular Cluster&lt;/DESCRIPTION&gt;
  &lt;/M&gt;
  &lt;M INDEX="3"&gt;
    &lt;CONSTELLATION&gt;Canes Venatici&lt;/CONSTELLATION&gt;
    &lt;DESCRIPTION&gt;Globular Cluster&lt;/DESCRIPTION&gt;
  &lt;/M&gt;
  &lt;M INDEX="4"&gt;
    &lt;CONSTELLATION&gt;Scorpius&lt;/CONSTELLATION&gt;
    &lt;DESCRIPTION&gt;Globular Cluster&lt;/DESCRIPTION&gt;
  &lt;/M&gt;
  &lt;M INDEX="5"&gt;
    &lt;CONSTELLATION&gt;Serpens&lt;/CONSTELLATION&gt;
    &lt;DESCRIPTION&gt;Globular Cluster&lt;/DESCRIPTION&gt;
  &lt;/M&gt;
  &lt;M INDEX="6"&gt;
    &lt;DESCRIPTION&gt;ONLY FOR TESTING&lt;/DESCRIPTION&gt;
  &lt;/M&gt;
&lt;/MESSIER&gt;</pre>
<p>This file is just a tiny amount of fixture data for testing.</p>
<p>The missing &lt;CONSTELLATION&gt; element within the final &lt;M&gt; element should &#8216;trigger&#8217; the XQuery engine to elide the empty &lt;destination:m /&gt; element that it would normally produce; thus the tests are all expecting 5 elements in the transformed XML, not 6 as in the source.</p>
<p>And now&#8230;without further ado&#8230;the <a href="http://en.wikipedia.org/wiki/Pièce_de_résistance">pièce de résistance</a>:</p>
<pre>
package transentia

import org.apache.xmlbeans.XmlObject
import org.apache.xmlbeans.XmlOptions
import org.apache.xmlbeans.XmlDateTime
import org.apache.xmlbeans.XmlBoolean
import org.apache.xmlbeans.XmlInteger
import org.apache.xmlbeans.XmlDouble
import org.apache.xmlbeans.XmlString

class XQueryTransformer {
  private final resultXML

  public XQueryTransformer(map, xQueryTransformSource) {

    XmlObject xmlObject = XmlObject.Factory.newInstance()
    XmlOptions options = new XmlOptions()

    options.setXqueryVariables(createOptions(map))

    XmlObject[] results = xmlObject.execQuery(new File(xQueryTransformSource).text, options)

    resultXML = results[0].xmlText(new XmlOptions().setSavePrettyPrint().setSavePrettyPrintIndent(2))
  }

  private createOptions(map) {
    def optionsMap = [:]
    map.each { k, v ->
      switch (v?.class) {
        case Date:
          XmlDateTime dt = XmlDateTime.Factory.newInstance();
          dt.setDateValue(v)
          optionsMap.put(k, dt)
          break
        case Boolean:
          XmlBoolean b = XmlBoolean.Factory.newInstance();
          b.set(v)
          optionsMap.put(k, b)
          break
        case [BigInteger, Integer, Long, Short, Byte, byte, short, int, long]:
          XmlInteger i = XmlInteger.Factory.newInstance();
          i.setBigIntegerValue(v as BigInteger)
          optionsMap.put(k, i)
          break
        case [BigDecimal, Float, Double, float, double]:
          XmlDouble xd = XmlDouble.Factory.newInstance();
          xd.setDoubleValue(v as double)
          optionsMap.put(k, xd)
          break
        case String:
          XmlString string = XmlString.Factory.newInstance();
          string.setStringValue(v);
          optionsMap.put(k, string)
          break
        case File:
          def txt = v.text

          // look for the prologue < ?xml ...?> processing instruction
          def m = txt =~ /(\< \?xml[^>]*\>)/
          if (m.count > 0) {
            def xmlPI = m[0][1]
            txt = """${xmlPI}
<temp42 :root42 xmlns:temp42='temp42'>${txt[xmlPI.size()..-1]}</temp42>
"""
          }
          else
            txt = "<temp42 :root42 xmlns:temp42='temp42'>${txt}</temp42>"

          // all the messing around with xml processing instruction/adding a new root above is because
          // selectChildren seems to be required. Don't know why...
          optionsMap.put(k, XmlObject.Factory.parse(txt).selectChildren("temp42", "root42")[0])
          break

        case null:
          XmlObject n = XmlObject.Factory.newInstance()
          n.setNil()
          optionsMap.put(k, n)
          break

        default:
          throw new Exception("Unhandled type: ${v.class}")
          break
      }
    }
    optionsMap
  }

  def withString(c) {
    c.call resultXML
  }
}
</pre>
<p>I&#8217;ve <a href="/wordpress/2010/02/23/the-old-groovy-switch-eroo-again/">said</a> it <a href="/wordpress/2009/03/11/inventing-a-new-statement-for-groovy-in-10- minutes/">before</a> and I&#8217;ll most likely say it again: <em>love</em> the Groovy switch statement!</p>
<p>A bit of clarification for the &#8216;File&#8217; case is in order, I guess because it&#8217;s quite confusing! I found that I had to wrap a dummy <temp42 :root42> root element around the original root <messier> element in order to immediately select only the single child element (the original </messier><messier>)&#8230;this is why I need to isolate the processing instruction: the opening tag has to go between the PI and the </messier><messier> tags. It seemed easiest to do this with simple string manipulation&#8230;</p>
<p>Here is the tricky bit&#8230;the various jars that need to be placed on the classpath:</p>
<pre>
oracle.nlsrtl_11.1.0\orai18n-collation.jar
oracle.xdk_11.1.0\xquery.jar
com.bea.core.xml.xmlbeans_2.0.0.0_2-5-1.jar
com.bea.core.xquery.xmlbeans-interop_1.3.0.0.jar
com.bea.core.binxml_1.3.0.0.jar
oracle.xdk_11.1.0\xml.jar
com.bea.core.xquery_1.3.0.0.jar
oracle.xdk_11.1.0\xmlparserv2.jar
com.bea.core.xquery.beaxmlbeans-interop_1.3.0.0.jar
weblogic.server.modules.xquery_10.3.3.0.jar
</pre>
<p>(Note the ordering: this is what <a href="http://confluence.jetbrains.net/display/IDEADEV/IDEA+X+EAP">IntelliJ X EAP</a> worked out for me; who am I to argue&#8230;)</p>
<p>And to cut out any confusion, here&#8217;s what I have in my Intellij project:</p>
<pre>
C:\DEVELOPMENT\XQueryTester&gt;tree /f /a
Folder PATH listing for volume Bugblatter
Volume serial number is 42E3-A91B
C:.
|   XQueryTester.iml
|
...
|
+---lib
|   |   com.bea.core.binxml_1.3.0.0.jar
|   |   com.bea.core.xml.xmlbeans_2.0.0.0_2-5-1.jar
|   |   com.bea.core.xquery.beaxmlbeans-interop_1.3.0.0.jar
|   |   com.bea.core.xquery.xmlbeans-interop_1.3.0.0.jar
|   |   com.bea.core.xquery_1.3.0.0.jar
|   |
|   +---modules
|   |   \---features
|   |           weblogic.server.modules.xquery_10.3.3.0.jar
|   |
|   +---oracle.nlsrtl_11.1.0
|   |       orai18n-collation.jar
|   |
|   \---oracle.xdk_11.1.0
|           xml.jar
|           xmlparserv2.jar
|           xquery.jar
|
...
|
+---src
|   \---transentia
|       |   XQueryTransformer.groovy
|       |
|       \---test
|               XQTest.groovy
|
+---xml
|       Messier.xml
|
\---xqueries
        Messier.xq

C:\DEVELOPMENT\XQueryTester&gt;
</pre>
<p>All requisite jars can be found within the OSB 11g installation.</p>
<blockquote><p><strong>Update 2011 01 01</strong>; at least one person has read this and given me some feedback:</p>
<p><em>I needed to add com.bea.core.antlr_2.7.7.jar to the build path as<br />
well. Maybe it&#8217;s because I use Eclipse and not IDEA.</em></p>
<p>Thanks, Morten!</p></blockquote>
<p>The proof, as &#8216;they&#8217; say is in the pudding&#8230;</p>
<p>Here&#8217;s the passing case:</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/11/XQTestSuccess.png" /></p>
<p>Now for the failing case (with the ? taken out of the XQuery transformation):</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/11/XQTestFailure.png" /></p>
<p>Take a good look at the way the failed assertion is represented in the above screenshot. Something else to love about Groovy!</p>
<p>Hope this helps some other OSB user actually trying to <em>embrace</em> good software engineering practices.</p>
<p>The above isn&#8217;t perfect but it&#8217;s better than nothing. Use it; improve it; share it. Please let me know what you have done&#8230;</p>
<p>Restating something I said in the Oracle SOA Suite forums:</p>
<blockquote><p>
IMHO it is RIDICULOUS that what we are trying to achieve here is not clearly described and supported for OSB.</p>
<p>For something like Apache Camel or Spring Integration testing is a complete no-brainer. For OSB it seems almost impossible to do properly. For me this is a (/one of the) killer points AGAINST OSB.
</p></blockquote>
<p>Its a shame that this is not available from Oracle but then one can&#8217;t really expect them to go to all that trouble of carefully crafting a tool like OSB with maximum lock-in potential and then make the APIs openly accessible, can one?<br />
(&#8230;and <strong>yes</strong> I <strong>do</strong> know the genesis of <a href="http://xmlbeans.apache.org/">Apache XMLBeans</a>&#8230;)</p>
<p>Ooohhhh&#8230;hope I&#8217;m not breaking any licensing rules here&#8230;don&#8217;t want to tangle with Oracle&#8217;s lawyers, after all!</messier></temp42></p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/11/20/unit-testing-xquery-using-osbs-api-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Emperor&#8217;s New Service Bus</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/11/07/the-emperors-new-service-bus/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/11/07/the-emperors-new-service-bus/#comments</comments>
		<pubDate>Sun, 07 Nov 2010 20:20:04 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[OSB]]></category>
		<category><![CDATA[Rant]]></category>
		<category><![CDATA[Retrospectives]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=996</guid>
		<description><![CDATA[I&#8217;m going to revist a previous topic here&#8230; I am currently working on a pretty simple systems integration task: read from a small bunch of database tables, munge the data and call a variety of webservices. Fundamentally a simpler integration problem than the exemplar for Spring Integration I worked up before. Pretty simple with Java [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m going to <a href="/wordpress/2009/02/25/soa-the-tarpit-of-irrelevancy/">revist</a> a <a href="http://wordpress.transentia.com.au/wordpress/2009/04/02/thank-you-oracle/">previous</a> topic here&#8230;</p>
<p>I am currently working on a pretty simple systems integration task: read from a small bunch of database tables, munge the data and call a variety of webservices. Fundamentally a simpler integration problem than <a href="/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/">the exemplar for Spring Integration I worked up before</a>. Pretty simple with Java and a framework like Spring Integration or Apache Camel; undoubtedly even simpler if I could add Groovy into the mix.</p>
<p>Organisation says: &#8220;Thou Shalt Use Oracle Service Bus.&#8221;</p>
<p>Ever heard the joke about regular expressions: <em>Once upon a time a programmer had a problem. He decided to solve it using Regular Expressions. Then he had two problems.</em></p>
<p>Welcome to my world (with an OSB flavour) :-)</p>
<p>I&#8217;ll try and capture a few thoughts and experiences below.</p>
<p>It is <strong>very rare</strong> that I react so strongly <em>against</em> a technology&#8230;.can&#8217;t really think of another example. I&#8217;m usually pretty gung-ho and even suffer from odd breakouts of evangelical fervour. I can even find a place for UML in the nerd-ish pantheon :-) For this product all bets are off. I&#8217;m struggling to find a silver lining in the cloud.</p>
<p>I hope that if I break things up into small doses, you won&#8217;t break down with sympathy tears&#8230;</p>
<h3>Positioning</h3>
<p>Why choose OSB vs a BPEL implementation? BPEL has an <a href="http://www.oasis-open.org/committees/tc_home.php?wg_abbrev=wsbpel">OASIS standard</a> behind it, is the richer language, is more mature and more expressive, has better tooling, has multivendor support, can deal with state, timouts and long-running workflows&#8230;all the things that one needs in an integration setting. OSB does practically none of these things, so <a href="http://www.lyricsdepot.com/dionne-warwick/alfie.html">what&#8217;s it all about, Larry</a>?</p>
<p>Ahhhh&#8230;perhaps that little &#8216;multivendor&#8217; word gives us a clue? &#8220;So young to be so cynical&#8221;, I hear you say.</p>
<p>I have heard it said that OSB is &#8220;high level&#8221; and the alternatives like <a href="http://camel.apache.org/">Apache Camel</a> and <a href="http://www.springsource.org/spring-integration">Spring Integration</a> are developers tools and as such are too &#8220;low level&#8221; to be true solutions. Sigh. I thought that old argument for <a href="http://en.wikipedia.org/wiki/Computer-aided_software_engineering">CASE</a> was put to bed long ago. It&#8217;s sad perhaps, but you still need developers to do complex development. Don&#8217;t believe me? Take a look at the average spreadsheet and then tell me how appropriate this &#8220;end-user engineering&#8221; idea is. </p>
<p>The task is not to find the most abstract or pretty tool but to put into the developers&#8217; sweaty hands the toolset capable of getting into the gnarly nooks and crannies of a problem space and still come out on top. Next time you hire a carpenter or electrician or plumber, take a look into his/her toolbox. It won&#8217;t be pretty but it will be varied and capable. I&#8217;ll bet that it took the tradesperson quite a bit of training and experience to work effectively with everything in it too&#8230;there is <em>no</em> magic bullet.</p>
<h3>Architectural</h3>
<p>&#8220;Stored Procedures migrate to Session Beans&#8221; used to be the J2EE catch-call (for very good reasons, IMHO, <a href="http://www.theserverside.com/discussions/thread.tss?thread_id=2613">YMMV</a>). In my current OSB-oriented project, this seems to have become &#8220;Let&#8217;s do as much as possible in stored procedures because it&#8217;s too darned painful to even consider otherwise.&#8221;</p>
<p>This is really <a href="http://idioms.thefreedictionary.com/go+against+the+grain">rubbing against the grain</a>!</p>
<p>It&#8217;s interesting that these days, discussions regarding Systems Integration always bring up the &#8220;<a href="http://www.slideshare.net/gschmutz/oracle-soa-suite-11g-mediator-vs-oracle-service-bus-osb">VETRO pattern</a>&#8220;: Validate, Enhance, Transform, Route, Operate. This is great, as far as it goes. In my experience however VETRO is by far the easy side of SI. Prising and cajoling the requisite data out from the various niches, repositories, formats, access methods, security regimes, etc. tends to be much more tricky and is a <b>necessary prerequisite</b>. It&#8217;s sad, but I can&#8217;t think of a catchy management friendly phrase for all this nasty boring legwork. The term &#8220;<a href="http://www.sas.com/technologies/analytics/datamining/">Data Mining</a>&#8221; is already taken, darn it! Regardless, I&#8217;m absolutely positive that no pretty picture is going to encapsulate the true reality of the SI task. I&#8217;m all for aspiring to do better but hey&#8230;even in <a href="http://www.startrek.com/">Star Trek</a> they sometimes need to reverse the polarity of their <a href="http://en.wikipedia.org/wiki/Polaron">polaron</a> fields in new and untested ways, and when they do they don&#8217;t draw pretty pictures but rip off the access panel to their nearest <a href="http://en.wikipedia.org/wiki/Jefferies_tube">Jeffries tube</a>, get down on their hands and knees and crawl.</p>
<p>In the integration community these days, it is common to tip the hat to <a href="http://www.eaipatterns.com/eaipatterns.html">Gregor and Hopke&#8217;s Enterprise Integration Patterns</a> work. The book sits on every &#8220;Integration Architect&#8221;&#8216;s shelf and provides a useful reference work. It&#8217;s very tempting to imagine architects sitting around designing systems using Star Trek-style dialog: &#8220;We&#8217;ll hook this Incoming Polling Consumer to this Aggregator, then to this Resequencer before Routing the incoming message to the outgoing Messaging Gateway.&#8221; Leaving aside the issue that this scenario and reality correspond to each other in roughly the same way that Star Trek corresponds to the NASA, let&#8217;s take a look at OSB&#8217;s support for patterns.</p>
<p>There&#8217;s a few: various species of polling consumer, a bit of routing, some basic message transformation and then&#8230;you&#8217;re on your own.</p>
<p>It is extremely cumbersome to do anything other than broad brush-stroke flows&#8230;I feel that I am being forced to spatter stored procedures, triggers, <a href="http://articles.techrepublic.com.com/5100-10878_11-5218671.html">DBMS_ALERT</a> calls and odd little support tables throughout my database, along with (as simple as possible) snippets of Java in the OSB application in a desperate attempt get OSB to do something useful.</p>
<p>I frequently repeat the following mantras: &#8220;OSB is just a dumb pipe&#8221; and  &#8220;Let&#8217;s keep OSB as dumb as possible.&#8221;</p>
<p>I simply can&#8217;t bring myself contemplate the effort needed to deal with all the callouts to all the Java objects needed to deal with any sort of sophisticated API or complex processing.</p>
<p>I&#8217;m pretty sure that I could replace much of the mess that has grown up as a result of OSB&#8217;s pathetically limited capabilities with a couple of standard Java collection classes mixed in with a decent polling implementation such as in Apache Camel or Spring Integration.</p>
<p>Compare and contrast with Camel, which has <a href="http://camel.apache.org/enterprise-integration-patterns.html">direct support</a> for about 50 of these patterns. That previous link also provides links to a nifty library of icons for them all, in various formats&#8230;very useful. Spring Integration also directly supports several of these patterns &#8220;out of the box.&#8221;</p>
<p>Seems to me (cynic that I am) that OSB successfully implements just two patterns: the &#8220;sell copies of Weblogic&#8221; pattern and the &#8220;extract lots of money from customers&#8221; pattern. </p>
<p>What goes into OSB, stays in OSB. For all but the simplest bit of work one typically needs to develop additional helper tools/applications/scripts, etc. Tools like JPA and Camel are by design flexible and make it possible to create these tools by reusing elements of the &#8216;main&#8217; development path (a part of the object model, or a transformer, say). OSB does not&#8230;quite the reverse, in fact (it is very much [Oracle Weblogic] server-side-only, for example). Any &#8216;investment&#8217;/effort put into OSB is in reality not going towards infrastructure development but is instead just bringing into existence another closed, siloed system. An <em>instant</em> legacy problem. The only investment that one does with OSB is investing into Oracle&#8217;s share price. This is unacceptable. It need not be this way. We have tools available that can be used to enhance our infrastructure, not fragment it, that can work <em>with</em> our Objects and APIs, not make an all-out (but subtle) effort to supplant them. </p>
<h3>Development/Engineering</h3>
<p>OSB has an &#8220;everything is XML&#8221; approach (OK I acknowledge that it&#8217;s slowly <a href="http://download.oracle.com/docs/html/E15866_01/jejb.htm">divesting</a> itself of this, but there&#8217;s a way to go yet before the alternatives are anything approaching useable). I like XML as much as the next guy, <a href="http://wordpress.transentia.com.au/wordpress/2009/07/03/xml-overview-for-developers-courseware-now-donationware/">probably more</a>;  it&#8217;s a great <em>interchange</em> format, but requiring it for all internal channels as well is a bit much: one ends up touching the in-flight data (translating/extracting/recomposing) too many times. With JPA and JAX-RPC, one can in essence and after a little housekeeping do:</p>
<pre>
WebService.doSomething(DBEntity.findByPrimaryKey(pk));
</pre>
<p>The equivalent OSB (with Database JCA Adapters in place) is horrendous, simply horrendous!</p>
<p>Don&#8217;t get me started on the Database JCA Adapters! They are supported in OSB but cannot (yet) be created via OSB&#8217;s Eclipse-based tooling. This means that one is required to use JDeveloper 11g to create the adapter bindings appropriate for the underlying databases and then manually copy the resulting batch of files (a group of up to 5 files for each table being used) into the Eclipse project. Automate <em>those</em> build steps, I challenge you!</p>
<p>It gets worse: an OSB proxy created to service a JCA adaptor is extremely fragile: changes to a database table requires a regeneration of the adapter files (or more like a recreation from scratch&#8230;manual click, click, <a href="http://www.ildado.com/bingo_nicknames.html">clickety, click</a>). Any slight change to an adapter forces a regeneration of the associated OSB proxy&#8230;which blows away any business logic (== pretty drawing) associated with the message flow. One is then forced to recreate the flow from scratch by hand (more manual click, click, clickety, click). Ghastly. Tedious. Error prone. Nonsense. It&#8217;s in the nature of the systems integration task that changes happen often. One gets tired of (re)drawing OSB&#8217;s pretty pictures very quickly, let me <a href="http://en.wikipedia.org/wiki/Testify_(Phil_Collins_album)">testify</a>.</p>
<p>One gets around this by splitting a flow into upper and lower levels: the upper level simply forwards to the lower level with as little effort as possible. The lower level flow does all the real work and is unaffected by changes to the adapter or upper level flow.</p>
<p>Some things might get cleaned up in the future (Oracle/BEA&#8217;s XQuery implementation is curently only partial [no module support], for instance) but I&#8217;m not holding my breath.</p>
<p>There&#8217;s even worse: OSB seems to confuse database <strong>polling</strong> frequency with database <strong>locking</strong> time: tell an adapter to poll every 10 secs and it seems to go away and lock all other processes out of the database for the next 10 secs, polling away in <a href="http://en.wikipedia.org/wiki/Splendid_isolation">splendid isolation</a>. This can lead to performance issues and effectively ties all adapters to a very short polling cycle. That&#8217;s a bit of a surprise and can lead to some subtle &#8216;issues&#8217; arising, let me tell you&#8230;</p>
<p>I a great fan of these adapters&#8230;I simply love the way that they get &#8216;stuck&#8217; every now and then (often when the underlying database is itself under some load). They often get &#8216;unstuck&#8217; as well. Usually&#8230;sometimes&#8230;. I love going into production with systems that &#8216;usually&#8217; work OK (that was sarcasm, in case you are <a href="http://the-big-bang-theory.com/quotes/character/Sheldon/">sarcastically-challenged</a> :-)).</p>
<p>OSB is completely <a href="http://forums.oracle.com/forums/thread.jspa?threadID=1075167">stateless</a>. To create something as simple as an &#8220;I have sent out a total of <em>n</em> messages&#8221; counter requires introducing a Java callout with an absurd amount of glue coding. Some things simply aren&#8217;t worth doing&#8230;</p>
<p>A good tool makes it easy to develop clear, relevant solutions close to the &#8220;problem space&#8221; without unnecessary obtuse &#8216;ceremony&#8217; getting in the way. OSB is not such a tool, sadly.</p>
<p>You know the acronym <a href="http://www.c2.com/cgi/wiki?DontRepeatYourself">DRY</a>? Well, forget it!</p>
<p>One can try to apply a <a href="http://forums.oracle.com/forums/thread.jspa?threadID=927438">workaround</a> and achieve a degree of DRY-ish-ness but the spaghetti flows that result aren&#8217;t worth the hassle. Here&#8217;s the issue: the process of munging a solution to fit in with OSB&#8217;s way of doing things results in a horrid unclear mess. Really. The cure ends up being worse than the disease: the resulting diagram becomes simply unintelligible&#8230;<em>much</em> less clear than the equivalent plain-old-text representation in Java. </p>
<p>Not convinced? OK, Mr./Mrs. Smarty-Pants: what values are being assigned and logged here?</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2020/08/osb-pipeline-163x300.png" alt="" title="osb-pipeline" width="163" height="300" /></p>
<p>To find out, you have to engage in a storm of clicking through the pretty icons and juggling Eclipe&#8217;s idiosyncratic idea of view focus control. After a while you will find that your wrists need to recover from their little workout, giving you time reflect on the fact that you&#8217;d be able to find out <em>instantly</em> when perusing a textual source, no clickety-click investigation needed. There&#8217;s a big difference between <em>reading</em> and <em>scanning</em> code; oftentimes the latter is what we <em>need</em> to do&#8230;and quickly.</p>
<p>On a related note, it&#8217;s hard to make the correspondence between trace logging output and the actual code. Consider, for illustration, that all service callouts have the same fixed label: &#8220;Service Callout.&#8221; It can be slightly awkward to pin down which &#8220;Service Callout&#8221; just logged something.</p>
<p>While it may be appealing to the naive or hopeful, Mouse-Hand Engineering&#8230;drawing pretty pictures&#8230;doesn&#8217;t really ease the development task. That&#8217;s just the nature of our complicated world&#8230;sad, but that&#8217;s life.</p>
<p>(You know, I was going to use the phrase &#8220;Right-Hand Engineering&#8221; but felt it was slightly too risque ;-))<br />
(And don&#8217;t get me started [<a href="http://wordpress.transentia.com.au/wordpress/?s=UML">again</a>] on UML, I&#8217;ve already thrown it a bone once in this posting :-))</p>
<p>Oh for the ability to &#8220;comment out&#8221; or bypass sections of a flow! It continually frustrates me that in most so-called modern languages, one cannot nest comments (something that Pascal had all worked out), but OSB drives me potty. Would the industry (yes, even this fad-ridden, silver-bullet-seeking, flavour-of-the-month driven IT industry) accept a textual language without a commenting convention, I wonder? This issue also relates to testing (see below).</p>
<p>Here&#8217;s a cute feature: every message that enters the system is given an unique message ID. Except that it isn&#8217;t actually unique, darn it! As a message is passed between services, each service  allocates it a brand new ID. This is dumb, dumb, <a href="http://www.imdb.com/title/tt0109686/">dumb</a>! One is forced either to fiddle with and refer to header fields all the time, or do what I did and use a message&#8217;s database-allocated <a href="http://thinkoracle.blogspot.com/2005/06/natural-vs-synthetic-keys.html">synthtic (surrogate) primary key</a> as the message ID. Way to make it easy for us, OSB!</p>
<p>Error handling is <a href="http://forums.oracle.com/forums/thread.jspa?messageID=4449336&amp;#4449336">broken</a>. I know I&#8217;m being picky but something a little more than &#8220;something bad happened somewhere in some downstream flow or other&#8221; would be helpful. There are rumors of patches for this issue; good luck is all I can say.</p>
<p>One can&#8217;t get at system parameters/classpath resources, etc. without falling back to Java. To do anything slightly out of OSB&#8217;s (putative) &#8220;sweet spot&#8221;, one falls back to Java&#8230;so why not use a Java-based framework?</p>
<p>Testing. Ha ha haaaah!</p>
<p>How does one go about testing a drawing? This is probably the #1 question on the OSB forum.</p>
<p>Yes, the OSB console web application allows one to &#8220;test drive&#8221; the various componentry. Surely we can do better than hand-driven integration testing, however. Tools like <a href="http://www.citrusframework.org/index.html">citrus</a> and <a href="http://soapui.org/">SoapUI</a> come close but don&#8217;t ring the bell for me&#8230;</p>
<p><a href="http://blogs.oracle.com/MarkSmith/2008/08/oracle_service_bus_and_unit_te.html">Mark Smith gives an overview of the ridiculous process of creating testing stubs/proxies and the associated rewiring required when testing a proxy service&#8217;s flow</a>. If a flow must be progressively rewired in order to be &#8216;tested&#8217;, is the flow actually being tested, I ask (rhetorically)?</p>
<p>Unit testing XQuery transformations should be simple, but isn&#8217;t&#8230;there&#8217;s no doco and a closed implementation. Writing testing flows in OSB seems ridiculous to me. Unit tests shouldn&#8217;t need a service bus and you shouldn&#8217;t be forced into integration-style testing for your atomic code units. Something smells quite wrong here.</p>
<p>I&#8217;ll probably pontificate on this some another time&#8230;for now, its in my &#8220;tried and failed to do something of value for the project&#8221; basket.</p>
<p>It may be a little churlish of me to point this out, but the XQuery editor always has <em>some</em> reason or other why it won&#8217;t let you do something&#8230;even dragging a dateTime onto a String:</p>
<p><img src="/wordpress/wp-content/uploads/2010/09/cantxquery-300x71.png" alt="" title="cantxquery" width="300" height="71" class="alignnone size-medium wp-image-1114" /></p>
<p>The editor gets in the way <em>many more times</em> than it helps. As <a href="http://rogervdkimmenade.blogspot.com/2009/07/xquery-use-within-osb-watch-out.html">Roger van de Kimmenade also noted</a>, it can get so completely messed up that it can&#8217;t do anything except show a blank screen. It can sometimes (usually when opening a file) even rewrite a transformation as it sees fit&#8230;blowing any hand-made changes away in the process. This is problematic &#8216;cos (as I have just pointed out) you have to do pretty much everything by hand. You Have Been Warned (hmmm&#8230;maybe Oracle should trademark this phrase. Hey: maybe <em>I</em> should&#8230;).</p>
<p>I particularly enjoy the fact that&#8211;although OSB is BEA Weblogic Server at its heart&#8211;OSB can&#8217;t readily create HTML. &#8220;Hang On a min., &#8221; you say &#8220;isn&#8217;t HTML just a variant of XML at heart? Surely OSB should be happy with HTML!&#8221; Surely. After I asked roughly the same question on the OSB forums, Manoj Neelapu was kind enough to work up a way of doing it. The eventual solution requires a gnarly combination of <a href="http://blogs.oracle.com/mneelapu/2010/09/how_to_serve_html_through_osb.html">two</a> <a href="http://blogs.oracle.com/mneelapu/2010/09/how_to_avoid_xml_declaration_in_the_response.html">techniques</a>, however. </p>
<p>Remember VETRO? In my current project, I have to process an incoming message which is defined by an XSD file included into an XSD file that is referenced by the service&#8217;s WSDL. If you followed that chain without getting confused you are doing better than OSB. Because of the include chain, OSB&#8217;s validate step won&#8217;t find the message type. The WSDL and XSDs are from a third-party vendor and so I&#8217;m loathe to touch/munge them. </p>
<p>This means that OSB is only capable of &#8216;&#8230;ETRO.&#8217; Quality stuff, this!</p>
<p>Deployment is &#8216;strange&#8217; as well. Took me a while to find the <a href="http://www.oracle.com/technetwork/middleware/docs/middleware-093940.html">up-to-date doco</a> telling you how to script the creation of an OSB domain from scratch. There are <a href="http://biemond.blogspot.com/search/label/WLST">a few helpful posts</a> out there telling you what to script <b>after</b> you get this beastie but so far this in in the same basket as XQuery unit testing. Seems to me that &#8220;Thou shalt not apply your existing deployment plan to a new domain.&#8221; Not if you want to keep your sanity, anyway.</p>
<h3>Other</h3>
<p>In no particular order:</p>
<ul>
<li>Eclipse IDE console&#8217;s &#8220;scroll lock&#8221; doesn&#8217;t work. You search through a long log trace looking for something and then&#8211;just as the line appears&#8211;the console refreshes, leaving you staring at the latest line to be added. <a href="http://en.wikipedia.org/wiki/Charlie_Brown">Good grief</a> but this is frustrating! I like Eclipse, have used it lots over the years (by choice, note!) but in this incarnation it is simply hateful, darn it!</li>
<li>From the sublime to the ridiculous: sometimes the console doesn&#8217;t actually deign to show anything at all. Many times I hear: &#8220;Bob. A message has gone missing again.&#8221; I now know that 9 times out of 10 what has actually happened is that the Eclipse console is blocking the server as it is trying to send debugging to System.out (I&#8217;m not directly using System.out please note&#8230;I&#8217;m not <em>that</em> naive). A quick keypress into the window unfreezes everything and Lo! I have miraculously found the missing message. It&#8217;s strange but even miracles can get old, fast.</li>
<li>JDeveloper periodically corrupts a project. One may work on a project for a week and then BAM! it fails to load up in the morning (this may be a local SOE issue but its still frustrating and I don&#8217;t get hassles from any other apps).</li>
<li>There exists a <a href=""http://forums.oracle.com/forums/forum.jspa?forumID=320">fairly small user community</a><a></a>. The Oracle forums are really not that active or useful. Apologies to those members out that that have tried their best to help me out&#8230;this comment is not intended to be an indictment of you guys (I AM grateful, really, I AM!). I am just trying to identify issues caused by community size &amp; experience.</li>
<li>OSB&#8217;s Eclipse tooling tries to deploy all the projects it can find&#8230;even if they are closed. This can lead to weird situations. You Have Been Warned&#8230;</li>
<li>It&#8217;s not just the older versions, either. In the latest update, Eclipse seems to take ages to realise that a change has happened and that a deployment refresh is needed&#8230;and then sometimes fails to see that a redeploy has happened.</li>
<li>&#8230;and what has happened to Weblogic? Even a simple change to a datasource&#8217;s configuration now requires a reboot. Shocking!</li>
<li>The weblogic log browser is&#8230;&#8217;idiosyncratic.&#8217; You can be eagerly following a chain of logging messages&#8230;clicking from one page to the next&#8230;homing in on the cause of all life&#8217;s woes&#8230;feeling the expectation of a debugging session drawing to a close welling up inside&#8230;and then <em>bloody thing</em> will decide to show page 0 again. Just for <a href="http://www.imdb.com/title/tt0118655/">shits and giggles</a>, it&#8217;ll be so confused that you will have to start a new web browser session. You quickly learn to munge the parameters displayed in the address bar, <a href="http://en.wikipedia.org/wiki/The_Outing">not that there&#8217;s anything wrong with that</a>, of course&#8230;</li>
</ul>
<p>My colleague <a href="http://davidninnes.blogspot.com/">David</a> has introduced me to a term that sums all this up nicely: <a href="http://www.urbandictionary.com/define.php?term=Complification">complification</a>. To <a href="http://www.urbandictionary.com/define.php?term=complify">complify</a> something is <em>&#8220;To dramatically increase the difficulty of something for no good or apparent reason.&#8221;</em></p>
<p>Of course, I am an ingenious guy and I can pull some sort of solution to all of these things out of my expansive&#8230;err&#8230;mind. <a href="http://www.last-word.com/">AFWSE</a>  is also my friend in many situations (but see my earlier comments regarding the size and vitality of the user community).</p>
<p>I am sure that you, dear browser, also pride yourself on your ingenuity and proven ability to wrestle a recalcitrant universe into shape.</p>
<p>This, Of course, is also the trouble! Ego comes riding into town&#8230;</p>
<p>My (rhetorical) question is: should we have to be so ingenious? Especially when many of the &#8216;issues&#8217; are those that OSB in and of itself causes?</p>
<p>So here we are: back to the title&#8230;I can&#8217;t help but imagine that somewhere within Oracle there is a poor, downtrodden group afraid to tell King Larry that OSB just doesn&#8217;t make sense.</p>
<p>Guys, let me try. I&#8217;ll be the plucky little boy from the crowd (I hope that remember your <a href="http://en.wikipedia.org/wiki/The_Emperor's_New_Clothes">Hans Christian Anderson fairy tale</a>?) that doesn&#8217;t understand he should be following the party line&#8230;</p>
<p>Larry, listen up! In my (not-so-)humble-opinion there are <a href="http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/">much</a> <a href="http://camel.apache.org/">better</a> ways to skin the integration cat that what I see here. OSB isn&#8217;t a worthy member of your product lineup. Don&#8217;t lead your customers down this particular garden path. The last decade has seen some good steady quiet progress in areas such as testing, interoperability and frameworks (to name but a few), please don&#8217;t set this industry back to the pre-2000s with this regressive, locked-down, locked-in, half-baked &#8216;thing.&#8217; Please!</p>
<p>Phew! Said it. I Feel much better now!</p>
<p>Lest you think that I am losing it, <a href="http://www.crazymcphee.net/x/2010/07/12/the-ordeal-of-installing-oracle-service-bus-on-a-windows-based-developer-workstation/">I&#8217;m not the only person saying this sort of thing</a>.</p>
<p>You know&#8230;the story doesn&#8217;t really say what happened to that plucky little boy from the crowd. Maybe he was showered in riches for saving the King&#8217;s honor. More likely, he was beheaded for embarrasing the high-and-mighty.</p>
<p><em>[edit]</em><br />
Some almost immediate&#8211;and pretty much equally jaundiced and cynical (although slightly more generic)&#8211;reaction.</p>
<blockquote><p>
Thank you &#8211; a rather excellent way to start my day :-)</p>
<p>Now let me also share something. You may or may not agree. Oracle makes a lot (LOT) of money by sending in the consultants.</p>
<p>The consultants get called in when the local team comes up with zip because it&#8217;s so damned hard to get the Oracle tools to work.</p>
<p>Consultants are charged out at $2k / day and become an on-going income stream as the client needs lots of refresh (code change) activity.</p>
<p>It serves the likes of the big consulting houses to have internally trained specialists who know nothing else but these ghastly tools.</p>
<p>In fact some outside consultants cash in big time by spending all their time focusing on nothing but &#8211; discovering all the tips and tricks from the Oracle paid guys.</p>
<p>I think this has been going on since I first entered the industry and it&#8217;s a great model. Not for the industry nor the profession, but for money making monsters of which Oracle is one of the best.</p>
<p>There, my take&#8230;take it or leave it, but it&#8217;s ultimate raison d&#8217;etre of the Closed source movement and some clients just gravitate to it&#8230;
</p></blockquote>
<p>I&#8217;ll leave the sender anonymous&#8230;no sense in taking other people&#8217;s career down alongside my own ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/11/07/the-emperors-new-service-bus/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solving the Enterprise Integration Puzzle with Spring Integration</title>
		<link>http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 12:28:45 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/wordpress/?p=652</guid>
		<description><![CDATA[Back in May 2009, I mentioned that I had an article published in GroovyMag. GroovyMag is very nice in that it allows the author to republish their work after a &#8216;decent&#8217; interval has passed (either 60 or 90 days, can&#8217;t quite remember at the moment). That period is well and truly passed for this article [...]]]></description>
			<content:encoded><![CDATA[<p>Back in May 2009, I <a href="/wordpress/2009/05/05/groovymag-may-issuenow-with-added-bob-brown/">mentioned</a> that I had an article published in <a href="http://groovymag.com/">GroovyMag</a>.</p>
<p>GroovyMag is very nice in that it allows the author to republish their work after a &#8216;decent&#8217; interval has passed (either 60 or 90 days, can&#8217;t quite remember at the moment). That period is well and truly passed for this article so here it is in its full resplendency. Enjoy!</p>
<p><em>[edit]</em><br />
Forgot to <a href='http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/01/exemplar-2009.apr.15.zip'>make the source available</a> when I first republished this article. Silly me. All fixed now!</p>
<hr />
<img src="/wordpress/wp-content/uploads/2009/05/gm7_400.jpg" alt="gm7_400" title="gm7_400" width="400" height="517" class="alignnone size-full wp-image-334" /></p>
<p><strong>Solving the Enterprise Integration Puzzle<br />
Getting Started with Spring Integration</strong></p>
<p>Groovy is frequently promoted as &#8220;the scripting language for the JVM.&#8221; Grails is often described as being &#8220;great for smaller, quick-to-build web applications.&#8221; Neither of these pieces of perceived wisdom really gives the Groovy/Grails combination its due: a powerful tool in the Systems Integrator&#8217;s armory. This article will show how Groovy and Grails&#8211;in conjunction with SpringSource&#8217;s up-and-coming &#8220;Spring Integration&#8221; project&#8211;can make complex systems integration tasks as easy as building a standalone web application.</p>
<h1>A Brief Overview of Spring Integration</h1>
<p>Systems integration is frequently likened to attempting to piece together a badly made jigsaw puzzle. The end goal is often quite fuzzy; there may be several potential solutions to consider; there may be many conflicting approaches to evaluate; and when all is said and done, sometimes all that can be done is to say &#8220;To heck with the Grand Plan!&#8221; and &#8216;adapt&#8217; the puzzle using a pair of nice sharp scissors.</p>
<p>Spring Integration (SI) is a recent project within the Spring stable that provides numerous tools to make the systems integration task less frustrating. SI builds on several existing Spring stablemates, but provides a unified way of configuring these components and linking them together. According to SI, all message endpoints (which act with and on behalf of application components) interact via messages sent over various flavors of messaging channels, perhaps undergoing various transformations along the way. In addition, external resources (files, JMS-based queueing systems, SOAP-based WebServices, etc.)  interact with these channels via simple-to-configure adapters.</p>
<p>SI imposes very little onto the developer; almost everything in the system can be implemented using simple POG/JOs (Plain Old Groovy/Java Objects) and configuration is typically via XML or Annotations.</p>
<p>SI provides out-of-the-box support for many of the patterns defined in Hohpe and Woolfe&#8217;s <em>Enterprise Integration Patterns</em> book and associated website and&#8211;as this article will show&#8211;is quite &#8220;Groovy friendly.&#8221;</p>
<h1>A Small Example Application</h1>
<p>In this article, I am going to take a very simple systems integration task and build a small example application. The application is a small Grails application that performs a simple function: given a customer number, it calculates the shipping cost for a single widget.</p>
<p>To show how Spring Integration can be used, I am assuming that a customer will enter their customer ID into a Grails-originated web page, which is then routed to one instance of a set of JMS servers. The associated address data is then retrieved, the city field extracted and then passed on to a SOAP-based WebService that calculates the cost of shipping widgets from Brisbane to the customer&#8217;s home city. To add a smidgen of realism, I have built the various services to be completely unrelated; in particular, they do not reference any form of standardized messaging schema. The integration pipeline needs to handle various simple message types, including strings, CSV-formatted data records, XML-formatted strings and floats.</p>
<p>Figure 1 provides a high-level view of the application.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/01/gm_si_image001.jpg" alt="gm_si_image001" title="gm_si_image001" width="665" height="289" class="alignnone size-full wp-image-667" /></p>
<p>Figure 1: The processing flow and major components comprising the example application</p>
<p>The various steps highlighted in this flow are:</p>
<ol>
<li>The customer ID (a simple string) is entered into the Grails web application and passed off to a generic SI gateway. The gateway places the customer ID on an internal channel that leads to a message router.</li>
<li>The router retrieves the message from its inbound channel and determines which available channel to use to ensure that the message is handled by the appropriate JMS server instance.</li>
<li>The message is then handled by a SI JMS &#8220;channel adapter,&#8221; which deals with the mechanics of working with the underlying external JMS server.</li>
<li>The nominated JMS server instance produces a record (a CSV-formatted string) that is placed onto a shared reply channel.</li>
<li>The CSV record is removed from the shared channel and transformed. The result of the transformation is an XML-formatted string which is again placed on a ‘downstream&#8217; queue.</li>
<li>The WebService channel adaptor removes the string from its request channel and invokes the external SOAP WebService for further processing.</li>
<li>The WebService response (a single float) is then passed back to the originating messaging gateway, which returns it to the Grails controller.</li>
</ol>
<p>This is a very simple system and it may seem that this is overkill. There is a payoff, however: SI makes it easy to plug in disparate (often legacy) systems and thus produces an expandable framework that is capable of being built out to cover future, more complex, situations.</p>
<h2>The Pieces of the Jigsaw Puzzle</h2>
<p>Before starting out on the integration exercise proper, it is worth taking a quick look at the various pieces of the jigsaw puzzle that are going to be joined together.</p>
<p>You will quickly see that all the pieces are exceptionally simplistic. I haven&#8217;t even tried to make them correspond to a multitude of real-life issues such as error handling, logging, configuration, etc., which have been almost completely ignored. This is by design: for the purposes of this article, I want to focus mostly on SI, not on the various services.</p>
<h2>The Grails Web Application</h2>
<p>Figure 2 shows the Grails web interface &#8220;in action.&#8221; It is very simple, with only a single form and a single results page.</p>
<p><img src="http://wordpress.transentia.com.au/wordpress/wp-content/uploads/2010/01/gm_si_image002.jpg" alt="gm_si_image002" title="gm_si_image002" width="665" height="246" class="alignnone size-full wp-image-670" /></p>
<p>Figure 2: The deployed Grails web application</p>
<p>The ‘meat&#8217; of the application (as far as this article is concerned) lies in the single Grails controller class shown in Listing 1.</p>
<pre>
public class SpringIntegrationController {

  def siGateway

  def index = { }

  def submit = {
    long start = System.currentTimeMillis()
    def msg = params.custid
    siGateway.send(msg)
    def got = siGateway.receive()
    flash.message =
      "Query took: ${System.currentTimeMillis() - start} millis."
    [shippingCost: got]
    }
  }
</pre>
<p>Listing 1: The Grails controller class</p>
<p>There are two points of interest in this simple class.</p>
<p>The siGateway instance injected from the Spring application context constitutes the sole point of contact between the Grails web application and the SI framework. (In theory, SI allows for an even less intrusive interface than this, based around dynamically constructed proxies, but a bug surfaced as I started writing the application…no matter, the hard way is not too onerous to use and I am sure that the SI guys will soon squash the bug.)</p>
<p>The submit closure is responsible for handling the POSTed form data and for driving the injected siGateway instance through its paces. It is pretty straightforward: all the action is happening over in &#8220;SI-land.&#8221;</p>
<h2>The JMS Application</h2>
<p>For the example application, I have written a very simple JMS service (using Apache ActiveMQ as the messaging provider), as shown in Listing 2.</p>
<pre>
import javax.jms.Session
import org.apache.activemq.ActiveMQConnectionFactory

public class AMQService
{
  private static factory =
	  new ActiveMQConnectionFactory("tcp://localhost:61616")

  public static void main(String[] args) throws Exception
  {
    def cKey = args[0]
    def cFile = args[1]

    println 'Starting...'
    println "Config key: $cKey"
    println "Config file: $cFile"

    def config =
      new ConfigSlurper(cKey).parse(new File(cFile).toURL())

    def database = config.database
    println "Database: $database"

    def inQ = config.inQ
    println "Incoming Queue: $inQ"

    def replyTopic = config.replyTopic
    println "Reply Topic: $replyTopic"

    def qConn = factory.createQueueConnection()
    def qSession =
      qConn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE)
    def consumer =
      qSession.createConsumer(qSession.createQueue(inQ))

    def tConn = factory.createTopicConnection()
    def tSession =
      qConn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE)
    def producer =
      tSession.createProducer(tSession.createTopic(replyTopic))

    qConn.start()
    tConn.start()

    for ( ; ; )
      process(database,
              tSession.createTextMessage(),
              consumer,
              producer)
  }

  private static process(database, replyMessage, consumer, producer)
  {
    try
    {
      def textMessage = consumer.receive()  // indefinite blocking
      replyMessage.with {
        setText(getResponse(database, textMessage.getText()))
        setJMSCorrelationID(textMessage.getJMSCorrelationID())
      }
      producer.send(replyMessage)
    }
    catch (Throwable t)
    {
      t.printStackTrace()
    }
  }

  private static getResponse(database, inMsg)
  {
    def resp = database[inMsg]
    println "Request: '$inMsg'; Response: '$resp'"
    resp
  }
}
</pre>
<p>Listing 2: The JMS server</p>
<p>This is a standard JMS service; no need to elaborate.</p>
<p>One point to note (that is not directly SI-related, but of interest nonetheless) is that the service is written to allow multiple instances to run at the same time, dealing with a partitioned data space. For the purposes of the example application, I have configured two instances. One instance is prepared to deal with customer IDs whose first character is in the range a-l and the second will deal with the rest of the alphabet.</p>
<p>The service accepts input via a uniquely-designated input queue, but sends its response to a shared topic. This structure simplifies things by ensuring that any downstream component merely has to handle a single publish/subscribe channel (which can carry data from multiple sources), rather than trying to deal with a multitude of point-to-point links.</p>
<p>Each server instance is driven by a pair of application parameters, defining:</p>
<ul>
<li>The location of the configuration file to use</li>
<li>The appropriate environment section in the designated configuration file</li>
</ul>
<p>The configuration file supplies:</p>
<ul>
<li>The name of the input queue to use</li>
<li>The name of the output topic to receive the responses</li>
<li>The actual static database to use (I did warn that these applications were extremely simple!)</li>
</ul>
<p>The service makes use of ConfigSlurper&#8217;s ability to deal with different environment sections and so I can define a single configuration file (see Listing 3) to configure the different instances uniquely.</p>
<pre>
replyTopic="SI.REPLY.TOPIC"

replyTopic="SI.REPLY.TOPIC"

environments {
  al {
    inQ="SI.AL.REQUEST"
    database=['b9876':'123 Nowhere St,Brisbane',
              'f0234':'42 Imaginary Place,Darwin']
    }
  mz {
    inQ="SI.MZ.REQUEST"
    database=['x5555':'123 Fake St,Hobart',
              'w8888':'000 Talkfest Lane,Canberra']
    }
  }
</pre>
<p>Listing 3: JMS server configuration file</p>
<p>This service accepts a string, but returns a CSV-formatted record.</p>
<h2>The WebService</h2>
<p>The final part in the jigsaw puzzle is a SOAP WebService built on top of the facilities provided by GroovyWS.</p>
<p>The service&#8217;s raison-d&#8217;être is to retrieve the cost of shipping <em>n</em> widgets between major cities in Australia; see Listing 4 and Listing 5.</p>
<pre>
public class ShippingCostWebService {

  static costs = [
    Brisbane: [ Brisbane:0.0F,
                Darwin:44.44F,
                Canberra:22.22F,
                Hobart:88.88F ],
    Darwin: [ Brisbane:44.44F,
              Darwin:0.0F,
              Canberra: 33.33F,
              Hobart: 99.99F ],
    Canberra: [ Brisbane:22.22F,
                Darwin:33.33F,
                Canberra: 0.0F,
                Hobart: 77.77F ],
    Hobart: [ Brisbane:88.88F,
              Darwin:99.99F,
              Canberra: 77.77F,
              Hobart: 0.0F ],
  ]

  Float calculateShippingCost(String fromLoc,
                              String toLoc,
                              Integer nItem) {
    def cost = costs[fromLoc][toLoc] * nItem
    println "calculateShippingCost($fromLoc,$toLoc,$nItem) => $cost"
    cost
    }
}
</pre>
<p>Listing 4: The shipping cost WebService</p>
<pre>
println 'Starting...'

def ws = new groovyx.net.ws.WSServer()

ws.setNode("ShippingCostWebService",
           "http://localhost:6980/ShippingCostWebService")

ws.start()

println '...Started.'
</pre>
<p>Listing 5: The GroovyWS WebService server harness</p>
<p>I can&#8217;t lie! This is just an old WebService that I had lying around that I created for a conference presentation, and which I have adopted for this application. It doesn&#8217;t have a customized API and isn&#8217;t necessarily a perfect fit to the task. In the systems integration world, improvisation is often required to squeeze data out of the numerous ‘sub-optimal&#8217; nooks and crannies that are found all over an enterprise.</p>
<h1>Joining the Pieces Together</h1>
<p>Now that you are familiar with the basic componentry, it is time to look at SI proper.</p>
<p>As with any Spring project, SI is configured separately to the actual code in an application. Since this application is based on Grails, I have chosen to use the nice resources.groovy Grails Spring Beans DSL configuration file, rather than the ‘traditional&#8217; XML-based configuration.</p>
<p>Listing 6 shows the complete configuration.</p>
<pre>
beans = {
  xmlns si:"http://www.springframework.org/schema/integration"
  xmlns jms:"http://www.springframework.org/schema/integration/jms"
  xmlns stream:"http://www.springframework.org/schema/integration/stream"
  xmlns ws:"http://www.springframework.org/schema/integration/ws"

  // SI componentry and plumbing
  si {
    poller(default: true) {
      "interval-trigger"(interval: 1, "time-unit": "SECONDS")
    }
    router("input-channel": "routerChannel",
           ref: "highLowRouter",
           method: "route")
    transformer("input-channel": "InboundTopic",
                "output-channel": "TransformedInbound",
                ref: "csvStringTransformer",
                method: "transform")
    channel(id: "routerChannel")
    channel(id: "ALOutboundChannel")
    channel(id: "MZOutboundChannel")
    channel(id: "RoutingRejectChannel") {
      queue(capacity: "256")
    }
    channel(id: "TransformedInbound") {
      queue(capacity: "16")
    }
    channel(id: "InboundTopic") {
      queue(capacity: "16")
    }
    channel(id: "ShippingCostChannel",
            dataType: "java.lang.Float") {
      queue(capacity: "16")
    }
  }

  stream {
    "stderr-channel-adapter"(channel:"errorChannel",
                             "append-newline": true)
  }

  // WebService stuff
  ws {
    "outbound-gateway"("request-channel": "TransformedInbound",
                       "reply-channel": "ShippingCostChannel",
                        uri: "http://localhost:6980/ShippingCostWebService")
  }

  // AMQ/JMS stuff
  connectionFactory(org.apache.activemq.pool.PooledConnectionFactory) { bean ->
    bean.destroyMethod = "stop"
    connectionFactory = { org.apache.activemq.ActiveMQConnectionFactory cf ->
      brokerURL = "tcp://localhost:61616"
    }
  }

  "AL.REQUEST"(org.apache.activemq.command.ActiveMQQueue, "SI.AL.REQUEST")
  "MZ.REQUEST"(org.apache.activemq.command.ActiveMQQueue, "SI.MZ.REQUEST")
  "REPLY"(org.apache.activemq.command.ActiveMQTopic, "SI.REPLY.TOPIC")

  jms {
    "outbound-channel-adapter"(channel: "ALOutboundChannel",
                               destination: "AL.REQUEST")

    "outbound-channel-adapter"(channel: "MZOutboundChannel",
                               destination: "MZ.REQUEST")

    "message-driven-channel-adapter"(channel: "InboundTopic",
                                     destination: "REPLY")
   }

  // general componentry
  siGateway(org.springframework.integration.gateway.SimpleMessagingGateway) {
    requestChannel = ref("routerChannel")
    replyChannel = ref("ShippingCostChannel")
    replyTimeout = "10000"
  }

  highLowRouter(au.com.transentia.si.LookupRouter)

  csvStringTransformer(au.com.transentia.si.CsvTransformer) {
    homeBase = 'Brisbane'
  }
}
</pre>
<p>Listing 6: The Spring Integration configuration</p>
<p>As you read the following discussion, you may find it useful to refer back to Figure 1.</p>
<p>The configuration is structured into various sections, according to the needs of SI and of the various resources that are being integrated.</p>
<p>The si section (more precisely, those elements of SI configured via the XML namespace allocated the si prefix in this document) configures the various aspects of SI itself. This includes establishing the various channels that interlink the components, defining a few application-specific components (such as the router and transformer), and putting in place a default polling schedule for those parts of SI that need to poll.</p>
<p>It is worth examining the router and transformer components here. I have mentioned that the JMS services deal with a partitioned data space and that traffic is directed to an individual service based on the actual data message being processed. SI allows for the definition of an application-specific router to perform this type of task, in this case the method route of the highLowRouter instance. Listing 7 shows the code for the router.</p>
<pre>
package au.com.transentia.si

public class LookupRouter {

  public String route(String msg) {
    switch(msg) {
      case ~/(?i:[a-l].*)/: return 'ALOutboundChannel'
      case ~/(?i:[m-z].*)/: return 'MZOutboundChannel'
      default: return 'reject'
    }
  }
}
</pre>
<p>Listing 7: The router class</p>
<p>The router examines the incoming message data and determines the appropriate outbound path for the message. Groovy&#8217;s wonderfully versatile switch statement, combined with the ability to do case-independent pattern matching, makes for beautifully minimalistic code.</p>
<p>The transformer is equally simple, as Listing 8 shows.</p>
<pre>
package au.com.transentia.si

public class CsvTransformer {
  def homeBase

  public String transform(String csv) {
    def dest = csv.tokenize(',')[1]

    """<def :calculateShippingCost xmlns:def="http://DefaultNamespace">
         </def><def :arg0>$homeBase</def>
         <def :arg1>$dest</def>
         <def :arg2>1</def>
      """
  }
}
</pre>
<p>Listing 8: The transformer class</p>
<p>This code is presented with an input CSV-formatted record, extracts the relevant field, and passes an XML-formatted string onwards.</p>
<p>Recall that the WebService&#8217;s API is not custom-built for the purpose of this application; for this use, arg2 (the nItems parameter) is always fixed at 1.</p>
<p>The stream section of the configuration merely allocates a generic channel listener so that the standard errorChannel is not silently ignored; this configuration will ensure that errors/exceptions, etc., are logged.</p>
<p>The ws section deals&#8211;unsurprisingly&#8211;with WebService integration. The section configures an SI outbound gateway that is capable of receiving a request on a specified channel, invoking the configured WebService and finally sending the result to the appropriate response channel. All this is specified declaratively: the actual mechanism of dealing with the WebService (retrieving WSDL documents, generating proxies and handling XML-based request/response messages) is completely hidden away.</p>
<p>The remaining configuration concerns SI&#8217;s JMS adapter and ActiveMQ integration.</p>
<p>The siGateway has been discussed previously.</p>
<p>By default, all SI&#8217;s JMS adapters reference a bean with the standard name of connectionFactory. It is the responsibility of this bean to ‘vend&#8217; connections to the external JMS system. In this case, a connection pool to a local Apache ActiveMQ server running at the URL &#8220;tcp://localhost:61616&#8243; is being created. Since the external connections are pooled for efficiency, by specifying destroyMethod=&#8217;stop&#8217; we ensure that they are simply inactivated after each (re)use and are never actually discarded.</p>
<p>Note: I found the actual syntax used to declare the connectionFactory a little tricky. I had to ask for help on the excellent user@grails.codehaus.org mailing list to get it right! Thanks to the generous souls who pointed me in the right direction.</p>
<p>Following the definition of the the connectionFactory, we create two instances of ActiveMQ queues and an instance of an ActiveMQ topic. It is these that carry the messages to/from the external JMS resources.</p>
<p>The jms section configures two JMS-specific outbound channel adapters and one inbound channel adapter. As the names suggest, these are concerned with driving (or being driven by) the ActiveMQ instances declared above. The configured message-driven-channel-adapter instance defines a component that will be asynchronously &#8220;actively invoked&#8221; to handle an incoming message. It is possible to configure a polling-oriented component, but this is generally less flexible, and may waste CPU, and increase the latency in the system.</p>
<p>As with the WebService gateway, everything is declarative.</p>
<h1>Admiring the Finished Puzzle</h1>
<p>SI has enabled a deceptively simple solution to a fairly complex problem. There are no messy tracts of confusing mechanistic code; the system is essentially defined all in a single configuration; the individual components are simple and (generally) reusable; and the groundwork for coping with change set with very little effort.</p>
<p>SI is a simple but powerful toolkit; the example application I have discussed here has really just touched the surface of what is possible. SI provides much more, including facilities for secure channels, inbound/outbound mail handling, event handling, RMI integration and much better XML handling than I have touched upon here.</p>
<p>Remember that these are still early days for SI: for example, there are no debuggers or GUI editors as found in the big &#8220;name brand&#8221; systems integration tools. In time these tools may come but for now remember that SI is orders of magnitude simpler, and the SI/Groovy/Grails triumvirate makes the developer many times more productive than some other tools I have used.</p>
<p>I hope that I have stimulated your interest in SI and shown that a Grails application need not be limited to serving up &#8220;little web apps&#8221; but can actually service the needs of larger-scale systems integration tasks.</p>
<p>I hope that I have also been able to show that when the time comes to get out the scissors, Groovy is more than equal to the task of &#8220;slicing and dicing&#8221; until the pieces of the systems integration jigsaw puzzle fit nicely together.</p>
<h1>Learn More</h1>
<ul>
<li>Gregor Hohpe and Bobby Woolf, <em>Enterprise</em><em> Integration Patterns : Designing, Building, and Deploying Messaging Solutions (ISBN 0321200683)</em>, also <a href="http://www.enterpriseintegrationpatterns.com/">http://www.enterpriseintegrationpatterns.com/</a></li>
<li>Spring Integration Home, <a href="http://www.springsource.org/spring-integration">http://www.springsource.org/spring-integration</a></li>
<li>Apche ActiveMQ, <a href="http://activemq.apache.org/">http://activemq.apache.org</a></li>
<li>GroovyWS, <a href="http://docs.codehaus.org/display/GROOVY/GroovyWS">http://docs.codehaus.org/display/GROOVY/GroovyWS</a>. The exemplar application uses the 0.5 snapshot jars from <a href="http://snapshots.dist.codehaus.org/groovy/distributions/groovyws/">http://snapshots.dist.codehaus.org/groovy/distributions/groovyws/</a></li>
</ul>
<p><em>Bob Brown is the director and owner of Transentia Pty. Ltd.. Based in beautiful Brisbane, Australia, Bob is a specialist in Enterprise Java and has found his niche identifying and applying leading-edge technologies and techniques to customers problems.</em></p>
<hr />
Watch out for my other Groovymag articles&#8230;coming soon to a browser near you.</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2010/01/25/solving-the-enterprise-integration-puzzle-with-spring-integration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SOAP/WebServices Courseware: Now DonationWare</title>
		<link>http://wordpress.transentia.com.au/wordpress/2009/07/05/soapwebservices-courseware-now-donationware/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2009/07/05/soapwebservices-courseware-now-donationware/#comments</comments>
		<pubDate>Sun, 05 Jul 2009 08:14:47 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[DonationWare]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/2009/07/05/soapwebservices-courseware-now-donationware/</guid>
		<description><![CDATA[DonationWare! I am opening up old courseware to the world on a &#8220;pay if you like it&#8221; or have it free basis. My fourth offering is SOAP/WebServices Overview. (You will find other offerings in this site&#8217;s DonationWare Category.) This course was created in mid-2003. It was a quick, one-day overview/review of the current &#8220;state of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&#038;hosted_button_id=6565587">DonationWare!</a> <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&#038;hosted_button_id=6565587"><img src="https://www.paypal.com/en_AU/i/btn/btn_donate_SM.gif" align="middle" border="0"/></a> </p>
<p>I am opening up old courseware to the world on a &#8220;pay if you like it&#8221; or have it free basis. </p>
<p>My fourth offering is <em>SOAP/WebServices Overview</em>.<br />
(You will find other offerings in this site&#8217;s <a href="/wordpress/category/donationware/">DonationWare Category</a>.)</p>
<p>This course was created in mid-2003.</p>
<p>It was a quick, one-day overview/review of the current &#8220;state of the art.&#8221;</p>
<p>How things change!</p>
<p>I remember  going down to Sydney to give this course on behalf of &#8220;A Famous Database Company&#8221; for a group of South Korean V.I.P.s&#8230;who (it turned out) did not speak ANY English. The poor translator almost had a nervous breakdown. It was a very strange session, almost surreal!</p>
<p>Here&#8217;s the &#8216;blurb&#8217;:</p>
<div style="padding-left:10px;padding-right:10px;margin-left:20px;margin-right:20px;background:#FFFFCC;">
<br />
The new internet-focussed software architectures now on the drawing boards of the World-Wide Web Consortium (W3C) and the major vendors are being planned around a triumvirate of standards-oriented XML-based technologies: SOAP, the Simple Object Access Protocol; WebServices; and UDDI, the Universal Description Discovery and Integration system. These new technologies are fated to become ever more important as they slowly assume the role of underpinning major initiatives such as Microsoft’s .NET and grow to provide the foundation for much of what HP, IBM and the various members of the open source community are intending to provide for the next iteration of the Internet. </p>
<p>This session will provide an overview of the new business-to-business technologies that are being promulgated for what some cynics have called “basically a more object-oriented, somewhat buzzword-compliant upgrade to CGI” and others have more charitably called the “grown up internet.”</p>
<p>&nbsp;
</p>
</div>
<p>The course is now well and truly at End of Life.</p>
<p>I figure that it would be such a pity for it to end as a set of bits decaying away on my hard disk so I am opening it up to the world on as &#8220;as-is&#8221; basis:</p>
<p><a href="/wordpress/wp-content/uploads/2009/07/sws-courseware-donationware.04.july.2009.zip">sws-courseware-donationware.04.july.2009.zip</a><br />
(MD5: 150f88d70d5a86d1129af4e21059594c; size:  6,692,573 bytes)</p>
<p>Some (unfortunately necessary) legalese:</p>
<ul>
<li>This content is provided &#8220;as-is&#8221;, with no guarantees.
</li>
<li>Feel free to use it, but not to abuse it (to give a couple of examples: don&#8217;t make hundreds of copies for friends; don&#8217;t claim it as your own work).
</li>
<li>I retain copyright, so &#8220;<a href="http://en.wikipedia.org/wiki/All_rights_reserved">all rights reserved</a>.&#8221;
</li>
</ul>
<p>Enjoy!</p>
<p>If you like it, or have any questions/comments, send me an email (<em><script type="text/javascript">
// obfuscate this stuff...
var who = 'soapwebservicescoursewaredonationware'
var a = 'transentia'
var b = 'com'
var c = 'au'
var s = who + '@' + a + '.' + b + '.' + c;
document.write(s)
</script></em>).</p>
<p>If you find this material useful, <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&#038;hosted_button_id=6565587">please consider paying me a small amount</a>: <a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&#038;hosted_button_id=6565587"><img src="https://www.paypal.com/en_AU/i/btn/btn_donate_SM.gif" align="middle" border="0"/></a> via PayPal.</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2009/07/05/soapwebservices-courseware-now-donationware/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Is SOA Dead?</title>
		<link>http://wordpress.transentia.com.au/wordpress/2009/05/28/is-soa-dead/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2009/05/28/is-soa-dead/#comments</comments>
		<pubDate>Thu, 28 May 2009 08:59:22 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/2009/05/28/is-soa-dead/</guid>
		<description><![CDATA[The title of a nice summary on infoq. A few gems: So having vendors claiming &#8220;we are still shifting products&#8221; while analysts who told people to go and buy those products are now complaining that they haven&#8217;t seen the value really is just a farce&#8230; SOA hasn&#8217;t failed, what has failed is the next generation [...]]]></description>
			<content:encoded><![CDATA[<p>The title of a <a href="http://www.infoq.com/news/2009/05/SOADead">nice summary</a> on infoq.</p>
<p>A few gems:</p>
<blockquote><p>So having vendors claiming &#8220;we are still shifting products&#8221; while analysts who told people to go and buy those products are now complaining that they haven&#8217;t seen the value really is just a farce&#8230; SOA hasn&#8217;t failed, what has failed is the next generation lipstick on the pig, buy my technology it will save your problems, do a big project it will fix everything style of IT that has <strong>always failed</strong>.</p>
</blockquote>
<p>And:</p>
<blockquote><p>&#8230;those companies that have not yet started a SOA initiative did so because they could not articulate and demonstrate its business value.</p>
</blockquote>
<p>And even:</p>
<blockquote><p>&#8230;you should probably avoid using the word &#8220;SOA&#8221; and instead focus your efforts on building &#8220;services&#8221; that deliver measurable value to the business.</p>
</blockquote>
<p>What a horrifying idea: &#8220;deliver measurable value to the business&#8221;! What will they think of next ;-)</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2009/05/28/is-soa-dead/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SoapUI 3.0 Beta</title>
		<link>http://wordpress.transentia.com.au/wordpress/2009/05/27/soapui-30-beta/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2009/05/27/soapui-30-beta/#comments</comments>
		<pubDate>Wed, 27 May 2009 09:02:22 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SOA]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/2009/05/27/soapui-30-beta/</guid>
		<description><![CDATA[Is available. Improvements include reporting and upgraded Groovy support.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.soapui.org/">Is available</a>.</p>
<p><a href="http://www.soapui.org/new_and_noteworthy_3_0.html">Improvements</a> include reporting and upgraded Groovy support.</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2009/05/27/soapui-30-beta/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SOA Source Book</title>
		<link>http://wordpress.transentia.com.au/wordpress/2009/05/14/soa-source-book/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2009/05/14/soa-source-book/#comments</comments>
		<pubDate>Thu, 14 May 2009 20:33:41 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Books]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/2009/05/14/soa-source-book/</guid>
		<description><![CDATA[The Open Group&#8217;s SOA Source Book is a collection of source material for use by enterprise architects working with Service-Oriented Architecture. Useful grist for the mill&#8230;]]></description>
			<content:encoded><![CDATA[<p>The Open Group&#8217;s <a href="http://www.opengroup.org/projects/soa-book/">SOA Source Book</a> is a collection of source material for use by enterprise architects working with Service-Oriented Architecture.</p>
<p>Useful <a href="http://en.wikipedia.org/wiki/Gristmill">grist</a> for the mill&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2009/05/14/soa-source-book/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Useful SOA Reference Site</title>
		<link>http://wordpress.transentia.com.au/wordpress/2009/03/19/a-useful-soa-reference-site/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2009/03/19/a-useful-soa-reference-site/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 23:16:43 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/2009/03/19/a-useful-soa-reference-site/</guid>
		<description><![CDATA[http://www.soapatterns.org/, a site dedicated to the on-going development and expansion of the SOA design pattern catalog. I came across it when I was trying to remind myself what VETRO stood for (&#8221;Validate, Enrich, Transform, Route, Operate&#8221;&#8230;I simply could not remember what the &#8216;O&#8217; was for&#8230;) .]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.soapatterns.org/">http://www.soapatterns.org/</a>, a site dedicated to the on-going development and expansion of the SOA design pattern catalog.</p>
<p>I came across it when I was trying to remind myself what <a href="http://it.toolbox.com/blogs/the-soa-blog/soa-integration-architect-4023">VETRO</a> stood for (&#8221;Validate, Enrich, Transform, Route, Operate&#8221;&#8230;I simply <em>could not</em> remember what the &#8216;O&#8217; was for&#8230;) .</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2009/03/19/a-useful-soa-reference-site/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SOA &amp; The Tarpit of Irrelevancy</title>
		<link>http://wordpress.transentia.com.au/wordpress/2009/02/25/soa-the-tarpit-of-irrelevancy/</link>
		<comments>http://wordpress.transentia.com.au/wordpress/2009/02/25/soa-the-tarpit-of-irrelevancy/#comments</comments>
		<pubDate>Wed, 25 Feb 2009 21:12:33 +0000</pubDate>
		<dc:creator>bob</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Grails]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://wordpress.transentia.com.au/2009/02/25/soa-the-tarpit-of-irrelevancy/</guid>
		<description><![CDATA[InfoQ précis a nicely down-to-earth examination of &#8220;the state of SOA/BPM software and its vendors.&#8221; Here&#8217;s a taster: While rank and file developers go to conferences to soak in deep technical content, their peripherally technical managers (the ones who wrote some rockin&#8217; good Cobol code back in the day, but now they make decisions about [...]]]></description>
			<content:encoded><![CDATA[<p>InfoQ <a href="http://www.infoq.com/news/2009/02/TarpitofIrrelevancy">précis a nicely down-to-earth examination</a> of &#8220;the state of SOA/BPM software and its vendors.&#8221;</p>
<p>Here&#8217;s a taster:</p>
<blockquote><p>While rank and file developers go to conferences to soak in deep technical content, their peripherally technical managers (the ones who wrote some rockin&#8217; good Cobol code back in the day, but now they make decisions about modern enterprise architecture) go to different conferences in Palm Springs. At those conferences, they have a 2-hour morning session, run by a big tool vendor, then play golf for the balance of the afternoon. And what the vendors show them is poison.</p>
</blockquote>
<p>I just <em>love</em> the term &#8220;doodleware&#8221; the author introduces!</p>
<p>It&#8217;s a curious thing: just yesterday I was pontificating on a similar theme to a colleague; it&#8217;s nice to know that my cynical world-view is not <em>completely</em> in my own head, after all&#8230;</p>
<p>Perhaps the author wanted something along the lines of <a href="http://www.grailsflow.org/">grailsflow</a>?</p>
]]></content:encoded>
			<wfw:commentRss>http://wordpress.transentia.com.au/wordpress/2009/02/25/soa-the-tarpit-of-irrelevancy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

