<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Architecture - Random Thoughts]]></title><description><![CDATA[About business and information technology]]></description><link>https://christoffer.soop.ch/</link><image><url>https://christoffer.soop.ch/favicon.png</url><title>Architecture - Random Thoughts</title><link>https://christoffer.soop.ch/</link></image><generator>Ghost 5.46</generator><lastBuildDate>Thu, 11 Jun 2026 16:22:24 GMT</lastBuildDate><atom:link href="https://christoffer.soop.ch/tag/architecture/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[How to stay DRY doing Microservices]]></title><description><![CDATA[Using the Dockerfile ONBUILD instruction boilerplate code and repetition can be avoided effectively creating abstractive based images for your Microservices]]></description><link>https://christoffer.soop.ch/how-stay-dry-doing-microservices/</link><guid isPermaLink="false">645818765c4dcc000153cb66</guid><category><![CDATA[Architecture]]></category><category><![CDATA[Development]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Microservices]]></category><dc:creator><![CDATA[Christoffer Soop]]></dc:creator><pubDate>Sat, 04 May 2019 15:08:00 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><em>This post is <a href="https://github.com/chrsoo/microservices/?ref=christoffer.soop.ch">also avaialble on GitHub</a> together with all the source files!</em></p>
<p>When using <code>Jenkinsfile</code> and <code>Dockerfile</code> with Microservices you are typically repeating the same boilerplate code over and over again. Initially this is not a problem but as the number of Microservices - and Git branches - start to increase it can become quite painful.</p>
<p>In order to stay <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself?ref=christoffer.soop.ch">DRY</a> you can leverage the <code>ONBUILD</code> Dockerfile keyword in a custom base image and a <a href="https://jenkins.io/doc/book/pipeline/shared-libraries/?ref=christoffer.soop.ch#defining-global-variablesME">global var</a> to define a reusable Jenkins pipeline.</p>
<p>With this solution each Microservice has a <a href="https://github.com/chrsoo/microservices/blob/master/Jenkinsfile?ref=christoffer.soop.ch">Jenkinsfile</a> similar to</p>
<pre><code>@Library(&quot;mylib@latest&quot;) _
mavenPipeline(java: &apos;8&apos;)
</code></pre>
<p>... and a <a href="https://github.com/chrsoo/microservices/blob/master/Dockerfile.microservice?ref=christoffer.soop.ch">Dockerfile</a> as simple as</p>
<pre><code>FROM mybase:latest
</code></pre>
<p>See <a href="https://github.com/chrsoo/microservices/blob/master/Dockerfile?ref=christoffer.soop.ch">Dockerfile</a> for an example on how the custom base image can look like and the <a href="https://github.com/chrsoo/microservices/blob/master/pom.xml?ref=christoffer.soop.ch">project pom</a> on how build both the base image and the Microservices using it!</p>
<p>Read the rest of the article if you are interested in the details or  if the above does not make much sense.</p>
<ul>
<li><a href="#context">Context</a></li>
<li><a href="#theproblem">The Problem</a></li>
<li><a href="#asolution">A Solution</a></li>
<li><a href="#anexample">An Example</a></li>
<li><a href="#lastwords">Last Words</a></li>
</ul>
<h1 id="context">Context</h1>
<p>Let&apos;s say you are using Microservices. Following best practices, each Microservice has its own source code repository. You start out with a few but this rapidly grows to a few dozen and with time you are managing a few hundred, perhaps more.</p>
<p>Each Microservice is built as a Docker image that defines a few labels, variables and some bootstrap code. A <code>Dockerfile</code> might look something like:</p>
<pre><code>FROM openjdk:8-jdk-alpine

ENV SVC_HOME=/opt/microservice
ENV SVC_ETC=${SVC_HOME}/etc SVC_LIB=${SVC_HOME}/lib SVC_CACHE=/var/cache/microservice BOOTSTRAP=${SVC_HOME}/bootstrap.sh

RUN addgroup --system microservice \
    &amp;&amp; adduser --system --ingroup microservice --home $SVC_HOME microservice

ADD src/files ${SVC_ETC}/
ADD bootstrap.sh ${BOOTSTRAP}

RUN mkdir -p $SVC_LOG $SVC_CACHE $SVC_ETC \
    &amp;&amp; chown -R microservice:microservice $SVC_LOG $SVC_CACHE $SVC_HOME \
    &amp;&amp; chmod +x ${BOOTSTRAP}

USER microservice

ARG JAR_FILE

ARG ARTIFACT_ID
ARG GROUP_ID
ARG VERSION

LABEL org.label-schema.vendor=&quot;My Company&quot; \
    org.label-schema.name=$ARTIFACT_ID \
    org.label-schema.description=&quot;Yet another Microservice&quot; \
    org.label-schema.usage=&quot;/README.md&quot; \
    org.label-schema.version=$VERSION \
    org.label-schema.schema-version=&quot;1.0&quot; \
    java.version=${JAVA_VERSION} \
    java.alpine.version=${JAVA_ALPINE_VERSION}

ENV \
    ARTIFACT_ID=${ARTIFACT_ID} \
    GROUP_ID=${GROUP_ID} \
    VERSION=${VERSION} \
    LOG_LEVEL=INFO \
    CACHE_DIR=${SVC_CACHE}/${ARTIFACT_ID} \
    ETC_DIR=${SVC_ETC}/${ARTIFACT_ID} \
    MICROSERVICE=${SVC_HOME}/${JAR_FILE}

ADD target/lib ${SVC_LIB}/
ADD target/${JAR_FILE} ${MICROSERVICE}

# HTTP
EXPOSE 9000
# JMX
EXPOSE 8181

ENTRYPOINT [&quot;/opt/microservice/bootstrap.sh&quot;]
</code></pre>
<p>Having fully bought into the whole DevOps and automation concept you have CI/CD pipelines to build and deploy your Microservices.</p>
<p>Jenkins you use out of habit, because this is what you know or because it seems to be a very popular choice. Who really knows why, but Jenkins is what you are currently stuck with.</p>
<p>Jenkins is configured to automatically detect new Git repositories and manage pipelines for each Git branch. A <code>Jenkinsfile</code> in your Git repository defines the steps for building a Microservice and pushing code automatically triggers the build.</p>
<pre><code>pipeline {
    agent docker
    stage (&apos;Build&apos;) {
        steps {
            ...
        }
    }
    stage (&apos;Test&apos;) {
        steps {
            ...
        }
    }
    stage (&apos;Verify&apos;) {
        steps {
            ...
        }
    }
    stage (&apos;Publish&apos;) {
        steps {
            ...
        }
    }
}
</code></pre>
<p>Thus the Git repository root contains two boilerplate files, one for Docker and one for Jenkins:</p>
<pre><code>Dockerfile
Jenkinsfile
</code></pre>
<p>In most cases these files are almost identical apart from label and environment values. In order to facilitate for developers these they are automatically generated using a template mechanism of some sorts. Perhaps the nifty <a href="https://blog.docker.com/2018/12/introducing-desktop-enterprise/?ref=christoffer.soop.ch">Docker Enterprise Desktop</a> shipping as a part of Docker EE 3.0</p>
<h1 id="theproblem">The Problem</h1>
<p>Requirements change or perhaps there is a bug but for whatever reason either the standard Jenkins pipeline and or Dockerfile change over time.</p>
<p>With a large number of Microservices that each has its own version of the <code>Jenkinsfile</code> and <code>Dockerfile</code>, multiple branches for handling the master line, development, features and bugs the relevance of the <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself?ref=christoffer.soop.ch">DRY</a> principle starts to sink in and you realize you have a <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself?ref=christoffer.soop.ch">WET</a> solution...</p>
<p><strong>For every change that comes along you now have to check out the code make the same edit for all branches.</strong></p>
<p>Cheery-picking and merging helps but still there is a lot of typing, committing and pushing going on. This increases the risk of typos and other inconsistencies, in particular if done by multiple teams and developers.</p>
<p>Of course, nothing prevents you from automating changes like this, but it would throwing code at a symptom instead of resolving the root cause.</p>
<h1 id="asolution">A Solution</h1>
<p>A solution that addresses the WET root cause comes in two parts:</p>
<ul>
<li>Use a custom base image in your Dockerfiles</li>
<li>Use pipeline DSL in your Jenkinsfiles</li>
</ul>
<h2 id="usingacustombaseimage">Using a Custom Base Image</h2>
<p>A custom base image should contain all things common to your downstream Microservices, things like</p>
<ul>
<li>standard image labels</li>
<li>log configuration files</li>
<li>common bootstrap shell scripts</li>
<li>runtime users</li>
<li>...</li>
</ul>
<p>The custom base image in itself uses a more standard upstream image, such as the alpine version for your language.</p>
<p>Some things depend on the <em>downstream</em> Microservice, however. What if you have a label containing the name or version of the Microservice? These are only known at build time of the Microservice itself, not when we are building the base image.</p>
<p>The key here is Docker&apos;s <code>ONBUILD</code> keyword which allows you to customize your base image to your Microservice using build time arguments.</p>
<p>For example we can set a <code>version</code> container label on the downstream Microservice with</p>
<pre><code>ONBUILD ARG VERSION
ONBUILD LABEL version=${VERSION}
</code></pre>
<p>Given that the base image is called <code>mybase</code> we then use a <code>Dockerfile</code> in Microservice repository with the following content:</p>
<pre><code>FROM mybase:latest
</code></pre>
<p><strong>That&apos;s it. That is the entire Dockefile.</strong></p>
<p>To build it we have to supply a build argument to the docker command, something along the lines of</p>
<pre><code>docker build --arg VERSION=1.3.9 .
</code></pre>
<p>The resulting image will then contain the container label <code>version: 1.3.9</code> (surprise!).</p>
<p><strong>If the we want to change something, perhaps adding another standard label, update the logic to the bootstrap script, change the log configuration or perhaps just update the to the latest alpine for Java, we only change it in one place, i.e. in the custom base image <code>mybase</code>.</strong></p>
<p>Of course, we still need to trigger the rebuild and redeployment of all our Microservices but the DRY principle is respected.</p>
<p>The beauty of this approach is that we still have our <code>Dockerfile</code> in each Git repository which can be customized if there is a real need. Just because there is a default base image does not mean that we force everybody to use it all the time. All our CI/CD tools will still work exactly the same and the only drawback is that we now have one exception to manage separately from the rest.</p>
<p>If you find yourself making a lot of similar exceptions, refactoring of the base image might be in place. Or perhaps there is a need for two different types of base images? In any case, try to keep it as simple and stupid as possible (cf. <a href="https://en.wikipedia.org/wiki/KISS_principle?ref=christoffer.soop.ch">KISS</a>).</p>
<p>Please see <a href="https://github.com/chrsoo/microservices/blob/master/Dockerfile?ref=christoffer.soop.ch">Dockerfile</a> for a more complete example of how a custom base image can look like!</p>
<h2 id="usepipelinedslinyourjenkinsfiles">Use pipeline DSL in your Jenkinsfiles</h2>
<p>Jenkins has support for building custom <a href="https://jenkins.io/doc/book/pipeline/syntax/?ref=christoffer.soop.ch">pipeline DSL</a> in Groovy.</p>
<p>This can be quite complicated given that Jenkins Groovy flavor is not 100% vanilla and it has a sour twist - not all Groovy features are available and you need follow certain conventions. If you stick to existing steps and very simple groovy code you should be good though.</p>
<p>Here we will not go into details on how to develop a Pipeline DSL but the basic idea is that you define a global variable for the entire pipeline and use it in your Jenkinsfiles.</p>
<p>Given a DSL library called <code>mylib</code> and a <a href="https://jenkins.io/doc/book/pipeline/shared-libraries/?ref=christoffer.soop.ch#defining-global-variables">global var</a> called <code>mavenPipeline</code> the Microservice <code>Jenkinsfile</code> could be as simple as this:</p>
<pre><code>@Library(&quot;mylib@latest&quot;) _
mavenPipeline(java: &apos;8&apos;)
</code></pre>
<p><em>Note the trailing underscore which is a package placeholder to which the annotation is attached!</em></p>
<p>Here we assume that <code>mavenPipeline</code> has parameter support for the java version to use. You can have others as well, if you like, but be careful not to repeat too many boilerplate settings!</p>
<p>Now, if there is a change to how the Microservice is built, how continuous delivery is done or perhaps if a new quality gate is added as a separate step, there is no need to change any of the Microservices. You just change the definition of the <code>mavenPipeline</code>.</p>
<p>Similar to how we handle the <code>Dockerfile</code> we can manage a custom <code>Jenkinsfile</code> if needed.</p>
<h1 id="anexample">An Example</h1>
<p>This Git repository contains a more complete example of a custom base image. It assumes Java based Microservices built by Maven but the concept should be easily adaptable to any language or platform.</p>
<ul>
<li><a href="https://github.com/chrsoo/microservices/blob/master/pom.xml?ref=christoffer.soop.ch">pom.xml</a> for building the image</li>
<li><a href="https://github.com/chrsoo/microservices/blob/master/bootstrap.sh?ref=christoffer.soop.ch">bootstrap.sh</a> docker entrypoint for launching the microservice</li>
<li><a href="https://github.com/chrsoo/microservices/blob/master/src/files/jmxremote.access?ref=christoffer.soop.ch">jmxremote.access</a> for configuring remote Java JMX access</li>
<li><a href="https://github.com/chrsoo/microservices/blob/master/src/files/logback.xml?ref=christoffer.soop.ch">logback.xml</a> for log configuration</li>
</ul>
<p>To build the base image you can launch</p>
<pre><code>mvn clean package
</code></pre>
<p>If you want to deploy the base image you need to</p>
<ul>
<li>Configure Maven <code>distributionManagement</code> settings; and</li>
<li>Make sure to change the <code>docker.namespace</code> to you Docker Hub account.</li>
</ul>
<p>If you are using a private registry you also need to update the <code>docker.registry</code> property and probably add credentials in Maven&apos;s <code>settings.xml</code> - YMMV!</p>
<p>Once Maven is properly configured you can then run...</p>
<pre><code>mvn clean deploy
</code></pre>
<p>... and Maven will happily deploy the (empty) JAR to your Maven registry and Docker image to Docker Hub or whatever you have configured.</p>
<p>Your Microservices should use <code>Dockerfile</code> along the lines of <a href="https://github.com/chrsoo/microservices/blob/master/Dockerfile.microservice?ref=christoffer.soop.ch">Dockerfile.microservice</a> in the root of each Microservice repository branch.</p>
<p><strong>(!) Note that the example requires Java 8 and Maven 3.5 to run!</strong></p>
<h2 id="jenkinsfile">Jenkinsfile</h2>
<p>The <a href="https://github.com/chrsoo/microservices/blob/master/Jenkinsfile?ref=christoffer.soop.ch">Jenkinsfile</a> will not work without you writing a custom DSL and adding the <code>mavenPipeline</code> global variable to your Jenkins instance.</p>
<p>Using a <code>Jenkinsfile</code> works best with a plugin like <a href="https://go.cloudbees.com/docs/plugins/bitbucket/?ref=christoffer.soop.ch">Bitbucket Branch Source Plugin</a> or similar so that all new repositories and branches are automagically discovered by Jenkins.</p>
<h2 id="pom">POM</h2>
<p>The Maven POM builds the Docker image using Spotify&apos;s  <a href="https://github.com/spotify/dockerfile-maven?ref=christoffer.soop.ch">dockerfile-maven-plugin</a>.</p>
<p>The POM is configured to</p>
<ul>
<li>Download all dependencies which are then added to the image</li>
<li>Create an executable JAR file which is also added to the image</li>
<li>Build the image if a Dockerfile is present using a Maven <code>docker</code> profile</li>
</ul>
<p>The base image pom.xml has two dependencies: the <a href="https://logback.qos.ch/?ref=christoffer.soop.ch">logback-classic</a> and <a href="https://github.com/logstash/logstash-logback-encoder?ref=christoffer.soop.ch">logstash-logback-encoder</a> libraries. These are shared by all our Microservices and are required for the  <a href="https://github.com/chrsoo/microservices/blob/master/src/files/logback.xml?ref=christoffer.soop.ch">logback.xml</a> configuration file.</p>
<p>The configuration found in the POM can be used both for building the base image and for building the Microservices, indeed given the use of a Maven <code>docker</code> <em>profile</em> it can be used for any Maven project with or without Dockerfiles.</p>
<p>In order to stay DRY the plugin configuration in the POM should be put in a parent pom shared by all Microservice projects. Or you will again end up with a WET solution...</p>
<h2 id="entrypoint">Entrypoint</h2>
<p>The <code>bootstrap.sh</code> shell script that serves as the docker image entry point.</p>
<p>It sets a few variables used for configuring the Microsevice and launches the microservice itself with a number of standard JVM arguments, including configuration of logback and JMX.</p>
<p>A nifty feature is that it will pass along all docker command line arguments to the Java runtime.</p>
<h1 id="lastwords">Last Words</h1>
<p>There are of course other solutions that still respect the DRY principle.</p>
<p>For example it might be preferable to get rid of the Dockerfile altogether. If you are building with Maven a good candidate is to use <a href="https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin?ref=christoffer.soop.ch">JIB</a>.</p>
<p>You could also get rid of the Jenkinsfile and implement auto discovery for Jenkins pipelines yourself but this seems like a rather cumbersome approach though. I would opt for an out-of-the-box solution that provisions build pipelines automatically.</p>
<p>I am not aware of any alternatives that do not use a Jenkinsfile, so it may be a good reason to look beyond Jenkins. Using another tool also has the benefit of not having to deal with Jenkins flavor of Groovy...</p>
<p>Any pointers on good alternatives that stay DRY for managing a large number of Git repositories and Dockerfiles are welcome!</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[Diaspora Seeds]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>Recently a couple of New York college students made a stir when they announced that they would write an open source and <strong>distributed</strong> social network server as an alternative to Facebook. This is really in the true spirit of the internet, where everyone can set up his or her own</p>]]></description><link>https://christoffer.soop.ch/diaspora-seeds/</link><guid isPermaLink="false">645818765c4dcc000153cb5c</guid><category><![CDATA[Architecture]]></category><category><![CDATA[internet]]></category><category><![CDATA[social network]]></category><dc:creator><![CDATA[Christoffer Soop]]></dc:creator><pubDate>Mon, 17 May 2010 16:17:14 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>Recently a couple of New York college students made a stir when they announced that they would write an open source and <strong>distributed</strong> social network server as an alternative to Facebook. This is really in the true spirit of the internet, where everyone can set up his or her own server and have them commicate, compare e.g. how email works. Incidentally, this is the way Instant Messaging should work but only SIP and Jabber (used by e.g. Google Talk) actually implement.<a href="http://www.kickstarter.com/projects/196017994/diaspora-the-personally-controlled-do-it-all-distr?ref=christoffer.soop.ch" title="Diaspora on Kickstarter"> Evidently they have raised about $170 000 in three weeks using Kickstarter, their initial target was $10 000</a>.</p>
<p>I sympathize 100% with their stated goals and will make sure I set up a Diaspora Seed once they make their first release.</p>
<p>More information on the <a href="http://joindiaspora.com/?ref=christoffer.soop.ch" title="Diaspora blog">Diaspora blog</a>.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[REST for Scott]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p><em>At the thanksgiving dinner of a friend from work I tried to explain REST-ful applications &#x2013; and I think I failed miserably. Even though there are plenty of good introductions out there I felt I needed to organize my thoughts a bit. Having some spare time on the train on</em></p>]]></description><link>https://christoffer.soop.ch/rest-for-scott/</link><guid isPermaLink="false">645818765c4dcc000153cb5a</guid><category><![CDATA[Architecture]]></category><category><![CDATA[REST]]></category><category><![CDATA[Web]]></category><dc:creator><![CDATA[Christoffer Soop]]></dc:creator><pubDate>Sat, 28 Nov 2009 08:07:22 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p><em>At the thanksgiving dinner of a friend from work I tried to explain REST-ful applications &#x2013; and I think I failed miserably. Even though there are plenty of good introductions out there I felt I needed to organize my thoughts a bit. Having some spare time on the train on the way home I made a second, more structured attempt in the form of this blog post.</em></p>
<p>Imagine you are a web developer and is asked by a friend with a travel agency to help out create a web site for his company. Among the services on the site is a small web application for searching for hotels recommended by the agency. These hotels have been carefully vetted for the agency&#x2019;s customer segment and useful hotel information is stored in a database.</p>
<p>Let us assume the web application manages the namespace under the URL</p>
<blockquote>
<p><a href="http://qualitytravel.com/hotel?ref=christoffer.soop.ch">http://qualitytravel.com/hotel</a></p>
</blockquote>
<p>One way to construct the application is by storing e.g. navigation state in a server side session or as post parameters in the HTTP requests. Or maybe use an AJAX user interface where parts of the page is updated asynchronously in the background. These approaches are, however, incompatible with the basic requirement of you friend the the travel agent, who frequently copies the URL of a particular hotel and sends it per email to potential customers. He would also like his customers and all other users of the web site to be able to send URLs, create bookmarks etc. Only by creating stable, re-usable URL&#x2019;s is this easily accomplished. Thus you decide on a basic categorization scheme where each hotel is listed under</p>
<blockquote>
<p><a href="http://qualitytravel.com/hotel/?ref=christoffer.soop.ch">http://qualitytravel.com/hotel/</a><country-code>/<city>/<hotel-name></hotel-name></city></country-code></p>
</blockquote>
<p>Where <country-code> is the two letter ISO code for the country, <city> the city name in english using only ascii characters and <hotel-name> is a unique name of the hotel (unique at least within the country). By typing in a URL like</hotel-name></city></country-code></p>
<blockquote>
<p><a href="http://qualitytravel.com/hotel/se/stockholm/grand-hotel?ref=christoffer.soop.ch">http://qualitytravel.com/hotel/se/stockholm/grand-hotel</a></p>
</blockquote>
<p>&#x2026; in a web browser you would end up with the HTML page describing the Grand Hotel in Stockholm, Sweden.</p>
<p>Your friend is very ambitious but would like to start out small. Uptime is of course important but not critical and you offer to host the site on your server at your place for a minor fee per month. (This would help pay the electricity and internet connection bills.)</p>
<p>Now, your friend has a business partner who organizes conferences in different countries around the globe. The business partner would like to link to specific hotels on your site, hotels your friend has arranged special deals and have pre-booked a number of rooms for. Since you are using stable and predictable URLs this is no big deal, for any particular conference the business partner can easily add the reference on a web page, add them in emails sent out to the participants and even in printed hard copy.</p>
<p>As the partnership between your friend and his business partner deepens, the business partner would like tighter integration between the two web sites. In particular he would like to create a mashup application where each conference has a map with all the hotels printed at the correct geographic location. Since your friend has stored the exact geo location of each hotel in his database it should not be too difficult to achieve.</p>
<p>Being well versed in XML and enterprise standards you now ponder a bit on web services. You could of course create a web service with a method which would accept a list of hotel identifiers and return a list coordinates&#x2026; After some deliberation you come to the conclusion it would be easiest to use the URLs as identifiers. They are unambiguous and you do not have to expose the primary keys of the database to the internet and there is no need to create new unique external identifiers. On top of that adding the identifiers to the mashup will be easy since the URLs are already used on the conference web page.</p>
<p>Thinking a bit further you realize that in the future there potentially is&#xA0; more information which could be useful, not just the coordinates. Right now you do not know exactly what information that would be, but if you return a list of XML documents containing basic information on each hotel and with geo-coordinates, you can always expend the XML document format to include additional information at a later stage. At least as long you are careful to keep the format backwards compatible. This you do by not changing the meaning and syntax of the existing XML and make sure the XML elements have the same position relative to the root element (i.e. that the XPath for the elements is stable).</p>
<p>Finally, you realize that instead of taking the pain of having to create a web service with SOAP, WSDLs etc you decide that each hotel URL should return the corresponding XML if the client asks to get the hotel information in XML format instead of HTML. This can easily be accomplished by using the standard HTTP content negotiation, i.e. the client sends a list of desired formats and the server responds with a document in one of the formats if it can.</p>
<p>The changes to the existing application are relatively minor, you only need to implement the content negotiation feature and in addition to render HTML you will need a mechanism to render XML. (In Java, using servlets, servlet filters and a templateing mechanism sounds like a good approach.)</p>
<p>The result is a huge success. Business is booming for your friend and traffic to your server is increasing at an alarming rate. You are sure that any minute your ISP will knock on the door telling you you are violating the fair use clause of your contract. In addition, uptime is becoming more of a concern. If not for the load so at least for redundancy you need two servers. You decide to move the web site to a hosting facility. Since state is not kept in a server side session you realize that clustering will be trivial. Each request is independent of the previous meaning it can land on either server without complication. This also means adding more servers to handle a larger load will be a breeze.</p>
<p>Some time later your friend has found an additional business partner &#x2013; this guy for some reason wants to create an AJAX client which uses the hotel information. The AJAX guys, programming in client side Java script, do not really like XML and prefer something called JSON. Would it be possible to add JSON support? In addition it would be nice if you could create a downloadable PDF for each hotel&#x2026;</p>
<p>Having the infrastructure already set up, all is needed is to add two new rendering templates, one for JSON and one for PDF&#x2019;s and add the two new formats to the lists served by the server.</p>
<p>&#x2013;</p>
<p>*The above scenario describes using REST &#x2013; <strong>RE</strong>presentational <strong>S</strong>tate <strong>T</strong>ransfer &#x2013; for building a web application. The text strives to illustrate the fundamental REST-ful principle of decoupling the reference of an object from its actual representation. It can also be said that in REST you take a resource or document oriented approach to software development, i.e. development is data-driven. This is opposed to service orientation with an RPC style of defining interfaces where focus is not on the data but rather on what you do with data; the focus is on the verbs instead of the nouns. In REST the actions are a well defined minimum like the four most well known HTTP verbs: GET, POST, PUT and DELETE. Above, only the implied use of GET is shown.<br>
*</p>
<p><em>Using REST principles is not constrained to web applications. It has been suggested that REST should be used instead of SOAP based web services in a SOA architecture, thus imbuing some of the webs scalability and robustness in an Enterprise Integraion scenario. Gartner has termed it <a href="http://hinchcliffe.org/archive/2008/02/27/16617.aspx?ref=christoffer.soop.ch" title="Web Oriented Architecture">WOA</a> for Web Oriented Architecture. WOA can be seen as a more constrained version of SOA.</em></p>
<p><em>It has even been suggested that REST is useful within applications. How this can be done is described in <a href="http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart1&amp;ref=christoffer.soop.ch" title="A Restful Core">four articles</a> on <a href="http://www.theserverside.com/?ref=christoffer.soop.ch" title="The Server Side">The Server Side</a>. Beware though, although well written they end up being a plug for <a href="http://1060.org/?ref=christoffer.soop.ch" title="1060 Net Kernel">NetKernel</a>, a REST-ful application server built on something they call ROC &#x2013; Resource Oriented Computing. I would say the jury is still out on question whether using REST internally in an application is a good alternative or not.</em></p>
<p><em><strong>References</strong></em></p>
<p><em>Wikipedia has a well written article on REST:</em></p>
<p><em><a href="http://en.wikipedia.org/wiki/REST?ref=christoffer.soop.ch" title="Wikipedia on REST">http://en.wikipedia.org/wiki/REST</a></em></p>
<p><em>Web Oriented Architecture</em></p>
<p>*<a href="http://hinchcliffe.org/archive/2008/02/27/16617.aspx?ref=christoffer.soop.ch" title="What is WOA?">http://hinchcliffe.org/archive/2008/02/27/16617.aspx</a><br>
*</p>
<p>*The Server Side, A Restful Core:<br>
*</p>
<p><em><a href="http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart1&amp;ref=christoffer.soop.ch" title="A Restful Core, part 1">http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart1</a> <a href="http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart2&amp;ref=christoffer.soop.ch" title="A Restful Core, part 2"></a></em></p>
<p><a href="http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart2&amp;ref=christoffer.soop.ch">http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart2</a></p>
<p><a href="http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart3&amp;ref=christoffer.soop.ch" title="A Restful Core, part 3">http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart3</a><br>
<a href="http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart3&amp;ref=christoffer.soop.ch" title="A Restful Core, part 4">http://www.theserverside.com/tt/articles/article.tss?l=ARESTfulCorePart4</a></p>
<!--kg-card-end: markdown-->]]></content:encoded></item><item><title><![CDATA[SOA is Dead (but the corpse is still kicking)]]></title><description><![CDATA[<!--kg-card-begin: markdown--><p>In a famous post from January this year (which I missed) Ann Thomas Manes declares SOA dead. She is a Reasearch Director within the Burton Group, has worked with SOA in the Burton Group and elsewhere, and is a co-author of the WS-* specifications.</p>
<p>The post has sparked fierce defense</p>]]></description><link>https://christoffer.soop.ch/soa-is-dead-but-the-corpse-is-still-kicking/</link><guid isPermaLink="false">645818765c4dcc000153cb58</guid><category><![CDATA[Architecture]]></category><category><![CDATA[REST]]></category><category><![CDATA[SOA]]></category><category><![CDATA[WOA]]></category><dc:creator><![CDATA[Christoffer Soop]]></dc:creator><pubDate>Thu, 23 Apr 2009 11:03:06 GMT</pubDate><content:encoded><![CDATA[<!--kg-card-begin: markdown--><p>In a famous post from January this year (which I missed) Ann Thomas Manes declares SOA dead. She is a Reasearch Director within the Burton Group, has worked with SOA in the Burton Group and elsewhere, and is a co-author of the WS-* specifications.</p>
<p>The post has sparked fierce defense from vendors like Oracle. During the half day <a href="http://www.oracle.com/webapps/events/EventsDetail.jsp?p_eventId=90347&amp;src=6640143&amp;src=6640143&amp;Act=575&amp;ref=christoffer.soop.ch">SOA Architect forum in Geneva</a> this Tuesday, Oracle spent the first seminar repeating that &#x201C;SOA is not dead&#x201D; like a mantra, I guess in order to reinforce the message. It seemed to be one of the mayor points they wanted to get across.</p>
<p>Excerpt from Ann Thomas Manes post <a href="http://apsblog.burtongroup.com/2009/01/soa-is-dead-long-live-services.html?ref=christoffer.soop.ch">SOA is Dead; Long Live Services</a></p>
<blockquote>
<p>Successful SOA (i.e., application re-architecture) requires disruption to the status quo. SOA is not simply a matter of deploying new technology and building service interfaces to existing applications; it requires redesign of the application portfolio. And it requires a massive shift in the way IT operates. The small select group of organizations that has seen spectacular gains from SOA did so by treating it as an agent of transformation. In each of these success stories, SOA was just one aspect of the transformation effort. And here&#x2019;s the secret to success: SOA needs to be part of something bigger. If it isn&#x2019;t, then you need to ask yourself why you&#x2019;ve been doing it.</p>
<p>The latest shiny new technology will not make things better. Incremental integration projects will not lead to significantly reduced costs and increased agility. If you want spectacular gains, then you need to make a spectacular commitment to change. Like Bechtel. It&#x2019;s interesting that the Bechtel story doesn&#x2019;t even use the term &#x201C;SOA&#x201D;&#x2014;it just talks about services.</p>
<p>And that&#x2019;s where we need to concentrate from this point forward: Services.</p>
</blockquote>
<p>This falls in line with my understanding that SOA without BPR/BPM/Transformation really does not amount to much. You need the entire organization to support a process and service view on business and IT in order to see real benefit.</p>
<p>In another post <a href="http://broadcast.oreilly.com/2009/01/soa-is-dead-its-about-time.html?ref=christoffer.soop.ch">SOA is Dead? It&#x2019;s About Time</a> by Kurt Cagle acknowledges Ann Thomas Manes view but complements the picture with adding that</p>
<blockquote>
<p>Perhaps my biggest reservation about SOA had to be the fact that, at the end of the day, it was still an RPC model that concentrated primarily on calling APIs that differed from one provider to the next. The result of this thinking is the sea of APIs, where there are now tens of thousands of APIs, each of which doing things a little (or in some cases, a lot) differently from one another, with very little cohesion, and with little thought to the semantic complexity that comes when you have that many microlanguages all competing for programmer attention.</p>
<p>Purists may argue that over time the SOA model (especially the SOAP/WSDL model) had been moving towards a more messaging-oriented architecture, but I&#x2019;d counter that all that a messaging queue does is to decouple the receipt of the message from the response &#x2013; if the message processor invokes a service, it is still an RPC, especially when transactions are involved.</p>
<p>This is one of the reasons that I think that resource oriented services &#x2013; RESTful services &#x2013; are beginning to gain real traction even as the big-box SOA projects are falling to the accountant&#x2019;s axe. The publish/subscribe model in which what you&#x2019;re publishing are not blogs but data documents (think XBRL or HL7) performs the same type of decoupling that message-oriented SOA did, but completely abstracts the intent from the process of communication.</p>
</blockquote>
<p>This is consistent with my view that SOA, which if done correctly, should be document or data driven and should rely on messaging. As an alternative to an ESB used mainly for RPC over SOAP Web Services, I think that an REST-ful approach should be seriously considered when attempting SOA. Some thinkers at Gartner have started talking about a WOA &#x2013; Web Oriented Architecture &#x2013; as further constrained subset of the SOA approach based on REST principles.</p>
<p>I believe the change will be heavily resisted by companies like Oracle and IBM since there is less money to be made on the simpler and less tool/platform-intensive REST-ful approach to enterprise computing. Also they all have invested heavily in the WS-* and RPC-style SOA corner and thus are reluctant to change. But change will come sooner or later and the ongoing economical crisis will be a strong driver.</p>
<!--kg-card-end: markdown-->]]></content:encoded></item></channel></rss>