- Szerezzük be a CoolRMI legfrissebb verzióját.
- Indítsuk el az OSGi konténert.
- Installáljuk majd indítsuk el a CoolRMI-t az OSGi konténerben.
Valami ilyesmit kell látnunk:
osgi> ss Framework is launched. id State Bundle 0 ACTIVE org.eclipse.osgi_3.6.0.v20100517 2 ACTIVE com.rizsi.coolrmi_1.1.0
- Hozzunk létre egy "Plug-in Project"-et az Eclipsben CoolRMI néven, majd a letöltött jar-ból a MANIFEST.MF-et és a forrás-fájlokat másoljuk a projektbe, végül pedig frissítsük a projektet. (nekem a MANIFEST.MF állományba az alábbi sort fel kellett venni: Import-Package: org.osgi.framework;version="1.3.0")
- Nyissuk meg az előzőekben service néven futó projektünket, és a MANIFEST.MF állomány Import-Package szekcióját bővítsük a CoolRMI exportjaival.
- Szerver oldalon a a szolgáltatás regisztrációjában van némi különbség. Jelen esetben nem az OSGi konténerbe kell regisztrálnunk a szolgáltatást, hanem a CoolRMI kontextusába, ezért az Activator.start metódusunkat az alábbira kell alakítani:
InetSocketAddress addr = new InetSocketAddress(9001); CoolRMIServer server = new CoolRMIServer(Activator.class.getClassLoader(), addr, true); //Register a service on the id: "service" //This id an be used client side to find the service on this server. server.getServiceRegistry().addService(new CoolRMIService("service", SimpleService.class, new SimpleServiceImpl())); server.start(); System.out.println("CoolRMI Service started.");
- Fordítsuk és telepítsük a szolgáltatást.
- Hozzunk létre egy "Java Project"-et, és importáljuk be az imént letöltött jar-t.
- Tegyük elérhetővé a service.SimpleService interfészt, hogy a kliens programunk tudja milyen metódusokat tud meghívni.
- A kliens osztály kódja az alábbi:
import java.net.InetSocketAddress; import service.SimpleService; import com.rizsi.coolrmi.CoolRMIClient; import com.rizsi.coolrmi.ICoolRMIProxy; public class Caller { public static void main(String[] args) throws Exception { // Create a client that connects to the server on the specified address. CoolRMIClient client = new CoolRMIClient( Caller.class.getClassLoader(), new InetSocketAddress("localhost", 9001), true); try { // Get a proxy for the remote service object // To access the remote object the remote interface // and the service Id must be known ICoolRMIProxy remoteService = client.getService(SimpleService.class, "service"); try { SimpleService service = (SimpleService) remoteService; service.echo("CoolRMI calling."); } finally { remoteService.disposeProxy(); } } finally { client.close(); } } }
- Futtassuk a klienset, és ellenőrizzük a kimenetet az OSGi konzolon.
osgi> CoolRMI calling.
2010. július 30., péntek
OSGi távoli kapcsolódás CoolRMI segítségével
Az előző bejegyzésben láthattuk miként készíthetünk OSGi keret-rendszer alá szolgáltatást, és hogyan kapcsolódhatunk ehhez a szolgáltatáshoz a keret-rendszeren belül. A mostani írás célja, hogy segédletet nyújtson távoli kapcsolat kialakítására, hiszen elengedhetetlen, hogy az OSGi konténeren kívül eső kód is használni tudja a szolgáltatásokat. Választásom a CoolRMI nevű eszközre esett, egyrészt mert magyar fejlesztés, és nyílt-forráskóddal lett publikálva, másrészt mert a környezetem ezt használja, és kipróbált alkalmazás-komponensnek minősült. A CoolRMI két részből tevődik össze. Az egyik fele az OSGi konténerben fut mint szolgáltatás, és várja a beérkező kéréseket, a másik fele pedig az alkalmazásunkban a kapcsolódásért felel.
2010. július 10., szombat
OSGi szárnypróbálgatás
Bár biztosan sokan ismeritek, de legalább hallottatok az Open Services Gateway Initiative-ról, ismertebb nevén az OSGi-ről, gondoltam én is kísérletet teszek rendszer a bemutatására. A témában kutakodva azonban találtam egy rövid írást Paller Gábor kollégától, melyben olyan érthetően megfogalmazza a technológia lényegét, hogy bizton állíthatom nekem sem sikerülne jobban, ezért meg sem próbálom. Az elméleti alapok elsajátítása után a gyakorlati megvalósításra szeretném helyezni a hangsúlyt.
OSGi pluginek fejlesztésére Eclipse IDE-t választottam, mely amellett, hogy ismeri a MANIFES.MF állomány függőségeit kezelni, rendelkezik beépített OSGi konténerrel (Equinox) is. Szerencsére a hazai bloggerek már több ízben is feszegették a témát, ennek köszönhetően pl. a jTechnics hasábjain olvashatunk a különféle konténer-implementációkról.
Megvalósítandó feladatként készítsünk egy bundlet, amely kiajánl egy szolgáltatást, amit egy másik bundeből meghívunk.
OSGi pluginek fejlesztésére Eclipse IDE-t választottam, mely amellett, hogy ismeri a MANIFES.MF állomány függőségeit kezelni, rendelkezik beépített OSGi konténerrel (Equinox) is. Szerencsére a hazai bloggerek már több ízben is feszegették a témát, ennek köszönhetően pl. a jTechnics hasábjain olvashatunk a különféle konténer-implementációkról.
Megvalósítandó feladatként készítsünk egy bundlet, amely kiajánl egy szolgáltatást, amit egy másik bundeből meghívunk.
A szerviz:
- Első lépésként hozzunk létre az Eclipsben egy "Plug-in Project"-et service néven, és az "on OSGi framework" opciónál állítsuk be az Equinox-ot.
- Hozzuk létre a service.SimpleService interfészt:
package service; public interface SimpleService { public void echo(Object message); }
- Majd hozzuk létre service.SimpleServiceImpl néven az szolgáltatás implementációját:
package service; public class SimpleServiceImpl implements SimpleService { @Override public void echo(Object message) { System.out.println(message); } }
- Szerkesszük a service.Activator osztályt a következőre:
package service; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.util.tracker.ServiceTracker; public class Activator implements BundleActivator { @Override public void start(BundleContext context) throws Exception { context.registerService(SimpleService.class.getName(), new SimpleServiceImpl(), new java.util.Hashtable()); //Check service ServiceTracker serviceTracker = new ServiceTracker(context, SimpleService.class.getName(), null); serviceTracker.open(); SimpleService simpleLogService = (SimpleService) serviceTracker.getService(); if(simpleLogService != null) System.out.println("Service started."); else System.out.println("Service init failed!"); serviceTracker.close(); } @Override public void stop(BundleContext context) throws Exception { System.out.println("Service stopped."); } }
- A META-INF/MANIFEST.MF állomány szerkesztésével készíthetjük fel bundlet a konténerrel való együttműködésre. Eclipsben az Import-Package szerkesztésével tudjuk a "Plug-in Dependencies"-eket szerkeszteni, az IDE automatikusan importálja az itt megadott csomagokat. Fontos továbbá, hogy az Export-Packagenél kiajánljuk a service csomagot, mert ellenkező esetben a kliens oldalon "class SimpleServiceImpl cannot be cast to class SimpleService" exceptiont fogunk kapni.
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Service Bundle-SymbolicName: service Bundle-Version: 1.0.0 Bundle-Activator: service.Activator Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Import-Package: org.osgi.framework;version="1.3.0",org.osgi.util.tracker;version="1.3.1" Export-Package: service;version="1.0.0"
- A MANIFEST.MF állomány->jobbklikk->Run As->Run Configuration ablakban tudjuk beállítani a konténert a teszteléshez.
- Fordításhoz vagy írunk saját ant/maven scriptet, vagy Exportáljuk a bundlet JAR formájában. Szeretném megjegyezni, hogy az Eclipse alapértelmezetten generálja a MANIFEST.MF állományt a jar-ba, viszont ebben az esetben a konténer nem fog tudni mit kezdeni a bundleval, ezért a "Use existing manifest from workspace" opció alatt (utolsó lépés) adjuk meg a megfelelő állományt.
A kliens:
- Ismét egy hasonlóan paraméterezett "Plug-in Projct"-re lesz szükségünk, de ezúttal caller néven.
- A caller.Activate osztályt hozzuk az alábbi formára:
package caller; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import service.SimpleService; public class Activator implements BundleActivator { @Override public void start(BundleContext context) throws Exception { //Another way to connect a service. ServiceReference reference = context.getServiceReference(SimpleService.class.getName()); SimpleService service = (SimpleService) context.getService(reference); if (service != null) service.echo("Service called."); else System.out.println("Service call error!"); } @Override public void stop(BundleContext context) throws Exception { } }
- A service.SimpleService interfészt mindenképpen tegyük elérhetővé ebben a projektben, az egyszerűség kedvéért hozzuk létre az objektumot.
- A META-INF/MANIFEST.MF állomány tartalma legyen a következő:
Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Caller Bundle-SymbolicName: caller Bundle-Version: 1.0.0 Bundle-Activator: caller.Activator Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Import-Package: org.osgi.framework;version="1.3.0",service;version="1.0.0"
Fontos, hogy a szervizben exportált service csomagot itt importáljuk. - A szerviznél leírtakkal azonos módon tesztelhetjük és fordíthatjuk a bundlet (nekem voltak problémák, amikor az IDE-ből próbáltam tesztelni a két bundlet együtt).
A konténer:
Utolsó egységként a konténert kell megismernünk, melynek vezérlése eltérő a különböző implementációk esetén. Az Equinoxot választva az alábbiakat kell tennünk.- Szerezzük be a nekünk megfelelő verziót, jelenleg a 3.6-os a legfrissebb.
- A `java -jar org.eclipse.osgi_3.6.0(.*?).jar -console` parancs futtatásával indíthatjuk el a konténert.
- Installáljuk a bundlekat:
osgi> install file:///path/to/file/service.jar Bundle id is 6 osgi> install file:///path/to/file/caller.jar Bundle id is 7
Eltávolítani az uninstall paranccsal, frissíteni pedig az updatetel lehet. - Az ss paranccsal lekérdezhetjük a telepített bundlek állapotát, mindkettőnek INSTALLED állapotban kell lennie:
osgi> ss Framework is launched. id State Bundle 0 ACTIVE org.eclipse.osgi_3.6.0.v20100517 6 INSTALLED service_1.0.0.qualifier 7 INSTALLED caller_1.0.0.qualifier
- Utolsó lépésként indítsuk el mindkét bundlet:
osgi> start service Service started. osgi> start caller Service called.
A bundle neve helyett használhatjuk az azonosítóját. - A stop paranccsal állítjuk le a bundlekat:
osgi> stop service Service stopped.
Feliratkozás:
Bejegyzések (Atom)