<?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>Gridshore &#187; maven</title>
	<atom:link href="http://www.gridshore.nl/tag/maven/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gridshore.nl</link>
	<description>A weblog about software engineering, Architecture, Technology an other things we like.</description>
	<lastBuildDate>Tue, 13 Dec 2011 15:36:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Cleaning up your maven repository with groovy</title>
		<link>http://www.gridshore.nl/2011/08/01/cleaning-up-your-maven-repository-with-groovy/</link>
		<comments>http://www.gridshore.nl/2011/08/01/cleaning-up-your-maven-repository-with-groovy/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 09:25:21 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[groovy and grails]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1165</guid>
		<description><![CDATA[<p>Ever looked at the space used by your maven repository? Think that this is to much? Start reading the blog post I wrote on my employers blog about a groovy script that you can use to clean your local maven repository. It removes old snapshots stored in your repo as well as old versions [...]]]></description>
			<content:encoded><![CDATA[<p>Ever looked at the space used by your maven repository? Think that this is to much? Start reading the blog post I wrote on my employers blog about a groovy script that you can use to clean your local maven repository. It removes old snapshots stored in your repo as well as old versions of artifacts.</p>
<p><a href="http://blog.jteam.nl/2011/08/01/cleaning-up-your-maven-repository">http://blog.jteam.nl/2011/08/01/cleaning-up-your-maven-repository</a></p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2011%2F08%2F01%2Fcleaning-up-your-maven-repository-with-groovy%2F&amp;title=Cleaning%20up%20your%20maven%20repository%20with%20groovy&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/08/01/cleaning-up-your-maven-repository-with-groovy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upgrade maven and switch between versions using bash on the mac</title>
		<link>http://www.gridshore.nl/2011/03/14/upgrade-maven-and-switch-between-versions-using-bash-on-the-mac/</link>
		<comments>http://www.gridshore.nl/2011/03/14/upgrade-maven-and-switch-between-versions-using-bash-on-the-mac/#comments</comments>
		<pubDate>Mon, 14 Mar 2011 17:25:17 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Mac OSX]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1142</guid>
		<description><![CDATA[<p>Over three years a go I wrote a blog post explaining the steps to upgrade you maven installation on Mac OS X Leopard. I have been using snow leopard now for a while and things changed a bit. In one of the comments to that post Oskar Carlstedt mentioned the steps required on Snow [...]]]></description>
			<content:encoded><![CDATA[<p>Over three years a go I wrote a <a href="http://www.gridshore.nl/2008/01/28/upgrading-maven-on-the-mac/">blog post explaining the steps to upgrade you maven installation on Mac OS X Leopard</a>. I have been using snow leopard now for a while and things changed a bit. In one of the comments to that post Oskar Carlstedt mentioned the steps required on Snow Leopard. This is all fine if you upgrade a minor version, but with maven 3 things changed a lot. I have some projects that require maven 2, we did not have time yet to fix problems we have with maven 3. Still I prefer using maven 3. Therefore I have to change between versions often. I decided to create a bash script to help me out.</p>
<p>Within this blogpost I&#8217;ll explain the installation of maven on Snow Leopard and I&#8217;ll present the bash script that can help you to switch between installations of maven.</p>
<p><span id="more-1142"></span><br />
<h2>Maven on the Mac (Snow Leopard)</h2>
<p>By default maven is installed in the path: /usr/share/java. The maven executables are installed as maven-3.0.2 and maven-2.2.1. Since the upgrade path is a bit slow I tend to install my own maven binaries. I extract them as provided by apache using the apache-maven-x.x.x format.</p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/Screen-shot-2011-03-14-at-10.45.03.png" alt="Maven installtions" border="0" width="600" height="217" /></p>
<p>A soft link is available in /usr/share/maven. This is the link that points to one of the maven binaries. This is the place where you switch between versions of maven. You can remove the soft link and create one to the right maven home folder. A small catch is that you need to be root to remove and create the link. Using sudo is good enough.</p>
<p>The commands to do this are:</p>
<pre>
cd /usr/share
sudo rm maven
ln -s /usr/share/java/apache-maven-3.0.2 maven
</pre>
<p>So not a lot of work, but just annoying to do one or more times a day. Therefore I have wanted to have a bash script to do it for me.</p>
<h2>Introducing bash</h2>
<p>When automating something on the Mac I tend to use bash. I am not an expert, but using google I can do interesting things. I&#8217;ll step to the script. To start off, define the two maven installations that I currently use:</p>
<pre>
maven2=apache-maven-2.2.1
maven3=apache-maven-3.0.2
</pre>
<p>Next step is to remove the current soft link if it exists.</p>
<pre>
if [ -e /usr/share/maven ]
then
	sudo rm /usr/share/maven
fi
</pre>
<p>Next is to store the maven implementation version in a variable</p>
<pre>
maven=$maven3

if [ $# == 0 ]
then
	echo "No Arguments supplied, using default maven 3"
elif [ $1 == 2 ]
then
	maven=$maven2
else
	echo "Using the default maven setting, provided argument [$1] is not recognized"
fi
</pre>
<p>The default is maven 3, than we check if arguments are provided to the script. If no arguments are provided, we do nothing and use the default. if an argument is provided we check if it is 2. If so, we set maven 2 as the implementation. If something else than 2 is provided we take the default which is maven 3. The final step is to create the soft link again.</p>
<pre>
sudo ln -s /usr/share/java/$maven /usr/share/maven
</pre>
<h3>Using spaces</h3>
<p>One thing that took me a few moments to understand is the use of spaces within bash. maven=$maven2 is not the same as maven = $maven2</p>
<h2>The complete script</h2>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash
echo &amp;quot;Setting the maven implementation version&amp;quot;

maven2=apache-maven-2.2.1
maven3=apache-maven-3.0.2

if [ -e /usr/share/maven ]
then
	echo &amp;quot;Remove the maven soft link.&amp;quot;
	sudo rm /usr/share/maven
else
	echo &amp;quot;Maven soft link could not be found.&amp;quot;
fi

maven=$maven3

if [ $# == 0 ]
then
	echo &amp;quot;No Arguments supplied, using default maven 3&amp;quot;
elif [ $1 == 2 ]
then
	echo &amp;quot;Setting maven to use to maven 2&amp;quot;
	maven=$maven2
else
	echo &amp;quot;Using the default maven setting, provided argument [$1] is not recognized&amp;quot;
fi

echo &amp;quot;Creating new soft link to $maven&amp;quot;
sudo ln -s /usr/share/java/$maven /usr/share/maven
</pre>
<h2>Room for improvement</h2>
<p>It would be nice to do a scan of the directory /usr/share/java and provide you with options to select from. You could also select the most recent version of maven 2 or 3 or even 2.2 and 3.0. If I have a need for that I&#8217;ll update the script <img src='http://www.gridshore.nl/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h2>Concluding</h2>
<p>That is it, you now have a script that you can call with the implementation you want to set. I called mine setmaven.sh and you would call it like:</p>
<pre>
./setmaven.sh 2
</pre>
<p>You can check if it is working with the well known mvn &#8211;version command</p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/Screen-shot-2011-03-14-at-18.59.53.png" alt="Screen shot 2011 03 14 at 18 59 53" border="0" width="600" height="388" /></p>
<p>Feel free to comment for improvements.</p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2011%2F03%2F14%2Fupgrade-maven-and-switch-between-versions-using-bash-on-the-mac%2F&amp;title=Upgrade%20maven%20and%20switch%20between%20versions%20using%20bash%20on%20the%20mac&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2011/03/14/upgrade-maven-and-switch-between-versions-using-bash-on-the-mac/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>My first steps with Gradle: creating a multi module java web project and running it with jetty.</title>
		<link>http://www.gridshore.nl/2010/09/08/my-first-steps-with-gradle-creating-a-multi-module-java-web-project-and-running-it-with-jetty/</link>
		<comments>http://www.gridshore.nl/2010/09/08/my-first-steps-with-gradle-creating-a-multi-module-java-web-project-and-running-it-with-jetty/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 09:34:06 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[groovy and grails]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[gradle]]></category>
		<category><![CDATA[intellij]]></category>
		<category><![CDATA[jetty]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[wrapper]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=1077</guid>
		<description><![CDATA[<p>I am a experienced maven user. Sometime I love it, sometimes I hate it. I like it a lot better than ant, but in some situation you would like maven to be easier and more descriptive. The past year there was a lot of fuzz about Gradle. This would give you the best of [...]]]></description>
			<content:encoded><![CDATA[<p>I am a experienced maven user. Sometime I love it, sometimes I hate it. I like it a lot better than ant, but in some situation you would like maven to be easier and more descriptive. The past year there was a lot of fuzz about Gradle. This would give you the best of ant as well as the best of maven, and even more. My first encounter was not very positive, but I kept it in my mind to try it later with a more serious project. This blogpost is about that second more serious try. It will not teach the gradle experts anything, but it will be an easy introduction in to what gradle has to bring for people that are just interested in gradle.</p>
<p><span id="more-1077"></span><br />
<h2>Project structure</h2>
<p>The structure of the project is fairly straightforward, but big enough to demonstrate some of the features that gradle has to offer. It consists of two modules:</p>
<ul>
<li>App</li>
<li>Web-ui</li>
</ul>
<p>We are creating an <a href="http://www.axonframework.org">Axonframework</a> sample, the app contains the command handling and for now the query part as well. The web-ui contains the spring mvc app with the controllers and the authentication using the spring-security framework. For now we make use of an in memory database and we want to be able to start the application without a lot of hassle. Using jetty in this case.</p>
<p>The modules have some shared dependencies for testing and logging. We also want to centralize the definition of some dependency versions.</p>
<h2>Multi module gradle build</h2>
<p>Gradle was build with multi module support from the start. So what do you need to create a multi-module build. We need a settings.gradle that defines the available modules. Next to that we need the main build.gradle as well as the modules build.gradle. Oke you can do without the per module configuration, but in my case that was not the intention. Let us focus first on the main build.gradle.</p>
<h3>Main build.gradle</h3>
<p>The main build.gradle is used to define some of the versions of the dependencies. The following code block shows the complete script.</p>
<pre class="brush: groovy; title: ; notranslate">
axonVersion = &quot;0.6&quot;
springVersion = &quot;3.0.4.RELEASE&quot;
springSecurityVersion = &quot;3.0.3.RELEASE&quot;
slf4jVersion = &quot;1.5.8&quot;
sourceCompatibility = 1.6

subprojects {
    apply plugin: 'java'

    configurations {
        all*.exclude group: &quot;commons-logging&quot;, module: &quot;commons-logging&quot;
    }

    repositories {
        mavenCentral()
    }

    dependencies {
        compile &quot;org.slf4j:jcl-over-slf4j:$slf4jVersion&quot;,
                &quot;org.slf4j:jul-to-slf4j:$slf4jVersion&quot;
        runtime &quot;org.slf4j:slf4j-log4j12:$slf4jVersion&quot;

        compile(&quot;log4j:log4j:1.2.15&quot;) {
            exclude group: &quot;com.sun.jdmk&quot;, module: &quot;jmxtools&quot;
            exclude group: &quot;com.sun.jmx&quot;, module: &quot;jmxri&quot;
            exclude group: &quot;javax.mail&quot;, module: &quot;mail&quot;
            exclude group: &quot;javax.jms&quot;, module: &quot;jms&quot;
        }

        testCompile 'junit:junit:4.7'
    }

    group = 'org.axonframework.samples.trader'
    version = '1.0-SNAPSHOT'
    sourceCompatibility = 1.6
}
</pre>
<p>As you can see, the script starts with the definition of the versions of dependencies. Than the script contains information for all the subprojects. You see we define the java plugin for all subprojects. Next to that the repositories and the dependencies are defined. Have a look at the mechanism to exclude transitive dependencies. For log4j we explicitly exclude some transitive dependencies. We also use a mechanism to exclude commons-logging from the complete build. Using the configurations hook we exclude it for all phases.</p>
<p>Finally we also define the group, version and source compatibility in the build configuration.</p>
<p>That is it, the following code block shows the required settings.gradle and after that we move on with the build.gradle of the app and web-ui subprojects.</p>
<pre class="brush: groovy; title: ; notranslate">
include &quot;app&quot;, &quot;web-ui&quot;
</pre>
<h3>Subprojects build.gradle</h3>
<p>The build.gradle for the app project is almost to easy to show. But I promised I would, so here we go:</p>
<pre class="brush: groovy; title: ; notranslate">
dependencies {
    compile &quot;org.axonframework:axon-core:$axonVersion&quot;

    compile &quot;org.hibernate:hibernate-entitymanager:3.4.0.GA&quot;,
            &quot;c3p0:c3p0:0.9.1&quot;,
            &quot;org.hsqldb:hsqldb:1.8.0.10&quot;

    compile &quot;org.springframework:spring-tx:$springVersion&quot;,
            &quot;org.springframework:spring-orm:$springVersion&quot;,
            &quot;org.springframework:spring-jdbc:$springVersion&quot;

    compile &quot;com.thoughtworks.xstream:xstream:1.3.1&quot;

    testCompile &quot;org.axonframework:axon-test:$axonVersion&quot;
}
</pre>
<p>The configuration only contains dependencies. I would like to be able to simplify the dependencies on the spring projects. Would be nice if I could group them somehow, like:</p>
<p>compile group:&#8221;org.springframework&#8221;, version:&#8221;$springVersion&#8221;, module:["spring-webmvc", "spring-aop"]</p>
<p>But the build config looks pretty clean. Now we move on to the creation of the war for the web project.</p>
<pre class="brush: groovy; title: ; notranslate">
apply plugin: 'war'

dependencies {
    compile project(':app')

    compile &quot;org.springframework:spring-webmvc:$springVersion&quot;,
            &quot;org.springframework:spring-aop:$springVersion&quot;

    compile &quot;org.springframework.security:spring-security-web:$springSecurityVersion&quot;,
            &quot;org.springframework.security:spring-security-config:$springSecurityVersion&quot;

    compile &quot;javax.validation:validation-api:1.0.0.GA&quot;,
            &quot;org.hibernate:hibernate-validator:4.0.2.GA&quot;

    runtime &quot;javax.servlet:jstl:1.1.2&quot;,
            &quot;taglibs:standard:1.1.2&quot;,
            &quot;opensymphony:sitemesh:2.4.2&quot;

    providedCompile &quot;javax.servlet:servlet-api:2.5&quot;
}
</pre>
<p>Again a pretty straightforward config. We use more types of dependencies. We now introduce the providedCompile. Jars that need not be included in the war should have this config for the dependency. Do mark that we have an apply plugin line at the top for creating the war. Finally have a look at the mechanism to show we have a dependency on another module of the project. We use the <strong>compile project (&#8216;:app&#8217;) </strong>to make the war include this created jar as well.</p>
<h2>Running with Jetty</h2>
<p>You think the jetty plugin for maven is easy, well check this out. We have to change only one word in the web project config. Look for the first line with <strong>apply plugin</strong>. Change the word war into jetty and you are done. Now you can run jetty with the following command from the root of the project:</p>
<p><em>gradle :web-ui:jettyRun</em></p>
<h2>The wrapper</h2>
<p>People that have gradle installed on their system can easily build the project and run jetty. But some people might not have gradle installed. You can help them to make it very easy. Gradle comes with a wrapper that downloads gradle and makes sure it&#8217;s on your path etc. The only thing the user needs to do is the following in the root of the project:</p>
<p><em>gradlew build</em></p>
<p>Pay attention to the &#8216;w&#8217; at the end of the gradle command. Next step is to start jetty. This is done with the same command as before with one change, the w at the end. To help your users with this, you need to do one thing. You have to add the following task to the main build.gradle. Than run gradle wrapper, checkin the generated files into your source control system. The gradlew script can be used by the people to build the project. Good stuff or not?</p>
<pre class="brush: groovy; title: ; notranslate">
task wrapper(type: Wrapper) {
    gradleVersion = '0.9-rc-1'
    jarPath = 'wrapper'
}
</pre>
<h2>Intellij integration</h2>
<p>Oke, this kinda hurts to say, but intellij support is not at a level that you would like to. At least that is what I could find out. You can easily run gradle builds from intellij. That is all nice. But I am really missing the dependency management part. Would be great to have support like for maven to setup your complete project. Wouldn&#8217;t it be great to have the import from external model feature for gradle as well? For now let us all vote for this issue, it might help:</p>
<p><a href="http://youtrack.jetbrains.net/issue/IDEA-57755">﻿http://youtrack.jetbrains.net/issue/IDEA-57755</a></p>
<p>I hope someone from jetbrains reeds this at thinks I am important enough to start creating this plugin <img src='http://www.gridshore.nl/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<h2>Performance</h2>
<p>The last remarks I want to make are about the performance of gradle. At the moment I have this build for maven as well as gradle and maven2 is twice as fast as gradle. I know work is being done on this. Gradle 0.9.1 will support a new feature that at least will speed up building the project of you have to do it a lot during the day. It will do something with a running gradle service that you can call each time you start a build. There are some items on the mailing list about this specific topic if you are interested.</p>
<p><a href="http://gradle.markmail.org/thread/xbqna6lowvsmm4ve">http://gradle.markmail.org/thread/xbqna6lowvsmm4ve</a></p>
<h2>Concluding</h2>
<p>Well that was part one of the experiment. I have not touched everything by a long run. Still I found out I like the configuration of gradle a lot better than I like maven. It is a lot cleaner and let&#8217;s you focus on the things that are important. I prefer groovy for this kind of work over xml. Still gradle has some ground to cover. For starters, tool integration. We must have something that makes working with intellij a lot better. In the future I will have a better look at plugins for release management and other stuff that I think is necessary for a good project build.</p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2010%2F09%2F08%2Fmy-first-steps-with-gradle-creating-a-multi-module-java-web-project-and-running-it-with-jetty%2F&amp;title=My%20first%20steps%20with%20Gradle%3A%20creating%20a%20multi%20module%20java%20web%20project%20and%20running%20it%20with%20jetty.&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2010/09/08/my-first-steps-with-gradle-creating-a-multi-module-java-web-project-and-running-it-with-jetty/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Building Spring DM server compliant OSGi bundles with Maven</title>
		<link>http://www.gridshore.nl/2009/01/03/building-spring-dm-server-compliant-osgi-bundles-with-maven/</link>
		<comments>http://www.gridshore.nl/2009/01/03/building-spring-dm-server-compliant-osgi-bundles-with-maven/#comments</comments>
		<pubDate>Sat, 03 Jan 2009 11:54:36 +0000</pubDate>
		<dc:creator>Allard</dc:creator>
				<category><![CDATA[Architecture]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[felix]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[OSGi]]></category>
		<category><![CDATA[Spring Dynamic Modules]]></category>
		<category><![CDATA[spring framework]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=594</guid>
		<description><![CDATA[<p> <p>Recently, SpringSource released the first version of their DM server. The SpringSource DM Server provides the ability to build enterprise web applications. In the basis, S2DM is a fine mixture of Equinox and Tomcat.</p> <p>Building OSGi-based web applications was already possible, but it is tedious and error prone work. The typical hello-world example [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.gridshore.nl/wp-content/uploads/s2-logo.png" alt="s2-logo" title="s2-logo" width="213" height="66" class="alignleft size-full wp-image-605" />
<p>Recently, SpringSource released the first version of their DM server. The SpringSource DM Server provides the ability to build enterprise web applications. In the basis, S2DM is a fine mixture of Equinox and Tomcat.</p>
<p>Building OSGi-based web applications was already possible, but it is tedious and error prone work. The typical hello-world example was easy to get going, but as soon as Hibernate or any other framework that helps in larger applications show up, so do your good old class loading problems. For classes to be visible in OSGi, a bundle must declare an Import-Package entry in the Manifest file. Chances are small that Hibernate (even if it were packaged as an OSGi bundle) has these entries for your persistent classes. This is where S2DM server comes in. It allows the more-than-hello-world web applications to be deployed in an environment where you can benefit from the best of OSGi, without the class loading misery. To do this, they have included some extra Manifest entries that are translated to OSGi-compliant directives at load time.</p>
<p>Comparable to the WAR, or better, EAR file, S2DM server supports the PAR file. A PAR file is much like a Jar, with some special headers in the Manifest file, containing all your bundle jars. Some of these jars may contain web bundles, while other typically contain domain classes or the service layer implementation. Contrary to EAR files, a PAR should only contain your own code. It is best practice to deploy frameworks and third party libraries separately. I&#8217;ll explain why later on.</p>
<p>With enterprise applications come enterprise development processes, using continuous integration, build servers and maven. In this post, I&#8217;ll lay out what you need to get maven to build S2DM server compliant bundles, and better, PAR files.</p>
<p><span id="more-594"></span></p>
<p><strong>OSGi manifest headers</strong></p>
<p>But before we move straight to maven, let&#8217;s have a look at what a Spring DM bundle looks like. Basically, a Spring DM bundle is an ordinary OSGi bundle. It has the same requirements for the MANIFEST.MF file, of which the major headers are listed below:</p>
<ul>
<li>
<div><code>Bundle-SymbolicName</code> is the only mandatory manifest header. It represents the technical name of your bundle. This value, in combination with the Bundle-Version, if present, must be unique.</div>
</li>
<li>
<div><code>Bundle-Version</code> is not mandatory, but defaults to 0.0.0, which isn&#8217;t a meaningful version. An OSGi compatible version number has the format: &lt;<em>major</em>&gt;.&lt;<em>minor</em>&gt;.&lt;<em>micro</em>&gt;-&lt;<em>classifier</em>&gt;.</div>
</li>
<li>
<div>The <code>Import-Package</code> header allows you to specify a list of packages that your bundle requires to operate. It is also possible to specify version ranges and that some packages are optional.</div>
</li>
<li>
<div><code>DynamicImport-Package</code> can be used to dynamically import packages at the moment they are required. Use a wildcard (*) to set package patterns to limit the dynamic import to.</div>
</li>
<li>
<div>The last entry I&#8217;ll mention here is <code>Export-Package</code>. It specifies the packages of the current bundle that form its API. Classes in these packages are available for other bundles to use.</div>
</li>
</ul>
<p>For more details about OSGi manifest headers, see the <a title="OSGi R4.1 specification download page" href="http://www.osgi.org/Download.Release4V41" target="_blank">OSGi-core specification</a>, section 3.2.</p>
<p>The OSGi specification requires you to import a package (which has to be exported by another bundle) for a class loader to find it. This lead to problems when using frameworks such as Hibernate, which has to instantiate classes from your application. There is no way a Hibernate OSGi bundle can know beforehand which classes it will instantiate. Another problem is that the number of packages you will have to import is probably very large. Frameworks sometimes offer large amounts of classes that have been grouped into numerous packages. To mention each of those packages in your <code>Import-Package</code> manifest header is a lot of work. You could use the <code>DynamicImport-Package</code> to import all packages you require, but that will create as many problems as it solves. OSGi is designed to only resolve bundles when all requirements have been met. By dynamically importing packages, the OSGi framework has no way to know whether requirements are met, and will resolve your bundle. During runtime, you could get class loader exceptions.</p>
<p><strong>Spring DM specific manifest headers</strong></p>
<p>To counter both the large number of imports and the class loading problems, Spring DM introduced some additional manifest headers. Not that these are not (yet) official OSGi compatible headers and are only evaluated by Spring DM compatible OSGi environments, such as <a href="http://www.springsource.com/products/suite/dmserver">Spring DM Server</a>, for which there is a community and an enterprise version.</p>
<p>The most important additional Spring DM manifest headers for bundles are:</p>
<ul>
<li>
<div><code>Import-Library</code> can be used to import a library. A library is a specification of a set of bundles that should be imported as a whole. Examples of libraries are Hibernate and the Spring Framework.</div>
</li>
<li>
<div><code>Import-Bundle</code> is used to import all the packages from a specific bundle, such as Spring-Core. Typically, this header is used in library specifications, but it may also be used in bundles manifests.</div>
</li>
<li>
<div><code>Module-Type</code> specifies the type of this bundle. At the time of writing, only &#8220;Web&#8221; is supported. When adding this header to the manifest, you indicate that this bundle is to be treated as a Web Module.</div>
</li>
<li>
<div><code>Web-context path</code> specifies the URL in which a Web Module must be deployed. It default to the module&#8217;s file name minus the extension.</div>
</li>
<li>
<div><code>Web-FilterMappings</code> is used to specify the filter names (that reference spring bean names) and their URL mappings</div>
</li>
<li>
<div><code>Web-DispatcherServletUrlPatterns</code> indicates the URLs that have to be mapped to the DispatcherServlet. In Spring DM, a dispatcher servlet is automatically initialized with the context files in <code>META-INF/spring/*.xml.</code></div>
</li>
</ul>
<p><strong>Creating an OSGi bundle with maven</strong></p>
<p>Now that we know which headers have to be generated, lets move on to maven to find how we can generate a manifest file for them. Obviously, you could generate one yourself. This is, however, tedious and error prone. It is best to conform yourself to some design standards, such as using <code>.internal</code> or <code>.impl</code> packages to store classes that are not part of your public API. When you do so, the maven-bundle-plugin.</p>
<p>The maven-bundle-plugin is used to generate an OSGi bundle from your module. In order to make it work, you have to make a few modifications to an otherwise normal <em>pom.xml</em>file:</p>
<ol>
<li>
<div>The &lt;packaging&gt; element value must be set to bundle: <code>&lt;packaging&gt;bundle&lt;packaging&gt;</code></div>
</li>
<li>
<div>Configure the org.apache.felix:maven-bundle-plugin</div>
</li>
</ol>
<p>
<pre class="brush: xml; title: ; notranslate">
&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.felix&lt;/groupId&gt;
            &lt;artifactId&gt;maven-bundle-plugin&lt;/artifactId&gt;
            &lt;extensions&gt;true&lt;/extensions&gt;
            &lt;configuration&gt;
                &lt;instructions&gt;
                    ...
                &lt;/instructions&gt;
            &lt;/configuration&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;
</pre>
</p>
<p>This configuration will generate OSGi compliant manifest files. The <code>Bundle-SymbolicName</code> will be formed from your modules groupId and artifactId and the <code>Bundle-Version</code> will be set to you module&#8217;s version. By default, all packages that are mentioned in your source code&#8217;s import statements will be imported by your bundle, even if these packages are also included in your bundle (see this <a href="http://www.osgi.org/blog/2007/04/importance-of-exporting-nd-importing.html" target="_blank">post</a> on the OSGi Alliance website). Furthermore, all packages available in your bundle will be exported, even the <code>.impl</code> and <code>.internal</code> packages.</p>
<blockquote><p><code>Manifest-Version: 1.0<br />
Export-Package: springdm.domain;uses:="javax.persistence",springdm.per<br />
&nbsp;sistence.impl;uses:="springdm.domain,org.springframework.transaction.<br />
&nbsp;annotation,springdm.persistence,javax.persistence,org.springframework<br />
&nbsp;.beans.factory",springdm.persistence;uses:="springdm.domain"<br />
Private-Package: springdm.*.impl.*<br />
Built-By: allard<br />
Tool: Bnd-0.0.255<br />
Bundle-Name: Spring DM Persistence<br />
Import-Library: org.hibernate.ejb;version="[3.3.2.GA,3.3.2.GA]"<br />
Created-By: Apache Maven Bundle Plugin<br />
Import-Bundle: org.springframework.orm;version="[2.5.6.A,2.5.6.A]"<br />
DynamicImport-Package: *<br />
Build-Jdk: 1.6.0_06<br />
Bundle-Version: 1.0.0.SNAPSHOT<br />
Bnd-LastModified: 1230983705375<br />
Bundle-ManifestVersion: 2<br />
Bundle-SymbolicName: springdm.persistence<br />
Import-Package: com.mysql.jdbc.jdbc2.optional,javax.persistence,javax.<br />
&nbsp;sql,org.hibernate.jdbc,org.springframework.beans.factory,org.springfr<br />
&nbsp;amework.transaction.annotation,springdm.domain,springdm.persistence,s<br />
&nbsp;pringdm.persistence.impl<br />
</code></p></blockquote>
<p>I am not going into more detail about how to configure the bundle plugin to keep implementation packages private. See the felix <a href="http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html" target="_blank">documentation</a> for more information about that.</p>
<p><strong>Adding Spring DM manifest headers</strong></p>
<p>Well, that actually quite easy. All you have to do is specify the name of the header as a sub element in the <code>&lt;instructions&gt;</code> element and the value of the header as the value of that element, for example: </p>
<blockquote><p><code>&lt;Import-Bundle&gt;org.springframework.orm;version="[2.5.6.A,2.5.6.A]"&lt;/Import-Bundle&gt;</code></p></blockquote>
<p>The problem is to find out which bundles or libraries there are to import, and which versions they have. That&#8217;s why Spring started the <a href="http://www.springsource.com/repository/app/" target="_blank">Spring DM bundle repository</a>. You can use it to find libraries and OSGi bundles for most commonly used frameworks. For each of thus libraries or bundles, it will tell you which maven dependency to use (for compilation) and which manifest entry has to be added to your bundle. Make sure that your maven dependencies and manifest entries are updated, otherwise you could run into problems at runtime.</p>
<p>For maven to find the artifacts in the bundle repository, you have to configure some repositories. You can find them <a href="http://www.springsource.com/repository/app/faq#q8" target="_blank">here</a>.</p>
<p>If your bundle is a Web Bundle, add the required <code>&lt;Module-Type&gt;Web&lt;/Module-Type&gt;</code> element to the instructions, as well as any other required Web-* headers.</p>
<p>That&#8217;s actually it. That&#8217;s all it takes to generate Spring DM specific manifest entries.</p>
<p><strong>Creating a PAR deployment unit</strong></p>
<p>The PAR file is the deployment unit for Spring DM applications. It is a Jar file with special manifest headers that contains all application specific bundles. You should never include framework bundles in the par file. In conventional environments, class loaders would prevent you from having different versions of the same class on your class path. Therefore, you had to add frameworks to the WAR file, to prevent version conflicts with other applications. In OSGi, there is no problem with having the same class multiple times. You just specify a version restriction in your import headers and OSGi takes care of the resolution process. To keep PAR files small, you can deploy required libraries and bundles in the /repository/libraries/usr and /repository/bundles/usr folders respectively. Any application can reuse any existing framework bundles.</p>
<p>The PAR file has another advantage. Spring DM Server prevents bundles from outside the PAR file from accessing bundles inside the PAR file. This way, you can deploy applications without running the risk of classes and services intermingling.</p>
<p>Now, let&#8217;s get back to maven to create ourselves a par file. First, create a new module in your maven project. This module&#8217;s pom file should have <code>&lt;packaging&gt;</code> set to <code>par</code>. Next, add dependencies to each module you want to be included in the par file. The par plugin does not include transitive dependencies, since framework bundles should not be included. Finally, add the maven-par-plugin to your plugin configuration.</p>
<p>
<pre class="brush: xml; title: ; notranslate">
&lt;build&gt;
    &lt;plugins&gt;
        &lt;plugin&gt;
            &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
            &lt;artifactId&gt;maven-par-plugin&lt;/artifactId&gt;
            &lt;version&gt;0.2.0&lt;/version&gt;
            &lt;extensions&gt;true&lt;/extensions&gt;
            &lt;configuration&gt;
                &lt;fqn&gt;true&lt;/fqn&gt;
                &lt;applicationSymbolicName&gt;gridshore.samples.springdm&lt;/applicationSymbolicName&gt;
                &lt;applicationVersion&gt;1.0.0&lt;/applicationVersion&gt;
                &lt;applicationDescription&gt;Gridshore Spring DM sample&lt;/applicationDescription&gt;
                &lt;applicationName&gt;Gridshore Spring DM sample&lt;/applicationName&gt;
            &lt;/configuration&gt;
            &lt;executions&gt;
                &lt;execution&gt;
                    &lt;goals&gt;
                        &lt;goal&gt;par&lt;/goal&gt;
                    &lt;/goals&gt;
                    &lt;phase&gt;package&lt;/phase&gt;
                &lt;/execution&gt;
            &lt;/executions&gt;
        &lt;/plugin&gt;
    &lt;/plugins&gt;
&lt;/build&gt;
</pre>
</p>
<p>You probably need to configure a repository to find this plugin: <a href="http://repo.steademy.com/beta/maven2">http://repo.steademy.com/beta/maven2</a>. You can find documentation of the maven-par-plugin <a href="http://blog.steademy.com/2008/05/29/maven-par-plugin/" target="_blank">here</a>.</p>
<p>Now run <code>mvn install</code> and see your PAR being created for you. Since your PAR does not contain framework bundles, you have to install them separately. To make sure that all dependencies are available, you can use the maven-assembly-plugin to create a zip file with the PAR file as well as all the framework bundles you require.</p>
<p>Have fun!</p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2009%2F01%2F03%2Fbuilding-spring-dm-server-compliant-osgi-bundles-with-maven%2F&amp;title=Building%20Spring%20DM%20server%20compliant%20OSGi%20bundles%20with%20Maven&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2009/01/03/building-spring-dm-server-compliant-osgi-bundles-with-maven/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Continuous Integration (Again)</title>
		<link>http://www.gridshore.nl/2008/08/29/continuous-integration-again/</link>
		<comments>http://www.gridshore.nl/2008/08/29/continuous-integration-again/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 12:55:56 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[artifactory]]></category>
		<category><![CDATA[continuous integration]]></category>
		<category><![CDATA[JTeam]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[teamcity]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=215</guid>
		<description><![CDATA[<p> <p>This blog item gives you an inside scoop into the continuous integration environment at JTeam. You’ll learn about the why, what and how of continuous integration. The tools we use are mainly open source.</p> Why continuous integration? <p> A number of years a go not many people new the term continuous integration. That [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.gridshore.nl/wp-content/uploads/jteamlogoallsmall.png" alt="jteamlogoallsmall.png" border="0" width="186" height="120" align="left" />
<p>This blog item gives you an inside scoop into the continuous integration environment at JTeam. You’ll learn about the why, what and how of continuous integration. The tools we use are mainly open source.</p>
<h2>Why continuous integration?</h2>
<p> A number of years a go not many people new the term continuous integration. That has changed a lot. All people at JTeam know what it is about and all projects use an environment that is set up to actually do continuous integration. For those that do not know what continuous integration is and those that need a short recap, we briefly explain what we think continuous integration is. Let’s start with the definition from Martin Fowler: </p>
<p><cite> Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least dail￼y &#8211; leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly </cite></p>
<p> Key to continuous integration is delivering high quality artifacts. It is not the silver bullet, developers still need to create great code, but using a good continuous integration process helps finding bugs. Checking your quality standards a long the way increases the effect. Of course extra actions are still necessary. You can think about actions like: manual code reviews, performance tests, functional tests, etc.</p>
<p>JTeam has been using continuous integration from the start. Recently we implemented the second version of our continuous integration environment. We introduced new tools, the process however stayed the same.</p>
<p><span id="more-215"></span><br />
<h2>What do you need?</h2>
<p><img src="http://www.gridshore.nl/wp-content/uploads/maven-feather.png" alt="maven-feather.png" border="0" width="90" height="30" align="right" />Continuous integration is about a lot of different things. So lets review them here. First of all, we have sources and a build. We tend to write a lot of java code, but we also need configuration files, html, style sheets, etc. With maven the way to structure your files has been standardized. We are using <a href="http://maven.apache.org">￼maven 2</a> for all our projects. Maven makes the life of a developer a lot more efficient while doing the normal tasks. Team leads and project leads also have reasons to implement maven in there projects. Maven has a lot of plugins that enable the projects spectators to see what is happening at the project. </p>
<p> Most of our projects are executed by more than one person, therefore a good source repository becomes very important. The source repository gives us more advantages, which I’ll talk about later. Within JTeam we have chosen to use <a href="http://subversion.tigris.org">subversion</a> for storing the sources of the projects. </p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/artifactorylogo.png" alt="artifactorylogo.png" border="0" width="151" height="35" align="left" />You can share sources and you have an automated build. Of course maven integrates very well with some IDE’s and it integrates kinda with some others. One of the important features of Maven is that it downloads dependencies from an online repository. Dependencies are libraries your project depends on. To limit network bandwidth, to store locally created libraries and to make libraries that are not available in an online repository accessible, you can connect to an internal repository. In maven this is called a proxy or a mirror. At JTeam we use a repository called <a href="http://www.jfrog.org/sites/artifactory/latest/">Artifactory</a>. Artifactory is a product from jfrog.</p>
<p> Having an automated build is not enough for good continuous integration. The automated build must be a continuous build. There are a lot of tools available that can give you continuous build. Some examples are : <a href="https://hudson.dev.java.net/">Hudson</a>, <a href="http://cruisecontrol.sourceforge.net/">CruiseControl</a> and <a href="http://luntbuild.javaforge.com/">Luntbuild</a>. We use <a href="http://www.jetbrains.com/teamcity/index.html">Teamcity</a> from Jetbrains to integrate all subversion checkins, run all the tests and every night run the maven reports. These maven reports are then published on a server so everybody can check the current status of the project. Teamcity is not open source and, there is a free license available, we use the commercial license. I explain later on why. </p>
<p> The following image gives you an overview of all services you need to have available for you to use in your project. The image shows more tools then I have discussed so far. They are not directly related to continuous integration, still they are very important for you when doing projects. Jira is about keeping track of requirements, issues and time estimations as well as time spend. Confluence is our knowledge base in which we document all our knowledge we gather while doing projects. Both jira and confluence are products from <a href="http://www.atlassian.com/">atlassian</a> and very well known. </p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/diagrams-applicationlandscape.png" alt="Diagrams-applicationlandscape.png" border="0" width="549" height="520"/></p>
<p>A last thing I would like to mention is a plugin for maven, the dashboard plugin. We are using this plugin now for a few projects and it gives some nice overviews. Graphical views of checkstyle, pmd, cobertura. When combining it with a database there is also the possibility of historical data, which is working very nice as well. You can find more information on the website including a lot of sample reports. <a href="http://mojo.codehaus.org/dashboard-maven-plugin/">http://mojo.codehaus.org/dashboard-maven-plugin/</a></p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2008%2F08%2F29%2Fcontinuous-integration-again%2F&amp;title=Continuous%20Integration%20%28Again%29&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2008/08/29/continuous-integration-again/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Doing flex with maven</title>
		<link>http://www.gridshore.nl/2008/07/24/doing-flex-with-maven/</link>
		<comments>http://www.gridshore.nl/2008/07/24/doing-flex-with-maven/#comments</comments>
		<pubDate>Thu, 24 Jul 2008 12:53:13 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Frontend Technology]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[flex3]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/?p=164</guid>
		<description><![CDATA[<p>This is a very short item. In my last few posts I have done some flex things. For most of them I was still using a bit of ant integrated with maven or even not integrated at all. Some days a go I was directed to this sample on the adobe developer connection. The [...]]]></description>
			<content:encoded><![CDATA[<p>This is a very short item. In my last few posts I have done some flex things. For most of them I was still using a bit of ant integrated with maven or even not integrated at all. Some days a go I was directed to this sample on the adobe developer connection. The example gives you an excellent walkthrough for using maven together with BlazeDS, spring and maven. I liked it so much that I immediately started rewriting my own sample to use the mentioned maven plugin and project architecture. So now please go to the website and check it out if you are having flex/maven problems.</p>
<p><a href="http://www.adobe.com/devnet/flex/">Adobe Developer Connection</a></p>
<p><a href="http://www.adobe.com/devnet/flex/articles/fullstack_pt1.html">The Flex, Spring, and BlazeDS full stack</a></p>
<p>The website that adobe has created for flex developers looks nice and might turn out to be a valuable resource for your flex and java coding. And if I am doing a good job, I will have an article posted there. So stay tuned.</p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2008%2F07%2F24%2Fdoing-flex-with-maven%2F&amp;title=Doing%20flex%20with%20maven&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2008/07/24/doing-flex-with-maven/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creating a Flex 3 DataGrid component with backend filtering</title>
		<link>http://www.gridshore.nl/2008/03/25/creating-a-flex-3-datagrid-component-with-backend-filtering/</link>
		<comments>http://www.gridshore.nl/2008/03/25/creating-a-flex-3-datagrid-component-with-backend-filtering/#comments</comments>
		<pubDate>Tue, 25 Mar 2008 09:32:31 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Frontend Technology]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[flex3]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[spring framework]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/2008/03/25/creating-a-flex-3-datagrid-component-with-backend-filtering/</guid>
		<description><![CDATA[<p>Previously I have written an article about integrating flex with spring. In this article I explained the steps to take when creating a flex 3 application that calls the back end implemented using spring. To enable flex to do this, I used the blazeDS technology. The theory is not very hard, the biggest problems [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.gridshore.nl/wp-content/uploads/flexlogo1.png" alt="flexlogo.png" border="0" width="100" height="100" align="left" />Previously I have written an article about <a href="http://www.gridshore.nl/2008/03/04/integrating-flex3-and-springframework-using-blazeds-and-intellij/#more-73">integrating flex with spring</a>. In this article I explained the steps to take when creating a flex 3 application that calls the back end implemented using spring. To enable flex to do this, I used the blazeDS technology. The theory is not very hard, the biggest problems you&#8217;ll face are hibernate problems with lazy initialization etc. While creating an application using flex I was amazed there is no standard component for filtering data in a DataGrid. Since I am using such a component based on ajax technology I wanted to have it in flex as well. After a shot search I came across actually nothing. So I decided to create a solution for myself. I do want to stress it does not have the flexibility you usually require from a standard component.</p>
<p><h2>Requirements</h2>
<ul>
<li>Input fields should be on top of each column.</li>
<li>Filter should be implemented on the back end.</li>
</ul>
<h2>Constraints</h2>
<ul>
<li>No drag able columns are supported</li>
</ul>
<p>Read on to find out how we implemented these requirements into a custom component for flex3 using the spingframework at the back end.</p>
<p><span id="more-85"></span></p>
<h2>Basic Architecture</h2>
<p>
For almost all my projects I start with a basic architecture. One module for business logic, this module contain the exposed services. The business services uses the integration module to access the database. The domain module contains JPA annotated configuration and finally there is a common module that contains objects accessible by al other modules. The flex module, which is actually a web project, uses the business module via blazeDS. Check the following image for an overview of the architecture.<br />
<img src="http://www.gridshore.nl/wp-content/uploads/compbasearchflex.png" alt="CompBaseArchFlex.png" border="0" width="557" height="527" />
</p>
<h2>Ant and maven for the build</h2>
<p>
For all the modules we use maven to create a deployable unit. So we have jars for he business, integration, domain and common. We have a war for the webproject containing flex. The jars are all pretty standard maven projects. For flex we have some issues. First of all there is no handy maven plugin available that is easy to use with flex 3, at least not that I know of. I also could not find the necessary jars including poms in an online repository. Therefore we have to add the jars to our local repository. The important part of the web project follows.</p>
<pre>
        &lt;!-- adobe dependencies -->
        &lt;dependency>
            &lt;groupId>backport-util-concurrent&lt;/groupId>
            &lt;artifactId>backport-util-concurrent&lt;/artifactId>
            &lt;version>3.1&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>commons-codec&lt;/groupId>
            &lt;artifactId>commons-codec&lt;/artifactId>
            &lt;version>1.3&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>commons-httpclient&lt;/groupId>
            &lt;artifactId>commons-httpclient&lt;/artifactId>
            &lt;version>3.0.1&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>concurrent&lt;/groupId>
            &lt;artifactId>concurrent&lt;/artifactId>
            &lt;version>1.3.4&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>xalan&lt;/groupId>
            &lt;artifactId>xalan&lt;/artifactId>
            &lt;version>2.6.0&lt;/version>
        &lt;/dependency>
        &lt;!-- created these dependencies myself from libraries provided -->
        &lt;dependency>
            &lt;groupId>adobe&lt;/groupId>
            &lt;artifactId>cfgatewayadapter&lt;/artifactId>
            &lt;version>3.0.0.544&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>adobe&lt;/groupId>
            &lt;artifactId>flex-messaging-common&lt;/artifactId>
            &lt;version>3.0.0.544&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>adobe&lt;/groupId>
            &lt;artifactId>flex-messaging-core&lt;/artifactId>
            &lt;version>3.0.0.544&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>adobe&lt;/groupId>
            &lt;artifactId>flex-messaging-opt&lt;/artifactId>
            &lt;version>3.0.0.544&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>adobe&lt;/groupId>
            &lt;artifactId>flex-messaging-proxy&lt;/artifactId>
            &lt;version>3.0.0.544&lt;/version>
        &lt;/dependency>
        &lt;dependency>
            &lt;groupId>adobe&lt;/groupId>
            &lt;artifactId>flex-messaging-remoting&lt;/artifactId>
            &lt;version>3.0.0.544&lt;/version>
        &lt;/dependency>
</pre>
<p>You can find the necessary jars in the blazeDS download. There is one thing I have not fixed yet, I still use ant to build the swf file from the flex resources. So I created a separate source folder for the flex resources and I added the ant scripts (just like in my previous post). For now I leave it to that, I guess I can use the ant scripts from within maven, but I&#8217;ll focus on the important stuff first <img src='http://www.gridshore.nl/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . For the scripts you can check the <a href="http://www.gridshore.nl/2008/03/04/integrating-flex3-and-springframework-using-blazeds-and-intellij">previous post about flex</a>. And of course you can <a href="http://code.google.com/p/gridshore/source/browse">check the sources of books-overview</a> sample online. So be aware when trying the sample you need the flex sdk, the blazeDS download and do not forget to run the ant script at least once if you change something. During development I run the ant script while the web application is running. This makes development easier. Therefore there are two lines of code in the local.build.properties of which one is commented out. Line one copies the file to the directory of which tomcat pics up the sources, the second is the one that is added to version control and therefore packaged into the war file.</p>
<pre>
deploymentPath=../../../target/books-flex
#deploymentPath=../webapp
</pre>
</p>
<h2>The search function using spring and hibernate</h2>
<p>
The following classes represent the domain model we use. Beware, we implement the domain model persistence with hibernate. It is not really advisable to create ManyToMany relationships. It might be better to use two ManyToOne relations. However for now we will do fine. There is a but. Searching for books based on author names becomes much harder. So maybe in the future I will introduce the class BookAuthor, this way you can assign properties to the relations ship as well. Think about Author type, like main author (is to be shown first in he list). Back to the sample, here is the domain model:<br />
<img src="http://www.gridshore.nl/wp-content/uploads/booksdomain-25-3-2008.png" alt="BooksDomain_25_3_2008.png" border="0" width="329" height="86"/><br />
The Business interface <strong>BookManager</strong> contains a method that enables you to filter the books (or search for books)</p>
<pre>
List<book> obtainFilteredBooks(BookSearchRequest searchRequest);
</book></pre>
<p>From this interface you can see there is a new object called <strong>BookSearchRequest</strong>, a Serializable object that is used to pass values for book title, book isbn and author name. Using this object we can perform a hibernate query that gets the results from the database.</p>
<pre>
public List&lt;Book> loadByFilter(BookSearchRequest searchRequest) {
    String queryStr = "select b from Book as b where lower(title) like lower(:title) and isbn like :isbn ";
    Query query = getEntityManager().createQuery(queryStr)
            .setParameter("title", '%' + searchRequest.getBookTitle() + '%')
            .setParameter("isbn", '%' + searchRequest.getBookIsbn() + '%')
            .setMaxResults(maxRecords);
    return query.getResultList();
}
</pre>
<p>The file <strong>spring-business.xml</strong> in the books-business component contains the configuration of the spring application context. We use annotation to configure bean dependencies. I do not use @Component annotation. I prefer to specify the beans themselves in xml. I do want to have a good look at the spring Configuration project, but that is for a next blog item.</p>
<pre>
    &lt;context:annotation-config/>
</pre>
<p>For transaction I also do not like to use annotations. I prefer to have it all in one place, it is a separate concern and therefore I want to configure it seperate (within xml). The code shows the pointcut that is used to wrap the txAdvice around all methods in classes ending with the name Manager in the business package. I do make a difference between methods beginning with obtain and the other methods. All methods beginning with <em>obtain</em> get the read-only context.</p>
<pre>
&lt;tx:advice id="txAdvice" transaction-manager="transactionManager">
    &lt;tx:attributes>
        &lt;tx:method name="obtain*" read-only="true"/>
        &lt;tx:method name="*"/>
    &lt;/tx:attributes>
&lt;/tx:advice>
&lt;aop:config>
    &lt;aop:pointcut id="serviceOperation"
                  expression="execution(* nl.gridshore.samples.books.business.*Manager.*(..))"/>
    &lt;aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
&lt;/aop:config>
</pre>
<p>I want to make a last remark about the spring configuration. For simplicity I define a bean that inserts some books and authors. This bean uses storeBook method in the mentioned manager class.</p>
<pre>
&lt;bean id="datastoreSetupBean" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    &lt;property name="targetObject">
        &lt;bean class="nl.gridshore.samples.books.business.helpers.PrefillDatastore" />
    &lt;/property>
    &lt;property name="targetMethod" value="initializeDatastore"/>
&lt;/bean>
</pre>
<p>That is everything I want to tell about the server related components. Let&#8217;s move on to the web project and of course flex.
</p>
<h2>Show the remote object usage</h2>
<p>If you want to learn more about the remoting using spring, please refer to my <a href="http://www.gridshore.nl/2008/03/04/integrating-flex3-and-springframework-using-blazeds-and-intellij/">previous post about this topic</a>. For this sample the following files are important:</p>
<ul>
<li>Home.mxml &#8211; Contains the main panel, the menu (a few buttons) and an even handler for choosing the content to show like books or authors.</li>
<li>FilteredBooks.mxml &#8211; Most important part, contains the DataGrid component and the input boxes for the filter content. We are going into a detailed discussion on this component.</li>
<li>BookAuthorsRenderer.mxml &#8211; Special renderer object to present all authors of a book into one DataGrid field.</li>
<li>BookSearchRequest.as &#8211; Object which is the same as the one specified in Java. This make it easier to create an instance of the object to be passed to the remote service.</li>
</ul>
<p>Now let&#8217;s have a look at <strong>FilteredBooks.mxmlx</strong>. We will start with the definition of the remote object. Before we can use a remote object, we need to configure it in the <strong>remoting-config.xml</strong> located in he WEB-INF/flex folder. To be able to have access to the spring bean called <strong>BookManager</strong> we add the configuration like this.</p>
<pre>
&lt;destination id="bookManager">
    &lt;properties>
        &lt;factory>spring&lt;/factory>
        &lt;source>bookManager&lt;/source>
    &lt;/properties>
&lt;/destination>
</pre>
<p>If you have read the post I mentioned before you by now should understand that we use a special spring factory class here to configure BlazeDS. Then within our mxml component we can define the remote object.</p>
<pre>
&lt;mx:RemoteObject id="srv" destination="bookManager" fault="faultHandler(event)"/>
</pre>
<p>Within the same component I have created a function that creates a BookSearchRequest object and calls the remote object.</p>
<pre>
function doFilterBooks():void {
    var bookSearchRequest:BookSearchRequest = new BookSearchRequest();
    bookSearchRequest.bookTitle = titleFilter.text;
    bookSearchRequest.bookIsbn = isbnFilter.text;
    srv.obtainFilteredBooks(bookSearchRequest)
}
</pre>
<p>Within the function I assign two values to the BookSearchRequest object. I am talking about titleFilter.text and isbnFilter.text. These are two TextInput fields used by the user to enter the filter texts. Let&#8217;s have a look at the code for the form containing the TextIinput fields. I tried to have these fields in the header columns of the DataGrid itself, but this did not work for me.</p>
<pre>
&lt;mx:VBox width="{myBooks.width}">
    &lt;mx:Form defaultButton="{doFilterButton}" paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0">
        &lt;mx:HBox width="100%">
            &lt;mx:Spacer width="100%"/>
            &lt;mx:Button id="doFilterButton" label="filter" click="doFilterBooks()"/>
            &lt;mx:Button label="clear" click="clearFilter()"/>
        &lt;/mx:HBox>
        &lt;mx:HBox width="100%" horizontalGap="0" borderStyle="solid" paddingTop="10" paddingBottom="10">
            &lt;mx:Spacer width="10"/>
            &lt;mx:TextInput id="titleFilter" width="{titleColumn.width-20}"/>
            &lt;mx:Spacer width="20"/>
            &lt;mx:TextInput id="isbnFilter" width="{isbnColumn.width-20}"/>
            &lt;mx:Spacer width="20"/>
            &lt;mx:Text id="authorFilter" width="{authorsColumn.width-20}" text=""/>
            &lt;mx:Spacer width="10"/>
        &lt;/mx:HBox>
    &lt;/mx:Form>
&lt;/mx:VBox>
</pre>
<p>As you can see there are two horizontal boxes wrapped within a vertical box. They must both have the same width and the buttons filter and cancel must be positioned at the right. The biggest problem is to position the input boxes on top of the DataGrid columns. We use the actual columns to measure the width <strong>titleColumn.width</strong>. The width of the VBox is set to the width of the DataGrid <strong>width=&#8221;{myBooks.width}&#8221;</strong>. I did have a problem when not using fixed width for the DataGrid and the columns. I also used the <strong>defaultButton</strong> property of the Form element. This enables the user to push the enter button when done typing the filter text. So you do not need to use the mouse to click the button. Is very handy when working with the application. The following code block shows the actual DataGrid component.</p>
<pre>
&lt;mx:DataGrid id="myBooks" dataProvider="{srv.obtainFilteredBooks.lastResult}" verticalScrollPolicy="on" height="100%">
    &lt;mx:columns>
        &lt;mx:DataGridColumn id="titleColumn" dataField="title" width="400" draggable="false"/>
        &lt;mx:DataGridColumn id="isbnColumn" dataField="isbn"  width="200" draggable="false"/>
        &lt;mx:DataGridColumn id="authorsColumn" sortable="false"  width="400" draggable="false">
            &lt;mx:itemRenderer>
                &lt;mx:Component>
                    &lt;rend:BookAuthorsRenderer/>
                &lt;/mx:Component>
            &lt;/mx:itemRenderer>
        &lt;/mx:DataGridColumn>
    &lt;/mx:columns>
&lt;/mx:DataGrid>
</pre>
<p>As you can see in the code, the data provider is listening to the lastResult of the RemoteObject call. You can also see we used fixed widths for the columns.
</p>
<p>
That is about it, you now have a component that presents data in a grid and has fields that you can use to filter the content in the underlying data set using a remote component on the server side. It is not a very generic components that you can reuse, but you can reuse the technology.
</p>
<p>
Freddie made a good suggestion about adding a screenshot, so here it is.</p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/screenshotdatagrid-25-3-2008.png" alt="Screenshotdatagrid_25_3_2008.png" border="0" width="700" height="428" />
</p>
<p>
Hope you liked this article, stay tuned for more articles about flex.</p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2008%2F03%2F25%2Fcreating-a-flex-3-datagrid-component-with-backend-filtering%2F&amp;title=Creating%20a%20Flex%203%20DataGrid%20component%20with%20backend%20filtering&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2008/03/25/creating-a-flex-3-datagrid-component-with-backend-filtering/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>Creating a jetty based OSGi HttpService for apache felix</title>
		<link>http://www.gridshore.nl/2008/02/29/creating-a-jetty-based-osgi-httpservice-for-apache-felix/</link>
		<comments>http://www.gridshore.nl/2008/02/29/creating-a-jetty-based-osgi-httpservice-for-apache-felix/#comments</comments>
		<pubDate>Fri, 29 Feb 2008 21:02:08 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[felix]]></category>
		<category><![CDATA[jetty]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[OSGi]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/2008/02/29/creating-a-jetty-based-osgi-httpservice-for-apache-felix/</guid>
		<description><![CDATA[<p>OSGi has a service spec called http.service (see Service Compendium document of the OSGi Alliance). Felix has an implementation for it that is based around jetty 4.x. Since we are at jetty 6.1.7 at the moment I thought about trying to create an implementation of my own. Not that it is really necessary, you [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.gridshore.nl/wp-content/logo1.png" alt="logo.png" border="0" width="165" height="63" align="left" />OSGi has a service spec called http.service (see Service Compendium document of the OSGi Alliance). Felix has an implementation for it that is based around jetty 4.x. Since we are at jetty 6.1.7 at the moment I thought about trying to create an implementation of my own. Not that it is really necessary, you can expose resources without complying to the spec (<a href="http://www.gridshore.nl/2008/02/15/embedding-jetty-in-osgi-osgi-felix-sample-step-3/">see my other post</a>).</p>
<p> But the spec is there for a reason, so let&#8217;s try to adhere to it first. The specification is up to the following two interfaces and one exception.</p>
<ul>
<li>HttpContext &#8211; Enables bundles to use provided information about a servlet or resource during registration.</li>
<li>HttpService &#8211; Enables other bundles to dynamically register sevlets or resources into the Http Service URI namespace.</li>
<li>NamespaceException &#8211; Thrown when a problem arises during registration of a servlet or resource into the Http Service UIR namespace.</li>
</ul>
<p>At first I tried to create my own implementation for these interfaces. It did not look to hard, but in the end I found the following patch which made my life a lot easier.<br /><a href="https://issues.apache.org/jira/secure/attachment/12372787/FELIX-55_jetty6.patch">jetty6 patch</a></p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/jetty-logo.gif" alt="jetty_logo.gif" border="0" width="269" height="112" align="right" />To be able to understand the implementation of an Http Service using jetty, you should understand the basics with respect to Jetty. In a forthcoming post I&#8217;ll talk more about these details. Within this post I&#8217;ll concentrate on the using of the service. I do need to make a few remarks. What if you do not want to apply the patch, change the pom, etc. Well you can download the one I have created from here : <a href="http://code.google.com/p/gridshore/source/browse/trunk/FelixTryout/RunnerApp/bundle/org.apache.felix.http.jetty-0.9.0-GRIDSHORE.jar">org.apache.felix.http.jetty-0.9.0-GRIDSHORE.jar</a>. Another thing I would like to stress is the current state of the bundle. There are a lot of TODO&#8217;d in there. It looks like security is not implemented as it should. There is a completely different implementation at the <a href="http://wiki.ops4j.org/confluence/display/ops4j/Pax+Web">ops4j website</a>. One disadvantage is the level of control, need to look into that thing again. It is much more complicated, uses other bundles of the pax project. It does look interesting, but for me it is not easy enough. Another implementation is available at the <a href="http://incubator.apache.org/sling/site/index.html">sling website</a>. But again a lot to graps before you can start. So for now I have chosen to continue with the slightly limited implementation, adhere to the spec and my bundles should work with the others as well.</p>
<p>Read more to learn about the sample using http.service and maven to build the bundle.</p>
<p><span id="more-66"></span></p>
<h2>The sample</h2>
<p>The goal was to play around with servlets and resources. I want to get a better idea about what OSGi can do. So I used the runner I introduced in my previous post (<a href="http://www.gridshore.nl/2008/02/10/starting-with-osgi-using-apache-felix-step-1/">starting-with-osgi-using-apache-felix-step-1</a>). Of course there are some other bundles and there is an extra property to configure the jetty intance:</p>
<pre>
<strong>configMap.put("org.osgi.service.http.port","9081"); // set the port to listen to for jetty</strong>
configMap.put(AutoActivator.AUTO_START_PROP + ".1",
    "file:" + BUNDLE_ROOT + "training-service/1.0-SNAPSHOT/training-service-1.0-SNAPSHOT.jar " +
    "file:" + BUNDLE_ROOT + "http-servlets/1.0-SNAPSHOT/http-servlets-1.0-SNAPSHOT.jar " +
    "file:" + JETTY_ROOT + "jetty/6.1.7/jetty-6.1.7.jar " +
    "file:" + JETTY_ROOT + "jetty-util/6.1.7/jetty-util-6.1.7.jar " +
    "file:" + JETTY_ROOT + "servlet-api-2.5/6.1.7/servlet-api-2.5-6.1.7.jar " +
    "file:bundle/org.osgi.compendium-1.0.0.jar " +
    "file:bundle/slf4j-api-1.4.3.jar " +
    "file:bundle/slf4j-simple-1.4.3.jar " +
<strong>    "file:bundle/org.apache.felix.http.jetty-0.9.0-GRIDSHORE.jar " + // use the created patched http.service</strong>
    "file:bundle/org.apache.felix.shell-1.0.0.jar " +
    "file:bundle/org.apache.felix.shell.tui-1.0.0.jar ");
</pre>
<p>The training service is a very easy service with one method returning a list of trainings. The more interesting bundle is the http-servlets bundle. This bundle contains the servlet that uses the training-service and some static resources like html pages, style sheets, etc. Let&#8217;s start with a look at the internal structure of the bundle. Please remember that we use the <a href="http://cwiki.apache.org/FELIX/bundle-plugin-for-maven-bnd.html">maven-bundle-plugin</a> plugin. Therefore we adhere to basic maven project structure. The java files are in the src/main/java folder. The static resources are in the src/main/resources folder. The plugin than creates the right MANIFEST.MF file.</p>
<pre>
Manifest-Version: 1.0
Built-By: jettro
Created-By: Apache Maven Bundle Plugin
Bundle-Activator: nl.gridshore.samples.bundles.httpservlets.impl.Activ
 ator
Import-Package: javax.servlet;version="2.5",javax.servlet.http;version
 ="2.5",nl.gridshore.samples.bundles.trainingservice.api,org.osgi.fram
 ework;version="1.3",org.osgi.service.http;version="1.2",org.slf4j;ver
 sion="1.4"
Bnd-LastModified: 1204315796232
Bundle-Version: 1.0.0.SNAPSHOT
Bundle-Name: http-servlets
Build-Jdk: 1.5.0_13
<strong>Private-Package: htmls,htmls.css,htmls.images,nl.gridshore.samples.bun
 dles.httpservlets.impl</strong>
Bundle-ManifestVersion: 2
Bundle-SymbolicName: http-servlets
Tool: Bnd-0.0.227
</pre>
<p>Take good notice of the Private-Packge, here the directories are listed that are in the resources folder. So by default these resources are private. We need the http service to expose these resources. The next step is to have a look at the Activator of the http-servlets bundle. Let&#8217;s step through the separate methods that are important.</p>
<pre>
<strong>public void start(BundleContext bundleContext) throws Exception</strong> {
    this.bundleContext = bundleContext;
    doRegister();
    synchronized (this) {
        bundleContext.addServiceListener(this,
                "(|(objectClass=" + TrainingService.class.getName() + ")" +
                "(objectClass=" + HttpService.class.getName() + "))");
    }
}
</pre>
<p>Two important things happen in the start method, we first try to register the servlet (more on that later). After that we add a service listener that listens to events related to the TrainingService class and the HttpService class. This means that if one of these instances are started, stopped or updated we are notified. This notification is important to unregister the servlet if the training service disappears. Of course it is also important to register the servlet if the http service becomes available. Let&#8217;s move on to the register methods.</p>
<pre>
<strong>private void register() throws InvalidSyntaxException, ServletException, NamespaceException</strong> {
    ServiceReference[] trainingReferences = bundleContext.getServiceReferences(TrainingService.class.getName(), null);
    TrainingService trainingService = null;
    if (trainingReferences != null) {
        trainingService = (TrainingService) bundleContext.getService(trainingReferences[0]);
    } else {
        logger.info("No training service available");
    }

    ServiceReference[] httpReferences = bundleContext.getServiceReferences(HttpService.class.getName(), null);
    HttpService httpService = null;
    if (httpReferences != null) {
        httpService = (HttpService) bundleContext.getService(httpReferences[0]);
    } else {
        logger.info("No http service available");
    }

    if ((trainingService != null) &#038;&#038; (httpService != null)) {
        logger.info("training servlet will be registered.");
        httpService.<strong>registerServlet</strong>("/trainings", new TrainingsServlet(trainingService), null, null);
        httpService.<strong>registerResources</strong>("/","/htmls",null);
    } else {
        logger.info("No servlet to register, problem with training service or http service");
    }
}

<strong>private void doRegister()</strong> {
    try {
        register();
    } catch (InvalidSyntaxException e) {
        logger.error("Could not register servlet based on an Invalid Syntax",e);
    } catch (ServletException e) {
        logger.error("Could not register servlet based on an Servlet exception",e);
    } catch (NamespaceException e) {
        logger.error("Could not register servlet based on an Namespace exception",e);
    }
}
</pre>
<p>Concentrate on the register method. First we check for available training service references. If a reference is available, we get the actual service. Then the same is done for the http service. If both of them are availble, we use the http service to register a new servlet that accepts the training service to obtain trainings from. As you can see we first register the servlet, the two null parameters represent the servlet config parameters and the special HttpContext. By providing null a default context is created. We also register a folder with static resources. The first string is the path or alias where the user should access the resources. The second string is the path to the resources within the bundle. The final parameter is the same as for the servlet, the HttpContext, again null so the default value. There are to more methods I want to show, first for unregistering and second for handling change events.</p>
<pre>
<strong>private void unregister() throws InvalidSyntaxException</strong> {
    logger.info("Unregister a servlet");
    ServiceReference[] httpReferences = bundleContext.getServiceReferences(HttpService.class.getName(), null);
    if (httpReferences != null) {
        HttpService httpService = (HttpService) bundleContext.getService(httpReferences[0]);
        httpService.unregister("/trainings");
        httpService.unregister("/");
    }
}

<strong>private void doUnregister()</strong> {
    try {
        unregister();
    } catch (InvalidSyntaxException e) {
        logger.error("Could not unregister servlet",e);
    }
}

<strong>public void serviceChanged(ServiceEvent event)</strong> {
    String objectClass = ((String[]) event.getServiceReference().getProperty("objectClass"))[0];
    logger.info("Service change event occurred for : {}", objectClass );
    if (event.getType() == ServiceEvent.REGISTERED) {
        doRegister();
    } else if (event.getType() == ServiceEvent.UNREGISTERING) {
        doUnregister();
    } else if (event.getType() == ServiceEvent.MODIFIED) {
        doUnregister();
        doRegister();
    }
}
</pre>
<p>The unregister function is pretty obvious. So let&#8217;s have a better look at the serviceChanged method. I took the easy way out here. Just check the type of event. In case of a new registration, register the servlet and resources. In case of an unregistration, we unregister the servlet and in case of a change we just do an unregister and a register. This works oke for my situation. Using the following screendumps I&#8217;ll show what happens when we start all bundles, stop de training-service bundle, and in the end start it again. First the output from the console, then the screens.</p>
<pre>
Welcome to Felix.
=================

1 [FelixStartLevel] INFO nl.gridshore.samples.bundles.httpservlets.impl.Activator - No http service available
1 [FelixStartLevel] INFO nl.gridshore.samples.bundles.httpservlets.impl.Activator - No servlet to register, problem with training service or http service
org.mortbay.log:Logging to org.mortbay.log via org.apache.felix.http.jetty.LogServiceLog
org.mortbay.log:started org.mortbay.jetty.servlet.HashSessionIdManager@2b2057
org.mortbay.log:started org.mortbay.jetty.servlet.HashSessionManager@85c0de
org.mortbay.log:starting OsgiServletHandler@395aaf
org.mortbay.log:started OsgiServletHandler@395aaf
org.mortbay.log:starting SessionHandler@70b819
org.mortbay.log:started SessionHandler@70b819
org.mortbay.log:starting org.mortbay.jetty.servlet.Context@1b50a1{/,null}
org.mortbay.log:starting ErrorHandler@46ad8b
org.mortbay.log:started ErrorHandler@46ad8b
org.mortbay.log:started org.mortbay.jetty.servlet.Context@1b50a1{/,null}
org.mortbay.log:jetty-6.1.x
org.mortbay.log:started Realm[OSGi HTTP Service Realm]==[]
org.mortbay.log:started org.mortbay.thread.BoundedThreadPool@ebaf12
org.mortbay.log:starting Server@32e910
org.mortbay.log:started org.mortbay.jetty.nio.SelectChannelConnector$1@19549e
org.mortbay.log:Started SelectChannelConnector@0.0.0.0:9081
org.mortbay.log:started SelectChannelConnector@0.0.0.0:9081
org.mortbay.log:started Server@32e910
191 [FelixStartLevel] INFO nl.gridshore.samples.bundles.httpservlets.impl.Activator - Service change event occurred for : org.osgi.service.http.HttpService
191 [FelixStartLevel] INFO nl.gridshore.samples.bundles.httpservlets.impl.Activator - training servlet will be registered.
org.mortbay.log:started /trainings/*
org.mortbay.log:started /htmls
-> stop 1
36499 [Felix Shell TUI] INFO nl.gridshore.samples.bundles.httpservlets.impl.Activator - Service change event occurred for : nl.gridshore.samples.bundles.trainingservice.api.TrainingService
36499 [Felix Shell TUI] INFO nl.gridshore.samples.bundles.httpservlets.impl.Activator - Unregister a servlet
-> start 1
org.mortbay.log:started /trainings/*
org.mortbay.log:started /htmls
43500 [Felix Shell TUI] INFO nl.gridshore.samples.bundles.httpservlets.impl.Activator - Service change event occurred for : nl.gridshore.samples.bundles.trainingservice.api.TrainingService
43500 [Felix Shell TUI] INFO nl.gridshore.samples.bundles.httpservlets.impl.Activator - training servlet will be registered.
->
</pre>
<p>Try to follow the steps, you can see the bundle containing the servlet starts before the training-service of the http-service. Then the change event is received and the servlet is registered. Next we stop the training service and the servlet is unregistered. And the servlet is registered again after a start of the training-service bundle (number 1).</p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/felix-osgi-training-step1.jpg" alt="felix-osgi-training-step1.jpg" border="0" width="536" height="355"/>This is the initial screen. Notice the url, this is a static resource called index.html that loads a stylesheet and an image from the bundle.</p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/felix-osgi-training-step2.jpg" alt="felix-osgi-training-step2.jpg" border="0" width="536" height="356"/>Now we have stopped the training service bundle, which has resulted in a unregister of the servlet, therefore the page is not available anymore.</p>
<p><img src="http://www.gridshore.nl/wp-content/uploads/felix-osgi-training-step3.jpg" alt="felix-osgi-training-step3.jpg" border="0" width="537" height="355"/>I have started the training service bundle again, so the servlet gets registered and now I have clicked the link for trainings. As you can see we have two very interesting trainings.</p>
<p>So that is about it, it turned out to become a pretty long post. Hope you liked it. Please leave a comment if you did, and of course if you did not. All your ideas and suggestions are welcome. If you want to have a look at the source, you can find everyting in the FelixTryout project at my <a href="http://code.google.com/p/gridshore/source/browse">google code website</a>. </p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2008%2F02%2F29%2Fcreating-a-jetty-based-osgi-httpservice-for-apache-felix%2F&amp;title=Creating%20a%20jetty%20based%20OSGi%20HttpService%20for%20apache%20felix&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2008/02/29/creating-a-jetty-based-osgi-httpservice-for-apache-felix/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Using maven to create an osgi bundle (osgi felix sample step 2)</title>
		<link>http://www.gridshore.nl/2008/02/13/using-maven-to-create-an-osgi-bundle-osgi-felix-sample-step-2/</link>
		<comments>http://www.gridshore.nl/2008/02/13/using-maven-to-create-an-osgi-bundle-osgi-felix-sample-step-2/#comments</comments>
		<pubDate>Wed, 13 Feb 2008 08:58:30 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[felix]]></category>
		<category><![CDATA[maven]]></category>
		<category><![CDATA[OSGi]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/2008/02/13/using-maven-to-create-an-osgi-bundle-osgi-felix-sample-step-2/</guid>
		<description><![CDATA[<p>This is the second step in a series of items about exploring the felix osgi container and some sidesteps to make life easier while developing osgi bundles. You can find the first step here: http://www.gridshore.nl/2008/02/10/starting-with-osgi-using-apache-felix-step-1/</p> <p>This is so easy, I do not want to spend to much time here. There is a special maven [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.gridshore.nl/wp-content/logo1.png" alt="logo.png" border="0" width="165" height="63" align="left" />This is the second step in a series of items about exploring the felix osgi container and some sidesteps to make life easier while developing osgi bundles. You can find the first step here: http://www.gridshore.nl/2008/02/10/starting-with-osgi-using-apache-felix-step-1/</p>
<p>This is so easy, I do not want to spend to much time here. There is a special maven 2 plugin to create a &#8220;bundle&#8221;, check out the following page that describes the plugin :<a href="http://felix.apache.org/site/maven-bundle-plugin-bnd.html"> maven-bundle-plugin</a>.</p>
<p>Create a new maven project using the most basic archetype.</p>
<p>mvn archetype:create -DgroupId=&lt;your.groupid&gt; -DartifactId=&lt;your.artifactId&gt;</p>
<p>Change the packaging of the pom to be &quot;bundle&quot;. Add a dependency to the core and configure the plug in. The possible parameters are described extensively at the mentioned web page. I&#8217;ll explain the what and why of the code below, not the theory. The following pom file is the pom of the project example-client in the FelixTryout project on my <a href="http://code.google.com/p/gridshore/source/browse">google code</a> page. As you can see there is a dependency on the training-service and on jetty. i am not going to talk about jetty here. More on that in one of the next steps.</p>
<pre>
&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;groupId&gt;nl.gridshore.samples.bundles&lt;/groupId&gt;
    &lt;artifactId&gt;example-client&lt;/artifactId&gt;
    &lt;packaging&gt;bundle&lt;/packaging&gt;
    &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
    &lt;name&gt;example-client&lt;/name&gt;
    &lt;url&gt;http://maven.apache.org&lt;/url&gt;
    &lt;dependencies&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;${pom.groupId}&lt;/groupId&gt;
            &lt;artifactId&gt;training-service&lt;/artifactId&gt;
            &lt;version&gt;1.0-SNAPSHOT&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.apache.felix&lt;/groupId&gt;
            &lt;artifactId&gt;org.osgi.core&lt;/artifactId&gt;
            &lt;version&gt;1.0.0&lt;/version&gt;
        &lt;/dependency&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.mortbay.jetty&lt;/groupId&gt;
            &lt;artifactId&gt;jetty&lt;/artifactId&gt;
            &lt;version&gt;6.1.7&lt;/version&gt;
        &lt;/dependency&gt;
    &lt;/dependencies&gt;
    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                    &lt;source&gt;1.5&lt;/source&gt;
                    &lt;target&gt;1.5&lt;/target&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.felix&lt;/groupId&gt;
                &lt;artifactId&gt;maven-bundle-plugin&lt;/artifactId&gt;
                &lt;version&gt;1.2.0&lt;/version&gt;
                &lt;extensions&gt;true&lt;/extensions&gt;
                &lt;configuration&gt;
                    &lt;instructions&gt;
                        &lt;Export-Package&gt;
                            nl.gridshore.samples.bundles.exampleclient.api
                        &lt;/Export-Package&gt;
                        &lt;Private-Package&gt;
                            nl.gridshore.samples.bundles.exampleclient.impl
                        &lt;/Private-Package&gt;
                        &lt;Bundle-SymbolicName&gt;${pom.artifactId}&lt;/Bundle-SymbolicName&gt;
                        &lt;Bundle-Activator&gt;
                            nl.gridshore.samples.bundles.exampleclient.impl.Activator
                        &lt;/Bundle-Activator&gt;
                    &lt;/instructions&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
&lt;/project&gt;
</pre>
<p>The export-package contains the packages that are exposed to other bundles. This results in the following manifest file:</p>
<pre>
Manifest-Version: 1.0
Built-By: jettro
Created-By: Apache Maven Bundle Plugin
Bundle-Activator: nl.gridshore.samples.bundles.exampleclient.impl.Acti
 vator
Import-Package: javax.servlet;version="2.5",javax.servlet.http;version
 ="2.5",nl.gridshore.samples.bundles.trainingservice.api,org.mortbay.j
 etty;version="6.1",org.mortbay.jetty.servlet;version="6.1",org.osgi.f
 ramework;version="1.3"
Bnd-LastModified: 1202823580612
Bundle-Version: 1.0.0.SNAPSHOT
Bundle-Name: example-client
Build-Jdk: 1.5.0_13
Private-Package: nl.gridshore.samples.bundles.exampleclient.impl
Bundle-ManifestVersion: 2
Bundle-SymbolicName: example-client
Tool: Bnd-0.0.227
</pre>
<p>Most of the items are pretty obvious if you look at the maven configuration. There is one thing that is more advanced. Have a look at the import-Package, this contains the packages that are imported by the classes. This is done automatically by the bundle plugin. You can prevent imports by configuring the &quot;ImportPackage&quot; and use the negative import.</p>
<p>&lt;Import-Package&gt;!org.foo.impl&lt;/Import-Package&gt;</p>
<p>That is about it, mvn clean install and your plugin is installed into the maven repository. Well, of course you do need to implement some java code. Just like I said before, you can find the implementation on google code. I will also introduce the concepts in the forthcoming steps or posts.</p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2008%2F02%2F13%2Fusing-maven-to-create-an-osgi-bundle-osgi-felix-sample-step-2%2F&amp;title=Using%20maven%20to%20create%20an%20osgi%20bundle%20%28osgi%20felix%20sample%20step%202%29&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2008/02/13/using-maven-to-create-an-osgi-bundle-osgi-felix-sample-step-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Upgrading maven on the mac</title>
		<link>http://www.gridshore.nl/2008/01/28/upgrading-maven-on-the-mac/</link>
		<comments>http://www.gridshore.nl/2008/01/28/upgrading-maven-on-the-mac/#comments</comments>
		<pubDate>Mon, 28 Jan 2008 21:58:14 +0000</pubDate>
		<dc:creator>jettro</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Mac OSX]]></category>
		<category><![CDATA[maven]]></category>

		<guid isPermaLink="false">http://www.gridshore.nl/2008/01/28/upgrading-maven-on-the-mac/</guid>
		<description><![CDATA[<p>Can you believe it, when you have Mac os-x 10.5 running, maven is pre-installed. If you are not programming java you practically do not care about it. But if you are not programming java you will not find this blog very interesting as well . So especially for those that like their Mac, program [...]]]></description>
			<content:encoded><![CDATA[<p>Can you believe it, when you have Mac os-x 10.5 running, maven is pre-installed. If you are not programming java you practically do not care about it. But if you are not programming java you will not find this blog very interesting as well <img src='http://www.gridshore.nl/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . So especially for those that like their Mac, program java and want to upgrade there maven version from 2.0.6 to for instance 2.0.8, this is what you need to do. You can find your current maven installation in he folder:</p>
<pre>
/usr/share/maven
</pre>
<p>This is a protected directory, so you&#8217;ll need some sudo commands here to do anything. I downloaded the file &quot;apache-maven-2.0.8.zip&quot;. On my system, zip files get extracted after download. Therefore I need a &quot;mv&quot; command. I did keep the original files by the way. You&#8217;ll need these commands:</p>
<pre>
cd /usr/share
sudo mv maven maven206
sudo cp -R /Users/jettro/Downloads/apache-maven-2.0.8 maven
</pre>
<p>Now it is time to check, just to be sure, open a new command shell and type the following command:</p>
<pre>
mvn -version
</pre>
<p>That should result in:
<pre>
</pre>
<p><pre>jettro:~ jettro$ mvn -version
Maven version: 2.0.8
Java version: 1.5.0_13
OS name: "mac os x" version: "10.5.1" arch: "i386" Family: "unix"
</pre>
</p>
<p>Now you have maven 2.0.8 available</p>
<p>One final remark, if you have changed the settings.xml file, do not forget to copy this back to the new folder.</p>
<div class='dd_post_share'><div class='dd_buttons'><div class='dd_button'><iframe src='http://widgets.dzone.com/links/widgets/zoneit.html?url=http%3A%2F%2Fwww.gridshore.nl%2F2008%2F01%2F28%2Fupgrading-maven-on-the-mac%2F&amp;title=Upgrading%20maven%20on%20the%20mac&amp;t=2' height='25' width='155' frameborder='0' scrolling='no'></iframe></div></div><div style='clear:both'></div></div><!-- Social Buttons Generated by Digg Digg plugin v4.5.3.4, 
    Author : Yong Mook Kim
    Website : http://www.diggdigg2u.com -->]]></content:encoded>
			<wfw:commentRss>http://www.gridshore.nl/2008/01/28/upgrading-maven-on-the-mac/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
	</channel>
</rss>

