<?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>Luminis Software Development &#187; spring</title>
	<atom:link href="http://lsd.luminis.nl/tag/spring/feed/" rel="self" type="application/rss+xml" />
	<link>http://lsd.luminis.nl</link>
	<description></description>
	<lastBuildDate>Mon, 19 Jul 2010 06:45:31 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>nl</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Getting started with Spring-OSGi &#8212; part 2</title>
		<link>http://lsd.luminis.nl/getting-started-with-spring-osgi-part-2/</link>
		<comments>http://lsd.luminis.nl/getting-started-with-spring-osgi-part-2/#comments</comments>
		<pubDate>Wed, 26 Sep 2007 20:42:20 +0000</pubDate>
		<dc:creator>Peter Doornbosch</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apache Felix]]></category>
		<category><![CDATA[OSGi]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://lsd.luminis.net/?p=145</guid>
		<description><![CDATA[<img class="thumbnail" src="http://blog.luminis.nl/luminis/resource/thumbnails/lego_thumb.gif">
The second installment of the hands-on guide to Spring-OSGi, focuses on using external OSGi services in a Spring bean and how to handle service dynamics...]]></description>
			<content:encoded><![CDATA[<p>
In the<br />
<a href="http://blog.luminis.nl/luminis/entry/getting_started_with_spring_osgi">previous</a><br />
blog entry about Spring-OSGi, we demonstrated how to develop a simple<br />
Spring-OSGi bundle that exposes a Spring bean as an OSGi service. In this installment<br />
we&#8217;ll have a look at how you can use OSGi services in a Spring-OSGi bundle.<br />
The sample code used in this blog builds on the sample of the previous blog<br />
and can of course be<br />
<a href="http://blog.luminis.nl/luminis/resource/peter/getting-started-with-SpringOSGi-part2.zip" onClick="javascript:pageTracker._trackPageview('/downloads/SprintOSGi-part2.zip'); ">downloaded</a> from our site.
</p>
<p>
For demonstrating the use of an external OSGi services, we&#8217;ll use a very simple bundle<br />
exposing an <code>AuditService</code> service that looks like this:</p>
<pre>
public interface AuditService
{
    public void audit(String action);
}
</pre>
<p>The bundle provides an implementation of this interface that simply prints a message to<br />
system out. You can download this bundle <a href="http://blog.luminis.nl/luminis/resource/peter/auditservice.jar">here</a>; of course the<br />
complete bundle source is available in the source<br />
<a href="http://blog.luminis.nl/luminis/resource/peter/getting-started-with-SpringOSGi-part2.zip">zip</a>. It&#8217;s a plain (non-Spring) bundle<br />
that use a standard OSGi activator; don&#8217;t bother if you don&#8217;t grasp all the details of this bundle<br />
implementation: we&#8217;ll just use it as an external service. If you install and start this<br />
bundle in Felix, you&#8217;ll see the new service appear when issue the <code>services</code> command.
</p>
<h3>Binding service to Spring bean</h3>
<p>
The next thing to do, is of course to adapt our <code>reversestringbean</code> bundle,<br />
to use this service. We change the <code>reverse</code> method to audit-log all<br />
invocations of the reverse method:</p>
<pre>
private AuditService m_auditService;

public String reverse(String arg) {
    if (m_auditService != null) {
        m_auditService.audit("reverse(String) called with argument '" + arg + "'");
    }
    ...
}
</pre>
</p>
<p>
If you have Felix running with the previous version of<br />
the <code>reversestringbean</code> bundle and made the change outlined above, you can<br />
replace the old bundle with the new version (issue<br />
an <code>update</code> command with the id of the old bundle and the file url of the<br />
new version), and see that the <code>reverse</code> command is still working, even<br />
though it has switched to the new version.<br />
(If you get an error like &#8220;Unresolved package in bundle 19: package;<br />
(package=nl.luminis.demo.audit)&#8221;, you forgot to install the audit bundle; install it<br />
and try to start the reversestring bundle again.)
</p>
<p>
The new <code>reversestringbean</code> implementation is not using the audit service yet, because the service<br />
reference is not set. When can make Spring do this, by specifying the service in<br />
the <code>spring.xml</code> file:</p>
<pre>
&lt;osgi:reference id="externalAuditService"
                interface="nl.luminis.demo.audit.AuditService"/>
</pre>
<p>and use this reference as property value for the bean that was already defined in the<br />
same <code>spring.xml</code> file:</p>
<pre>
&lt;bean name="reverseBean" class="nl.luminis.demo.reversestring.ReverseStringBean">
    &lt;property name="auditService" ref="externalAuditService"/>
&lt;/bean>
</pre>
<p>When you build the bundle with the updated <code>spring.xml</code> file and reload it,<br />
Spring will notice that<br />
the <code>reversestringbean</code> bundle requires an <code>AuditService</code>, and<br />
pass the bean a reference to that service. When you issue the <code>reverse</code><br />
command again, you&#8217;ll see the audit message printed to the console:</p>
<pre>
-> reverse hello there!
AuditService: reverse(String) called with argument ' hello there!'
!ereht olleh
->
</pre>
</p>
<h3>Service not available</h3>
<p>
Now it&#8217;s time for a little experiment, to see how things behave when the audit service<br />
is not (yet) available. After all, we&#8217;re now working in a service oriented environment<br />
and service orientation is all about dynamics.<br />
<br />
We&#8217;ll restart the Felix framework, with a non-active audit service. To do so, issue the<br />
stop command on the audit service bundle and restart Felix. The framework will remember<br />
each bundle&#8217;s last state, so after the restart, the state of the audit service bundle<br />
will be &#8220;Resolved&#8221; (check this with the <code>ps</code> command). Note that we can&#8217;t<br />
uninstall the audit service bundle, as it is the only bundle providing<br />
the <code>AuditService</code> <em>interface</em>, and this interface (its class file)<br />
is needed by the <code>reversestringbean</code> bundle. A better alternative would be<br />
to split the audit service bundle and have the interface and implementation in two<br />
separate bundles: in that case you could now uninstall the implementation bundle and<br />
leave the interface bundle &#8211; this is left as an exercise for the reader <img src='http://lsd.luminis.nl/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .
</p>
<p>
Issue a <code>reverse</code> again: you&#8217;ll get a message (from the command bundle)<br />
telling you that there<br />
is no string service. If you&#8217;d study the output of the <code>services</code> command,<br />
you&#8217;ll notice that although the <code>reversestringbean</code> bundle is started and<br />
active, it is not publishing any service: not even Spring&#8217;s<br />
<code>org.springframework.context.ApplicationContext</code> service we saw earlier.<br />
The explanation for this behaviour is that Spring will not activate the bundle before<br />
all its required dependencies are satisfied. You can verify this by starting the audit<br />
service and trying again: now it works as before.<br />
<br />
To continue our little experiment, stop the audit service again, study the output of<br />
the <code>services</code> command and issue the <code>reverse</code> command<br />
again. This time, the reverse string service is still there, even though the bundle&#8217;s<br />
required services are not satisfied anymore. So, Spring refuses to start our bean when<br />
the required service(s) (i.e. the audit service) are not there, but it doesn&#8217;t bother<br />
to stop the bean when the required service(s) disappear. Personally I dislike this<br />
non-symmetric behaviour and I think it shows that Spring was never designed for dynamic<br />
systems: somehow they can&#8217;t really stop an ApplicationContext (and<br />
restart it later) once it is created, I guess.
</p>
<h3>Optional service dependency</h3>
<p>To return to our sample bundle that won&#8217;t start when there is not audit service:<br />
 this is not what we want. The <code>reversestringbean</code> bundle<br />
should always perform the reverse operation; whether or not the audit service is there<br />
(in a banking example this might not be the case, but for this example, assume<br />
auditting is not crucial).<br />
The solution is in the word &#8220;required&#8221;: if<br />
we define the audit service to be optional, Spring will start the bundle, even when the<br />
audit service is not there yet.</p>
<p>Let&#8217;s try this: add cardinality &#8220;0 to 1&#8243; to the service reference definition:</p>
<pre>
&lt;osgi:reference id="externalAuditService"
                interface="nl.luminis.demo.audit.AuditService"
                cardinality="0..1" />
</pre>
<p>and additionally, add the <code>lazy-init="true"</code> to the bean definition. Now<br />
build and reload the bundle and issue another <code>reverse</code> command. To your<br />
surprise (I guess&#8230;, at least to mine!), it still won&#8217;t work; you&#8217;ll get<br />
a <code>ServiceUnavailableException</code> now.<br />
Check the output of the <code>services</code> command: the reverse string<br />
service <em>is</em> published. What&#8217;s going on here?
</p>
<p>
The point is that, in constrast to &#8216;plain&#8217; OSGi behaviour, Spring provides the bean<br />
with a proxy to the service, instead of a plain Java reference to the service<br />
implementation (as the OSGi framework itself does). Moreover, this proxy is set,<br />
irrespective of whether the service is available. The<br />
<code>ServiceUnavailableException</code> is intentional: you should always be prepared<br />
to get an exception when calling an external service.<br />
<br />
I can agree with this last rule: in a dynamic environment, you can never be sure<br />
whether a service is there; even when it was there a few minutes ago, it might be gone<br />
at the very moment you&#8217;re using the service. However, in a case like this, I wouldn&#8217;t<br />
expect the service proxy to be passed to the bean in the first place, until the service it<br />
represents actually exists. We&#8217;ll come back to this in a minute.
</p>
<p>
Let&#8217;s add a try-catch block to the code around calling the service and try again.<br />
This time it works as expected, although it might take a little longer than you expect:<br />
that&#8217;s because Spring has a default wait time when it tries to find a service. You can<br />
skip this by adding a attribute <code>timeout="0"</code> to<br />
the <code>&lt;osgi:reference></code> element in the <code>spring.xml</code> file.<br />
Now, the service behaves as expected: it does its job whether or not the audit service<br />
is available, and it does it without any additional delay.
</p>
<h3>Dynamic services</h3>
<p>
There is an alternative to the setter injection, that better suits dynamic<br />
behaviour: callback methods on the bean. As you&#8217;d expect from the Spring framework,<br />
your bean doesn&#8217;t have to implement an interface in order to be listener; just add two<br />
methods and specify their names in the <code>spring.xml</code>:</p>
<pre>
&lt;osgi:reference id="externalAuditService"
                interface="nl.luminis.demo.audit.AuditService"
                cardinality="0..1">
  &lt;osgi:listener ref="reverseBean"
                 bind-method="serviceAdded"
                 unbind-method="serviceRemoved"/>
&lt;/osgi:reference>
</pre>
</p>
<p>Note that the signature of the methods is fixed to this (at least in Spring-OSGi<br />
1.0-m2; it was different in earlier versions, so it might as well differ in newer<br />
versions):</p>
<pre>
public void serviceAdded(AuditService service, Dictionary d) {
    m_auditService = service;
}

public void serviceRemoved(AuditService service, Dictionary d) {
    m_auditService = null;
}
</pre>
<p>Don&#8217;t forget to remove the (setter injection) property from the bean definition. If you<br />
add <code>println's</code> to these listener methods, you&#8217;ll see that these are indeed<br />
called exactly at the moment the service appears or disappears.
</p>
<p>
You might wonder what happens when the cardinality is set to something else, e.g. 1 to<br />
many 0 to many. In both cases, the setter that receives the service(s) is supposed to<br />
receive a collection instead of a single service reference. The collection is managed<br />
by Spring behind the scenes: each time you iterate over this collection, it&#8217;s contents<br />
may be different, as it reflects the current state of the OSGi framework. Handling of<br />
the case that there is no service is easy, as an iterator over the collection will<br />
return nothing. However, one has still to cover for the<br />
dreadfull <code>ServiceUnavailableException</code>, as a service may disappear between<br />
the moment you get its reference from the collection and call a method on it.
</p>
<h3>Conclusion</h3>
<p>
We&#8217;ve seen how a normal Spring bean can interact with external OSGi services, and that<br />
by using setter injection, the implementation of the bean doesn&#8217;t have to different<br />
from a bean that is used within Spring exclusively. On the other hand, we&#8217;ve also seen<br />
that a <code>ServiceUnavailableException</code> is always to be expected and that the<br />
setter injection solution doesn&#8217;t combine very well with the dynamic behaviour of a<br />
service oriented framework.<br />
<br />
If you want to get it right, you can&#8217;t get away with a normal Spring bean<br />
implementation that does not handle <code>ServiceUnavailableException's</code> and is<br />
not prepared to handle missing dependencies. It&#8217;s an illusion that you can take an<br />
existing Spring bean implementation and use it unmodified in an OSGi context. It&#8217;s<br />
similar to having to deal with remote calls: you can&#8217;t hide remoteness from your<br />
application, as remote calls might fail, and your code has to be aware of it &#8211; provided<br />
you aim at robust code, of course. The same holds for a dynamic service oriented<br />
environment: you have to deal with disappearing services, you can&#8217;t simply ignore<br />
that. That is what makes OSGi different from old fashioned Spring usage that always<br />
assumes that all beans are there, once the system is started.<br />
<br />
The good news though, is that with Spring-OSGi, handling dynamic service is possible<br />
and that it can&#8217;t be done without implementing specific interfaces. In that sense,<br />
Spring-OSGi is non-intrusive, just like plain Spring is. You can&#8217;t ignore the fact that<br />
you&#8217;ve to deal with disappearing services, but you can do it in a way that does not<br />
limit reuse of your beans in other (non-OSGi) environments.
</p>
<p>
Finally a tip for those who want to experiment with the Spring-OSGi framework: enable<br />
Spring (log4j) logging. It&#8217;s hard to get it all right the first time, especially with<br />
all the xml-configuration stuff, and sometimes errors are swallowed by the framework,<br />
leaving you in total dispair. Logging can enabled by passing a system property on the<br />
java command line: </p>
<pre>
-Dlog4j.configuration=file:///your/path/to/spring-log4j.properties
</pre>
<p>You&#8217;ll find a sample log4j.properties file in the source zip. Happy coding!</p>
]]></content:encoded>
			<wfw:commentRss>http://lsd.luminis.nl/getting-started-with-spring-osgi-part-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting started with Spring-OSGi</title>
		<link>http://lsd.luminis.nl/getting-started-with-spring-osgi/</link>
		<comments>http://lsd.luminis.nl/getting-started-with-spring-osgi/#comments</comments>
		<pubDate>Sun, 26 Aug 2007 19:32:42 +0000</pubDate>
		<dc:creator>Peter Doornbosch</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[Apache Felix]]></category>
		<category><![CDATA[OSGi]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://lsd.luminis.net/?p=147</guid>
		<description><![CDATA[<img class="thumbnail" src="http://blog.luminis.nl/luminis/resource/thumbnails/lego_thumb.gif"> With the introduction of Spring OSGi, it becomes relatively easy to develop a Spring application 
as a number of separate OSGi bundles. This blog post gets you up and running with this new way of deploying Spring applications...  ]]></description>
			<content:encoded><![CDATA[<h2>Getting started with Spring-OSGi</h2>
<p>
With the introduction of <a href="http://www.springframework.org/osgi">Spring OSGi</a>,<br />
it becomes relatively easy to split up a Spring application in separate OSGi bundles,<br />
and have a much more modular application architecture, without all the classloading<br />
hassle you may encounter when deploying components in J2EE application servers.
</p>
<p>
The purpose of this series of blog posts is to get you started with Spring-OSGi. We&#8217;ll<br />
develop some simple examples that will get you up and running.<br />
Theoretically, it is possible to use Eclipse for developing OSGi bundles using Spring,<br />
but, at least in my experience, this is a bumpy road with lots of obstacles, and in the<br />
end it does not lead to better understanding of the concepts. Therefore, the samples<br />
presented here will be provided with simple ant build files and do not require special<br />
tools to build or deploy. The complete source code of the samples can be found in this<br />
<a href="http://blog.luminis.nl/luminis/resource/peter/getting-started-with-SpringOSGi.zip" onClick="javascript:pageTracker._trackPageview('/downloads/SpringOSGi-part1.zip'); ">zip file</a>.
</p>
<p>
OSGi is (a standard defining) a service oriented framework as well as a number of<br />
standard services that can be deployed on these frameworks. Key concepts are &#8220;bundles&#8221;<br />
and &#8220;services&#8221;. A bundle is essentially a normal Java jar file and is the unit of<br />
deployment, i.e. you can install, update and de-install them in a running<br />
framework. Each bundle can publish one or more services, that can be used by other<br />
bundles. Bundles can locate services by querying the OSGi service registry. One of the<br />
most important aspects of OSGi, is that even bundles that use each others services,<br />
have nothing more in common than the service interface. <br />
A complete introduction on OSGi is beyond the scope of this blog post, but there is<br />
enough information online, see for example<br />
<a href="http://www.osgi.nl">OSGi.nl</a>,<br />
<a href="http://www.aqute.biz/OSGi/Tutorial">www.aqute.biz/OSGi/Tutorial</a>,<br />
<a href="http://www.osgi.org">www.osgi.org</a>,<br />
<a href="http://felix.apache.org">felix.apache.org</a>.
</p>
<h3>Hello&#8230;, OSGi</h3>
<p>
We&#8217;ll start with a simple &#8220;hello world&#8221; like sample, that exposes a trivial Spring bean<br />
as an OSGi service. The next step will be to create a bundle that actually uses this<br />
service, so we can run the demo in an OSGi framework and experiment with this. Also,<br />
these samples will help us to setup the compile time and run time environment<br />
correctly.
</p>
<p>
As said, we start with a simple, not to say trivial (Spring) bean. Here is its source:
</p>
<pre>
package nl.luminis.demo.reversestring;

public class ReverseStringBean
{
    public String reverse(String arg) {
        String result = "";
        for (int i = arg.length() - 1; i >= 0; i--)
            result += arg.charAt(i);
        return result;
    }
}
</pre>
<p>
To make it Spring bean, we have to add a configuration file that defines the bean. In<br />
plain Spring this would be something like:
</p>
<pre>
&lt;beans xmlns="http://www.springframework.org/schema/beans"&gt;
  &lt;bean name="reverseBean"
        class="nl.luminis.demo.reversestring.impl.ReverseStringImpl"/&gt;
&lt;/beans>
</pre>
<p>
(omitting xml namespace stuff for brevity, see the zip for complete source).
</p>
<p>
Exposing beans as OSGi services is fairly simple in Spring-OSGi. Basically, the only<br />
thing you&#8217;ll have to do is to add an <code>&lt;osgi:service></code> element to the<br />
spring xml configuration file like this:
</p>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;beans> &lt;!-- (again, namespace declarations omitted) -->

  &lt;bean name="reverseBean"
        class="nl.luminis.demo.reversestring.ReverseStringImpl"/>
  &lt;osgi:service ref="reverseBean"
                interface="nl.luminis.demo.string.ReverseString"/>

&lt;/beans>
</pre>
<p>
Of course, we need an interface that defines the service we&#8217;re exposing, so we define<br />
the <code>ReverseString</code><br />
interface and add the <code>reverseString()</code> method to it.
</p>
<p>
To make it a bundle, the last thing to do is add a manifest file with the (OSGi)<br />
required entries:
</p>
<pre>
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: ReverseStringBean
Bundle-SymbolicName: ReverseStringBean
Bundle-Version: 1.0.0
</pre>
<p>
Strictly speaking, not all of these entries are required, but it is common practice to<br />
have at least these entries in the manifest file.
</p>
<p>
This completes our first bundle. If you&#8217;re familair with OSGi you might wonder if our<br />
bundle doesnt&#8217; need a <code>BundleActivator</code>, that provides <code>start()</code><br />
and <code>stop()</code> lifecyle methods that the OSGi framework can call to start or<br />
stop our bundle. The answer is that it doesn&#8217;t need it, because Spring-OSGi works<br />
similar to the OSGi declarative service specification: the framework will inspect the<br />
service declaration and instantiate the service on our bundle&#8217;s behalf; instead of<br />
publishing the service ourselves (from within the BundleActivators start method), the<br />
framework &#8220;pulls&#8221; the service out of our bundle, so to speak.
</p>
<p><h3>Setting up the runtime environment</h3>
<p>Now it&#8217;s time to set up our run time environment. For the demo we will<br />
use <a href="http://felix.apache.org">Apache Felix</a> 1.0, but you can deploy the<br />
bundle in any OSGi framework, e.g. (Eclipse) Equinox, or Knopflerfish. Download felix<br />
and start it by executing the jar file in its bin directory and enter a profile<br />
name. If you enter <code>ps</code> on the prompt you&#8217;ll see that there are only three<br />
bundles active: the system bundle (i.e. the framework ifself) and two bundles that<br />
constitute the shell service that executes the commands your typing at the<br />
prompt. Install our demo bundle by using the <code>install</code> command, passing it a<br />
file url that points to the bundle:
</p>
<pre>
-> install file:///Users/peter/.../reverestringbean.jar
</pre>
<p>
You can <code>start</code> the bundle now, but it won&#8217;t register any services yet, as no<br />
one is paying attention to our service declaration in the <code>spring.xml</code><br />
file. Execute the <code>services</code> command to confirm this.
</p>
<p>
As the final step in setting up the run time environment, we&#8217;ll install the Spring-OSGi<br />
framework. For this demo, we used the <a href="http://sourceforge.net/project/showfiles.php?group_id=73357&#038;package_id=227224&#038;release_id=507778">milestone 2 release of Spring-OSGi 1.0</a>; newer versions should work also, but of course, small (presumably subtle) differences may occur.<br />
Make sure you download the &#8220;-with-dependencies&#8221; zip file.
</p>
<p>
Install these Spring-OSGi bundles from the <code>dist</code> directory:</p>
<ul>
<li>spring-osgi-core-1.0-m2.jar
<li>spring-osgi-extender-1.0-m2.jar
<li>spring-osgi-io-1.0-m2.jar
</ul>
<p>These bundles depend on (but do not include) the plain Spring code, so you have to install<br />
a number of bundles (all of which can be found in the <code>lib</code><br />
directory) that contain the plain spring framework modules:</p>
<ul>
<li>spring-core-2.0.5-osgi-m2.jar (from spring-core/2.0.5-osgi-m2/)
<li>spring-aop-2.0.5-osgi-m2.jar (from spring-aop/2.0.5-osgi-m2/)
<li>spring-beans-2.0.5-osgi-m2.jar (from spring-beans/2.0.5-osgi-m2/)
<li>spring-context-2.0.5-osgi-m2.jar (from spring-context/2.0.5-osgi-m2/)
<li>aopalliance.osgi-1.0-SNAPSHOT.jar (from aopalliance.osgi/1.0-SNAPSHOT/)
<li>backport-util-concurrent-3.0-SNAPSHOT.jar (from backport-util-concurrent/3.0-SNAPSHOT/)
</ul>
<p>Additionally, some <a href="http://www.slf4j.org/download.html">SLF4J</a> libraries<br />
have to be installed. SLF4J is a logging facade for several logging implementations,<br />
similar to Apache Commons Logging. An important difference with Apache Commons Logging<br />
is that in order to determine what implementation to use, it does not rely on<br />
classloading tricks that can cause a lot of <a href="http://www.qos.ch/logging/classloader.jsp">trouble</a>, especially when<br />
used in dynamic environments like an OSGi framework.
</p>
<p>
From SLF4J you need the following libraries:</p>
<ul>
<li>slf4j-api-1.4.3.jar (contains only the SLF4J API)
<li>slf4j-log4j12-1.4.3.jar (implementation of SFL4J, hard-wired to log4j)
<li>jcl104-over-slf4j-1.4.3.jar (100% compatible drop-in replacement for Commons Logging)
</ul>
<p>Just install them as normal bundles, these libraries are OSGi ready. The<br />
jcl104-over-slf4j library contains modified versions<br />
of <code>org.apache.commons.logging.Log.java</code> etc, that redirect to SLF4J. This<br />
will take care of libraries using the Commons Logging API.
</p>
<p>
As we&#8217;ll be using log4j as the logging implementation that does the real work, we&#8217;ll<br />
have to install that too. An OSGi compatible version of log4j can be found in the<br />
Spring OSGi package</p>
<ul>
<li>log4j.osgi-1.2.13-SNAPSHOT.jar (from src/spring-modules/spring-required-libraries/log4j/target)
</ul>
<p>but, you&#8217;ll have to build it first (with maven). Alternatively, you can download the<br />
file <a href="http://blog.luminis.nl/luminis/resource/peter/log4j.osgi-1.2.13-SNAPSHOT.jar">here</a>.
</p>
<p>
After you&#8217;ve installed these bundles, you can start them all. Note that if you try to<br />
start some bundles before you installed them all, you&#8217;re likely to get errors about<br />
unresolved packages; to avoid that you would have to install them in the right order.<br />
You&#8217;ll probably see some warnings about resources files and namespace handlers that<br />
can&#8217;t be found, which you can just ignore.
</p>
<p>
Now the Spring-OSGi extender is running, it should have discovered and published our<br />
service. Due to a bug in the M2 release (fixed in later releases), it doesn&#8217;t yet work this way and you have to<br />
restart our bundle. If you do so, you&#8217;ll get some warnings about BeanInfo classes not<br />
being found; ignore these too.
</p>
<p><h3>Using the service</h3>
<p>If you issue the <code>services</code> command once again, you&#8217;ll notice that our simple demo<br />
bundle provides to services: <code>nl.luminis.demo.string.ReverseString</code><br />
and <code>org.springframework.context.ApplicationContext</code>. The latter is the<br />
well known Spring application context, that is merely provided as OSGi service for<br />
debugging purposes (you shouldn&#8217;t use it to access a bean from outside its bundle).
</p>
<p>
Essentially, we&#8217;re ready now, as our first spring enabled bundle is up and running and<br />
publishes its service. However, we can&#8217;t be satisfied until we&#8217;ve actually seen it do<br />
something &#8220;usefull&#8221;. To make that happen, we&#8217;ll write an extension for the felix<br />
command interpreter, that will call our service. This extension will be a bundle on its<br />
own. As it hooks in into the Felix command shell, this of course is a Felix specific<br />
solution, but similar constructs exist for Equinox and Klopflerfish.
</p>
<p>
The heart of this command bundle is the <code>execute()</code> method, that tries to<br />
locate the service and calls it:</p>
<pre>
public void execute(String line, PrintStream out, PrintStream err)
{
    // (...)
    ServiceReference ref = m_context.getServiceReference("nl.luminis.demo.string.ReverseString");
    Object service = (ref != null)? m_context.getService(ref): null;
    if (service != null)
        try {
            out.println(((ReverseString) service).reverse(arg));
        }
        catch (Exception e) {
            err.println("calling reverse string service failed: " + e);
        }
    else {
        err.println("no reverse string service, ref=" + ref);
    }
}
</pre>
<p>See the source.zip for the complete source code.
</p>
<p>
After installing and starting the command bundle, you&#8217;ll notice the new &#8220;reverse&#8221; command in the<br />
help text:</p>
<pre>
-> help
...
install &lt;URL> [&lt;URL> ...]           - install bundle(s).
ps [-l | -s | -u]                   - list installed bundles.
resolve [&lt;id> ...]                  - attempt to resolve the specified bundles.
reverse &lt;arg>                       - reverses a string, using a ReverseString service
services [-u] [-a] [&lt;id> ...]       - list registered or used services.
...
</pre>
<p>and issuing this command will finally show that our service works correctly:</p>
<pre>
-> reverse  OSGi is cool!
!looc si iGSO
->
</pre>
</p>
<p>
This concludes our first working Spring-OSGi sample. It&#8217;s not yet a full-blown J2EE<br />
application, but it clearly shows what is needed to make a basic Spring-OSGi bundle<br />
work and have it publish a bean as an OSGi service. In future installments, we&#8217;ll have a<br />
look at using external OSGi services in our beans, and experiment with some less<br />
trivial bundles, including a simple web application and database access.</p>
]]></content:encoded>
			<wfw:commentRss>http://lsd.luminis.nl/getting-started-with-spring-osgi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
