felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Chetan Mehrotra (Confluence)" <conflue...@apache.org>
Subject [CONF] Apache Felix > Apache Felix Tutorial Example 10
Date Sun, 17 Nov 2013 13:59:01 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/en/2176/1/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+10">Apache
Felix Tutorial Example 10</a></h2>
    <h4>Page  <b>added</b> by             <a href="https://cwiki.apache.org/confluence/display/~chetanm">Chetan
Mehrotra</a>
    </h4>
         <br/>
    <div class="notificationGreySide">
         <h1><a name="ApacheFelixTutorialExample10-Example10SpellCheckerServiceusingDeclarativeServices"></a>Example
10 - Spell Checker Service using Declarative Services</h1>

<p>The purpose of this example is to re-implement the spell checker service in Example
6, but to do so using Declarative Services; to complete this, we must download the SCR bundle.
The SCR bundle is needed to enable the functionality offered by Declarative Services at run
time. Readers are also suggested have a look at <a href="http://wiki.osgi.org/wiki/Declarative_Services"
class="external-link" rel="nofollow">OSGi Wiki</a> on Declarative Services</p>

<p>The spell checker service of Example 6 was complex because it needed to aggregate
all available dictionary services and monitor their dynamic availability. In addition, the
spell checker service's own availability was dependent upon the availability of dictionary
services; in other words, the spell checker service had a dynamic, one-to-many dependency
on dictionary services. As it turns out, service dependencies are not managed at all by the
OSGi framework and end up being the responsibility of the application developer. Declarative
Services allow to eliminate complex and error-prone service dependency handling by automating
it. To do this, we provide an XML file that declare the exposed and consumed services. Instead
of writing a lot of complex code, we simply write a declarative XML file. For an example,
consider the following code for the new service implementation called <tt>SpellCheckerImpl.java</tt>:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="theme: Default; brush: java; gutter: false" style="font-size:12px; font-family:
ConfluenceInstalledFont,monospace;">
package tutorial.example10;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import tutorial.example2.service.DictionaryService;
import tutorial.example6.service.SpellChecker;

/**
 * A class that implements a spell checker service; see
 * SpellChecker for details of the service.
 * &lt;p&gt;
 * The dependent services are injected through the
 * Declarative Services mechanism.
 **/
public class SpellCheckerImpl implements SpellChecker {

    private Collection dictionaries = new java.util.ArrayList();

    public void addDictionary(DictionaryService dict) {
        synchronized(this) {
            this.dictionaries.add(dict);
        }
    }

    public void removeDictionary(DictionaryService dict) {
        synchronized(this) {
            this.dictionaries.remove(dict);
        }
    }

    /**
     * Implements SpellChecker.check(). Checks the given passage for
     * misspelled words.
     *
     * @param passage
     *            the passage to spell check.
     * @return An array of misspelled words or null if no words are
     *         misspelled.
     **/
    public String[] check(String passage) {
        // No misspelled words for an empty string.
        if ((passage == null) || (passage.length() == 0)) {
            return null;
        }

        List errorList = new java.util.ArrayList();

        // Tokenize the passage using spaces and punctionation.
        StringTokenizer st = new StringTokenizer(passage, " ,.!?;:");

        // Lock the service list.
        synchronized (this) {
            // Loop through each word in the passage.
            while (st.hasMoreTokens()) {
                String word = st.nextToken();

                boolean correct = false;

                // Check each available dictionary for the current word.
                Iterator iter = this.dictionaries.iterator();
                while (iter.hasNext()) {
                    DictionaryService dictionary = (DictionaryService)iter.next();
                    if (dictionary.checkWord(word)) {
                        correct = true;
                        break;
                    }
                }

                // If the word is not correct, then add it
                // to the incorrect word list.
                if (!correct) {
                    errorList.add(word);
                }
            }
        }

        // Return null if no words are incorrect.
        if (errorList.size() == 0) {
            return null;
        }

        // Return the array of incorrect words.
        return (String[])errorList.toArray(new String[errorList.size()]);
    }
}
</pre>
</div></div>

<p>Notice how much simpler this service implementation is when compared to the same
service implemented in Example 6. There are no references to OSGi interfaces in our application
code and all tricky and complex code dealing with monitoring of services is handled for us.
We don't even need an Activator anymore although we can still provide one. We must still create
a <tt>manifest.mf</tt> file that contains the meta-data for the bundle; the manifest
file is as follows:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Spell checker service (DS)
Bundle-Description: A bundle that implements a simple spell checker service and uses declarative
services
Bundle-Vendor: The Apache Software Foundation
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework,
 org.osgi.service.component,
 osgi.tutorial.example2.service,
 osgi.tutorial.example6.service
Service-Component: OSGI-INF/spellchecker.xml
</pre>
</div></div>

<p>Notice that we import the <tt>org.osgi.service.component</tt> package.
You'll also notice that there's no <tt>Bundle-Activator</tt> attribute because
we don't need it in this example. At the bottom, we have the <tt>Service-Component</tt>
entry where we specify the XML file we were talking about above. (Note: Make sure your manifest
file ends in a trailing carriage return or else the last line will be ignored.) Of course,
we also have to supply that XML file.</p>

<p>Create a new directory called <tt>OSGI-INF</tt> in the root of the project
(next to <tt>META-INF</tt>). In the <tt>OSGI-INF</tt> directory place
the following XML file we've named <tt>spellchecker.xml</tt>:</p>

<div class="preformatted panel" style="border-width: 1px;"><div class="preformattedContent
panelContent">
<pre>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;component name="tutorial.example10.spellchecker" immediate="true"&gt;
    &lt;implementation class="tutorial.example10.SpellCheckerImpl"/&gt;
    &lt;service&gt;
        &lt;provide interface="tutorial.example6.service.SpellChecker"/&gt;
    &lt;/service&gt;
    &lt;reference name="DICTIONARY"
        interface="tutorial.example2.service.DictionaryService"
        bind="addDictionary"
        unbind="removeDictionary"
        cardinality="1..n"
        policy="dynamic"/&gt;
&lt;/component&gt;
</pre>
</div></div>

<p>The XML basically tells the SCR bundle that the <tt>SpellChecker</tt>
service is implemented by the <tt>SpellCheckerImpl</tt> class and that we need
1..n <tt>DictionaryService</tt> instances. You'll guess that the <tt>bind</tt>
and <tt>unbind</tt> specify the method names that will be used by the SCR bundle
to inject (and remove) the dependent services.</p>

<p>We'll skip all the details for compiling the new example as it's basically the same
as for the previous examples. One particularity, though, is the <tt>OSGI-INF</tt>
directory. You have to make sure it is included in the bundle.</p>

<p>To run this example, you may have to temporarily disable the <tt>Bundle-Activator</tt>
for example 6 which contains the service interface and a service implementation. Otherwise,
the OSGi container may use the service implementation of example 6 while you actually wanted
to see the new implementation here in action.</p>

<p>Furthermore, you may have to restart the client before it can acquire the spell checker
service, as the code<br/>
for the client is part of the bundle activator which interferes with service startup.</p>

    </div>
    <div id="commentsSection" class="wiki-content pageSection">
       <div style="float: right;" class="grey">
                        <a href="https://cwiki.apache.org/confluence/users/removespacenotification.action?spaceKey=FELIX">Stop
watching space</a>
            <span style="padding: 0px 5px;">|</span>
                <a href="https://cwiki.apache.org/confluence/users/editmyemailsettings.action">Change
email notification preferences</a>
</div>
       <a href="https://cwiki.apache.org/confluence/display/FELIX/Apache+Felix+Tutorial+Example+10">View
Online</a>
              |
       <a href="https://cwiki.apache.org/confluence/display/FELIX/Apache+Felix+Tutorial+Example+10?showComments=true&amp;showCommentArea=true#addcomment">Add
Comment</a>
           </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message