<?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 servlets</title>
	<atom:link href="http://dani.calidos.com/tag/java-servlets/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 (5): better Unit Testing</title>
		<link>http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-testing/</link>
		<comments>http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-testing/#comments</comments>
		<pubDate>Sun, 03 Jan 2010 23:20:15 +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[junit]]></category>
		<category><![CDATA[osgi]]></category>
		<category><![CDATA[tomcat]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=217</guid>
		<description><![CDATA[In this installment of the OSGi series, we add more complete Unit Testing support in the project. We also establish that some behaviour of the Servlet Bridge may not be what we want  and then provide a way to customize it.

Please make sure you read the previous installments before you continue with this article…
To [...]]]></description>
			<content:encoded><![CDATA[<p>In this installment of the OSGi series, we add more complete Unit Testing support in the project. We also establish that some behaviour of the Servlet Bridge may not be what we want  and then provide a way to customize it.</p>
<p><span id="more-217"></span></p>
<p>Please make sure you read the<a href="http://dani.calidos.com/category/computing/java/"> previous installments </a>before you continue with this article…</p>
<p>To ensure greater flexibility, performance and encapsulation, we will be using OSGi fragments.</p>
<p>http://static.springsource.org/osgi/docs/1.1.3/reference/html/appendix-tips.html</p>
<p>OSGi fragments attach to &#8220;host&#8221; bundles and can be used to extend functionality, provide configuration and even extra manifest entries.</p>
<p>On the first part, we move our unit tests to fragments. This has the benefit of being able to separate tests from actual code as well as allowing us to deploy using a smaller footprint in situations where we don&#8217;t want test code such as production deployments.</p>
<p>If we start with the cache code we&#8217;ve got so far we need to separate the test code from two bundles: &#8216;com.calidos.dani.osgi.cache.provider.memory&#8217; and &#8216;com.calidos.dani.osgi.cache.provider.memcached&#8217;. That is easy enough.</p>
<p>We create a new OSGi bundle fragment project like this:</p>
<p><img alt="New fragment" src="http://dani.calidos.com/img/2010/osgi-05/new-fragment.png" title="New fragment" width="472" height="566" /></p>
<p>We specify the bundle the new fragment is attaching to:</p>
<p><img alt="Specify host bundle" src="http://dani.calidos.com/img/2010/osgi-05/specify-bundle.png" title="Specify host bundle" width="455" height="107" /></p>
<p>The next step is to move the JUnit code from the main bundle onto the fragment. If we run the test independently we see that it passes as the classpath of the host and fragment bundles is merged into one.</p>
<p>We then add the fragment to our existing run configuration and it will be loaded onto our environment. So far so good, but there is no way to run the tests outside our controlled Eclipse.</p>
<p>Slim Ouertani at Javalobby shows us how to <a href="http://java.dzone.com/articles/osgi-junit-test-extender-using">run fragment tests from within the OSGi environment</a> in a great article. His code uses the new bundle tracker feature to discover any test fragments and exposing functionality to be able to run the tests.</p>
<p>You can get the source at kenai: <a href="http://kenai.com/projects/testosgifragment">http://kenai.com/projects/testosgifragment</a></p>
<p>We read the article thoroughly, fetch the source and build test.extender using maven:</p>
<p><code><br />
mvn install<br />
</code></p>
<p>The code works great but has a bug which is triggered when the code looks for the host of the fragment by reading the &#8216;Fragment-Host:&#8217; header. If the value specifies any kind of version qualifier it fails. It also crashes when trying to test a bundle or a fragment that doesn&#8217;t have the &#8216;Unit-Test&#8217; custom header.</p>
<p>The &#8216;Unit-Test&#8217; custom header lives on the fragment manifest and is used by test.extender to control who is able to be tested and if tests are done manually or automatically.</p>
<p>If no &#8216;Unit-Test&#8217; header is present or if its value is empty, test.extender will refuse to run any tests present on the bundle. If the value is &#8216;true&#8217; then test.extender will run the tests automatically whenever the test fragment bundle is loaded. If the value is anything else the tests won&#8217;t run automatically but you can still run them using the &#8216;test&#8217; and &#8216;testall&#8217; commands.</p>
<p>I have patched the code to accept a version qualifier for the fragment host as well as giving out an informative error message when attempting to test the wrong bundle.</p>
<p>Once this is done, we play with the test.extender by obtaining the fragment bundle id and issuing &#8216;test &lt;id&gt;&#8217; on the console:</p>
<p><code><br />
osgi&gt; test 80<br />
Bundle : [80] : com.calidos.dani.osgi.cache.provider.memory.test<br />
_<br />
CLASS : [com.calidos.dani.osgi.cache.provider.memory.test.MemoryCacheTest]<br />
___________________________________________________________________________<br />
Method : [ testClear ] PASS<br />
Method : [ testInit ] PASS<br />
Method : [ testInitInt ] PASS<br />
Method : [ testSize ] PASS<br />
Method : [ testSet ] PASS<br />
Method : [ testGet ] PASS<br />
Method : [ testGetStatus ] PASS<br />
___________________________________________________________________________<br />
_<br />
</code></p>
<p>We can also use the &#8216;testall&#8217; command which will look for all the testable fragment bundles and run the test there.</p>
<p>Having tested that functionality, we separate the tests from the memcached bundle and move them onto their own bundle.</p>
<p><a href="http://dani.calidos.com/img/2010/osgi-05/test-fragments.tar.gz">Here</a> you can download the two test fragments and the <a href="http://dani.calidos.com/img/2010/osgi-05/test-extender-patch">patch</a> to modify test.extender, neat.</p>
<p>Ok then, we move onto the next thing that is looking closely at the Servlet Bridge and its behaviour. What we are interested in is what happens when the container deploys and inits the Web app itself, starting up the servlet bridge. The bridge uses the container temporary folder to deploy the OSGi environment in a subfolder, copying any bundles into that subfolder. If the subfolder exists and there are bundles that have the same names, they won&#8217;t be copied. I have found this behaviour to be very confusing for newbies to the platform and very annoying for veterans. I&#8217;m not entirely sure if this is deliberate and has performance reasons or what. Calling the framework controls to prevent that is not optimal and manually removing the temporary folder isn&#8217;t, either. One possible solution would be to use a building system that increments the micro number every time there is a build and remember to clear up the container temporary folder from time to time. That is not always desirable or possible but fortunately, the servlet bridge implementation provides a way to customize it to our heart&#8217;s content.</p>
<p>Basically we have the following code in the bridge init() method:</p>
<pre class="java:nocontrols:nogutter">
	framework.init(getServletConfig());
	framework.deploy();
	framework.start();
	frameworkStarted = true;
</pre>
<p>In this case, &#8216;framework&#8217; is a instance of the FrameworkLauncher class which is created just before this code snippet. The FrameworkLauncher is the class responsible for deploying and launching OSGi. We note that the object is created by default as a plain FrameworkLauncher instance. However, the class to be used can be customized by specifying it in the web.xml file using the  &#8216;frameworkLauncherClass&#8217; servlet initialization parameter. As long as that class is a subclass of FrameworkLauncher the appropriate contract is fulfilled.</p>
<p>This means we can override some behaviour and delete the framework deployment folders upon startup:</p>
<pre class="java:nocontrols:nogutter">
@Override
public void init() {

super.init();

File servletTemp = (File) context.getAttribute("javax.servlet.context.tempdir");
File platformDirectory = new File(servletTemp, "eclipse");

if (platformDirectory.exists()) {
	deleteDirectory(platformDirectory);
}

}
</pre>
<p>Cool, so we need to export this as a jar file named dani-frameworklauncher.jar into the package project lib folder:</p>
<p><img alt="Export framework launcher" src="http://dani.calidos.com/img/2010/osgi-05/export-launcher.png" title="Export framework launcher" width="485" height="589" /></p>
<p>Next we change the servletbridge web.xml configuration parameter to load the new framework launcher:</p>
<p><code><br />
&lt;init-param&gt;<br />
&lt;param-name&gt;frameworkLauncherClass&lt;/param-name&gt;<br />
&lt;param-value&gt;com.calidos.dani.osgi.servletbridge.FrameworkLauncher2&lt;/param-value&gt;<br />
&lt;/init-param&gt;<br />
</code></p>
<p>To test, we can add a file onto the $APACHE_TOMCAT/work/Catalina/localhost/<webappname>/eclipse folder and restart Tomcat. Before this new launcher was in place, the file would be kept but now it is deleted alongside the rest. Any other methods can also be extended to customize the bridge behaviour without having to modify the launcher class.</p>
<p><a href="http://dani.calidos.com/img/2010/osgi-05/dani-framework-launcher.tar.gz">Here</a> you can download the framework launcher project, put it on the WEB-INF/lib folder alongside the servlet bridge and enjoy!</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-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>Experiencing server-side OSGi with Equinox</title>
		<link>http://dani.calidos.com/2008/12/27/experiencing-server-side-osgi-with-equinox/</link>
		<comments>http://dani.calidos.com/2008/12/27/experiencing-server-side-osgi-with-equinox/#comments</comments>
		<pubDate>Sat, 27 Dec 2008 18:59:39 +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>

		<guid isPermaLink="false">http://dani.calidos.com/?p=50</guid>
		<description><![CDATA[There is currently a lot of buzz about the OSGi java component technology, also server-side. I have been playing -and working- with this interesting technology recently, mainly the Equinox server-side bundles that allow deployment of an OSGi environment in a java servlet environment.
A fundamental problem that this technology solves is being able to load an [...]]]></description>
			<content:encoded><![CDATA[<p>There is currently a lot of <a href="http://www.google.com/trends?q=osgi%2C+java+framework&amp;ctab=0&amp;geo=all&amp;date=all&amp;sort=1">buzz</a> about the <a href="http://www.osgi.org/About/WhyOSGi">OSGi</a> java component technology, also <a href="http://www.webforefront.com/archives/2007/07/osgi_takes_on_s.html">server-side</a>. I have been playing -and working- with this interesting technology recently, mainly the <a href="http://www.eclipse.org/equinox/server/">Equinox server-side</a> bundles that allow deployment of an OSGi environment in a java servlet environment.</p>
<p>A fundamental problem that this technology solves is being able to load an OSGi environment on a servlet server. That is a relatively costly operation that needs to be done only once and be persistent on the server in between client requests. After that point, state is maintained and bundles can be deployed and managed as needed. Creating, loading and destroying the environment for each request would just be unacceptable. One interesting functionality is then being able to serve client requests, specially HTTP requests, uploads, provide REST interfaces, etc.</p>
<p>Eclipse provides a <a href="http://www.eclipse.org/equinox/server/http_in_container.php">number of projects</a> to load the environment, register servlets, handle http requests, etc. Of particular interest is the &#8216;org.eclipse.equinox.servletbridge&#8217; project, which initally starts the framework, loads the appropriate framework bundles, etc.</p>
<p>Looking at the code, you can start by checking out the main class, which has a number of interesting responsabilities:</p>
<pre class="java:nocontrols:nogutter">/**
 * The BridgeServlet provides a means to bridge the servlet and
OSGi runtimes. This class has 3 main responsibilities:
 * 1) Control the lifecycle of the associated FrameworkLauncher
in line with its own lifecycle
 * 2) Provide a servlet "hook" that allows all servlet requests
to be delegated to the registered servlet
 * 3) Provide means to manually control the framework lifecycle
 */</pre>
<p>I personally like classes that have a small set of responsabilities, but one can argue that the three are so related that they are expressions of the same one. The first responsability described is actually managing the lifecycle of the OSGi framework FrameworkLauncher class.</p>
<p>Basically, the Servlet Container will load the bridge web application, create an instance of ServletBridge and call its init method (defined by the <a href="http://java.sun.com/products/servlet/2.1/api/javax.servlet.http.HttpServlet.html">HttpServlet</a> interface which it implements). In that method the OSGi environment will be created and loaded by the following code:</p>
<pre class="java:nocontrols:nogutter">framework.init(getServletConfig());
framework.deploy();
framework.start();
frameworkStarted = true;</pre>
<p>The attribute &#8216;framework&#8217; is an instance of the &#8216;FrameworkLauncher&#8217; class, which encapsulates the OSGi environment management logic. The &#8216;init&#8217; method pulls information from the servlet configuration (such as the name of the &#8216;WEB-INF&#8217; folder) and calls an overloaded empty init method that could be exploited by specialised subclasses (more on this later).</p>
<p>After that, the framework is &#8220;deployed&#8221;. The method in question declares the following contract:</p>
<pre class="java:nocontrols:nogutter">/**
* deploy is used to move the OSGi framework libraries into a location
   suitable for execution.
* The default behavior is to copy the contents of the webapp's
   WEB-INF/eclipse directory to the webapp's temp directory.
*/</pre>
<p>And that&#8217;s right, the code is quite straightforward and goes along the lines of:</p>
<pre class="java:nocontrols:nogutter">File servletTemp = (File) context.getAttribute("javax.servlet.context.tempdir");
platformDirectory = new File(servletTemp, "eclipse");
if (!platformDirectory.exists()) {
	platformDirectory.mkdirs();
}
File plugins = new File(platformDirectory, "plugins");
copyResource(resourceBase + "plugins/", plugins);</pre>
<p>Which copies the bundles you want to deploy onto the OSGi environment onto the Servlet Container temporary folder (the &#8216;work&#8217; folder in the case of <a href="http://tomcat.apache.org/">Apache Tomcat</a>).</p>
<p>After that the framework is started, reading .ini configuration options, command line switches, bundle list, run levels and so forth. We have not been able to get bundles started automatically unless we specify the bundle filename, complete with &#8216;.jar&#8217; extension and all. One interesting option is the ability to fire up a standard OSGi console that uses the STDIN/OUT of the Servlet Container process.</p>
<p>Using the very same servlet bridge, there are a number of URLs that can be hit do control the framework, start, stop, undeploy, etc.</p>
<p>After that, one can register servlets as extension points or listen for services named &#8220;org.osgi.service.http.HttpService&#8221; and adding servlets with code going along these lines:</p>
<pre class="java:nocontrols:nogutter">public Object addingService(ServiceReference reference) {
	HttpService httpService = (HttpService) context.getService(reference);
	httpService.registerServlet(url, servlet, null, null);
}</pre>
<p>All is well and good. However, in working with the bridge code we have found a glitch in the startup code. Whenever the bridge app is started anew, it does the framework deployment and startup as expected but if there are any bundles that have any changes they will not be read by the environment unless the redeploy url is hit. This is fine in development environments but not on production, where you want to keep things  as smooth as possible.</p>
<p>Behold the power of OSS, we took a look at the code and submitted a <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=256470">bug entry</a> complete with a working patch that fixes the problem. It is not pretty but it works (it has some code duplication).</p>
<p>Server-side OSGi is proving to be the place to be, or at least it is quite promising. Give it a try.</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2008/12/27/experiencing-server-side-osgi-with-equinox/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
