Testing Hotswapping on Java with Apache Felix’ OSGi Tutorial

A Variant of Example 6: A Meta Dictionary Service

In a first attempt I wanted to figure out whether I understood all concepts properly. Thus I decided to implement a variant of example 6: I wanted to implement a meta dictionary service. This service should register the same way as the two other dictionary services did, but once being asked it should not decide on its own, but should query all other registered dictionary services. This enables the consumer of such a service not to specify the language (if he knows the language the words are in, it is anyway a better idea to use the direct dictionary service of that corresponding language), but to ask for validating a word independently of the language. Here you can review my result (here available in a condensed version; full version in the download package above):

package tutorial.example6var;
 
import java.util.Properties;
import java.util.StringTokenizer;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.util.tracker.ServiceTracker;
import tutorial.example2.service.DictionaryService;
 
/**
 *
 * @author Nico
 */
public class Activator implements BundleActivator {
    // Bundle's context.
    private BundleContext m_context = null;
    // The service tacker object.
    private ServiceTracker m_tracker = null;
 
    public void start(BundleContext context) throws Exception {
        this.m_context = context;
 
        // Create a service tracker to monitor dictionary services.
        m_tracker = new ServiceTracker(
            m_context,
            m_context.createFilter(
                "(&" +
                    "(objectClass=" + DictionaryService.class.getName() + ")" +
                    "(Language=*)" +
                    "(!(Language=Meta))" +
                 ")"),
            null);
        m_tracker.open();
 
        Properties props = new Properties();
        props.put("Language", "Meta");
 
        m_context.registerService(DictionaryService.class.getName(), new MetaSpellChecker(), props);
 
    }
 
    /**
     * Implements BundleActivator.stop(). Does nothing since
     * the framework will automatically unget any used services.
     * @param context the framework context for the bundle.
    **/
    public void stop(BundleContext context)
    {
    }
 
    public class MetaSpellChecker implements tutorial.example2.service.DictionaryService {
        // now could also be multiples
        public boolean checkWord(String word) {
 
            // No misspelled words for an empty string.
            if ((word == null) || (word.length() == 0)) {
                return true;
            }
 
            // Tokenize the passage using spaces and punctionation.
            StringTokenizer st = new StringTokenizer(word, " ,.!?;:");
 
            // get the list of all available spell checker services
            Object[] spellchecker_objects = m_tracker.getServices();
 
            if ( (spellchecker_objects == null) || (spellchecker_objects.length == 0) )
                return false;
 
            while (st.hasMoreTokens()) {
                String singleWord = st.nextToken();
 
                boolean found = false;
                for (Object o : spellchecker_objects) {
 
                    if (o == null)
                        continue;
 
                    DictionaryService ds = (DictionaryService) o;
                    if (ds.checkWord(singleWord))  {
                        found = true;
                        break;
                    }
                }
 
                if (!found)
                    return false;
            }
 
            return true;
        }
 
    }
}

As you can see this component uses both registration of a service interface and the tracker functionality to consume other services. Thus, I would call it a hybrid component: on the one hand it acts as a server while dispatching (other) requests to further components acting there in client mode. It is both consumer and provider at the same time.
Please also note a very tiny trick which costed me one hour to debug a StackOverflow exception: Line 31 of the coding starts the filter of the tracker by explicitly excluding the meta service from the selection. This is necessary because otherwise the tracker would find the meta service itself as well and – as in most cases the meta service is being registered last – puts it in the first position of the Service array at line 65. This then causes an endless recursive loop of method checkWord(String) because of line 81.

VN:F [1.9.22_1171]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.22_1171]
Rating: 0 (from 0 votes)

7 Comments

  1. Yet another good post. I put in a plug for this blog at mine. Anyway, I am sure most people forget the point you are making.

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  2. Great information. Keep up the great work. […]

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  3. Thanks much for this method excellent article content; this is the kind of step that continues me though out the day.I’ve already been searching around for one’s webpage just after I learned about these from a good friend and was pleased when I was able to find it just after searching for a while. Being a devoted blogger, I’m thrilled to view other people taking effort and adding towards the neighborhood. I just wished to review to show my thanks for your personal post as it is especially inviting, and many copy writers do not get the credit score they deserve. I am certain I’ll be back and will send a few of my mates.

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)
  4. Thanks for sharing your thoughts on hotswap. Regards

    VA:F [1.9.22_1171]
    Rating: 0 (from 0 votes)

Leave a Reply

Your email address will not be published. Required fields are marked *

*