<?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>The moons of Verthandi - Blog by Dani Giribet &#187; Java</title>
	<atom:link href="http://dani.calidos.com/tag/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://dani.calidos.com</link>
	<description></description>
	<lastBuildDate>Wed, 16 Jun 2010 19:38:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Components on the server (6): adding Integration Testing</title>
		<link>http://dani.calidos.com/2010/05/07/components-on-the-server-6-adding-integration-testing/</link>
		<comments>http://dani.calidos.com/2010/05/07/components-on-the-server-6-adding-integration-testing/#comments</comments>
		<pubDate>Fri, 07 May 2010 19:59:48 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Equinox]]></category>
		<category><![CDATA[integration testing]]></category>
		<category><![CDATA[osgi]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=265</guid>
		<description><![CDATA[In this installment of the server-side OSGi series, we add integration testing capabilities to our project. Integration testing goes beyond plain unit testing and checks the interactions between real components. This is in contrast with unit testing, which generally uses mockups to represent components outside the one being tested. Please take a look at previous [...]]]></description>
			<content:encoded><![CDATA[<p>In this installment of the server-side OSGi series, we add integration testing capabilities to our project. Integration testing goes beyond plain unit testing and checks the interactions between real components. This is in contrast with unit testing, which generally uses mockups to represent components outside the one being tested. Please take a look at previous installments, as usual.</p>
<p>In the case of integration testing, it is manly used in a pre-production environment, with a valid build that has all unit tests passed. It can even be used in production to just after a deployment is made, taking care not to have destructive checks or massive load tests in the integration test code. YMMV.</p>
<p>To achieve integration testing we need to check the various OSGi components deployed interact in the way that is expected of them. Therefore we need to test the components in a group and not in isolation. To do that in the OSGi world means we need to have access to the OSGi context from within the tests to access services, call them and check their responses, etc.</p>
<p>To allow for this kind of integration testing within the OSGi environment, we make a slight modification to the excellent test.extender we have already patched in the previous installment.</p>
<p>Basically, the basic test.extender seeks out any JUnit test classes within the fragment bundle, creates an instance using an empty constructor and then fires up the tests. This is activated either by default when the fragment is loaded or by using &#8216;test <bundleid>&#8216; in the console. For further information please see the <a href="http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-testing/">previous post</a> about this subject.</p>
<p>For our integration testing, we add an extra command to test.extender:</p>
<pre class="java:nocontrols:nogutter">
public Object _integrationTest(CommandInterpreter intp) {
        String nextArgument = intp.nextArgument();
    	testExtender.integrationTest(Long.parseLong(nextArgument));
    	return null;
}
</pre>
<p>And we refactor the TestExtender to add the integrationTest method which reuses some of the code to instantiate test cases using a constructor that accepts the OSGi context as a parameter.</p>
<pre class="java:nocontrols:nogutter">
Constructor<?>[] constructors = clazz.getConstructors();
boolean foundConstructor = false;
for (int i = 0; i < constructors.length &#038;&#038; !foundConstructor; i++) {
	Constructor<?> constructor = constructors[i];
	Class<?>[] types = constructor.getParameterTypes();
	if (types.length==1 &#038;&#038; types[0].isInstance(context)) {
		foundConstructor = true;
		EClassUtils.testClass(inspectClass, constructor.newInstance(context));
	}
} // for
</pre>
<p>The OSGi context is passed onto the constructor and then the test class is run. It is obviously up to the test class to use the context appropriately for its integration testing.</p>
<p>In our cache project setup, we can do some useful integration testing on the cache.controller component, basically checking if the interaction with the provider components is behaving as we expect it. The integration testing is also added to a fragment that can be deployed optionally, of course.</p>
<p>We start by creating the fragment and adding a testing class like this:</p>
<p><img alt="Adding test class" src="http://dani.calidos.com/img/2010/osgi-06/junit-test-case.png" title="Adding test class" class="alignnone" width="472" height="540" /></p>
<p>Next, we add the constructor that accepts an OSGi context, which is very simple:</p>
<pre class="java:nocontrols:nogutter">
public CacheIntegrationTest(BundleContext ctx) {
	super();
	this.context = ctx;
}
</pre>
<p>In the setup and teardown methods we get and unget the cache service to perform the testing:</p>
<pre class="java:nocontrols:nogutter">

public void setUp() throws Exception {
	serviceReference = context.getServiceReference(Cache.class.getName());
	controller = (CacheControllerCore) context.getService(serviceReference);

}

public void tearDown() throws Exception {
	context.ungetService(serviceReference);
	controller = null;
}
</pre>
<p>In this case we get the controller cache service and store it in an instance used to perform the tests. This is quite simple and fulfills our intended purpose but we still have the flexibility to make more complex integration testing if needed.</p>
<p>Next we create as many test cases as needed:</p>
<pre class="java:nocontrols:nogutter">
public void testGet() {
	try {
		controller.init();
		double v = Math.random();
		String k = "/k"+v;
		controller.set(k, v);
		assertEquals(v, controller.get(k));
	} catch (CacheProviderException e) {
		e.printStackTrace();
		fail(e.getMessage());
	}

}
</pre>
<p>It should be noted that while the code looks like regular testing code, it is actually using real services from the OSGi environment as opposed to mockups. This means we are testing the real integration between components as well as the individual controller component code. The disadvantage here is that if there is an error in the controller we might mistake the problem with an issue with the services used. In conclusion, having integration code doesn&#8217;t negate the need to have unit tests.</p>
<p>Once we load the fragment onto the environment, first we need to obtain the bundle id of the integration fragment and then launch the integration testing in this manner:</p>
<p><code><br />
osgi> integrate 125<br />
Bundle : [125] : com.calidos.dani.osgi.cache.controller.integration<br />
_<br />
CLASS : [com.calidos.dani.osgi.cache.controller.CacheIntegrationTest]<br />
___________________________________________________________________________<br />
Method : [ testInit ] PASS<br />
Method : [ testInitInt ] PASS<br />
Method : [ testSize ] PASS<br />
14:21:43,077 WARN  CacheControllerCore Couldn't clear some of the provider caches as operation is unsupported<br />
14:21:43,077 WARN  CacheControllerCore Couldn't clear some of the provider caches as operation is unsupported<br />
Method : [ testClear ] PASS<br />
Method : [ testSet ] PASS<br />
Method : [ testGet ] PASS<br />
Method : [ testGetStatus ] PASS<br />
___________________________________________________________________________<br />
</code></p>
<p>The results tell us that all operations are OK but we need to bear in mind that the clear operation is not supported in some backend caches. If this is what is expected by the operator then all is fine.</p>
<p>We take advantage of the new integration testing functionality to make some extensive changes to logging and exception handling of the controller code. By running the integration tests we make sure all seems to work fine  (even though we still need some proper unit testing of the controller). Modifications are made quite quickly thanks to the integration tests.</p>
<p>To recap, we&#8217;ve added integration testing support to the existing &#8216;test.extender&#8217; bundle and created integration testing code for the cache controller component. This has allowed us to make code changes quickly with less risk of mistakes.</p>
<p><a href="http://dani.calidos.com/img/2010/osgi-06/test-extender-patch.txt">Here</a> you can find a patch for the test extender project as well as the patched <a href="http://dani.calidos.com/img/2010/osgi-06/test.extender-1.0-SNAPSHOT.jar">testing bundle</a> already compiled. Enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2010/05/07/components-on-the-server-6-adding-integration-testing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Components on the server (4): adding Tomcat support</title>
		<link>http://dani.calidos.com/2009/12/01/components-on-the-server-4-adding-tomcat-support/</link>
		<comments>http://dani.calidos.com/2009/12/01/components-on-the-server-4-adding-tomcat-support/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 08:42:31 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Equinox]]></category>
		<category><![CDATA[java servlets]]></category>
		<category><![CDATA[osgi]]></category>
		<category><![CDATA[tomcat]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=196</guid>
		<description><![CDATA[In this post, we examine what is needed to deploy OSGi in a regular Servlet Container using the Equinox Servlet Bridge. We also use the Servlet Bridge to deploy our OSGi cache using Tomcat and wrap it up all together in a standalone WAR archive.
Please read the previous installments to get up to speed and [...]]]></description>
			<content:encoded><![CDATA[<p>In this post, we examine what is needed to deploy OSGi in a regular Servlet Container using the Equinox Servlet Bridge. We also use the Servlet Bridge to deploy our OSGi cache using Tomcat and wrap it up all together in a standalone WAR archive.</p>
<p>Please read the <a href="http://dani.calidos.com/tag/osgi/">previous installments</a> to get up to speed and see the source used in this post.</p>
<p>Firstly, we need to setup some kind of project to hold all that is going in the WAR archive. This can be done using the WTP (Web Tools Project) or just as a regular project.</p>
<p>In this case we do it using a plain-vanilla resource project but feel free to use WTP as the basics are the same.</p>
<p>So firstly we create a resources project to hold the stuff, named &#8216;com.calidos.dani.osgi.cache.package&#8217; for instance.<br />
Secondly, we create the folder structure we need to hold all the files that need to reside in the final WAR webapp, so we create a WEB-INF folder to hold all the classes, libraries metadata and configuration.</p>
<p>We also know we need a web.xml file to define all the servlets this webapp declares. This is where the Equinox Servlet Bridge kicks in. It provides a Servlet that loads up the environment as well as forwards any HTTP requests onto our OSGi-managed Servlet instances.</p>
<p>We check the Equinox in a servlet container <a href="http://www.eclipse.org/equinox/server/http_in_container.php">article</a> and learn what the bridge Servlet is called, what parameters it can take and any other web.xml details we need.</p>
<p>For instance, we declare that the webapp service class is our BridgeServlet class:<br />
<code><br />
&lt;servlet-class&gt;org.eclipse.equinox.servletbridge.BridgeServlet&lt;/servlet-class&gt;<br />
&lt;init-param&gt;<br />
	&lt;param-name&gt;commandline&lt;/param-name&gt;<br />
	&lt;param-value&gt;-console&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
&lt;init-param&gt;<br />
	&lt;param-name&gt;enableFrameworkControls&lt;/param-name&gt;<br />
	&lt;param-value&gt;true&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
</code></p>
<p>We also add two parameters (more information and additional options can be found on the FrameworkLauncher servlet bridge class and the Equinox documentation).</p>
<p>Next, we need this special servlet itself. I prefer to check out the servlet from CVS and compile it myself but you can also find it <a href="http://download.eclipse.org/equinox/">here</a> (from the the Latest Release pick up the org.eclipse.equinox.servletbridge jar). In the case of using the source, the CVS connection data is the following:</p>
<p><code><br />
Method: pserver<br />
User: anonymous<br />
Host: dev.eclipse.org<br />
Repository path: /cvsroot/rt<br />
CVS Module: org.eclipse.equinox/server-side/bundles/org.eclipse.equinox.servletbridge<br />
</code></p>
<p>Once we import the project into Eclipse it looks like this:</p>
<p><img alt="Servlet bridge project" src="http://dani.calidos.com/img/2009/osgi-04/01-servlet-bridge.png" title="Servlet bridge project" width="300" height="181" /></p>
<p>As we can see, there are just three classes which compose the servlet, a special classloader and finally a class that launches OSGi.</p>
<p>If we import the project into our workspace, we have compiled classes in the bin/ folder of the project but we really want them neatly packaged as a jar file. Therefore, we right-click on the project to export as a JAR java package:</p>
<p><img alt="Servlet bridge JAR export" src="http://dani.calidos.com/img/2009/osgi-04/02-servlet-bridge-export.png" title="Servlet bridge JAR export" width="483" height="568" /></p>
<p>We take this JAR archive and save it in our package project WEB-INF/lib folder. We also check the composition of the file to make sure it includes all the classes we need.</p>
<p>This takes care of the plain webapp side of things so we move onto actually loading OSGi and what configuration it needs.</p>
<p>As mandated by Equinox we add a launch.ini file to clear and possibly override System properties (please see the source for details on that).</p>
<p>We then create an eclipse folder, which the servlet bridge expects to find the OSGi platform jar and any bundles (including ours).</p>
<p>We select all our project bundles, right-click and select the &#8216;Export&#8230;:Deployable plug-ins and fragments&#8217; option.</p>
<p>This leaves us with a list of bundles that compose our custom code:<br />
<code><br />
com.calidos.dani.osgi.cache.controller_1.0.0.beta.jar<br />
com.calidos.dani.osgi.cache.frontend.http_1.0.0.beta.jar<br />
com.calidos.dani.osgi.cache.log4jconfig_1.0.0.beta.jar<br />
com.calidos.dani.osgi.cache.provider.memcached_1.0.0.beta.jar<br />
com.calidos.dani.osgi.cache.provider.memory_0.0.1.dev.jar<br />
</code></p>
<p>Good, as we know, there are some standard and some special bundle dependencies we need as well. Let&#8217;s go through them by groups. We get a bunch of basic OSGi bundles we should include in most projects:<br />
<code><br />
org.eclipse.equinox.registry_3.4.100.v20090520-1800.jar<br />
org.eclipse.osgi.services_3.2.0.v20090520-1800.jar<br />
org.eclipse.osgi.util_3.2.0.v20090520-1800.jar<br />
org.eclipse.osgi_3.5.1.R35x_v20090827.jar<br />
</code></p>
<p>There are several options to obtain these bundles:</p>
<p>For expediency, we can go to our Eclipse installation folder and look for them in the &#8216;plugins&#8217; subfolder. We then copy them into our package &#8216;plugins&#8217; folder and there you go.</p>
<p>The second option is to get them from the <a href="http://download.eclipse.org/equinox/">Equinox distribution</a>.</p>
<p>Another option is to the prepackaged servlet bridge feature which can be picked from CVS as well:</p>
<p>Method: pserver<br />
User: anonymous<br />
Host: dev.eclipse.org<br />
Repository path: /cvsroot/rt<br />
CVS Module: org.eclipse.equinox/server-side/features/org.eclipse.equinox.servletbridge.feature</p>
<p>Once that is loaded onto our workspace, we open the feature.xml and select the &#8216;Export Wizard&#8217;  form the &#8216;Exporting&#8217; section. This lets us export these minimum bundles and generate both the deployment &#8216;feature.xml&#8217; file as well as the bundle listing (even though the wizard actually takes them from our Eclipse platform).</p>
<p>We also have some more dependencies related to doing HTTP and the logging platform:<br />
<code><br />
org.apache.log4j_1.2.13.v200903072027.jar<br />
org.eclipse.equinox.common_3.5.1.R35x_v20090807-1100.jar<br />
org.eclipse.equinox.http.registry_1.0.200.v20090520-1800.jar<br />
org.eclipse.equinox.http.servlet_1.0.200.v20090520-1800.jar<br />
org.eclipse.equinox.registry_3.4.100.v20090520-1800.jar<br />
</code></p>
<p>These can also be obtained from the Eclipse plugins folder or Equinox distribution folder. One should note that modifying the feature.xml taken from the Eclipse CVS repository, adding any  required plugins there and then running the Export Wizard. </p>
<p>Finally, we have two dependencies we need to pay special attention to:<br />
<code><br />
org.eclipse.equinox.http.servletbridge_1.0.200.200911180023.jar<br />
javax.servlet_2.4.0.200911240836.jar<br />
</code></p>
<p>In the first case, it&#8217;s a special minimal bundle that hooks the plain webapp servlet bridge with the OSGi &#8216;org.eclipse.equinox.http.servlet&#8217; standard component which publishes a servlet service onto the OSGi platform.</p>
<p>This are the details to get it from CVS:</p>
<p>Method: pserver<br />
User: anonymous<br />
Host: dev.eclipse.org<br />
Repository path: /cvsroot/rt<br />
CVS Module: org.eclipse.equinox/server-side/bundles/org.eclipse.equinox.http.servletbridge</p>
<p>We export it as a deployable plug-in and add it to the mix. We can also download it from the Equinox distribution site as well.</p>
<p>In the second case, this bundle contains the basic servlet classes and interfaces and I have found problems of class signatures when using 2.5 along with the servlet bridge so unless all is compiled against 2.5 the safest bet is to go with 2.4.</p>
<p>(Check <a href="http://www.eclipse.org/equinox/documents/quickstart.php">http://www.eclipse.org/equinox/documents/quickstart.php</a> for more info).</p>
<p>Next, Equinox requires an XML file to define some metadata about the loaded bundles and make our configuration easier. The file sits in a folder called &#8216;features&#8217; plus a subfolder with a reverse DNS name and is called feature.xml.</p>
<p>The structure is quite simple (though it can be created using the Eclipse Feature Export Wizard) and mainly holds a list of plugins, their version data and some more fields:<br />
<code></p>
<plugin<br />
         id="org.eclipse.osgi"<br />
         download-size="0"<br />
         install-size="0"<br />
         version="3.5.1.R35x_v20090827"<br />
         unpack="false"/>
<plugin<br />
         id="org.eclipse.osgi.services"<br />
         download-size="0"<br />
         install-size="0"<br />
         version="3.2.0.v20090520"<br />
         unpack="false"/><br />
</code></p>
<p>We complete the list with all our bundles, fully knowing that we can extend our environment on the fly once it&#8217;s loaded if we need it.</p>
<p>Next, we create the config.ini file which really tells equinox which of the bundles stated in the feature file to start, at which start level and lets us add even more bundles (though we need to specify where the actual file is located and the full filename in that case). It also lets us configure the environment pretty thoroughly.</p>
<p>The resulting config.ini file looks like this:</p>
<p><code><br />
#Eclipse Runtime Configuration File<br />
osgi.bundles=org.eclipse.equinox.common@1:start, org.apache.log4j@start, org.eclipse.osgi.util@start, org.eclipse.osgi.services@start, org.eclipse.equinox.http.servlet@start, \<br />
 org.eclipse.equinox.servletbridge.extensionbundle, \<br />
 org.eclipse.equinox.http.servletbridge@start, \<br />
 javax.servlet@start, org.eclipse.equinox.registry@start, org.eclipse.equinox.http.registry@start, org.eclipse.equinox.servletbridge.extensionbundle \<br />
 org.eclipse.equinox.http.servlet@start, org.eclipse.equinox.common@start, com.calidos.dani.osgi.cache.log4jconfig, \<br />
 com.calidos.dani.osgi.cache.provider.memcached@3:start, com.calidos.dani.osgi.cache.provider.memory, com.calidos.dani.osgi.cache.controller@4:start, \<br />
 com.calidos.dani.osgi.cache.frontend.http@5:start</p>
<p>osgi.bundles.defaultStartLevel=4<br />
</code></p>
<p>We decide not to start the in memory bundle as it only works reliably in a single instance deployment scenario. Otherwise, in a multiple server setup the in-memory cache data would become inconsistent.</p>
<p>Also, be sure to check the <a href="http://www.eclipse.org/equinox/documents/quickstart.php">Equinox quickstart guide</a> and documentation for more information.</p>
<p>Once all is is done, the project looks like this:</p>
<p><img alt="Finished package project" src="http://dani.calidos.com/img/2009/osgi-04/03-danicache-package.png" title="Finished package project" width="423" height="414" /></p>
<p>Time to right-click on the project and select &#8216;Export:Archive file&#8217; to save it in zip format and rename it to .war. Ready to deploy! Remember to access it using the URL /<WAR-name>/cache/<cache-key>. In web.xml the &#8216;-console 6666&#8242; parameter means that doing a telnet on port 6666 of the machine initiates a session within the OSGi console. <strong>WARNING: there is absolutely NO SECURITY so disable, firewall or ACL that port NOW.</strong></p>
<p>As usual, here you can find the <a href="http://dani.calidos.com/img/2009/osgi-04/danicache.tar.gz">source</a> and the<a href="http://dani.calidos.com/img/2009/osgi-04/danicache.war"> completed WAR</a> though they are one and the same.</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2009/12/01/components-on-the-server-4-adding-tomcat-support/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Components on the server (3): adding a HTTP frontend</title>
		<link>http://dani.calidos.com/2009/11/08/components-on-the-server-3-adding-a-http-frontend/</link>
		<comments>http://dani.calidos.com/2009/11/08/components-on-the-server-3-adding-a-http-frontend/#comments</comments>
		<pubDate>Sun, 08 Nov 2009 15:06:40 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Equinox]]></category>
		<category><![CDATA[java servlets]]></category>
		<category><![CDATA[memcached]]></category>
		<category><![CDATA[osgi]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=182</guid>
		<description><![CDATA[Welcome to the third instalment of our OSGi ABC tutorial. Please make sure you check both the 1st installment and the 2nd.
In this post, we will add another cache provider implementation to the mix as well as provide an HTTP front-end so the whole application can be tested.
First of all, let&#8217;s present a conceptual diagram [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the third instalment of our OSGi ABC tutorial. Please make sure you check both the <a href="http://dani.calidos.com/2009/08/24/components-on-the-server-an-osgi-mini-project/">1st</a> installment and the <a href="http://dani.calidos.com/2009/10/24/components-on-the-server-2-creating-the-first-bundles/">2nd</a>.</p>
<p>In this post, we will add another cache provider implementation to the mix as well as provide an HTTP front-end so the whole application can be tested.</p>
<p>First of all, let&#8217;s present a conceptual diagram of all the bundles and fragments involved so far.</p>
<p><img src="http://dani.calidos.com/img/2009/osgi-03/Pasted-Graphic-4.png" alt="Components diagram" /></p>
<p>Read on for more&#8230;</p>
<p><span id="more-182"></span></p>
<p>We start with providing the extra implementation. We will be making a memcached cache provider using the excellent memcached-spy java library (MIT licensed).</p>
<p>As usual, we create a new plug-in project and name it accordingly (com.calidos.dani.osgi.cache.provider.memcached). We firstly create source folders named &#8217;src&#8217; and &#8216;test&#8217; to hold any unit tests. Secondly, we download the spy memcached library from <a href="http://code.google.com/p/spymemcached/">here</a>.</p>
<p>We create a &#8216;lib&#8217; folder on the project to hold the library and modify the classpath of the plug-in so its code is able to see the memcached client classes (but not the bundle clients!). In the runtime section of the MANIFEST.MF editor we select the library like this:</p>
<img alt="Classpath for memcached bundle" src="http://dani.calidos.com/img/2009/osgi-03/Pasted-Graphic-1.png" title="Classpath for memcached bundle" width="269" height="234" />
<p>We also add the controller as a dependency so we can properly implement the CacheProvider service interface.</p>
<p>Secondly, we &#8220;copy&#8221; the unit testing code from the Memory cache bundle as all tests will be quite similar (as both bundles basically fulfil the same contract).</p>
<p>When doing all this work, we discover that the memcached system doesn&#8217;t have some functionality other cache systems might have. For instance, the number of elements in the cache can&#8217;t be counted (not easily and cheaply). Additionally, the cache can&#8217;t really be cleared without restarting all memcached instances.</p>
<p>So it makes sense to add the UnsupportedOperationException exception to the interface, acknowledging the fact that some cache implementations might not provide all the facilities of the service. Other strategies would be to use subclassing, specialise the providers, etc In this case, we opt for adding the exceptions where it makes sense. That is, in the case of the get and set operations we can&#8217;t allow a service that doesn&#8217;t let you manage its elements. That&#8217;s not our definition of &#8220;cache&#8221;.</p>
<p>We adjust the code and tests in the Memory cache if necessary to adapt to the new interface and implement the mecached client (the unit tests will need some modification).</p>
<p>The memcached bundle in the project view ends looking like this:</p>
<img alt="Memcached bundle project view" src="http://dani.calidos.com/img/2009/osgi-03/Pasted-Graphic.png" title="Memcached bundle project view" width="271" height="277" />
<p>We make sure tests pass on this new bundle, to do that we need to tweak the test code a little bit (to capture new exceptions being thrown).</p>
<p>Next, we register the Cache service proper from the core controller tracker like this:</p>
<pre class="java:nocontrols:nogutter">
controller = new CacheControllerCore();
controller.addCacheProvider(cacheProvider);

//we have a provider, we can start publishing our service
registration = context.registerService(Cache.class.getName(),controller,null);
</pre>
<p>Note that we register the Cache service once we have added the first provider backend. This ensures that at least a backend is available as soon as the main service is registered.</p>
<p>At this point, things are looking good on backend implementation bits so we can move to providing a nice HTTP front-end for the cache so it can be used.</p>
<p>Therefore, we create a new bundle and call it something appropriate, such as &#8216;com.calidos.dani.osgi.cache.frontend.http&#8217;. The main function of this bundle is to glue together a HTTP Service being made available in the context to the business logic Cache service (provided by the core controller bundle). In this manner, the controller bundle does not need to know anything about HTTP or Servlet implementation. Moreover, this bundle only uses the Cache and doesn&#8217;t know about providers or implementation details.</p>
<p>We need to import a few packages and require the equinox http bundle to be present:</p>
<img alt="Required plugins for http frontend bundle" src="http://dani.calidos.com/img/2009/osgi-03/Pasted-Graphic-3.png" title="Required plugins for http frontend bundle" width="359" height="174" />
<img alt="Required packages for http frontend bundle" src="http://dani.calidos.com/img/2009/osgi-03/Pasted-Graphic-2.png" title="Required packages for http frontend bundle" width="348" height="196" />
<p>As an HTTP provider we can use the one provided by Jetty (that is bundled with Equinox).</p>
<p>Following the same model that on the controller bundle, we register two trackers one for the http service and another for the Cache service. Once both are made available we can create the servlet and glue them together.</p>
<p>There is a method to register the servlet on a particular URL:</p>
<pre class="java:nocontrols:nogutter">
cacheHttpFrontend.setCacheService(cacheService);
httpService.registerServlet("/cache", cacheHttpFrontend, null, null);
</pre>
<p>From that moment onwards we are sending any &#8216;/cache&#8217; URLs onto the servlet instance, which will use &#8216;/cache&#8217;<rest-of-the-URL> as the key.</p>
<p>The servlet can implement the usual methods &#8216;doPost&#8217; and &#8216;doPut&#8217; to add data onto the cache and doGet to retrieve it. These method calls translate into the appropriate Cache calls. Any exceptions or null values can be translated into equivalent HTTP errors or responses. For example, we can return a 500 if an unrecoverable exception is thrown from the cache or a 400 if the path is simply &#8216;/cache&#8217; (which means no key is provided).</p>
<p>As a result of thinking in HTTP terms, we come to realise we need some metadata about the contents of the cache. At least, we need to store the mime type of the data so we can properly serve multimedia and any content other than text. Moreover, we could store some more metadata to tune up the cache, do automatic refreshing of the content, etc.</p>
<p>One possible strategy is to ask the Cache to store a POJO instance that holds the metadata as well as the cached content itself. This seems the simplest approach at the moment so this is what we do. The Cache is still a generic service and as long as we prefix the HTTP caches accordingly at the app level we will be fine with using it in other clients (and these might revert to MIME as their way to tag content types as well).</p>
<p>We can create a custom class POJO but that means that any backend that does POJO serialisation needs access to this class so it can create one. To avoid that class and encapsulation break we just use a plain vanilla serialisable class (Map). In any case, we need to make a not of this problem of the design so it is addressed in the future.</p>
<p>NOTE: it could be addressed in a simple enough manner. The cache entry object interface could be formalised and exported by the controller. In this manner, the front-end and the providers could make use of it and serialise it properly.</p>
<p>We create the cache entry Map instance in a simple enough manner:</p>
<pre class="java:nocontrols:nogutter">
HashMap<String, CharSequence> httpCacheEntry = new HashMap<String, CharSequence>(2);
httpCacheEntry.put(ENTRY_BODY_KEY, body);
httpCacheEntry.put(ENTRY_MIME_KEY, contentType);
cache.set(key,httpCacheEntry);
</pre>
<p>In this manner, we can recover the appropriate metadata (in this case MIME type) from the entry cache whenever we do a get() operation. This doesn&#8217;t mean we expect all requested entries to have that structure (principle of robustness), it just means we will use it if it&#8217;s there, setting the HTTP response MIME type accordingly.</p>
<p>With these enhancements and a few more small code refactors we can stabilise our code and call it a day. To summarise what we have done in this post:</p>
<ul>
<li>Created a new CacheProvider implementation using memcached</li>
<li>Added a bundle that provides a frontend of the system using HTTP and a Servlet</li>
<li>Devised a way to store some metadata on the cache</li>
<li>Done some code cleanup and refactoring.</li>
</ul>
<p>As usual, you can download the code <a href="http://dani.calidos.com/img/2009/osgi-03/OSGI-abc-3rd-installment.tar.gz">here</a>. Thanks!</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2009/11/08/components-on-the-server-3-adding-a-http-frontend/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Components on the server (2): creating the first bundles</title>
		<link>http://dani.calidos.com/2009/10/24/components-on-the-server-2-creating-the-first-bundles/</link>
		<comments>http://dani.calidos.com/2009/10/24/components-on-the-server-2-creating-the-first-bundles/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 18:37:11 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Equinox]]></category>
		<category><![CDATA[osgi]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=158</guid>
		<description><![CDATA[Hopefully you enjoyed the OSGi journey in its first installment.
Though simple and easy to understand, the first example does nothing out of the ordinary. It is far more interesting to start exploiting some of the basic features OSGi gets us &#8220;for free&#8221;.
For instance, we could begin by moving our first basic implementation into a separate [...]]]></description>
			<content:encoded><![CDATA[<p>Hopefully you enjoyed the OSGi journey in its <a href="http://dani.calidos.com/2009/08/24/components-on-the-server-an-osgi-mini-project/">first installment</a>.</p>
<p>Though simple and easy to understand, the first example does nothing out of the ordinary. It is far more interesting to start exploiting some of the basic features OSGi gets us &#8220;for free&#8221;.</p>
<p>For instance, we could begin by moving our first basic implementation into a separate &#8220;model&#8221; bundle and enhancing the interface so it can throw exceptions. For instance, an exception can be thrown when no implementations are available or cannot be contacted/operated.</p>
<p>Read the rest of the post for the implementation details&#8230;</p>
<p><span id="more-158"></span></p>
<p>We start by picking up the project as we left it and firstly export the controller service. Open the MANIFEST.MF and on the &#8216;Runtime&#8217; section we add the &#8216;com.calidos.dani.osgi.cache.controller&#8217; package. This will enable any bundle clients to use the cache.</p>
<p>Secondly we create and expose the backend interface we want the model bundles to implement. This is the &#8217;service&#8217; the bundles can offer that our controller is interested in and is able to use as engines to store the cache data. The interface obviously needs to mimic most if not all of the cache&#8217;s public service but we also add lower level functionality, etc. A trivial way to do that is to have the declared backend interface inherit from the public service one.</p>
<pre class="java:nocontrols:nogutter">
public interface CacheProvider extends Cache {

CacheProviderStatus getStatus();	

}
</pre>
<p>At the moment we define a method to get the status of the backend implementation, we return an object as opposed to a simple type to be able to enrich it in the future. If we place this interface in its own package we need to export it on the plug-in manifest as well.</p>
<p>We then the enhance  the original interface with exceptions, which give information about the cause of the problem yet they shouldn&#8217;t  break up too much encapsulation.</p>
<pre class="java:nocontrols:nogutter">
public interface Cache {
[...]
void init() throws CacheProviderException;
[…]
</pre>
<p>It is interesting to note that depending on how we leverage the component nature of OSGi some of these errors can actually be recoverable which is what makes exceptions shine in java.</p>
<p>When adding the exceptions all our tests don&#8217;t compile anymore so it&#8217;s time to fix them by for example adding the throws declaration into the test signature as at the moment there is squat we can do about exceptions being thrown and these should be test failures anyway.</p>
<p>Cool, so next we create a new project to hold the in-memory implementation of the cache on its own. So we create a new plug-in project and name it accordingly:</p>
<p><img src="http://dani.calidos.com/img/2009/osgi-02/osgi-2nd-new.png" alt="Imported packages" /></p>
<p>Good, next we move our code from the controller bundle onto the new one. First of all we need to modify the new plug-in MANIFEST.MF to reflect we depend on the CacheProvider and Cache interfaces:</p>
<p><img src="http://dani.calidos.com/img/2009/osgi-02/osgi-2nd-imported.png" alt="Imported packages" /></p>
<p>This means we can move the code from the controller onto this new provider bundle. Code compiles but our original tests don&#8217;t as the actual code has moved.<br />
We first need to change the BasicCacheController class so it implements the more low-level provider interface, time for some refactoring (we also rename the implementation class to something more indicative of its function). </p>
<p>The tests need passing and actually we can move the old test code onto the new component as it effectively tests the in-memory implementation perfectly well. The controller component will need more sophisticated code which we will do after we finish the cleanup. Once the test is moved and the refactoring is complete tests on the new plug-in pass.</p>
<p>Summarizing:</p>
<ul>
<li>Move BasicCache class to com.calidos.dani.osgi.cache.provider.memory bundle</li>
<li>Rename BasicCache to MemoryCache</li>
<li>Move test from old bundle onto com.calidos.dani.osgi.cache.provider.memory</li>
<li>Fix compiling errors on the test and rename it to MemoryCacheTest</li>
<li>Make MemoryCache implement the CacheProvider interface</li>
<li>Modify the MemoryCacheTest class to test the extended CacheProvider functionality</li>
</ul>
<p>hat&#8217;s cool so now it is time to work in the OSGi world to wire the components together. To do that we edit the memory cache provider Activator class to register the service once it is activated like this:</p>
<pre class="java:nocontrols:nogutter">
public class Activator implements BundleActivator {

private MemoryCache cacheService;
private ServiceRegistration registration;

<em>/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
*/</em>
public void start(BundleContext context) throws Exception {

cacheService = new MemoryCache();
cacheService.init();
registration = context.registerService(CacheProvider.class.getName(), cacheService, null);

}

<em>/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
*/</em>
public void stop (BundleContext context) throws Exception {

registration.unregister();
cacheService.clear();

}

}
</pre>
<p>On the start() method we are creating a memory cache object and then registering it under the CacheProvider interface class name. This means that any other bundle in the OSGi environment that is interested in cache services can use the service provided by this bundle.</p>
<p>This highlights an interesting problem. Is it better to be active like this code and init the service before registering it? Or should we wait for the consumer to do it and follow a more lazy-loading design? That is actually a good question and I have just decided to create self-contained services that are fully operative once published as I think that leverages OSGi better but YMMV.</p>
<p>Next, we need the main controller to wait for cache provider services. To do that we can create a ServiceTracker subclass on the controller component. On that subclass we implement two methods that are called whenever a cache provider is registered into the context and when it is unregistered. We also supply a constructor that stores the controller Activator so we can pass the services back.</p>
<pre class="java:nocontrols:nogutter">
public class CacheProviderTracker extends ServiceTracker {

protected Activator activator;
protected static Logger log = Logger.getLogger(CacheProviderTracker.class);

public CacheProviderTracker (BundleContext context, String clazz,
		ServiceTrackerCustomizer customizer, Activator activator) {

super(context, clazz, customizer);
log.debug("CacheProviderTracker built");
this.activator = activator;

}

@Override
public Object addingService (ServiceReference reference) {		

	CacheProvider cacheProvider = (CacheProvider) context.getService(reference);
	log.debug("Obtained a new CacheProvider service");
	return cacheProvider;

}

@Override
public void removedService(ServiceReference reference, Object service) {

	log.debug("A CacheProvider service has been removed from the context");
	context.ungetService(reference);		

}

}
</pre>
<p>We then modify the callbacks so the services are actually passed onto the Activator for their use. We need to create the appropriate methods in the Activator and we will fill them up next.</p>
<pre class="java:nocontrols:nogutter">
public void addCacheProvider(CacheProvider cacheProvider) {
}

public void removeService(CacheProvider service) {
}
</pre>
<p>Now we need to glue the backend provider with the controller so any Cache interface requests are passed onto CacheProvider services. To do that we create a new Cache interface implementation class in the controller bundle (appropriately named CacheControllerCore). The signature is something like:</p>
<pre class="java:nocontrols:nogutter">
public class CacheController implements Cache {
</pre>
<p>Which means we can offer this class as a Cache service once it&#8217;s ready. So when should we create a CacheControllerCore instance and offer it as a service? Well, whenever we have backend providers ready, not before. Therefore we now complete the addCacheProvider in the Activator method to do so:</p>
<pre class="java:nocontrols:nogutter">
if (controller==null) {
	controller = new CacheControllerCore();
	controller.addCacheProvider(cacheProvider);
} else {
	controller.addCacheProvider(cacheProvider);
}
</pre>
<p>This creates the instance only the fist time a provider is registered and after that just simply tells the controller class that an extra one is available. An added bonus of doing on a controller class instead of directly in the Activator is that we don&#8217;t want to overload the Activator with lots of logic. We also complete the removeService method. If in the future we deal with more services we will need a refactor as we would be dealing with a lot of handover methods from the activator class onto the core controller.</p>
<p>Okay, so what is the main goal of the CacheControllerCore then? To maintain a list of providers and hand over requests to them. As a convention and for greater flexiblity, it will send all messages to all services except for get, which will basically hand over the first object it finds.</p>
<p><strong>DESIGN WARNING</strong>: <em>in doing the implementation of the core controller we realise there are potential thread-safe potential problems in accessing the provider list. This is a cache and not an ACID system and we are looking for speed + 99.99% efficacy when changing providers and 100% efficacy when providers are stable. One should consider that in 99.9999999% of the time we are not changing providers mid-flight we wouldn&#8217;t want to compromise the overall efficiency of the architecture by the odd chance that two or three requests out of a million might actually get a miss from the cache where they should have had a hit or a cache set operation needs to be retried. Therefore, we implement a few basic checks on the core to minimize problems and provide graceful degradation of service in edge cases as opposed to meaningless null pointer exceptions.</em></p>
<p>Once this cautious but hopefully practical implementation is complete we can take a step back and review what we have done so far.</p>
<ul>
<li>We have defined a cache backend provider interface</li>
<li>Also created a simple provider implementation that stores data in memory</li>
<li>We have also glued the backend example to the core and refactored things a bit</li>
<li>The core now loops through available backends and is reasonably resilient</li>
</ul>
<p>Click <a href="http://dani.calidos.com/img/2009/osgi-02/OSGI-abc-second-installment.tar.gz">here</a> to download the code as it stands. More to come!</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2009/10/24/components-on-the-server-2-creating-the-first-bundles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
