cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache CXF > DOSGi Discovery Demo page
Date Fri, 04 Dec 2009 16:50:00 GMT
<html>
<head>
    <base href="http://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/1519/1/11/_/styles/combined.css?spaceKey=CXF&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background-color: white" bgcolor="white">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
     <h2><a href="http://cwiki.apache.org/confluence/display/CXF/DOSGi+Discovery+Demo+page">DOSGi
Discovery Demo page</a></h2>
     <h4>Page <b>edited</b> by             <a href="http://cwiki.apache.org/confluence/display/~davidb@apache.org">David
Bosschaert</a>
    </h4>
     Update to new properties
          <div id="versionComment" class="noteMacro" style="display:none; padding: 5px;">
     Update to new properties<br />
     </div>
          <br/>
     <div class="notificationGreySide">
         <p>This page describes the demo that shows the Discovery functionality of Distributed
OSGi.</p>

<p>It assumes that you have set up your DOSGi/ZooKeeper based Discovery system as outlined
in the <a href="/confluence/display/CXF/DOSGi+Discovery" title="DOSGi Discovery">DOSGi
Discovery</a> page.</p>


<h2><a name="DOSGiDiscoveryDemopage-Demodesign"></a>Demo design</h2>

<p>This demo consists of a display controller node that writes messages on all the available
display instances. Display instances are realized as remote OSGi services, which are registered
with the ZooKeeper-based Discovery system. The discovery system informs the controller, which
is a consumer of the DisplayServices, of any available remote instances of this service.<br/>
@@@ add an image here @@@</p>

<p>As with most of the other demos, the actual implementation consists of 3 bundles.</p>
<ul>
	<li>A DisplayService interface bundle.</li>
	<li>A DisplayService implementation bundle.</li>
	<li>A DisplayService client bundle, which takes the role of the display controller.</li>
</ul>


<p>The <a href="http://svn.apache.org/repos/asf/cxf/dosgi/trunk/samples/discovery/interface/src/main/java/org/apache/cxf/dosgi/samples/discovery/DisplayService.java"
rel="nofollow">Display Service interface</a> is as follows:</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> DisplayService {
    <span class="code-object">boolean</span> displayText(<span class="code-object">String</span>
text);
    <span class="code-object">String</span> getID();
}</pre>
</div></div>

<h2><a name="DOSGiDiscoveryDemopage-TheDisplayController%28serviceconsumer%29"></a>The
Display Controller (service consumer)</h2>
<p>Let's start with the controller, which is a consumer to the the DisplayService. It's
simply using an OSGi ServiceTracker to consume all DisplayService services. It also uses a
Scheduled Executor to periodically send test messages to all registered displays. Here's the
<a href="http://svn.apache.org/repos/asf/cxf/dosgi/trunk/samples/discovery/client/src/main/java/org/apache/cxf/dosgi/samples/discovery/consumer/Activator.java"
rel="nofollow">Activator</a>:</p>
<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> ServiceTracker tracker;
    <span class="code-keyword">private</span> Map&lt;DisplayService, <span
class="code-object">String</span>&gt; displays = <span class="code-keyword">new</span>
ConcurrentHashMap&lt;DisplayService, <span class="code-object">String</span>&gt;();

    <span class="code-keyword">public</span> void start(BundleContext bc) <span
class="code-keyword">throws</span> Exception {
        tracker = <span class="code-keyword">new</span> ServiceTracker(bc, DisplayService.class.getName(),
<span class="code-keyword">null</span>) {
            <span class="code-keyword">public</span> <span class="code-object">Object</span>
addingService(ServiceReference reference) {
                <span class="code-object">Object</span> svc = <span class="code-keyword">super</span>.addingService(reference);
                <span class="code-keyword">if</span> (svc <span class="code-keyword">instanceof</span>
DisplayService) {
                    DisplayService d = (DisplayService) svc;
                    <span class="code-object">System</span>.out.println(<span
class="code-quote">"Adding display: "</span> + d.getID() + <span class="code-quote">"
("</span> + d + <span class="code-quote">")"</span>);
                    displays.put(d, d.getID());
                }
                <span class="code-keyword">return</span> svc;
            }

            <span class="code-keyword">public</span> void removedService(ServiceReference
reference, <span class="code-object">Object</span> service) {
                <span class="code-object">String</span> value = displays.remove(service);
                <span class="code-object">System</span>.out.println(<span class="code-quote">"Removed
display: "</span> + value);
                <span class="code-keyword">super</span>.removedService(reference,
service);
            }            
        };        
        tracker.open();
        <span class="code-comment">// ... scheduler stuff that sends messages to all
registered displays ommitted
</span>    }

    <span class="code-keyword">public</span> void stop(BundleContext bc) <span
class="code-keyword">throws</span> Exception {
        tracker.close();
    }
}</pre>
</div></div>
<h3><a name="DOSGiDiscoveryDemopage-No%7B%7Bremoteservices.xml%7D%7Dfile%21"></a>No
<tt>remote-services.xml</tt> file!</h3>
<p>As we are using Discovery here, there is no static remote service metadata required.
So no <tt>remote-services.xml</tt> file. Discovery will dynamically inform the
DOSGi implementation of the locations of available remote services. The DOSGi implemenation
will in turn register proxies for the remote services in the local service registry. As a
service consumer you simply depend on the service - e.g. by using a ServiceTracker as above,
or through a component framework such as Blueprint or DS. </p>

<h3><a name="DOSGiDiscoveryDemopage-Runningthecontroller"></a>Running the
controller</h3>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
-&gt; install http:<span class="code-comment">//repo1.maven.org/maven2/org/apache/cxf/dosgi/samples/cxf-dosgi-ri-samples-discovery-client/1.1/cxf-dosgi-ri-samples-discovery-client-1.1.jar
</span>-&gt; install http:<span class="code-comment">//repo1.maven.org/maven2/org/apache/cxf/dosgi/samples/cxf-dosgi-ri-samples-discovery-<span
class="code-keyword">interface</span>/1.1/cxf-dosgi-ri-samples-discovery-<span
class="code-keyword">interface</span>-1.1.jar
</span>-&gt; start 7
-&gt; start 8
-&gt; ps
START LEVEL 1
   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] [Resolved   ] [    1] OSGi R4 Compendium Bundle (4.1.0)
[   5] [Active     ] [    1] Distributed OSGi Distribution Software Single-Bundle Distribution
[   6] [Active     ] [    1] Distributed OSGi Zookeeper-Based Discovery Single-Bundle Distribution
[   7] [Active     ] [    1] Distributed OSGI Discovery Sample Client Bundle
[   8] [Active     ] [    1] Distributed OSGI Discovery Sample Interface Bundle
</pre>
</div></div>
<p>After a brief moment, you will see messages appearing on the controller side. These
are the messages sent to all registered displays. Since there are none, they won't show up
anywhere just yet.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">Sending text to displays: some text 1
Sending text to displays: some text 2
Sending text to displays: some text 3
...</pre>
</div></div>

<h2><a name="DOSGiDiscoveryDemopage-TheRemoteDisplays%28serviceimplementation%29"></a>The
Remote Displays (service implementation)</h2>
<p>Every Display in the system registers a <a href="http://svn.apache.org/repos/asf/cxf/dosgi/trunk/samples/discovery/impl/src/main/java/org/apache/cxf/dosgi/samples/discovery/impl/DisplayServiceImpl.java"
rel="nofollow">Display Service implementation</a> in the local Service Registry.
This happens in the <a href="http://svn.apache.org/repos/asf/cxf/dosgi/trunk/samples/discovery/impl/src/main/java/org/apache/cxf/dosgi/samples/discovery/impl/Activator.java"
rel="nofollow">Activator</a> of the service implementation bundle. It adds the properties
to make the service available remotely as well:
<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 reg;

    <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();
        
        <span class="code-object">String</span> host = getHostName(); <span
class="code-comment">// obtain the current host name
</span>        <span class="code-object">int</span> port = getPort();  
     <span class="code-comment">// find a free port
</span>        
        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">"org.apache.cxf.ws"</span>);
        props.put(<span class="code-quote">"org.apache.cxf.ws.address"</span>,
<span class="code-quote">"http:<span class="code-comment">//"</span> + host
+ <span class="code-quote">":"</span> + port + <span class="code-quote">"/display"</span>);
</span>
        reg = bc.registerService(DisplayService.class.getName(), 
                <span class="code-keyword">new</span> DisplayServiceImpl(host
+ <span class="code-quote">":"</span> + port), props);
    }

    <span class="code-keyword">public</span> void stop(BundleContext bc) <span
class="code-keyword">throws</span> Exception {
        reg.unregister();
    }
}</pre>
</div></div>Note that the port where the service is made available is dynamically
set to be any free port in the system. So you can safely run any number of remote Display
Services on the same machine. Because we're using Discovery here, a well-known port is not
needed. Registering the service as in the previous code snippet will make it available remotely
<em>and</em> publish it to the installed Discovery system.</p>

<p>Once the provider side bundles are started:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">-&gt; install http:<span class="code-comment">//repo1.maven.org/maven2/org/apache/cxf/dosgi/samples/cxf-dosgi-ri-samples-discovery-<span
class="code-keyword">interface</span>/1.1/cxf-dosgi-ri-samples-discovery-<span
class="code-keyword">interface</span>-1.1.jar
</span>-&gt; start 7
-&gt; install http:<span class="code-comment">//repo1.maven.org/maven2/org/apache/cxf/dosgi/samples/cxf-dosgi-ri-samples-discovery-impl/1.1/cxf-dosgi-ri-samples-discovery-impl-1.1.jar
</span>-&gt; start 8
-&gt; ps
START LEVEL 1
   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] [Resolved   ] [    1] OSGi R4 Compendium Bundle (4.1.0)
[   5] [Active     ] [    1] Distributed OSGi Distribution Software Single-Bundle Distribution
(1.1.0.SNAPSHOT)
[   6] [Active     ] [    1] Distributed OSGi Zookeeper-Based Discovery Single-Bundle Distribution
(1.1.0.SNAPSHOT)
[   7] [Active     ] [    1] Distributed OSGI Discovery Sample Interface Bundle
[   8] [Active     ] [    1] Distributed OSGI Discovery Sample Implementation Bundle
</pre>
</div></div>
<p>You will start seeing the messages appear on the remote display:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">DisplayService [myhost:1816]: some text 145
DisplayService [myhost:1816]: some text 146
... </pre>
</div></div>
<p>You can add more Display Services and they will also receive the messages. </p>
<h2><a name="DOSGiDiscoveryDemopage-UnderthehoodintheZooKeeperserver"></a>Under
the hood in the ZooKeeper server</h2>
<p>The Discovery system uses standard OSGi mechanisms to publish the metadata of the
services that are exposed remotely in a centralized server, a ZooKeeper server. On the consumer
side, the services are looked up in Discovery through standard OSGi mechanisms as well. These
mechanisms are independent of ZooKeeper, so they will work with any Distributed OSGi standards-compliant
Dicovery implementation.</p>

<p>ZooKeeper comes with a client program (<tt>zkCli</tt>) that allows you
to look in the ZooKeeper virtual filesystem. All of the OSGi-registered services are stored
in a virtual directory under the node <tt>/osgi/service_registry</tt>. The virtual
directory name is based on the fully qualified name of the interface that is implemented by
the remote service. So in the case of the DisplayService the remote service metadata is stored
under <tt>/osgi/service_registry/org/apache/cxf/dosgi/samples/discovery/DisplayService</tt>:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
$ bin/zkCli localhost:2181

-&gt; ls /osgi/service_registry/org/apache/cxf/dosgi/samples/discovery/DisplayService
Processing ls
[myhost#1816##display]
</pre>
</div></div>
<p>Every instance of a remote service that implements the org.apache.cxf.dosgi.samples.discovery.DisplayService
interface will get a virtual file in this location. The virtual file is only there for the
lifetime of the service. If you stop the service, or kill the OSGi container that hosts it,
its associated file in this directory will disappear.<br/>
You can obtain the information stored in the node, to get an idea of the metadata that's being
communicated using the Discovery system:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">-&gt; get /osgi/service_registry/org/apache/cxf/dosgi/samples/discovery/DisplayService/myhost#1816##display
Processing get
#
#Tue Jun 09 14:52:39 BST 2009
osgi.remote.endpoint.location=http\:<span class="code-comment">//myhost\:1816/display
</span>osgi.remote.interfaces=*
osgi.remote.configuration.pojo.address=http\:<span class="code-comment">//myhost\:1816/display
</span>osgi.remote.configuration.type=pojo
osgi.remote.endpoint.id=0ffe1fbf-c029-4096-bc14-3c7d77470dfd

cZxid = 511
ctime = Tue Jun 09 14:52:39 BST 2009
mZxid = 511
mtime = Tue Jun 09 14:52:39 BST 2009
pZxid = 511
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 81563124471365634
dataLength = 338
numChildren = 0
</pre>
</div></div>

<h2><a name="DOSGiDiscoveryDemopage-OtherResources"></a>Other Resources</h2>
<p>Introducing Dynamic Discovery into OSGi Distributed Applications - <a href="http://blog.akquinet.de/2009/09/23/introducing-dynamic-discovery-into-osgi-distributed-applications/"
rel="nofollow">http://blog.akquinet.de/2009/09/23/introducing-dynamic-discovery-into-osgi-distributed-applications/</a></p>
     </div>
     <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;">
            <a href="http://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
       </div>

       <a href="http://cwiki.apache.org/confluence/display/CXF/DOSGi+Discovery+Demo+page">View
Online</a>
       |
       <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=119713&revisedVersion=14&originalVersion=13">View
Change</a>
              |
       <a href="http://cwiki.apache.org/confluence/display/CXF/DOSGi+Discovery+Demo+page?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message