<?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/category/computing/java/feed/" rel="self" type="application/rss+xml" />
	<link>http://dani.calidos.com</link>
	<description></description>
	<lastBuildDate>Mon, 15 Aug 2011 20:26:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Building an FTP server Maven plugin from scratch</title>
		<link>http://dani.calidos.com/2011/08/15/building-an-ftp-server-maven-plugin-from-scratch/</link>
		<comments>http://dani.calidos.com/2011/08/15/building-an-ftp-server-maven-plugin-from-scratch/#comments</comments>
		<pubDate>Mon, 15 Aug 2011 20:23:47 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[apache commons net]]></category>
		<category><![CDATA[apache ftp server]]></category>
		<category><![CDATA[apache mina]]></category>
		<category><![CDATA[ftp]]></category>
		<category><![CDATA[ftp server]]></category>
		<category><![CDATA[integration testing]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[maven failsafe plugin]]></category>
		<category><![CDATA[maven surefire plugin]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=362</guid>
		<description><![CDATA[In this post we design and code a new Maven plugin that fires up a FTP server to aid in integration testing of FTP-bound processes, thus demonstrating the flexibility and power of Maven plugins. Introducing Maven and testing It is &#8230; <a href="http://dani.calidos.com/2011/08/15/building-an-ftp-server-maven-plugin-from-scratch/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In this post we design and code a <strong>new Maven plugin</strong> that fires up a FTP server to aid in integration testing of FTP-bound processes, thus demonstrating the flexibility and power of Maven plugins.</p>
<h3>Introducing Maven and testing</h3>
<p>It is well known and accepted that the <a href="http://maven.apache.org/" title="Apache Maven">Maven</a> build system from Apache is very powerful and capable. It is also easy to use and hard to master.</p>
<p><a href="http://maven.apache.org/plugins/index.html " title="Official Maven plugin list">Countless</a> plugins to extend its functionality <a href="http://code.google.com/hosting/search?q=maven+plugin+label%3Amaven&#038;projectsearch=Search+Projects" title="Maven plugin search">can be found</a>.</p>
<p>One of the main functionalities offered by Maven is assisting in various levels of testing, made possible by some powerful plugins.</p>
<p>In building and testing software, individual software components and classes should be <a href="http://en.wikipedia.org/wiki/Unit_testing" title="Unit Testing">unit tested</a> using mockup objects and at a level of granularity that is independent of any services being available, both internal and external.</p>
<p>In this case Maven offers very good solutions, such as the ubiquitous <a href=" http://maven.apache.org/plugins/maven-surefire-plugin/ " title="Maven official unit testing plugin">Surefire plugin</a>. Using this plugin unit testing with a variety of testing frameworks is quite straightforward and easy.</p>
<p>On the other hand, <a href="http://en.wikipedia.org/wiki/Software_testing#Integration_testing" title="Integration Testing">Integration Testing</a> is done at a higher level, verifying that the integration between components, both internal and external is done correctly and to help identify problematic areas. Once a faulty integration is discovered, its unit test results can be examined in detail or if it is an external system, further diagnostics on it can be run.</p>
<p>Good judgement on the programmer is key to apply testing at the most convenient levels though on large enterprise systems usually a <strong>combination of unit testing and integration testing</strong> is most appropriate.</p>
<p>Though less well known than Surefire, Maven offers the <a href="http://maven.apache.org/plugins/maven-failsafe-plugin/" title="Maven Integration Testing plugin">Failsafe plugin</a>, designed specifically for integration testing.</p>
<p>It is interesting to note that the name has been chosen to emphasize that failures don&#8217;t stop the Maven lifecycle allowing for gracefully cleaning up any resources used during the testing. As resources can be external it i risky -and rather inelegant- not to clean them up correctly.</p>
<p>According to the Failsafe documentation, it needs to be attached to the integration-test and verify phases (though it seems to work if attached only to the integration-phase). In any case, once invoked it runs through the relevant goals and relevant tests are run.</p>
<h3>Testing FTP and SFTP functionality under Maven</h3>
<p>We have discussed instances of problems where powerful, established plugins are available to do what we want (in this case, testing). However, we need to do something in Maven for where there are no plugins or they are not easy to find. Look it up twice as it is quite likely someone else has solved the problem before though it may be the case no solution exists.</p>
<p>One of such problems is <strong>testing systems that depend on external services such as FTP or SFTP</strong>. Say we have a client that downloads some data off such a server, such as XML files or large binaries and no other interface is available.</p>
<p>A good non-legacy example of such a service is <a href="http://www.youtube.com/t/contentid " title="YouTube Content ID API">YouTube&#8217;s API</a>.</p>
<p>Even though YouTube offers <a href="http://code.google.com/apis/youtube/2.0/developers_guide_java.html" title="YouTube Content ID Java API">programmatic APIs in Java</a> for instance, to use more advanced functionality and for efficient bulk uploading an SFTP interface needs to be used. There are many other examples of such services, using both FTP and SFTP.</p>
<p>Unit tests on the system can be done with mockup objects as usual. However, to do integration testing things get more interesting.</p>
<p>We could, of course, use our YouTube production service to do some integration tests using dummy files, etc. Using production for testing is usually not a very good idea, with potential for disaster. Therefore, using the YouTube production service is not advisable.</p>
<p>Ideally, we should be able to create a mock but fully functional FTP environment, containing exactly the files we need where we can upload and download whatever is necessary and if needed, a small script (say, <a href="http://docs.codehaus.org/display/GMAVEN/Executing+Groovy+Code " title="Executing Groovy from Maven">groovy</a> or something) that simulates whatever it is that YouTube does with your files behind the scenes.</p>
<p>The basic workflow would look like this:</p>
<p><img src="http://dani.calidos.com/wp-content/uploads/2011/08/maven-ftp-server-general.png" alt="FTP Server Maven pluging Phases" title="maven-ftp-server-general" width="603" height="355" class="aligncenter size-full wp-image-369" /></p>
<p>Therefore, we need a <strong>plugin that fires up a FTP server</strong> and points users to specific areas of the target folder. Ideally, it fires up during the pre-integration-test phase and shuts down on the post-integration-test. Easy as a cake.<br />
A google search of &#8216;<a href="http://www.google.com/search?q=maven+ftp+server+plugin" title="Search for FTP server maven plugin">maven ftp server plugin</a>&#8216; yields no significant results and looking up on the <a href="http://maven.apache.org/plugins/index.html" title="Maven official plugin list">official list of plugins here</a>. Also doing a <a href="http://code.google.com/hosting/search?q=maven+plugin+label%3Amaven+ftp&#038;projectsearch=Search+projects" title="Looking up Maven FTP Server plugins on code.google.com">google code search</a> is of no use, either. Lots of stuff to perform FTPs and file transfers but no starting up servers.</p>
<p>Instead of giving up or firing up some server using Ant or even worse, manually(!), we go on and do it the Maven way.</p>
<p>Namely, we develop a plugin that fires up an (S)FTP server on the desired integration test phases.</p>
<p>Firstly, we need a FTP backbone written in Java so it can be integrated easily and of a suitable license. The <a href="http://mina.apache.org/ftpserver/" title="Apache FTP Server">Apache FtpServer</a> is perfect for that purpose. It is a high-performance server based on <a href="http://www.google.com/search?client=safari&#038;rls=en&#038;q=apache+mina&#038;ie=UTF-8&#038;oe=UTF-8" title="Apache MINA project">Apache MINA</a> for I/O and it is ridiculously easy to embed from any Java app. </p>
<h3>Creating the Maven plugin basics</h3>
<p>Firstly, we create a plugin skeleton project using the <a href="http://docs.codehaus.org/display/MAVENUSER/Archetypes+List" title="Maven Archetype plugin listing of templates">Maven Archetype plugin</a>:</p>
<pre name="code">
mvn org.apache.maven.plugins:maven-archetype-plugin:1.0-alpha-7:create -DgroupId=cat.calidos.maven.ftpserver -DartifactId=ftpserver-maven-plugin -DarchetypeArtifactId=maven-archetype-plugin -DarchetypeGroupId=org.apache.maven.archetypes
</pre>
<p>This creates an empty Maven plugin project ready to start adding stuff such as code and tests. We also need to run</p>
<pre name="code">
mvn eclipse:eclipse
</pre>
<p>to create Eclipse settings for the project. We also need to run it whenever we add new dependencies to the POM file so they are also included in the Eclipse world.</p>
<p>Firstly, we add the dependencies for the Apache Ftp server (*):</p>
<pre name="code" class="xml">
	<dependency>
		<groupId>org.apache.ftpserver</groupId>
		<artifactId>ftpserver-core</artifactId>
		<version>1.0.6</version>
	</dependency>
	<dependency>
		<groupId>org.apache.ftpserver</groupId>
		<artifactId>ftplet-api</artifactId>
		<version>1.0.6</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-api</artifactId>
		<version>1.6.1</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-log4j12</artifactId>
		<version>1.6.1</version>
	</dependency>
</pre>
<p>We can find the details on dependencies and versions on a Maven repo such as <a href="http://mvnrepository.com/" title="A large maven repository">MVNrepository</a>. </p>
<p>In this case, we also add the <a href="http://www.slf4j.org/" title="Simple Logging Facade for Java ">Simple Logging Facade for Java</a> &#8216;Log4j&#8217; implementation< so the ftp server can output logs.</p>
<p>This means that whenever we use the maven plugin we should provide a log4j configuration file through the usual methods. Plugin will still work but will complain about the missing configuration. In any case, should we desire to use another logging framework we only need to change the dependency to our chosen implementation artifact.</p>
<h3>Adding our first mojo</h3>
<p>Next, we need to start adding some &#8216;<a href="http://maven.apache.org/plugin-developers/index.html" title="What is a Maven Mojo?">mojos</a>&#8216;, or &#8216;Maven plain Old Java Object&#8217;, which are the fine-grained goals we need to run (or what is the same, tasks that we want Maven to execute). For more information, read the <a href="http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html" title="Intro to the Maven Build Lifecycle">Introduction to the Build Lifecycle</a> article on the official documentation which is very clarifying and chock full of valuable information.</p>
<p>Examining the source of other Maven plugins, we observe a common enough pattern which is to have an abstract superclass with some of the attributes needed by our mojos.</p>
<pre name="code" class="java">
public abstract class AbstractFtpServerMojo extends AbstractMojo {
</pre>
<p>On this class we can add common attributes to our mojos such as the Maven project instance</p>
<pre name="code" class="java">
/** Encompassing maven project
*	@parameter default-value="${project}"
* 	@required
* 	@readonly
*/
protected MavenProject mavenProject;
</pre>
<p>To the attributes we add the revelant annotations which let the Maven runtime inject following the popular <strong>Inversion of Control</strong> pattern. More documentation on the annotations can be found on the <a href="http://maven.apache.org/developers/mojo-api-specification.html" title="Mojo API spec">Mojo API Specification</a>.</p>
<p>Basically, we need one mojo to start the server at the &#8216;pre-integration-test&#8217; phase and another to stop it at the &#8216;post-integration-test&#8217; phase, which gives us this a class hierarchy like this:</p>
<p><img src="http://dani.calidos.com/wp-content/uploads/2011/08/maven-ftp-server-uml1.png" alt="Maven FTP Server mojo classes" title="maven-ftp-server-uml1" width="603" height="355" class="aligncenter size-full wp-image-372" /></p>
<p>Ok, so now we need to take a look at the <a href="http://mina.apache.org/ftpserver/embedding-ftpserver-in-5-minutes.html" title="Apache FTP Server docs">Apache Ftp Server documentation</a> to discover how to embed it.</p>
<p>Fortunately it is pretty straightforward. A server factory instance is created from which a server instance can be created and attached to a specific port. Any such configuration such as adding users, setting up SSL keystores or port and interface attachment are configured using &#8216;<a href="http://mina.apache.org/ftpserver/listeners.html" title="Apache FTP Server configuration classes">listeners</a>&#8216;, which are configuration classes. Multiple listener instances can be set onto the same instance, to allow for multiple interfaces, etc. In the case of this example plugin we aim to configure a subset of all setup possibilities as it is only for integration testing and shouldn&#8217;t be used to deploy production FTP servers. For proper deployment, it can be run and configured fully from the command line or as a Windows service very <a href="http://mina.apache.org/ftpserver/running-ftpserver-stand-alone-in-5-minutes.html" title="Run Apache FTP Server standalone">easily</a>.</p>
<p>Ok, so we add a method to the &#8216;run&#8217; mojo to create the relevant instances</p>
<pre name="code" class="java">
/** Create a server instance with default values
*///////////////////////////////////////////////////////////////////////////////
private void initServer() {

	// add relevant system property variables
	if (systemPropertyVariables!=null) {
		Set<?> propertyNames = systemPropertyVariables.keySet();
		for (Iterator<?> iterator = propertyNames.iterator(); iterator.hasNext();) {
			String propertyName = (String) iterator.next();
			String propertyValue = (String) systemPropertyVariables.get(propertyName);
			getLog().debug("Setting system variable '"+propertyName+"'");
			System.setProperty(propertyName, propertyValue);
		}
	}

	serverFactory = new FtpServerFactory();
	factory = new ListenerFactory();

	// set the port of the listener
	getLog().debug("Using port "+port);
	factory.setPort(port);
	serverFactory.addListener("default", factory.createListener());
	server = serverFactory.createServer();

}	// initServer
</pre>
<p>Firstly, we add any system variables that our POM wants to have added to our environment. This is a common pattern on many plugins and allows plugin users to fine tune system properties on that particular plugin environment. A very important possibility is to be able to configure a custom location of the log4j configuration using the &#8216;log4j.configuration&#8217; system variable. For another example of setting system properties you can look at the excellent <a href="http://wiki.eclipse.org/Jetty/Feature/Jetty_Maven_Plugin#Configuring_Containers" title="Jetty Maven plugin docs">Jetty Maven plugin</a>.</p>
<p>As properties are just key-value pairs of strings, we allow for the Maven injection to inject them defining the appropriate attribute parameter.</p>
<pre name="code" class="java">
/** Additional system property variables (to pass onto tests, etc.)
*	@parameter
*/
protected Map<String,String> systemPropertyVariables;
</pre>
<p>Secondly, we create the factory, listener and server instance. To make use of the more sophisticated features of the Apache Ftp Server we would only need to modify this method a little bit, for instance to allow to bind to a different network interface, etc.</p>
<h3>Adding user management</h3>
<p>Another common enough configuration that is definitely needed is user setup, including password setup, write permissions, home location, simultaneous logins, etc. </p>
<p>Examining the documentation we see a simple yet very flexible <a href="http://mina.apache.org/ftpserver/managing-users.html" title="User management for Apache FTP Server">API to manage users</a>. An interface to an user manager class is provided, &#8216;org.apache.ftpserver.ftplet.UserManager&#8217; and two ready made implementations are available: a properties-based manager and a database-based one. This is very convenient and we could easily have the mojo provide database connection details or a path to a property file. However, we would rather provide configuration details on the POM file itself so all settings are selfcontained in the Maven world.</p>
<p>This means we need a simple factory, user manager and a trivial user class, where all user details are created in Java code.</p>
<p>We start by creating a skeleton factory:</p>
<pre name="code" class="java">
public class SimpleUserManagerFactory implements UserManagerFactory {
</pre>
<p>And fill the necessary methods, in this case, only the &#8216;createUserManager&#8217; method.<br />
We follow by creating a simple User class:</p>
<pre name="code" class="java">
public class User implements org.apache.ftpserver.ftplet.User  {
</pre>
<p>We shouldn&#8217;t really use the Ftp Server User implementation &#8216;BaseUser&#8217; for two reasons: a) it&#8217;s in a private implementation package &#8216;impl&#8217; on ftpserver-core so it can&#8217;t really be used (the interface is public and resides in the ftplet-api library) and b) we want to <strong>populate its details through the POM file</strong> so we need to add appropriate Maven annotations to its attributes.</p>
<p>It is no big deal as it is an easy enough interface to implement, with several key-value pairs, related to the different settings users can have such as maximum number of logins, username, password, etc. We tag the attributes with the Maven annotations and implement all the interface methods.</p>
<pre name="code" class="java">
/** @parameter
*	@required */
protected String name;

/** @parameter
*	@required */
protected String password;
</pre>
<p>Creating the user manager is also pretty straightforward, implementing the UserManager interface of the ftplet API:</p>
<pre name="code" class="java">
public class SimpleUserManager implements UserManager {
</pre>
<p>As a &#8216;repository&#8217; to hold the User data we employ a simple in-memory Map instance:</p>
<pre name="code" class="java">
private HashMap<String, User>	users;
</pre>
<p>The resulting class structure is clear in its intent and purpose:</p>
<p><img src="http://dani.calidos.com/wp-content/uploads/2011/08/maven-ftp-server-um-user.png" alt="Maven FTP Server plugin user management classes" title="maven-ftp-server-um-user" width="603" height="355" class="aligncenter size-full wp-image-373" /></p>
<h3>Testing user management code</h3>
<p>Both the manager and the manager factory classes are pretty much self-contained it is fairly easy to create tests for most of that functionality. For example. in the case of the user manager, on the <a href="http://www.codeguru.com/forum/showthread.php?t=322481" title="Good jUnit setup info">setUp() jUnit method</a> we create a sample environment which we use on each test.</p>
<pre name="code" class="java">
/* (non-Javadoc)
* @see junit.framework.TestCase#setUp()
*///////////////////////////////////////////////////////////////////////////////
protected void setUp() throws Exception {

	super.setUp();

	String adminName = "admin";
	userManager = new SimpleUserManager(adminName,new ClearTextPasswordEncryptor(),false);
	saveUser("demo","demo");
	saveUser("demo2","demo");
	saveUser(adminName,"administrator");

}	// setUp
</pre>
<p>Note that we use the clear text password encryptor both on the test and on the functional code as the passwords are only stored in memory therefore they do not really need to be encrypted and they are in plain view in the POM file anyway.</p>
<p>Using the sample environment we test functionality of the user manager:</p>
<pre name="code" class="java">
/**
* Test method for {@link cat.calidos.maven.ftpserver.users.SimpleUserManager#authenticate(org.apache.ftpserver.ftplet.Authentication)}.
*///////////////////////////////////////////////////////////////////////////////
public void testAuthenticate() {

	loginShouldWork("demo", "demo");
	loginShouldFail("demo", "FAIL");
	loginShouldFail("DOESNTEXIST", "whatever");
	loginShouldWork("admin", "administrator");
	loginShouldFail("admin", "FAIL");

}	// testAuthenticate
</pre>
<p>Methods &#8216;saveUser&#8217;, &#8216;loginShouldWork&#8217; and &#8216;loginShouldFail&#8217; are private convenience methods to aid in testing and make tests more readable, <strong>tests are still code</strong> and should be readable and well-structured like regular functional code.</p>
<h3>Run server mojo</h3>
<p>Next, we add some code to have our configured FTP server instance run:</p>
<pre name="code" class="java">
/** Startup the server and store it on the project properties if possible
*	@throws MojoFailureException
*//////////////////////////////////////////////////////////////////////////////
private void runServer() throws MojoFailureException {

	getLog().debug("About to start FTP server...");

	try {

		server.start();
		getLog().info("FTP server started.");

	} catch (FtpException e) {

		getLog().error("Could not start FTP server...");
		throw new MojoFailureException("Could not start FTP server instance", e);

	}

	Properties properties = null;
	if (mavenProject!=null) {
		properties = mavenProject.getProperties();
		properties.put(FtpServerConstants.FTPSERVER_KEY, server);
	} else {
		throw new MojoFailureException("Can't add ftpserver instance as maven project is null");
	}

}	// runServer
</pre>
<p>The &#8216;start&#8217; method does not block and creates a new thread, where the server code will run and listen for upcoming connections. We also add the instance to the project properties so the server can be stopped gracefully on the &#8216;post-integration-test&#8217; phase.</p>
<p>Also, we do not forget to add the annotation to the &#8216;FtpServerRunMojo&#8217; class that binds the run mojo to the &#8216;pre-integration-test&#8217; phase:</p>
<pre name="code" class="java">
/** Mojo to start the apache FTP server as an integration instance
*	@goal run
*	@phase pre-integration-test
*///////////////////////////////////////////////////////////////////////////////
</pre>
<h3>Stopping the server mojo</h3>
<p>Once our run mojo starts the server, integration tests can be run on the &#8216;integration-test&#8217; phase. Please bear in mind that client POMs can still be configured to run the server on whatever phases they need through XML tweaking.</p>
<p>The stop mojo &#8216;execute&#8217; method is quite straightforward as well:</p>
<pre name="code" class="java">
public void execute() throws MojoFailureException {

	getLog().debug("Stopping FTP server...");
	Properties properties = null;
	if (mavenProject!=null) {
		properties = mavenProject.getProperties();
	} else {
		throw new MojoFailureException("Can't access maven project to stop FTP server (null)");
	}

	if (properties!=null) {

		FtpServer ftpServer;
		try {
			ftpServer = (FtpServer) properties.get(FtpServerConstants.FTPSERVER_KEY);
		} catch (ClassCastException e) {
			throw new MojoFailureException("Context doesn't contain a valid ftp server instance",e);
		}
		if (ftpServer==null) {
			throw new MojoFailureException("Context doesn't contain any ftp server instance");
		}
		if (!ftpServer.isStopped()) {
			ftpServer.stop();
			getLog().info("FTP server stopped.");
		} else {
			getLog().info("FTP server was stopped already");
		}

	} else {
		throw new MojoFailureException("Maven project has null properties",new NullPointerException());
	}

}	// execute
</pre>
<p>After error and sanity checks we retrieve the ftp server instance and stop it. Easy.<br />
Bear in mind that, exceptions during the integration-test phase should be instances of  &#8216;MojoFailureException&#8217; which do not cause the build to die (please check the appropriate documentation on the <a href="http://www.sonatype.com/books/mvnref-book/reference/writing-plugins-sect-custom-plugin.html#writing-plugins-sect-failure" title="Mojo exceptions">Maven reference book</a>).</p>
<p>So, if for instance a single test fails, the other tests can run and the server is gracefully stopped at the end. Using &#8216;MojoExecutionException&#8217; would cause the whole build to stop and if done before the stop mojo has a chance to run the server is not stopped. All probable exceptions on the Maven ftp server plugin are of the type &#8216;MojoFailureException&#8217; as we do not want to stop the whole build if integration tests fail, we report them and it will be up to the client developer to decide what to do.</p>
<h3>Testing the mojos the right way</h3>
<p>Unit testing mojo code is made easier thanks to the &#8216;AbstractMojoTestCase&#8217;</p>
<pre name="code" class="java">
public class FtpServerMojoTest extends AbstractMojoTestCase {
</pre>
<p>This superclass contains some methods to help in testing mojos, mainly methods to read POM files and run mojos. </p>
<p>We also need an FTP client to connect to the running instance. The excellent <a href="http://commons.apache.org/net/" title="Apache Commons Net lib">Apache Commons Net</a> library is ideal for that purpose.</p>
<p>To use it we add the relevant test dependencies to our project POM with a &#8216;test&#8217; scope which means they will only be used on the &#8216;test&#8217; phase and not when the plugin is ran:</p>
<pre name="code" class="xml">
	<dependency>
		<groupId>org.apache.maven.plugin-testing</groupId>
		<artifactId>maven-plugin-testing-harness</artifactId>
		<version>1.2</version>
		<scope>test</scope>
	</dependency>
	<dependency>
	    <groupId>commons-net</groupId>
	    <artifactId>commons-net</artifactId>
   		 <version>3.0.1</version>
    	<scope>test</scope>
    </dependency>
</pre>
<p>So what we want to do is run the FTP server startup method on each test setup and stop it on each test teardown.</p>
<pre name="code" class="java">
/** Read pom and start FTP server
*	@throws java.lang.Exception
*///////////////////////////////////////////////////////////////////////////////
public void setUp() throws Exception {

	super.setUp() ;

	pom = getTestFile("src/test/resources/unit/test-project/pom.xml");
	assertNotNull("Test pom not found",pom);
	assertTrue("Test pom not found",pom.exists());

	port = getFreePort();

	FtpServerRunMojo runMojo = (FtpServerRunMojo) lookupMojo("run", pom);

	// all this will be set on a real project (it's not on the test environment)
	runMojo.serverRoot = new File(PlexusTestCase.getBasedir()+"/target");
	runMojo.port = port;
	runMojo.mavenProject = new MavenProject();
	runMojo.mavenProject.getModel().setProperties(new Properties());
	runMojo.execute();
	ftpServer = (FtpServer) runMojo.mavenProject.getProperties().get(FtpServerConstants.FTPSERVER_KEY);

    ftp = new FTPClient();
    ftp.connect("localhost",port);    

}	// setUp
</pre>
<p>First we call the superclass as it configures stuff we need to call the convenience methods, load up a test pom and find a free port to run the server. Next we lookup the &#8216;run&#8217; mojo and add the relevant data that it needs to start such as the server root, port, container Maven project, etc. All that data is automatically set on a non-test environment but it is not on a test setup. Last on the setup is to connect to the FTP server.</p>
<p>Teardown needs to cleanup the ftp connection and run the stop mojo:</p>
<pre name="code" class="java">
/** Run stop server mojo
* 	@throws java.lang.Exception
*///////////////////////////////////////////////////////////////////////////////
public void tearDown() throws Exception {

	if (ftp.isAvailable()) {
		if (ftp.isConnected()) {
			ftp.disconnect();
		}
	}

	FtpServerStopMojo stopMojo = (FtpServerStopMojo) lookupMojo("stop",pom);

	Properties properties = new Properties();
	properties.put(FtpServerConstants.FTPSERVER_KEY, ftpServer);
	stopMojo.mavenProject = new MavenProject();
	stopMojo.mavenProject.getModel().setProperties(properties);
	stopMojo.execute();

	super.tearDown();	// called last as it dismantles running mojo stuff

}	// tearDown
</pre>
<p>Note we create a Maven project instance to store the running FTP instance which will be stopped by the &#8216;stop&#8217; mojo. We also call &#8216;super.tearDown()&#8217; last to make sure any superclass resources are cleaned up when we are done cleaning up ourselves.</p>
<p>The <strong>test POM</strong> should contain appropriate test data so significant tests can be run, therefore we add different configuration settings to the XML</p>
<pre name="code" class="xml">
<plugin>
	<groupId>cat.calidos.maven.ftpserver</groupId>
	<artifactId>ftpserver-maven-plugin</artifactId>
	<version>1.0</version>
		<configuration>
			<adminUser>
				<name>admin</name>
<password>admin00</password>
			</adminUser>
			<users>
				<user>
					<name>demo</name>
<password>demo</password>
				</user>
				<user>
					<name>disabled</name>
<password>disabled</password>
					<enabled>false</enabled>
				</user>
				<user>
					<name>classes-root</name>
<password>classes-root</password>
					<relativehomeDirectory>./classes</relativehomeDirectory>
				</user>
				<user>
					<name>write-disabled</name>
<password>write-disabled</password>
					<writePermission>false</writePermission>
				</user>

			</users>
		</configuration>
	</plugin>
</pre>
<p>This setup lets us test the administrator user, a regular user, a disabled one, home folders and write-disabled users. There are far more features exposed by the Apache FTP Server though it is not the aim of this test to test them all, just to make a general set of features work as expected. Obviously, to get higher code coverage more tests can be added as needed.</p>
<p>After the POM is ready, we add some unit tests such as the regular user test:</p>
<pre name="code" class="java">
/** Demo user should be able to login
*	@throws SocketException
*	@throws IOException
*//////////////////////////////////////////////////////////////////////////////
public void testDemoUser() throws SocketException, IOException {

    ftp.login("demo", "demo");
	int reply = ftp.getReplyCode();
    assertTrue(FTPReply.isPositiveCompletion(reply));
    assertTrue("Can't login with demo user",ftp.isConnected());

	String filename = "test-file";
	putFile(filename);
	boolean found = findRemoteItem(filename);
	assertTrue(filename+" can't be uploaded",found);

    ftp.disconnect();

}	// testDemoUser
</pre>
<p>We connect, add a test file and ensure it has been uploaded successfully. Both &#8216;putFile&#8217; and &#8216;findRemoteItem&#8217; are convenience methods created on the test class.</p>
<p>Adding more test cases is pretty straightforward, like in the test for readonly users:</p>
<pre name="code" class="java">
/**	User shouldn't have write permissions
*	@throws IOException
*//////////////////////////////////////////////////////////////////////////////
public void testCannotWrite() throws IOException {

	ftp.login("write-disabled", "write-disabled");
	int reply = ftp.getReplyCode();
	assertTrue(FTPReply.isPositiveCompletion(reply));
	assertTrue(ftp.isConnected());

	String filename = "test-file2";
	putFile(filename);
	boolean found = findRemoteItem(filename);
	assertFalse(filename+" can be put on nonwrite permissions user",found);

	ftp.disconnect();

}	// testCannotWrite
</pre>
<h3>Using the plugin</h3>
<p>Doing <strong>integration testing with our completed FTP Server Maven plugin</strong> is pretty straightforward using the &#8216;maven-failsafe-plugin&#8217; to fire up the tests and the &#8216;ftpserver-maven-plugin&#8217; itself to run the FTP server</p>
<pre name="code" class="xml">
<plugin>
	<groupId>cat.calidos.maven.ftpserver</groupId>
	<artifactId>ftpserver-maven-plugin</artifactId>
	<version>1.0</version>

		<configuration>
			<adminUser>
				<name>admin</name>
<password>admin00</password>
			</adminUser>
		<systemPropertyVariables>
			<log4j.configuration>file:target/test-classes/log4j.properties</log4j.configuration>
		</systemPropertyVariables>
	</configuration>

	<!-- start and stop server on the pre and post integration phases -->
	<executions>
		<execution>
			<id>start-ftpserver</id>
			<goals>
				<goal>run</goal>
			</goals>
		</execution>
		<execution>
			<id>stop-ftpserver</id>
			<goals>
				<goal>stop</goal>
			</goals>
		</execution>
	</executions>
</plugin>
</pre>
<p>Not that, unlike in unit testing and the &#8216;maven-surefire-plugin&#8217; the standard test location for the log4j configuration file does not work so we need to specify it on the POM. We also need to specify the goals for the FTP server to startup and shutdown, much along the lines of the <a href="http://maven.apache.org/plugins/maven-failsafe-plugin/usage.html" title="Maven Failsafe plugin usage docs">Maven Failsafe plugin</a> itself.</p>
<p>If any of the integration tests fails the stop goal is still ran and the server shuts down gracefully. </p>
<p>Additionally, if running the FTP server is needed on phases other than the integration testing ones the goals be attached to the relevant phases through our client POM.</p>
<h3>Wrapping up: creation of an FTP server plugin</h3>
<p>We have identified a need of using a fully functional FTP and SFTP server in integration testing using Maven. Looking up available plugins on the Web does not yield any already available plugins. We have gone ahead and built a plugin from scratch using the Apache FTP Server opensource library.</p>
<p>You can download the source code of version 1.0 of the <a href="/img/2011/ftpserver-maven-plugin-1.0-sources.zip" title="FTP Server Maven plugin source">maven-ftpserver-plugin</a> as well as a <a href="/img/2011/ftpserver-maven-plugin-sample-1.0-sources.zip" title="FTP Server Maven Plugin usage sample">sample client project</a>. Enjoy and comments are welcome.</p>
<p><em>(*) Between completing the code and writing the article Apache FtpServer came out with a new release (1.0.6). Thanks to Maven and the fair amount testing it was ridiculously easy to upgrade the project, just changed the dependency numbers on the pom file and ran a maven build.<br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2011/08/15/building-an-ftp-server-maven-plugin-from-scratch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Templating the OSGi way with Freemarker</title>
		<link>http://dani.calidos.com/2010/08/11/templating-the-osgi-way-with-freemarker/</link>
		<comments>http://dani.calidos.com/2010/08/11/templating-the-osgi-way-with-freemarker/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 19:52:08 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[bundles]]></category>
		<category><![CDATA[freemarker]]></category>
		<category><![CDATA[osgi]]></category>
		<category><![CDATA[templating]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=285</guid>
		<description><![CDATA[After some well-deserved rest the OSGi components on the server series is back with a vengeance and a somewhat independent post. For some background please check the other posts in the series. A common feature of Web applications is the &#8230; <a href="http://dani.calidos.com/2010/08/11/templating-the-osgi-way-with-freemarker/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>After some well-deserved rest the OSGi components on the server series is back with a vengeance and a somewhat independent post. For some background please check <a href="http://dani.calidos.com/category/computing/java/">the other posts in the series</a>.</p>
<p>A common feature of Web applications is the need to output structured content, be it XML, XHTML markup, JSON or many others. A number of technologies is used to do that but few seem to be that dynamic, usually only reloading templates when they change or loading them from URLs. Surely we can leverage OSGi to make things more interesting&#8230;</p>
<p>Therefore we should be following the OSGi dynamic philosophy as much as possible, exploiting the features made available by the framework such as dynamic discovery, services, bundle headers and the lot.</p>
<p>In the case of our cache app we are violating quite a few basic design principles by having the format embedded in the java code. So we should as well use a template separate from the code and if possible reuse some existing well-known templating engine from somewhere.</p>
<p>Given these basic design principles let&#8217;s get started.</p>
<p>Firstly, we need a robust and flexible templating engine. We select the mature <a href="http://freemarker.sourceforge.net/">Freemarker</a> engine which is reasonably speedy and has the power and flexibility we want. Make sure you check out the <a href="http://freemarker.sourceforge.net/docs/app_license.html">license</a>, of course.</p>
<p>We could stop at putting the library JAR in a bundle and package it so it can be used by any other bundle and that is what we do to be able to use it in OSGi. That however doesn&#8217;t exploit many of the nicer OSGi capabilities so we will create another bundle called &#8216;com.calidos.dani.osgi.freemarker-loader&#8217;.</p>
<p>What we want is to allow bundles to carry templates inside them and have our freemarker-loader templating bundle discover them automagically. This is the same technique that the Spring dynamic modules use and you can find more info <a href="http://eclipse.dzone.com/articles/osgi-42-extender-pattern-and">here</a>. The mechanism is described in this diagram:</p>
<p><img alt="OSGi freemarker templating diagram" src="http://dani.calidos.com/img/2010/osgi-08/osgi-template-components.png" title="OSGi freemarker templating diagram" class="alignnone" width="429" height="434" /></p>
<p>That is easy enough with a BundleTracker and a BundleTrackerCustomizer implementation. The BundleTracker class tracks bundles being added to the environment like this:</p>
<pre name="code" class="java">
tracker = new BundleTracker(context, Bundle.RESOLVED, templateTracker);
tracker.open();
</pre>
<p>With this snippet the tracker instance will look for bundles in the RESOLVED state (which lets us track fragments). The &#8216;templateTracker&#8217; object is an instance of BundleTrackerCustomizer and will receive callbacks whenever bundles are added to the environment.</p>
<p>For instance, when a bundle is added we check for a special header in the bundle which tells us what is the relative path of available templates in the bundle being resolved:</p>
<pre name="code" class="java">
public Object addingBundle(Bundle bundle, BundleEvent event) {

// we look for the header and act accordingly
String templatesLocation = (String) bundle.getHeaders().get(TEMPLATE_HEADER);
if (templatesLocation!=null) {

	Enumeration<URL> bundleTemplates = bundle.findEntries(templatesLocation, "*.ftl", true);
	HashSet<URL> templatesFromAddedBundle = new HashSet<URL>();
	while (bundleTemplates.hasMoreElements()) {

		URL templateURL = bundleTemplates.nextElement();
		addTemplate(bundle, templateURL,templatesLocation);
		templatesFromAddedBundle.add(templateURL);

	}

	templatesOfEachBundle.put(bundle.getBundleId(), templatesFromAddedBundle);

}
return null;

}	// addingBundle
</pre>
<p>An interesting method being used here is &#8216;findEntries&#8217; which loads all the entries in the provided templates folder and lets us add them to our holding structure. We also take care to implement the methods to remove the templates and update them accordingly whenever bundles are updated or unloaded from the environment.</p>
<p>Having TEMPLATE_HEADER with a value of &#8216;Freemarker-Templates&#8217; means that bundles having a header such as <code>Freemarker-Templates: /templates</code> will have any templates within that folder (<i>please note that the &#8216;/templates&#8217; bit is not added to template URLs!</i>).</p>
<p>The next thing we need to do is make the loaded templates available to the environment. To do that we make a freemarker Configuration object accessible as an OSGi service object. That Configuration instance is the main object Freemarker to load and use templates and has an interesting mechanism to override its template loading mechanism we use to make available our OSGi environment templates.</p>
<pre name="code" class="java">
freemarkerConfig.setTemplateLoader( new URLTemplateLoader() {

@Override
protected URL getURL(String url) {
Stack<TemplateEntry> templateStack = templates.get(url);
if (templateStack!=null) {
	TemplateEntry templateStackTop = templateStack.peek();
	if (templateStackTop!=null) {
		return templateStackTop.getTemplateURL();
	}
	return null;
}
return null;
}

});
</pre>
<p>The service Configuration object is set with a template loader inner class that uses our template holding objects to retrieve templates stored in our OSGi context. Cool.</p>
<p>This also allows us to effectively disable the template refreshing cycles that Freemarker does by default (allegedly making it slightly more efficient). Now we only need to refresh a bundle containing the templates to get the new version. This can be modified by using the appropriate methods on the Configuration service of course. (<i>There is another method explained later</i>).</p>
<p>An interesting feature we can add to exploit the dynamic nature of OSGi is to make templates available in a stack. This means different bundles can dynamically overwrite templates by the same name. Moreover, once a template is removed the previous version becomes available. This can be used to make temporary changes to templates to add or remove diagnostics information, test new templates temporarily, etc.</p>
<p>We do that using a Stack of TemplateEntry objects, TemplateEntry being a helper class to store template entries.</p>
<p>This is all very nice but we have a problem when having multiple versions of the same bundle that hold multiple copies of the same template, this means they will stack and we have no way to access a particular version of a template. To solve this problem we store each template in three different stacks by three different URLs:</p>
<ul>
<li>&#8216;path/file.ftl&#8217;</li>
<li>&#8216;bundle://bundlename/path/file.ftl&#8217;</li>
<li>&#8216;bundle://bundlename:version/path/file.ftl&#8217;</li>
</ul>
<p>In this manner we can use the more generic URL in most cases but still can access specific versions when needed. It is important to think about the dynamic nature of OSGi as well as the possibility of several versions of the same bundle coexisting peacefully in the same environment.</p>
<p>From the perspective of any bundle using the service in the simplest case it only needs to look for a service named &#8216;freemarker.template.Configuration&#8217;. For convenience, the property &#8216;dynamicConfiguration&#8217; is set to &#8216;true&#8217; to coexist peacefully with other Configuration services (maybe coming from an official Freemarker bundle). For instance, if we know for sure our dynamic Configuration service is the only one present we can do:</p>
<pre name="code" class="java">
context.getServiceReference(Configuration.class.getName());
</pre>
<p>That will give us the highest ranking Configuration service. If there are several such services we can use a call like this to get the one that has the dynamic OSGi loader:</p>
<pre name="code" class="java">
context.getServiceReferences(Configuration.class.getName(), "dynamicConfiguration=true");
</pre>
<p>There is one last feature which lets bundle users feed an already configured template configuration object to the bundle by publishing a Configuration service with property &#8216;preparedConfiguration&#8217; set to &#8216;true&#8217;. This will get picked up by the bundle and its template loader put in sequence with the dynamic OSGi template loader. This means that any original Configuration settings are maintained (<i>For further information on service filtering based on properties please check the <a href="http://www.osgi.org/javadoc/r4v42/org/osgi/framework/BundleContext.html">BundleContext</a> javadoc.</i>).</p>
<p>Best thing to do is to go and try it by downloading the bundles <a href="http://dani.calidos.com/img/2010/osgi-08/freemarker-bundles-bin.zip">here</a>. Source is also <a href="http://dani.calidos.com/img/2010/osgi-08/osgi-template-source.tar.gz">available</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2010/08/11/templating-the-osgi-way-with-freemarker/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<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 &#8230; <a href="http://dani.calidos.com/2010/05/07/components-on-the-server-6-adding-integration-testing/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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 (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 &#8230; <a href="http://dani.calidos.com/2010/01/04/components-on-the-server-5-better-unit-testing/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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 &#8230; <a href="http://dani.calidos.com/2009/12/01/components-on-the-server-4-adding-tomcat-support/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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 &#8230; <a href="http://dani.calidos.com/2009/11/08/components-on-the-server-3-adding-a-http-frontend/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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 &#8216;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 &#8230; <a href="http://dani.calidos.com/2009/10/24/components-on-the-server-2-creating-the-first-bundles/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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 &#8216;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>
		<item>
		<title>Components on the server: an OSGi mini-project</title>
		<link>http://dani.calidos.com/2009/08/24/components-on-the-server-an-osgi-mini-project/</link>
		<comments>http://dani.calidos.com/2009/08/24/components-on-the-server-an-osgi-mini-project/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 20:57:40 +0000</pubDate>
		<dc:creator>dani</dc:creator>
				<category><![CDATA[Computing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[log4j]]></category>
		<category><![CDATA[osgi]]></category>

		<guid isPermaLink="false">http://dani.calidos.com/?p=106</guid>
		<description><![CDATA[The best way to start with OSGi on the server side is with a mini-project to help clarify concepts and workout the mechanics. I have chosen a simple idea: build a volatile cache that stores objects. The interface with it &#8230; <a href="http://dani.calidos.com/2009/08/24/components-on-the-server-an-osgi-mini-project/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The best way to start with OSGi on the server side is with a mini-project to help clarify concepts and workout the mechanics.</p>
<p>I have chosen a simple idea: build a volatile cache that stores objects. The interface with it is simple HTTP calls to perform usual operations: get, set, clear and get info. Additionally, Unit Testing will of course be used (but not Acceptance Testing in this case).</p>
<p>We start with building a component that serves as the controller for the system. It encapsulates any implementation details and answers to the system requests.</p>
<p>Read on for a short tutorial on how to setup the a first bundle, add an interface and some logging and fire up the appropriate OSGi environment.</p>
<p><span id="more-106"></span></p>
<p><strong>Setting up the project</strong></p>
<p>We fire up Eclipse and switch to the &#8216;Plug-in Development&#8217; perspective and create a new &#8216;Plug-in Project&#8217; using the Other option.</p>
<p><img src="/img/2009/osgi-01/01-Pasted-Graphic.png" alt="New project" width="472" height="450" /></p>
<p>As we are bulding the main controller component for the cache, we name it appropriately e.g. &#8216;com.calidos.dani.osgi.cache.controller&#8217;. Remember to select Equinox as the targeted environment as well as create a Java project along with it.</p>
<p><img src="/img/2009/osgi-01/02-Pasted-Graphic-4.png" alt="Plug-in Content" width="472" height="612" /></p>
<p>Next step is to specify the plug-in basic data such as ID and minimum requested execution environment.</p>
<p>In this case we select Java SE 1.6 but in production we should select something lower unless there are any specific VM requirements. As this is a controller-like component it is quite likely that some sort of state activation will take place at some point so we have the wizard generate an activator class.</p>
<p>We unselect the template (we will not be using any) and off we go onto the next step.</p>
<p><strong>Adding some logging</strong></p>
<p>The first thing the wizard does after the definition is finished is present the Manifest overview screen and from there we can tweak dependencies, API exposure and any other properties of the bundle. We can also examine the default Activator java class that contains empty stub start and stop methods.</p>
<p>We clearly need some sort of logging so we add log4j support using the &#8216;dependencies&#8217; tab.</p>
<p><img class="alignnone" src="/img/2009/osgi-01/03-Pasted-Graphic-3.png" alt="Dependencies" width="371" height="436" /></p>
<p>This means that the bundle won&#8217;t load unless the official org.apache.log4j bundle is present in the environment. Additionally, we need somewhere to put the log4j configuration file. There are several alternatives for this but one I feel to be quite elegant is to create a bundle fragment to hold the configuration and attach it to wherever needed.</p>
<p>Using the wizard, we can create a Plug-in Fragment project named &#8216;com.calidos.dani.osgi.cache.log4jconfig&#8217;. In this case we don&#8217;t need to create a Java project as the fragment doesn&#8217;t have any java code. We configure the fragment to be attached to the log4j bundle. We then add our preferred log4j.properties file to the root of that fragment. To make sure we export the configuration file we select it on the &#8216;Build&#8217; tab of the manifest wizard. When the fragment is loaded unto the log4j bundle, the log4j.properties file will be made visible to the bundle and configure the log4j environment accordingly.</p>
<p><img src="/img/2009/osgi-01/04-Pasted-Graphic-1.png" alt="Fragment build configuration" width="405" height="514" /></p>
<p>We create the OSGi environment where we can test our bundle by selecting  &#8216;Run:Run Configurations&#8230;&#8217;. We create a new &#8216;OSGi&#8217; configuration and we name it something like &#8216;Basic Cache env&#8217;. One quick way to create the environment is to first deselect all bundles, look for the main bundle ID we wat to run (in this case &#8216;com.calidos.dani.osgi.cache.controller&#8217;) and click on &#8216;Add Required Bundles&#8217;. This should automagically add any required bundles you may need. Make sure the log4j fragment is also selected.</p>
<p>We run the &#8216;Basic Cache env&#8217; and all should load appropriately. Typing &#8216;ss&#8217; on the console should spit out something like:</p>
<pre class="java:nocontrols:nogutter">Framework is launched.

id	State       Bundle
0	ACTIVE      org.eclipse.osgi_3.4.3.R34x_v20081215-1030
1	ACTIVE      com.calidos.dani.osgi.cache.controller_1.0.0
2	ACTIVE      org.apache.log4j_1.2.13.v200806030600
	            Fragments=4
4	RESOLVED    com.calidos.dani.osgi.cache.log4jconfig_1.0.0
	            Master=2</pre>
<p>This is telling us we have only loaded the bundles we want and all are loaded and properly started. Note that the fragment is only &#8216;RESOLVED&#8217; as it is not a full bundle in itself.</p>
<p>In true test-driven development style, we can write some tests first that help define the expected behaviour of the bundle. There are several options and schools of thought about how to best do this (for instance creating a separate bundle for the tests, etc.). In our case we incorporate the test in the bundle for simplicity.</p>
<p>We edit our MANIFEST.MF and add org.junit4 as an optional &#8216;Required Plug-in&#8217; to be able to load tests. In this case then we create a separate &#8216;test&#8217; java source folder for the bundle and add test cases to it. To define the test cases we need to think about the main interface of the cache.</p>
<p>It seems clear that we can initialize and check the status of the cache and ask how many items we have got on it. We can also clear all items present in the cache. We create the interface and an implementation stub and finally add test code. The interface looks like this:</p>
<pre class="java:nocontrols:nogutter">public interface Cache {

/** Initialize with 0 elems and default starting capacity
*/
void init();

/**	Initialize the cache with zero elements
* 	@param startingCapacity hint to make room
*/
void init(int startingCapacity);

/** @return the number of objects at this time
*/
int size();

/** Clear the cache from any elements
*/
void clear();

[...]

}</pre>
<p>Obviously all tests fail at the beginning as the default behaviour for them should be failing (and the current JUnit 4 Eclipse integration puts a &#8216;fail&#8217; on each test). As it is an internal Unit test we expose the implementation on the setup test method but we actually use the interface on the tests themselves, which preserves implementation details from the tests themselves.</p>
<p>Selecting the test class and choosing &#8216;Run:Run As&#8217; menu option we can run the tests as standalone JUnit tests or within an OSGi environment, shell included.</p>
<p><a href="/img/2009/osgi-01/OSGI-abc-first-installment.tar.gz">Here</a> you can download an export of the project with all the source so far. Hope this is useful and complements other similar resources on the Web. The source is available in the Apache 2.0 license so enjoy.</p>
<p><strong>Update:</strong> <a href="http://dani.calidos.com/img/2009/osgi-01/OSGI-abc-first-installment-frag.tar.gz">here</a> you can find an archive with the logging configuration fragment</p>
<p>PS: I have an easy and straightforward method to write this post offline. I write the article on TextEdit, pasting the images as I go. This creates a .rtfd folder with the images stored in the TIFF inside. I&#8217;ve written a trivial 5-minute Automator script that turns the images into PNGs, numbers, sorts and renames the files. It is quite handy as I finally post this.</p>
]]></content:encoded>
			<wfw:commentRss>http://dani.calidos.com/2009/08/24/components-on-the-server-an-osgi-mini-project/feed/</wfw:commentRss>
		<slash:comments>1</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 &#8230; <a href="http://dani.calidos.com/2008/12/27/experiencing-server-side-osgi-with-equinox/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></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>

