Először is regisztrálnia kell az objektumot a másik csomagaktivátorban OSGi szolgáltatásként. Ebben az esetben szinte mindenhonnan elérheti.
A másik kérdés: hogyan lehet hozzáférni a másik oldalról? Sok lehetőség van, van, amelyik jobb, van, amelyik rosszabb.
Egy egyszerű, de nem igazán szép megoldás:
Bundle bundle = FrameworkUtil.getBundle(this.getClass());
// Getting the service and using it based on the bundle
Ezzel a megoldással az a probléma, hogy minden kéréshez le kell szerezni az OSGi szolgáltatást az OSGi szolgáltatásnyilvántartásból szűrők alapján, és a függvényhívás után törölni kell, felesleges többlet.
A ServiceTrackeren alapuló megoldás:
Ha szolgáltatáskövetőt használ, azzal a problémával kell szembenéznie, hogy valahol ki kell nyitnia és be kell zárnia. Megoldás lehet a konstruktorban való nyitás, de a pihenőórán nem találsz olyan helyet, ahol bezárhatod. Megoldás lehet, hogy létrehozol egy Servlet figyelőt, ott megnyitod és bezárod a nyomkövetőt, és beviszed a szolgáltatáskövetőt a servlet kontextus attribútumtérképébe. A REST függvényben elérheti a szervlet kontextust, és minden hívásban megkaphatja a szolgáltatáskövetőt, mint a tracker.getService(). Ez a funkció visszaadja a szükséges objektumot vagy nullát, ha még nincs regisztrálva.
Megoldás, amely nem teszi szükségessé az OSGi-vel kapcsolatos kódot a REST osztályba:
Előfordulhat, hogy nem szeretné használni a ServiceTracker-t a REST kódban, mivel nem akar az OSGi-től függeni. Ebben az esetben használhat egy nagyon egyszerű könyvtárat, amelyet megvalósítottam :). A következő címen érhető el: https://github.com/everit-org/osgi-servicereference .
A módszertan ugyanaz. Írsz egy Listenert, amely: - ServiceReference-t hoz létre - Meghívod a serviceReference getProxtInstance-jét a ServletContextbe - A REST függvényben megadott interfész alapján megkapod a proxy objektumot, és meghívod a rajta lévő metódusokat.
A ServiceReference a Blueprint megvalósítás részeként valósult meg. Ezért ugyanúgy működik, mint a címke egy XML-tervfájlban. Példányosíthat egy szolgáltatási hivatkozást, és megnyithatja azt (a megnyitás után az OSGi szolgáltatások nyomon követhetők). A getProxyInstance metódussal kaphat egy objektumot, amely megvalósítja a szükséges (Ön által biztosított) interfészeket.
Amikor függvényhívás történik az objektumhoz az interfész alapján:
- Ha elérhető egy OSGi szolgáltatás, a funkcióhívás át lesz delegálva arra a szolgáltatásra
- Ha nem érhető el OSGi szolgáltatás, a függvényhívás egy időtúllépésig tart (egyszerű thread.wait). Ha van OSGi szolgáltatás az időtúllépés előtt, a funkcióhívás delegálásra kerül. Ha nem, akkor a rendszer egy ServiceUnavailableException kivételt dob. Az időtúllépési viselkedést felülírhatja egy másik időtúllépés-kezelő beállításával a ServiceReference objektumhoz.
A normál függvényhívás a következő:
hívó -> OSGiService.function
A ServiceReference Proxy objektumon keresztüli függvényhívás így néz ki:
hívó -> ServiceReference.proxyObject -> OSGiService.function (ha az OSGiService elérhető)
Most a gyakorlatban a megoldás:
Írjon egy figyelőt a webalkalmazáshoz:
private Reference reference;
@Override
public void contextInitialized(final ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
BundleContext bundleContext = (BundleContext) servletContext.getAttribute("osgi-bundlecontext");
try {
Filter filter = bundleContext.createFilter("(objectClass=" + MyInterface.class.getName() + ")");
// MyInterface is the interface the OSGi service implements (there can be multiple) and the timeout until function calls will wait is 5s.
reference = new Reference(bundleContext, new Class<?>[] { MyInterface.class }, filter, 5000);
// Opening the reference is necessary to track services
reference.open();
// Taking the proxy object into the servlet context attributes
servletContext.setAttribute("myService", reference.getProxyInstance());
} catch (InvalidSyntaxException e) {
LOGGER.error(e.getMessage(), e);
}
}
@Override
public void contextDestroyed(final ServletContextEvent sce) {
if (reference != null) {
reference.close();
sce.getServletContext().removeAttribute("myService");
}
}
Miután rendelkezik ezzel a figyelővel, a következőhöz hasonló proxy objektumot mindenhol megkaphatja a kódokban (ahol elérheti a servlet kontextust):
MyInterface myService = servletContext.getAttribute("myService");
myService.foo();
21.08.2013