cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject [CONF] Apache CXF > Distributed OSGi Greeter Demo Walkthrough
Date Tue, 15 Sep 2009 12:42:02 GMT
    <base href="">
            <link rel="stylesheet" href="/confluence/s/1519/1/11/_/styles/combined.css?spaceKey=CXF&amp;forWysiwyg=true"
<body style="background-color: white" bgcolor="white">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
     <h2><a href="">Distributed
OSGi Greeter Demo Walkthrough</a></h2>
     <h4>Page <b>edited</b> by             <a href="">David
     <div class="notificationGreySide">
         <p>This is a walkthrough of the Distributed OSGi Greeter Demo. It should help
users of the Distributed OSGi get started with it. </p>

<p>The greeter demo can be found in the <a href=""
rel="nofollow">samples/greeter directory</a> of the SVN code base and implements
a simple OSGi Greeter Service and a consumer to that service with a trivial UI. <br/>
In this walkthrough all the required bundles are installed straight from the maven release
repository, so no need to check out SVN and build anything to get started with the Greeter

<p><b>NOTE</b>: this demo requires CXF/DOSGi 1.1-SNAPSHOT</p>

<h3><a name="DistributedOSGiGreeterDemoWalkthrough-TheGreeterdemodesign"></a>The
Greeter demo design</h3>
<p>The demo is composed of 3 bundles:</p>
	<li>The Greeter Interface bundle</li>
	<li>The Greeter Service Implementation bundle</li>
	<li>The Greeter Service Consumer bundle</li>

<p>The <b>Greeter Interface</b> bundle exports the <tt>GreeterService</tt>
interface which both other bundles depend on. This is the interface:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> <span
class="code-keyword">interface</span> GreeterService {
    Map&lt;GreetingPhrase, <span class="code-object">String</span>&gt;
greetMe(<span class="code-object">String</span> name);
    GreetingPhrase [] greetMe(GreeterData name) <span class="code-keyword">throws</span>
<p>The <tt>GreetingPhase</tt> and <tt>GreeterException</tt>
classes are also defined by this bundle.</p>

<p>In this walkthrough, the following setup will be used:<br/>
<img src="/confluence/download/attachments/107706/dosgi_cxf.png" align="absmiddle" border="0"
The client side bundles will be running in Equinox, invoking on a Distributed OSGi Service
running in Felix. Note that the choice of containers is completely trivial. Any OSGi container
that implements the Service Registry Hooks (a new feature in OSGi 4.2) can be used on either

<h3><a name="DistributedOSGiGreeterDemoWalkthrough-TheServerSide"></a>The
Server Side</h3>
<p>The <b>Greeter Service</b> implementation bundle provides a <a href=""
rel="nofollow">trivial implementation of the GreeterService interface</a>. Additionally,
it has an <a href=""
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java"><span class="code-keyword">public</span> class Activator
<span class="code-keyword">implements</span> BundleActivator {
    <span class="code-keyword">private</span> ServiceRegistration registration;

    <span class="code-keyword">public</span> void start(BundleContext bc) <span
class="code-keyword">throws</span> Exception {
        Dictionary props = <span class="code-keyword">new</span> Hashtable();

        props.put(<span class="code-quote">"service.exported.interfaces"</span>,
<span class="code-quote">"*"</span>);
        props.put(<span class="code-quote">"service.exported.configs"</span>,
<span class="code-quote">""</span>);
        props.put(<span class="code-quote">""</span>,
<span class="code-quote">"http:<span class="code-comment">//localhost:9090/greeter"</span>);
        registration = bc.registerService(GreeterService.class.getName(), <span class="code-keyword">new</span>
GreeterServiceImpl(), props);

    <span class="code-keyword">public</span> void stop(BundleContext bc) <span
class="code-keyword">throws</span> Exception {
</div></div>Besides creating the service instance, the activator sets the additional
properties on the service that are required to make it available remotely:</p>
	<li>The <tt>service.exported.interfaces</tt> property is set to <tt>*</tt>,
which means that all the interfaces passes to registerService should be made accessible remotely.
In this case it's just the <tt>GreeterService</tt> interface.</li>
	<li>The <tt>service.exported.configs</tt> is set to <tt></tt>,
which is a CXF specific configuration type that can be used to expose the OSGi Service as
a Web Service over SOAP/HTTP. The address of the service is specified via the <tt></tt>

<p>Let's run the server in Felix 1.8.0. As a prerequisite it requires some of the OSGi
Compendium Specification interfaces. These don't come with the Felix download, but you can
install a bundle that contains these interfaces straight from Maven.<br/>
In this walkthrough I'm using the single-bundle distribution of CXF/DOSGi which can be installed
straight from the Maven release repository.</p>

<p>To set up my Felix environment, I'm running the following commands:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">C:\felix-1.8.0&gt;java -jar bin\felix.jar

Welcome to Felix.

-&gt; ps
   ID   State         Level  Name
[   0] [Active     ] [    0] <span class="code-object">System</span> Bundle (1.8.0)
[   1] [Active     ] [    1] Apache Felix Shell Service (1.2.0)
[   2] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)
[   3] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)
-&gt; start http:<span class="code-comment">//
</span>-&gt; start https:<span class="code-comment">//</span>
<p>Some log messages may come up now.<br/>
Note that instead of manually adding these bundles to the Felix container, you can also append
the <tt>target/</tt> file to the <tt>&lt;felix-root&gt;/conf/</tt>
file. This will automatically load these two bundles when Felix starts up.</p>

<p>Now let's start up the server-side greeter bundles. Like with the DOSGi bundle itself,
I'm installing these straight from the Maven release repository.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
-&gt; start https:<span class="code-comment">//<span
</span>-&gt; start https:<span class="code-comment">//
</span>-&gt; ps
   ID   State         Level  Name
[   0] [Active     ] [    0] <span class="code-object">System</span> Bundle (1.8.0)
[   1] [Active     ] [    1] Apache Felix Shell Service (1.2.0)
[   2] [Active     ] [    1] Apache Felix Shell TUI (1.2.0)
[   3] [Active     ] [    1] Apache Felix Bundle Repository (1.4.0)
[   4] [Active     ] [    1] OSGi R4 Compendium Bundle (4.1.0)
[   5] [Active     ] [    1] Distributed OSGi Distribution Software Single-Bundle Distribution
[   8] [Active     ] [    1] CXF Distributed OSGi Greeter Demo Interface Bundle
[   9] [Active     ] [    1] CXF Distributed OSGi Greeter Demo Service Implementation Bundle

<p>Some more log messages come up. When it says <em>INFO: Remote org.apache.cxf.dosgi.samples.greeter.GreeterService
endpoint has been published into Discovery service</em> you know that the service is
exposed remotely, and you can verify this by requesting the WSDL:</p>

<p><img src="/confluence/download/attachments/107706/greeter_wsdl.jpg" align="absmiddle"
border="0" /></p>

<p>This WSDL was dynamically generated from the exposed <tt>GreeterService</tt>
Java interface. Under the hood, the Aegis data binding is used for this.</p>

<h3><a name="DistributedOSGiGreeterDemoWalkthrough-TheServiceConsumerside."></a>The
Service Consumer side.</h3>
<p>The Service Consumer Java code contains no specific Distribution-related elements.
It's simply an <tt>Activator</tt> that creates a <tt>ServiceTracker</tt>
listening for services that implement the <tt>GreeterService</tt> interface. When
the service becomes available it opens a little GUI window that asks you for an argument that
can be sent to the Greeter service. <a href=""
rel="nofollow">See here for the actual code</a></p>

<div class='panelMacro'><table class='tipMacro'><colgroup><col width='24'><col></colgroup><tr><td
valign='top'><img src="/confluence/images/icons/emoticons/check.gif" width="16" height="16"
align="absmiddle" alt="" border="0"></td><td>Note that in many cases using
an OSGi Component Framework such as Spring-DM, iPojo or OSGi DS is highly recommeded when
writing OSGi Service Consumers. OSGi Services are highly dynamic in nature. They can come
and go. Using a component framework will generally save you from writing <tt>ServiceTracker</tt>
code as the framework will generally provide the service consumer with a reference to the
service via injection.</td></tr></table></div>

<p>So the remote service is simply looked up the normal way, via the OSGi Service Registry.
<b>How does it get there?</b> The fact that a lookup on a service is done internally
triggers a <b>Service Registry Hook</b>. This will go out to any registered Distributed
OSGi Discovery implementations and query them for any matching services. <br/>
However, <b>in our setup we haven't yet registered a Discovery implementation</b>.
There is an alternative, more static way to provide discovery type information, in case this
info is not available via discovery. It can be specified in a <tt>OSGI-INF/remote-service/*.xml</tt>
file. This the content of the Greeter Service Consumer <a href=""
rel="nofollow">remote-services.xml</a> file:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">&lt;service-descriptions xmlns=<span class="code-quote">"http:<span
</span>  &lt;service-description&gt;
    &lt;provide <span class="code-keyword">interface</span>=<span class="code-quote">"org.apache.cxf.dosgi.samples.greeter.GreeterService"</span>/&gt;
    &lt;property name=<span class="code-quote">"service.exported.interfaces"</span>&gt;*&lt;/property&gt;
    &lt;property name=<span class="code-quote">"service.exported.configs"</span>&gt;;/property&gt;
    &lt;property name=<span class="code-quote">""</span>&gt;http:<span
</span>  &lt;/service-description&gt;

<p>Let's run the consumer in Equinox, so that we have the bundles running in Equinox
talking to a remoted service running in Felix!<br/>
As with Felix, we will have to load the bundle with the OSGi compendium interfaces. There's
one that ships with Equinox.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
java -jar plugins/org.eclipse.osgi_3.5.0.v20090520.jar -configuration conf -console
osgi&gt; install file:plugins/org.eclipse.osgi.services_3.2.0.v20090520-1800.jar
Bundle id is 1
osgi&gt; start 1

osgi&gt; install https:<span class="code-comment">//
</span>Bundle id is 2
osgi&gt; start 2
<p>Some logging messages may appear. You can also automatically load the DOSGi bundles
by appending the target/equinox.config.ini.append to you equinox config.ini file.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
osgi&gt; install http:<span class="code-comment">//<span
class="code-keyword">interface</span>/1.0/cxf-dosgi-ri-samples-greeter-<span class="code-keyword">interface</span>-1.0.jar
</span>Bundle id is 3
osgi&gt; install http:<span class="code-comment">//
</span>Bundle id is 4
osgi&gt; ss

Framework is launched.

id      State       Bundle
0       ACTIVE      org.eclipse.osgi_3.5.0.v20081201-1815
1       ACTIVE      org.eclipse.osgi.services_3.2.0.v20081205-1800
2       ACTIVE      cxf-dosgi-ri-singlebundle-distribution
3       INSTALLED   cxf-dosgi-ri-samples-greeter-<span class="code-keyword">interface</span>
4       INSTALLED   cxf-dosgi-ri-samples-greeter-client

osgi&gt; start 4</pre>
<p>After a few moments the following window appears:</p>

<p><img src="/confluence/download/attachments/107706/greeterui.jpg" align="absmiddle"
border="0" /></p>

<p>The window appears once the ServiceTracker in the consumer has received a callback
that the <tt>GreeterService</tt> has been found. The value entered will used to
invoke the (remote) OSGi service, with a call like this:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Map&lt;GreetingPhrase, <span class="code-object">String</span>&gt;
result = greeterService.greetMe(<span class="code-quote">"foobar"</span>);</pre>
<p>I can see that the invocation has been received by the service implementation as
in the Felix window the following appears.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">-&gt; Invoking: greetMe(foobar)</pre>
<p>In the Equinox window I can see the response:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">osgi&gt; greetMe(<span class="code-quote">"foobar"</span>)
  Hola foobar
  Bonjour foobar
  Hoi foobar
  Hello foobar</pre>
     <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;">
            <a href=""
class="grey">Change Notification Preferences</a>

       <a href="">View
       <a href="">View
       <a href=";showCommentArea=true#addcomment">Add

View raw message