Creation d'un client pour le service dictionnaire
Nous allons créer un client interactif pour tester le
service
dictionnaire. Ce client ne se servira du service dictionnaire que si il
le trouve lors de son démarrage.
/* * OSGi and Gravity Service Binder tutorial. * Copyright (c) 2003 Richard S. Hall * http://oscar-osgi.sourceforge.net **/
package tutorial.example3;
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException;
import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference;
import tutorial.example2.service.DictionaryService;
/** * This class implements a bundle that uses a dictionary * service to check for the proper spelling of a word by * check for its existence in the dictionary. This bundle * uses the first service that it finds and does not monitor * the dynamic availability of the service (i.e., it does not * listen for the arrival or departure of dictionary services). * When starting this bundle, the thread calling the start() * method is used to read words from standard input. You can * stop checking words by entering an empty line, but to start * checking words again you must stop and then restart the bundle. **/ public class Activator implements BundleActivator { /** * Implements BundleActivator.start(). Queries for * all available dictionary services. If none are found it * simply prints a message and returns, otherwise it reads * words from standard input and checks for their existence * from the first dictionary that it finds. * (NOTE: It is very bad practice to use the calling thread * to perform a lengthy process like this; this is only done * for the purpose of the tutorial.) * @param context the framework context for the bundle. **/ public void start(BundleContext context) throws Exception { // Query for all service references matching any language. ServiceReference[] refs = context.getServiceReferences( DictionaryService.class.getName(), "(Language=*)");
if (refs != null) { try { System.out.println("Enter a blank line to exit."); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String word = "";
// Loop endlessly. while (true) { // Ask the user to enter a word. System.out.print("Enter word: "); word = in.readLine();
// If the user entered a blank line, then // exit the loop. if (word.length() == 0) { break; }
// First, get a dictionary service and then check // if the word is correct. DictionaryService dictionary = (DictionaryService) context.getService(refs[0]); if (dictionary.checkWord(word)) { System.out.println("Correct."); } else { System.out.println("Incorrect."); }
// Unget the dictionary service. context.ungetService(refs[0]); } } catch (IOException ex) { } } else { System.out.println("Couldn't find any dictionary service..."); } }
/** * 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) { // NOTE: The service is automatically released. } }
Noter que le code fait référence au package du
service
dictionnaire défini dans l'exemple antérieur. Voici le
manifeste pour le client:
Bundle-Activator: tutorial.example3.Activator Import-Package: tutorial.example2.service Import-Service: tutorial.example2.service.DictionaryService Bundle-Name: Dictionary client Bundle-Description: A bundle that uses the dictionary service if it finds it at startup Bundle-Vendor: Richard Hall Bundle-Version: 1.0.0
Voici aussi le fichier build_example3.xml
pour ant. Lancer la cible example3.bundle, si tout se passe bien, nous
devons retrouver le fichier example3.jar sous le répertoire
bundle que nous pouvons installer dans le framework.
->
install file:/chemin_du_projet/bundle/example3.jar
-> ps
[
0] [Active ] System Bundle
[
1] [Active ] Oscar Shell Service
[
2] [Active ] Shell TUI
[
3] [Active ] Oscar Bundle Repository
[
4] [Active ] Service listener example
[
5] [Active ] English Dictionary
[
6] [Installed ] French Dictionary
[
7] [Installed ] Dictionary Client
->
start 7
Enter
a blank line to exit.
Enter
word: wellcome
Incorrect.
Enter
word: welcome
Correct.
Enter
word:
->
|
Question: Que se
passe-t'il si le dictionnaire n'est pas actif lorsqu'on active le
client ?
A Faire: Modifier le
client pour qu'il soit à l'écoute des
évènements du framework. Pour cela il faut implementer
l'interface ServiceListener et s'enregistrer auprès du framework
lors du démarrage. La propriété objectClass est
ajoutée par défault par le framework chaque fois qu'un
service est enregistré:
// Listen for events pertaining to dictionary services. m_context.addServiceListener(this,"(&(objectClass=" + DictionaryService.class.getName() + ")" + "(Language=*))");
Il faut ensuite implementer l'interface ServiceListener
qui n'a qu'une méthode: serviceChanged()
/** * Implements ServiceListener.serviceChanged(). Checks * to see if the service we are using is leaving or tries to get * a service if we need one. * @param event the fired service event. **/ public void serviceChanged(ServiceEvent event) { // If a dictionary service was registered, see if we // need one. If so, get a reference to it. if (event.getType() == ServiceEvent.REGISTERED) { // COMPLETER } // If a dictionary service was unregistered, see if it // was the one we were using. If so, unget the service // and try to query to get another one. else if (event.getType() == ServiceEvent.UNREGISTERING) { if (event.getServiceReference() == m_ref) { // COMPLETER } } }
Pour tester si notre client marche, il faut prévoir le
cas ou le
service disparait au milieu de l'exécution du client. Pour faire
que le service disparaisse, il faut arreter le bundle qui fournit le
service le dictionnaire lors de l'execution, mais le client ne nous le
permet pas car il monopolise l'entrée de texte. Pour
résoudre ce problème nous allons utiliser une console
graphique qui nous permettra de faire ceci en même temps. La
console graphique fait partie d'une collection de bundles accessibles
depuis oscar à travers la comande obr (taper obr -help pour plus
de détail).
ATTENTION:
si les bundles correspondant a Shell Component et a Shell GUI ne sont
pas installés par OBR, il faut les installer à partir du
répertoire /bundle de
OSGi, les bundles correspondants sont appelés shellcomponent.jar
et shellgui.jar.
->
obr Shell Component
Installing
dependency Service Binder...
Installing
dependency Table Layout...
Installing
dependency Gravity...
Installing
Shell Component...
->
obr Shell GUI
Installing
Shell GUI...
-> start 12
-> start 7
Enter
a blank line to exit.
Enter
word: wellcome
Incorrect.
Enter
word: welcome
Correct.
Enter
word:
|
Lors du démarrage du Shell GUI, nous aurons une
interface graphique qui nous permettra de faire l'équivalent de
la console.
Le client doit être capable de gérer le
départ des
services dont il dépend à tout moment. Tester si ca
marche...
Voici la solution (Activator.java),
son manifest.mf et le fichier build_example4.xml, tester avec
celle ci. Verifier qu'elle supporte les changements au niveau des
services.
|