felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Felix > Apache Felix Tutorial Example 2
Date Sun, 04 Dec 2011 08:17:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/1/_/styles/combined.css?spaceKey=FELIX&amp;forWysiwyg=true"
type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/FELIX/Apache+Felix+Tutorial+Example+2">Apache
Felix Tutorial Example 2</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~heavy@ungoverned.org">Richard
S. Hall</a>
    </h4>
        <br/>
                         <h4>Changes (3)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >package tutorial.example2; <br>
<br></td></tr>
            <tr><td class="diff-changed-lines" >import <span class="diff-deleted-words"style="color:#999;background-color:#fdd;text-decoration:line-through;">java.util.Properties;</span>
<span class="diff-added-words"style="background-color: #dfd;">java.util.Hashtable;</span>
<br></td></tr>
            <tr><td class="diff-unchanged" > <br>import org.osgi.framework.BundleActivator;
<br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >    public void start(BundleContext
context) <br>    { <br></td></tr>
            <tr><td class="diff-deleted-lines" style="color:#999;background-color:#fdd;text-decoration:line-through;">
       Properties props = new Properties(); <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">
       Hashtable&lt;String, String&gt; props = new Hashtable&lt;String, String&gt;();
<br></td></tr>
            <tr><td class="diff-unchanged" >        props.put(&quot;Language&quot;,
&quot;English&quot;); <br>        context.registerService( <br></td></tr>
            <tr><td class="diff-snipped" >...<br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="ApacheFelixTutorialExample2-Example2DictionaryServiceBundle"></a>Example
2 - Dictionary Service Bundle</h2>

<p>This example creates a bundle that implements an OSGi service. Implementing an OSGi
service is a two-step process, first we must define the interface of the service and then
we must define an implementation of the service interface. In this particular example, we
will create a dictionary service that we can use to check if a word exists, which indicates
if the word is spelled correctly or not. First, we will start by defining a simple dictionary
service interface in a file called <tt>DictionaryService.java</tt>:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
/*
 * Apache Felix OSGi tutorial.
**/

<span class="code-keyword">package</span> tutorial.example2.service;

/**
 * A simple service <span class="code-keyword">interface</span> that defines a
dictionary service.
 * A dictionary service simply verifies the existence of a word.
**/
<span class="code-keyword">public</span> <span class="code-keyword">interface</span>
DictionaryService
{
    /**
     * Check <span class="code-keyword">for</span> the existence of a word.
     * @param word the word to be checked.
     * @<span class="code-keyword">return</span> <span class="code-keyword">true</span>
<span class="code-keyword">if</span> the word is in the dictionary,
     *         <span class="code-keyword">false</span> otherwise.
    **/
    <span class="code-keyword">public</span> <span class="code-object">boolean</span>
checkWord(<span class="code-object">String</span> word);
}
</pre>
</div></div>

<p>The service interface is quite simple, with only one method that needs to be implemented.
Notice that we put the service interface in the package <tt>tutorial.example2.service</tt>,
instead of just putting it in <tt>tutorial.example2</tt>. We did this because
we need to share the interface definition with other bundles, therefore it is better to separate
service interfaces that need to be shared from code that does not need to be shared. Such
an approach ensures a strong separation between interface and implementation.</p>

<p>In the following source code, the bundle uses its bundle context to register the
dictionary service. We implement the dictionary service as an inner class of the bundle activator
class, but we could have also put it in a separate file. The source code for our bundle is
as follows in a file called <tt>Activator.java</tt>:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
/*
 * Apache Felix OSGi tutorial.
**/

<span class="code-keyword">package</span> tutorial.example2;

<span class="code-keyword">import</span> java.util.Hashtable;

<span class="code-keyword">import</span> org.osgi.framework.BundleActivator;
<span class="code-keyword">import</span> org.osgi.framework.BundleContext;
<span class="code-keyword">import</span> org.osgi.framework.ServiceListener;
<span class="code-keyword">import</span> org.osgi.framework.ServiceEvent;

<span class="code-keyword">import</span> tutorial.example2.service.DictionaryService;

/**
 * This class <span class="code-keyword">implements</span> a simple bundle that
uses the bundle
 * context to register an English language dictionary service
 * with the OSGi framework. The dictionary service <span class="code-keyword">interface</span>
is
 * defined in a separate class file and is implemented by an
 * <span class="code-keyword">inner</span> class.
**/
<span class="code-keyword">public</span> class Activator <span class="code-keyword">implements</span>
BundleActivator
{
    /**
     * Implements BundleActivator.start(). Registers an
     * instance of a dictionary service using the bundle context;
     * attaches properties to the service that can be queried
     * when performing a service look-up.
     * @param context the framework context <span class="code-keyword">for</span>
the bundle.
    **/
    <span class="code-keyword">public</span> void start(BundleContext context)
    {
        Hashtable&lt;<span class="code-object">String</span>, <span class="code-object">String</span>&gt;
props = <span class="code-keyword">new</span> Hashtable&lt;<span class="code-object">String</span>,
<span class="code-object">String</span>&gt;();
        props.put(<span class="code-quote">"Language"</span>, <span class="code-quote">"English"</span>);
        context.registerService(
            DictionaryService.class.getName(), <span class="code-keyword">new</span>
DictionaryImpl(), props);
    }

    /**
     * Implements BundleActivator.stop(). Does nothing since
     * the framework will automatically unregister any registered services.
     * @param context the framework context <span class="code-keyword">for</span>
the bundle.
    **/
    <span class="code-keyword">public</span> void stop(BundleContext context)
    {
        <span class="code-comment">// NOTE: The service is automatically unregistered.
</span>    }

    /**
     * A <span class="code-keyword">private</span> <span class="code-keyword">inner</span>
class that <span class="code-keyword">implements</span> a dictionary service;
     * see DictionaryService <span class="code-keyword">for</span> details of
the service.
    **/
    <span class="code-keyword">private</span> <span class="code-keyword">static</span>
class DictionaryImpl <span class="code-keyword">implements</span> DictionaryService
    {
        <span class="code-comment">// The set of words contained in the dictionary.
</span>        <span class="code-object">String</span>[] m_dictionary =
            { <span class="code-quote">"welcome"</span>, <span class="code-quote">"to"</span>,
<span class="code-quote">"the"</span>, <span class="code-quote">"osgi"</span>,
<span class="code-quote">"tutorial"</span> };

        /**
         * Implements DictionaryService.checkWord(). Determines
         * <span class="code-keyword">if</span> the passed in word is contained
in the dictionary.
         * @param word the word to be checked.
         * @<span class="code-keyword">return</span> <span class="code-keyword">true</span>
<span class="code-keyword">if</span> the word is in the dictionary,
         *         <span class="code-keyword">false</span> otherwise.
        **/
        <span class="code-keyword">public</span> <span class="code-object">boolean</span>
checkWord(<span class="code-object">String</span> word)
        {
            word = word.toLowerCase();

            <span class="code-comment">// This is very inefficient
</span>            <span class="code-keyword">for</span> (<span class="code-object">int</span>
i = 0; i &lt; m_dictionary.length; i++)
            {
                <span class="code-keyword">if</span> (m_dictionary[i].equals(word))
                {
                    <span class="code-keyword">return</span> <span class="code-keyword">true</span>;
                }
            }
            <span class="code-keyword">return</span> <span class="code-keyword">false</span>;
        }
    }
}
</pre>
</div></div>

<p>Note that we do not need to unregister the service in the <tt>stop()</tt>
method, because the OSGi framework will automatically do so for us. The dictionary service
that we have implemented is very simple; its dictionary is a static array of only five words,
so this solution is not optimal and is only intended for educational purposes. We must create
a <tt>manifest.mf</tt> file that contains the meta-data for our bundle; the manifest
file contains the following:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>Bundle-Name: English dictionary
Bundle-Description: A bundle that registers an English dictionary service
Bundle-Vendor: Apache Felix
Bundle-Version: 1.0.0
Bundle-Activator: tutorial.example2.Activator
Export-Package: tutorial.example2.service
Import-Package: org.osgi.framework
</pre>
</div></div>

<p>We specify which class is used to activate our bundle via the <tt>Bundle-Activator</tt>
attribute and also specify that our bundle exports a shared package using the <tt>Export-Package</tt>
attribute. The <tt>Export-Package</tt> attribute makes it possible for other bundles
to import our dictionary service interface. The <tt>Import-Package</tt> attribute
informs the framework of the bundle's dependencies on external packages; all bundles with
an activator must import <tt>org.osgi.framework</tt> since it contains the core
OSGi class definitions. Any packages dependencies will be verified and resolved by the OSGi
framework. (Note: Make sure your manifest file ends in a trailing carriage return or else
the last line will be ignored.)</p>

<p>To compile our source code, we need the <tt>felix.jar</tt> file (found
in Felix' <tt>bin</tt> directory) in our class path. We compile the source file
using a command like:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>javac -d c:\classes *.java
</pre>
</div></div>

<p>This command compiles all source files and outputs the generated classes into a subdirectory
of the <tt>c:\classes</tt> directory; this subdirectory is <tt>tutorial\example2</tt>,
named after the package we specified in the source file. For the above command to work, the
<tt>c:\classes</tt> directory must exist. After compiling, we need to create a
JAR file containing the generated package directories. We will also add our manifest file
that contains the bundle's meta-data to the JAR file. To create the JAR file, we issue the
command:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>jar cfm example2.jar manifest.mf -C c:\classes tutorial\example2
</pre>
</div></div>

<p>This command creates a JAR file using the manifest file we created and includes all
of the classes in the <tt>tutorial\example2</tt> directory inside of the c:\classes
directory. Once the JAR file is created, we are ready to install and start the bundle.</p>

<p>To run Felix, we follow the instructions described in usage.html. When we start Felix,
it asks for a profile name, we will put all of our bundles in a profile named <tt>tutorial</tt>.
After running Felix, we should make sure that the bundle from Example 1 is active. We can
use the Felix <tt>lb</tt> shell command to get a list of all bundles, their state,
and their bundle identifier number. If the Example 1 bundle is not active, we should start
the bundle using the <tt>start</tt> command and the bundle's identifier number
that is displayed by the <tt>lb</tt> command. Now we can install and start our
dictionary service bundle. Assuming that we created our bundle in the directory c:\tutorial,
we can install and start it in Felix' shell using the following command:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>start file:/c:/tutorial/example2.jar
</pre>
</div></div>

<p>The above command installs and starts the bundle in a single step; it is also possible
to install and start the bundle in two steps by using the Felix <tt>install</tt>
and <tt>start</tt> shell commands. To stop the bundle, use the Felix <tt>stop</tt>
shell command. If the bundle from Example 1 is still active, then we should see it print out
the details of the service event it receives when our new bundle registers its dictionary
service. Using the Felix shell <tt>lb</tt> command to get the bundle identifier
number for our dictionary service bundle and we can stop and restart it at will using the
<tt>stop</tt> and <tt>start</tt> commands, respectively. Each time
we start and stop our dictionary service bundle, we should see the details of the associated
service event printed from the bundle from Example 1. In Example 3, we will create a client
for our dictionary service. To exit Felix, we use the <tt>shutdown</tt> command.</p>
    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action"
class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/FELIX/Apache+Felix+Tutorial+Example+2">View
Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=59682&revisedVersion=8&originalVersion=7">View
Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/FELIX/Apache+Felix+Tutorial+Example+2?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message