<?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>Over Software Architectuur &#38; SOA</title>
	<atom:link href="http://blog.josnieuwenhuis.nl/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.josnieuwenhuis.nl</link>
	<description>door Jos Nieuwenhuis</description>
	<lastBuildDate>Sat, 20 Mar 2010 09:34:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Performance van embedded databases</title>
		<link>http://blog.josnieuwenhuis.nl/2010/03/20/performance-van-embedded-databases/</link>
		<comments>http://blog.josnieuwenhuis.nl/2010/03/20/performance-van-embedded-databases/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 08:04:17 +0000</pubDate>
		<dc:creator>Jos Nieuwenhuis</dc:creator>
				<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://blog.josnieuwenhuis.nl/?p=65</guid>
		<description><![CDATA[Voor een desktop applicatie wil ik gebruik maken van een embedded database. Hiervan bestaan er echter verschillende, elk zo  met hun eigen toepassingsgebied. Mijn aandacht ging uit naar een database die snel is. Om erachter te komen welke database het snelste is. De volgende heb ik vergeleken: Oracle Berkeley DB Java Edition,  Sun Java DB (Apache Derby), DB4O, Apache Lucene en Neo4J. Uit de testresultaten kun je concluderen dat zowel Lucene als Berkeley DB heel snel zijn.]]></description>
			<content:encoded><![CDATA[<p>Voor een desktop applicatie wil ik gebruik maken van een embedded database. Hiervan bestaan er echter verschillende, elk zo  met hun eigen toepassingsgebied. Mijn aandacht ging uit naar een database die snel is. Om erachter te komen welke database het snelste is. De volgende heb ik vergeleken:</p>
<ul>
<li><a href="http://www.oracle.com/technology/products/berkeley-db/index.html">Oracle Berkeley DB Java Edition 4.0.71</a> – Database met een Java API</li>
<li><a href="http://developers.sun.com/javadb/">Sun Java DB (Apache Derby) 10.5.3.0_1</a> – SQL database</li>
<li><a href="http://www.db4o.com/">DB4O 7.13</a> – Object database</li>
<li><a href="http://lucene.apache.org/java/">Apache Lucene 2.9.0 </a>– Search index</li>
<li><a href="http://neo4j.org/">Neo4J 1.0-rc</a> – Graph database</li>
<li><a href="http://java.sun.com/javase/6/docs/api/java/util/HashMap.html">HashMap</a> – Java Collection</li>
</ul>
<p>Lucene en HashMap zijn eigenlijk geen embedded databases, maar je kunt ze wel gebruiken om gegevens in op te slaan. In elk van de databases heb ik het volgende Java object opgeslagen:</p>
<pre  name="code" class="java:nocontrols">
public class Book {
	List authors;
	String isbn;
	String title;
	String publisher;
	String description;
	String edition;
	Date publicationDate;
	String ean;
	int numberOfPages;
	String imageUrl;
	String year;

	//Getters and Setters ..
}
</pre>
<p>De code voor het opslaan, lezen, wijzigen en verwijderen is gebaseerd op de voorbeeld code die ik van de websites van de verschillende producten te vinden is. Elke implementatie heeft de volgende interface:</p>
<pre  name="code" class="java:nocontrols">
public interface BookDAO {
    public abstract boolean create(Book book);
    public abstract boolean update(Book book);
    public abstract boolean delete(Book book);
    public abstract Book findByISBN(String isbn);
}
</pre>
<p>De performance testen werden uitgevoerd met behulp van <a href="http://jakarta.apache.org/jmeter/index.html">JMeter</a> <a href="http://jakarta.apache.org/jmeter/api/org/apache/jmeter/protocol/java/sampler/JavaSampler.html">JavaSampler</a> die vanuit een maven project wordt aangeroepen met behulp van de <a href="http://www.ronniealleva.org/index.php/maven-jmeter-plugin/">Maven JMeter plugin</a> (deze heb ik zelf nog moeten wijzigen om rekening te houden met <a href="http://my.opera.com/mateamargo/blog/2007/09/27/running-junitsampler-with-maven"> classpath dependencies</a>). Mijn test set bestaat uit 1137 records. Deze werden eerst opgeslagen, vervolgens gelezen, aangepast en tenslotte verwijderd. Onderstaande tabel toont de gemiddelde tijd om een actie uit te voeren. </p>
<style type="text/css">
table.sample {
border-width: medium medium medium medium;
border-spacing: 0px;
border-style: solid solid solid solid;
border-color: gray gray gray gray;
border-collapse: separate;
background-color: white;
}
table.sample th {
border-width: 1px 1px 1px 1px;
padding: 1px 1px 1px 1px;
border-style: inset inset inset inset;
border-color: gray gray gray gray;
background-color: #999;
-moz-border-radius: 0px 0px 0px 0px;
}
table.sample td {
border-width: 1px 1px 1px 1px;
padding: 1px 1px 1px 1px;
border-style: inset inset inset inset;
border-color: gray gray gray gray;
background-color: white;
-moz-border-radius: 0px 0px 0px 0px;
width: 150px;
}
</style>
<table class="sample">
<thead>
<tr>
<th><strong>Data store</strong></th>
<th><strong>Operation</strong></th>
<th><strong>Average duration<br />
in milliseconds</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="4">Berkeley DB</td>
<td>Create</td>
<td align="right">0.52</td>
</tr>
<tr>
<td>Read</td>
<td align="right">0.44</td>
</tr>
<tr>
<td>Update</td>
<td align="right">0.65</td>
</tr>
<tr>
<td>Delete</td>
<td align="right">0.53</td>
</tr>
<tr>
<td rowspan="4">Java DB</td>
<td>Create</td>
<td align="right">1.13</td>
</tr>
<tr>
<td>Read</td>
<td align="right">0.51</td>
</tr>
<tr>
<td>Update</td>
<td align="right">1.44</td>
</tr>
<tr>
<td>Delete</td>
<td align="right">1.19</td>
</tr>
<tr>
<td rowspan="4">DB4O</td>
<td>Create</td>
<td align="right">0.52</td>
</tr>
<tr>
<td>Read</td>
<td align="right">18.18</td>
</tr>
<tr>
<td>Update</td>
<td align="right">19.43</td>
</tr>
<tr>
<td>Delete</td>
<td align="right">11.72</td>
</tr>
<tr>
<td rowspan="4">Lucene</td>
<td>Create</td>
<td align="right">0.44</td>
</tr>
<tr>
<td>Read</td>
<td align="right">0.33</td>
</tr>
<tr>
<td>Update</td>
<td align="right">0.40</td>
</tr>
<tr>
<td>Delete</td>
<td align="right">0.07</td>
</tr>
<tr>
<td rowspan="4">Neo4J</td>
<td>Create</td>
<td align="right">104.94</td>
</tr>
<tr>
<td>Read</td>
<td align="right">2.12</td>
</tr>
<tr>
<td>Update</td>
<td align="right">0.65</td>
</tr>
<tr>
<td>Delete</td>
<td align="right">52.41</td>
</tr>
<tr>
<td rowspan="4">HashMap</td>
<td>Create</td>
<td align="right">0.04</td>
</tr>
<tr>
<td>Read</td>
<td align="right">0.03</td>
</tr>
<tr>
<td>Update</td>
<td align="right">0.04</td>
</tr>
<tr>
<td>Delete</td>
<td align="right">0.04</td>
</tr>
</tbody>
</table>
<p>Uit de resultaten kun je concluderen dat zowel Lucene als Berkeley DB heel snel zijn.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.josnieuwenhuis.nl/2010/03/20/performance-van-embedded-databases/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>(Her)bruikbaarheid van services</title>
		<link>http://blog.josnieuwenhuis.nl/2009/10/23/herbruikbaarheid-van-services/</link>
		<comments>http://blog.josnieuwenhuis.nl/2009/10/23/herbruikbaarheid-van-services/#comments</comments>
		<pubDate>Fri, 23 Oct 2009 19:44:10 +0000</pubDate>
		<dc:creator>Jos Nieuwenhuis</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[Ontwerpproces]]></category>
		<category><![CDATA[Reusability]]></category>

		<guid isPermaLink="false">http://blog.josnieuwenhuis.nl/?p=51</guid>
		<description><![CDATA[Eén van de belangrijkste eigenschappen van Service Oriented Architecture is de herbruikbaarheid. Herbruikbaarheid impliceert dat je rekening moet houden met verschillende situaties. Hoe doe je dat? Hoe voorkom je dat je te veel functionaliteit bouwt welke in de praktijk niet gebruikt gaat worden? Hoe kun je rekening houden met toekomstig gebruik? 
Het antwoord op deze [...]]]></description>
			<content:encoded><![CDATA[<p>Eén van de belangrijkste eigenschappen van Service Oriented Architecture is de herbruikbaarheid. Herbruikbaarheid impliceert dat je rekening moet houden met verschillende situaties. Hoe doe je dat? Hoe voorkom je dat je te veel functionaliteit bouwt welke in de praktijk niet gebruikt gaat worden? Hoe kun je rekening houden met toekomstig gebruik? </p>
<p>Het antwoord op deze vragen krijg je door het ontwikkelproces op de juiste manier te structureren. Dus niet zomaar iets gaan bouwen en hopen dat het voorziet in een behoefte. Nee, een zorgvuldige analyse is vereist. Het doel moet altijd zijn: hoe kun je een product (service) ontwikkelen met maximale meerwaarde voor de organisatie. Naar mijn mening moet je niet te veel kijken naar de toekomst. Wat je ontwikkelt moet nu meerwaarde bieden. Niemand kan de toekomst voorspellen. Je zou dus niet te veel tijd moeten besteden aan functionaliteit die niet direct gebruikt gaat worden. Dit is duur en eigenlijk verloren tijd.  </p>
<p>Vantevoren moet je begrijpen wie de doelgroep is en wat deze doelgroep nodig heeft. Dit is eigenlijk precies hetzelfde als het ontwerpen van (industriële) producten. Ook hiervoor maak je een grondige analyse van bedrijfsdoelstellingen, bedrijfsprocessen, doelgroepen en analyse van concurrerende producten. Marktonderzoek kan hiervoor heel nuttig zijn. In het geval van SOA werk je meestal binnen een organisatie. Dit maakt marktonderzoek een stuk eenvoudiger. Je hoeft namelijk niet meer anoniem te werken en kunt rechtstreeks naar mensen toe stappen. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.josnieuwenhuis.nl/2009/10/23/herbruikbaarheid-van-services/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gebruik maken van Amazon&#8217;s Product Advertising API</title>
		<link>http://blog.josnieuwenhuis.nl/2009/10/18/amazons-product-advertising-api/</link>
		<comments>http://blog.josnieuwenhuis.nl/2009/10/18/amazons-product-advertising-api/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 06:29:10 +0000</pubDate>
		<dc:creator>Jos Nieuwenhuis</dc:creator>
				<category><![CDATA[SOA]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[SOAP]]></category>
		<category><![CDATA[Webservices]]></category>

		<guid isPermaLink="false">http://blog.josnieuwenhuis.nl/?p=33</guid>
		<description><![CDATA[In een zelfgemaakte applicatie maak ik gebruik van Amazon Product Advertising API om informatie over boeken op te halen. Jarenlang kon ik deze webservice zonder enige aanpassing gebruiken. Recentelijk is echter het authenticatie mechanisme gewijzigd. Amazon biedt twee mogelijkheden om de authenticatie toe te passen: met of zonder WS-Security. Als er geen gebruik wordt gemaakt [...]]]></description>
			<content:encoded><![CDATA[<p>In een zelfgemaakte applicatie maak ik gebruik van <a href="http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/CHAP_Intro_AAWS.html">Amazon Product Advertising API</a> om informatie over boeken op te halen. Jarenlang kon ik deze webservice zonder enige aanpassing gebruiken. Recentelijk is echter het authenticatie mechanisme gewijzigd. Amazon biedt twee mogelijkheden om de authenticatie toe te passen: met of zonder WS-Security. Als er geen gebruik wordt gemaakt van WS-Security moet de AWS identificatie in combinatie met een te berekenen hash worden meegestuurd in de SOAP Header. </p>
<p>In plaats van de bestaande code aan te passen besloot ik om deze weg te gooien en opnieuw te beginnen. Dit maal besloot ik om alles in een Maven artifact te stoppen. Dit biedt als voordeel dat elke IDE mits geïntegreerd met Maven deze library kan gaan gebruiken. Ik besloot om de library in NetBeans IDE 6.7 te programmeren. Dit bleek heel eenvoudig. Met behulp van de Web Service Client wizard kan het Maven POM bestand worden gegenereerd. In de wizard heb ik gekozen voor <a href="https://jax-ws.dev.java.net/">JAX-WS</a> Style. De WSDL van de webservice staat op de volgende locatie: <a href="http://webservices.amazon.com/AWSECommerceService/AWSECommerceService.wsdl">WSDL</a>. Hieronder de gegenereerde POM:</p>
<pre name="code" class="xml:nocontrols">
&lt;project&gt;
  &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
  &lt;groupId&gt;com.amazon.webservices&lt;/groupId&gt;
  &lt;artifactId&gt;aws-ecommerce-service&lt;/artifactId&gt;
  &lt;packaging&gt;jar&lt;/packaging&gt;
  &lt;version&gt;2009_10_01&lt;/version&gt;
  &lt;name&gt;AWSECommerceServicet&lt;/name&gt;
  &lt;build&gt;
    &lt;plugins&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
        &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
        &lt;version&gt;2.0.2&lt;/version&gt;
        &lt;configuration&gt;
          &lt;source&gt;1.5&lt;/source&gt;
          &lt;target&gt;1.5&lt;/target&gt;
        &lt;/configuration&gt;
      &lt;/plugin&gt;
      &lt;plugin&gt;
        &lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;
        &lt;artifactId&gt;jaxws-maven-plugin&lt;/artifactId&gt;
        &lt;version&gt;1.10&lt;/version&gt;
        &lt;executions&gt;
          &lt;execution&gt;
            &lt;goals&gt;
              &lt;goal&gt;wsimport&lt;/goal&gt;
            &lt;/goals&gt;
            &lt;configuration&gt;
              &lt;wsdlFiles&gt;
                &lt;wsdlFile&gt;AWSECommerceService.wsdl&lt;/wsdlFile&gt;
              &lt;/wsdlFiles&gt;
              &lt;staleFile&gt;${project.build.directory}
              /jaxws/stale/AWSECommerceService.stale&lt;/staleFile&gt;
            &lt;/configuration&gt;
            &lt;id&gt;wsimport-generate-AWSECommerceService&lt;/id&gt;
            &lt;phase&gt;generate-sources&lt;/phase&gt;
          &lt;/execution&gt;
        &lt;/executions&gt;
        &lt;dependencies&gt;
          &lt;dependency&gt;
            &lt;groupId&gt;javax.xml&lt;/groupId&gt;
            &lt;artifactId&gt;webservices-api&lt;/artifactId&gt;
            &lt;version&gt;1.4&lt;/version&gt;
          &lt;/dependency&gt;
        &lt;/dependencies&gt;
      &lt;/plugin&gt;
    &lt;/plugins&gt;
  &lt;/build&gt;
  &lt;dependencies&gt;
    &lt;dependency&gt;
      &lt;groupId&gt;com.sun.xml.ws&lt;/groupId&gt;
      &lt;artifactId&gt;webservices-rt&lt;/artifactId&gt;
      &lt;version&gt;1.4&lt;/version&gt;
      &lt;scope&gt;provided&lt;/scope&gt;
    &lt;/dependency&gt;
  &lt;/dependencies&gt;
&lt;/project&gt;
</pre>
<p>Met behulp van het Maven commando <code>mvn clean install</code> wordt de library gegenereerd, gecompileerd en geïnstalleerd in de lokale Maven repository. </p>
<p>In een ander Maven project gebruik ik deze library. Dit project fungeert als een soort adapter. Uiteindelijk wil ik vanuit de applicatie alleen een simpele interface aanspreken om boek-informatie op te halen:</p>
<pre  name="code" class="java:nocontrols">
public interface BookService {
  public abstract Book findByISBN(String isbn);
}
</pre>
<p>Het toevoegen van de authenticatie code bleek nog niet zo eenvoudig. Met behulp van een SOAPHandler is de Header van een SOAP bericht te manipuleren: </p>
<pre  name="code" class="java:nocontrols">
public Book findByISBN(String isbn) {
  AWSECommerceService awsecommerceservice = new AWSECommerceService();
  awsecommerceservice.setHandlerResolver(new HandlerResolver() {
    @Override
    public List&lt;Handler&gt; getHandlerChain(PortInfo portInfo) {
      List&lt;Handler&gt; handlerList = new ArrayList&lt;Handler&gt;();
      handlerList.add(new AmazonSOAPHandler());
      return handlerList;
    }
  });
  AWSECommerceServicePortType awsecommerceserviceport =
      awsecommerceservice.getAWSECommerceServicePort();
  List&lt;ItemLookupRequest&gt; request = createItemLookupRequest(isbn);
  Holder&lt;List&lt;Items&gt;&gt; items = new Holder&lt;List&lt;Items&gt;&gt;();
  awsecommerceserviceport.itemLookup(null, AWS_ACCESS_KEY_ID, null, null,
      null, null, null, request, null, items);
  return parseResults(items);
}
</pre>
<p>De SOAPHandler bevat de volgende methode om de Header aan te passen:</p>
<pre name="code" class="java:nocontrols">
public boolean handleMessage(SOAPMessageContext context) {
  Boolean outboundProperty =
      (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  if (outboundProperty.booleanValue()) {
    try {
      AmazonSOAPHeaderData headerData = new AmazonSOAPHeaderData();
      SOAPEnvelope envelope = context.getMessage().getSOAPPart().getEnvelope();
      SOAPHeader header = envelope.addHeader();
      headerData.addInformationToSOAPHeader(header);
    } catch (Exception ex) {
      Logger.getLogger(AmazonSOAPHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
  }
  return true;
}
</pre>
<p>AmazonSOAPHeaderData class bevat de informatie die in de header moet worden toegevoegd. Tevens wordt de &#8216;handtekening&#8217; (Signature) in deze class berekend. Deze is bijna identiek aan het algoritme in de <a href="http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/NotUsingWSSecurity.html">documenentatie van Amazon</a>. Ik moest een kleine aanpassing doen om de code correct te laten werken:</p>
<pre name="code" class="java:nocontrols">
public class AmazonSOAPHeaderData {

    private static final String UTF8_CHARSET = "UTF-8";
    private static final String HMAC_SHA256_ALGORITHM = "HmacSHA256";
    private String awsAccessKeyId = "XXXXXXXXXXXXXXXXXXXX";
    private String awsSecretKey = "SSSSSSSSSSSSSSSSSSSSSSSS";
    private String action = "ItemLookup";
    private static final String prefix = "aws";
    private static final String uri = "http://security.amazonaws.com/doc/2007-01-01/";
    private SecretKeySpec secretKeySpec = null;
    private Mac mac = null;

    public AmazonSOAPHeaderData() {
        try {
            byte[] secretyKeyBytes = awsSecretKey.getBytes(UTF8_CHARSET);
            secretKeySpec = new SecretKeySpec(secretyKeyBytes, HMAC_SHA256_ALGORITHM);
            mac = Mac.getInstance(HMAC_SHA256_ALGORITHM);
            mac.init(secretKeySpec);
        } catch (Exception e) {
            throw new RuntimeException(HMAC_SHA256_ALGORITHM + " is unsupported!", e);
        }
    }

    private String hmac(String stringToSign) {
        String sig = "";
        byte[] data;
        byte[] rawHmac;
        try {
            data = stringToSign.getBytes(UTF8_CHARSET);
            rawHmac = mac.doFinal(data);
            Base64 encoder = new Base64();
            sig = new String(encoder.encode(rawHmac));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(UTF8_CHARSET + " is unsupported!", e);
        }
        return sig.trim();
    }

    private String createTimestamp() {
        Calendar cal = Calendar.getInstance();
        DateFormat dfm = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        dfm.setTimeZone(TimeZone.getTimeZone("GMT"));
        return dfm.format(cal.getTime());
    }

    public void addInformationToSOAPHeader(SOAPHeader header) throws SOAPException {
        SOAPFactory factory = SOAPFactory.newInstance();
        String timestamp = createTimestamp();
        String signature = hmac(action + timestamp);

        SOAPElement accessKeyElem =
                factory.createElement("AWSAccessKeyId", prefix, uri);
        accessKeyElem.addTextNode(awsAccessKeyId);
        SOAPElement timestampElem =
                factory.createElement("Timestamp", prefix, uri);
        timestampElem.addTextNode(timestamp);
        SOAPElement signatureElem =
                factory.createElement("Signature", prefix, uri);
        signatureElem.addTextNode(signature);

        header.addChildElement(accessKeyElem);
        header.addChildElement(timestampElem);
        header.addChildElement(signatureElem);
    }
}
</pre>
<p>Met deze code is het mogelijk om boekinformatie op te halen. De complete broncode staat <a href="http://blog.josnieuwenhuis.nl/download/aws-ecommerce-client-code.tar.gz">hier</a>. Uiteraard moet je om gebruik te maken van de Product Advertising API een account aanvragen. Dit is gratis en staat verder beschreven op de website van de <a href="http://aws.amazon.com/">Amazon WebServices</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.josnieuwenhuis.nl/2009/10/18/amazons-product-advertising-api/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
