[Java, OSGi] OSGi Resolver handmatig oproepen via Bndtools?

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 03-10 15:43
Hallo,

ik ben op zoek naar mensen die iets meer kennis hebben van het OSGi framework dan mezelf en dit gebruiken in combinatie met de hulptool Bndtools.
Ik ben zelf wat aan de slag gegaan met OSGi specification en de informatie die ik kon vinden om mijn eigen project op te zetten, een bundel aan te maken en hier een component in te maken.

Welke software gebruik ik?
Ik gebruik Eclipse 2018-12 en Bndtools

Waar kan mijn werk gezien worden?
Ik heb mijn project gepushed naar Github zodat jullie kunnen zien wat ik gedaan/niet gedaan heb bij onduidelijkheden: https://github.com/BramCoding/bnd-workspace

Wat heb ik op dit moment gedaan?
Ik probeer zo kort en goed mogelijk uit te leggen wat ik op dit moment gedaan heb, en in mijn volgende puntje dan wat ik eigenlijk wil, maar waar ik vast loop.

1) Ik heb een nieuwe bnd-workspace aangemaakt zodat mijn OSGi project gemaakt wordt.
2) Ik heb een nieuwe OSGi project toegevoegd, met andere woorden een OSGi bundle dus: org.bram.demo
3) Ik heb van deze bundle enkele zaken zaken ingesteld die er weinig toe doen: versie, naam, ..
4) Dan heb ik voor deze bundle een package aangemaakt: org.bram.demo
5) Dan heb ik in deze package 2 klasses gemaakt: DemoComponent.java en DemoComponent2.java. De bedoeling hiervan is dat ik hier eens een Component ga aanmaken en kijken of dat lukt.
6) In de bnd.bnd van org.bram.demo heb ik geen Export-Packages toegevoegd. Wel heb ik bij het Build Path osgi.core, osgi.annotation en osgi.cmpn toegevoegd (om Component te kunnen maken). Zie hieronder:
Afbeeldingslocatie: https://i.imgur.com/dx15vzM.png

7) Ik heb de klasses DemoComponent en DemoComponent2 vervolledigd zodat de Component aangemaakt wordt bij het opstarten van de bundel:
Afbeeldingslocatie: https://i.imgur.com/OVkhOfX.png
Afbeeldingslocatie: https://i.imgur.com/J9D0EiA.png

8 ) ik maakte een run.bndrun bestand aan waar de Resolving gebeurt. Ik heb mijn Run Requirements en na het Resolven ook mijn Run Bundles:
Afbeeldingslocatie: https://i.imgur.com/E6tCmhF.png
Afbeeldingslocatie: https://i.imgur.com/Vyuv2V1.png

9) Ik start het project op, en kan zien dat mijn gemaakte bundle actief is in de Gogo shell + als ik activeer of deactiveer van deze bundle dan starten en stoppen de twee Components:
Afbeeldingslocatie: https://i.imgur.com/tNjstui.png

Wat is dan nu de bedoeling/het probleem?
Het is de bedoeling dat ik nu niet via de Bndtools GUI de Resolver zijn werk laat doen, maar dat ik de Resolver vanuit mijn code oproep. Dit is omdat ik verder in mijn project at runtime requirements wil toevoegen die dan ook moeten Resolved worden.

Ik denk (aangezien ik via Bndtools werk) dat ik dit het makkelijkste kan via de Resolver van Bnd. Op hun Github is een heleboel code te vinden die ik kan gebruiken: https://github.com/bndtools/bnd.
Zo zien we bijvoorbeeld biz.aQute.resolve.

Ik wil deze bundle dus graag gaan gebruiken zodat ik de Resolver kan oproepen vanuit mijn code. Echter loop ik hier helemaal vast. Ik typ hieronder even mijn stappenplan uit wat ik denk dat er moet gebeuren:

1) PROBLEEM 1: Deze biz.aQute.resolve-bundle moet ik mijn Local Repository geraken in mijn eigen project. Ik vond via deze FAQ-link al dat dit gewoon via drag-and-drop kon (https://bndtools.org/faq.html). Probleem is, als ik de bnd github repository clone, dat deze bundles geen .jar files zijn, en ik deze dus niet als bundle kan inladen in mijn eigen project? Hoe kan ik dan gebruik maken van deze bundles?

2) PROBLEEM 2: Hierna veronderstel ik dus dat ik deze bundle biz.aQute.resolve zal moeten toevoegen aan het build path van mijn eigen gemaakte bundle org.bram.demo. Hierdoor zou ik toegang moeten krijgen tot de klassen en methoden die de biz.aQute.resolve-bundle heeft.

Ik ben dus al eens gaan kijken in de klasses die in deze biz.aQute.resolve-bundle zitten, maar ik ben nog niet helemaal mee hoe dit in elkaar zit.
Een goed startpunt is volgens mij de klasse BndResolver.java, deze implements Resolver (van OSGi zelf dan denk ik?). Deze heeft een methode resolve die als argument een ResolveContext object nodig heeft. Deze heeft ook een methode resolveDynamic maar dat is voor mij (nog) niet belangrijk volgens ik gelezen heb. Voor deze code, zie hieronder:
Afbeeldingslocatie: https://i.imgur.com/FO8QCB2.png

Ik zal dus een BndResolver-object aanmaken en moet hiermee dan de resolve methode uitvoeren. Hiervoor heb ik dus dat ResolveContext-object nodig en daar loop ik dan ook vast qua denkwijze.
Ik ga dan door naar de klasse AbstractResolveContext.java omdat deze extend van ResolveContext. In deze klasse zit dan heel veel methodes waar ik nog geen vat op heb wat deze doen/kunnen doen/moeten doen.

Mijn voornaamste vraag dus: is hier iemand met wat meer OSGi en Bnd ervaring die mij de goede weg kan opsturen? Ik loop op dit moment helemaal vast en ben overweldigd door de grote happen code die plots beschikbaar worden maar waarmee ik niet weet wat te doen.

Een kleine duw in de goede richting, of het praktisch voorbeeld zou heel mooi zijn, aangezien ik zelf nog geen voorbeeld heb gevonden van iemand die hetzelfde als mij probeert (Resolver oproepen vanuit code).

Hopelijk is het wat duidelijk en voldoende informatie, zo niet dan vul ik het graag nog wat verder aan.
Alvast bedankt!

Alle reacties


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 13:59
Ik zou verbaasd zijn als je hier een antwoord krijgt. Je zou 't eens op https://reddit.com/r/java kunnen proberen? OSGi is zo goed als dood.

[ Voor 3% gewijzigd door Hydra op 01-04-2019 13:38 ]

https://niels.nu


Acties:
  • +1 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 17:31
BndTools is bedoeld als build-tool en niet voor de runtime. Als ik het goed begrijp wil je at runtime automatisch nieuwe bundles ontdekken. Dit kan bijvoorbeeld met Apache Felix prima, bijvoorbeeld het eenvoudigst met de File Install plugin. Hiermee kun een een directory aanmaken die gepolled wordt om te kijken of er nieuwe bundles aanwezig zijn.

Je kunt natuurlijk ook zelf iets maken als je iets anders wilt, je hoeft alleen maar BundleContext.installbundle(...) aan te roepen.
Hydra schreef op maandag 1 april 2019 @ 13:38:
Ik zou verbaasd zijn als je hier een antwoord krijgt. Je zou 't eens op https://reddit.com/r/java kunnen proberen? OSGi is zo goed als dood.
Het is voor mij al wel wat jaren geleden, maar toevallig nog wel een paar jaar mee gewerkt :)

[ Voor 19% gewijzigd door Marcj op 01-04-2019 13:43 ]


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 03-10 15:43
Hydra schreef op maandag 1 april 2019 @ 13:38:
Ik zou verbaasd zijn als je hier een antwoord krijgt. Je zou 't eens op https://reddit.com/r/java kunnen proberen? OSGi is zo goed als dood.
Ik ga daar zeker ook eens kijken. Nog niet echt veel gebruik gemaakt van reddit dus zelf nog niet opgekomen.

Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 03-10 15:43
Marcj schreef op maandag 1 april 2019 @ 13:43:
BndTools is bedoeld als build-tool en niet voor de runtime. Als ik het goed begrijp wil je at runtime automatisch nieuwe bundles ontdekken. Dit kan bijvoorbeeld met Apache Felix prima, bijvoorbeeld het eenvoudigst met de File Install plugin. Hiermee kun een een directory aanmaken die gepolled wordt om te kijken of er nieuwe bundles aanwezig zijn.

Je kunt natuurlijk ook zelf iets maken als je iets anders wilt, je hoeft alleen maar BundleContext.installbundle(...) aan te roepen.


[...]

Het is voor mij al wel wat jaren geleden, maar toevallig nog wel een paar jaar mee gewerkt :)
Klopt, ik wil at runtime een nieuwe bundle installeren als iets ontdekt wordt. Ik wil in mijn geval een EnOcean USB-stick inpluggen, dan moet het framework dit detecteren, kijken welke versie het nodig heeft, en dan de correct bundle installeren.
Dit houdt dus in dat ik handmatig de Resolver moet gaan aanspreken (en bnd gebruikt hiervoor nog steeds OSGi's Resolver) wanneer de EnOcean USB-stick gedetecteerd is. Dat is voornamelijk het probleem op dit moment, de Resolver vanuit code laten werken.

Die poller kijkt enkel of er nieuwe bundles aanwezig zijn, maar in mijn geval moet de bundel ergens aanwezig zijn, en pas geresolved worden wanneer het nodig is.
Snapt u wat ik bedoel?

Acties:
  • +1 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 17:31
BramVanha schreef op maandag 1 april 2019 @ 14:43:
[...]


Klopt, ik wil at runtime een nieuwe bundle installeren als iets ontdekt wordt. Ik wil in mijn geval een EnOcean USB-stick inpluggen, dan moet het framework dit detecteren, kijken welke versie het nodig heeft, en dan de correct bundle installeren.
Dit houdt dus in dat ik handmatig de Resolver moet gaan aanspreken (en bnd gebruikt hiervoor nog steeds OSGi's Resolver) wanneer de EnOcean USB-stick gedetecteerd is. Dat is voornamelijk het probleem op dit moment, de Resolver vanuit code laten werken.

Die poller kijkt enkel of er nieuwe bundles aanwezig zijn, maar in mijn geval moet de bundel ergens aanwezig zijn, en pas geresolved worden wanneer het nodig is.
Snapt u wat ik bedoel?
Wat bedoel je met "Wanneer het nodig is"? Wat je standaard vaak doet is de bundles wel automatisch laden, maar de components niet (die immediate flag dus op false). Dan kun je de componenten laden wanneer je deze wilt gebruiken. Bijvoorbeeld kun je dan in jouw eigen code alle componenten van een bepaald type opvragen om te starten.

Normaal maak je er dan een Service van en gebruik je bijvoorbeeld BundleContext.getServiceReferences(...) om alle services van een bepaald type op te zoeken. Het makkelijkst is dan wel om een interface te definieren die elke van deze objecten moet implementeren.

edit:
Je kunt trouwens ook prima meerdere versies van een zelfde bundle laden. Je kunt dan bijvoorbeeld Filters gebruiken op de service te vinden die het beste past bij het apparaat wat ingeladen wordt.

[ Voor 22% gewijzigd door Marcj op 01-04-2019 16:06 ]


Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 03-10 15:43
Marcj schreef op maandag 1 april 2019 @ 15:40:
[...]


Wat bedoel je met "Wanneer het nodig is"? Wat je standaard vaak doet is de bundles wel automatisch laden, maar de components niet (die immediate flag dus op false). Dan kun je de componenten laden wanneer je deze wilt gebruiken. Bijvoorbeeld kun je dan in jouw eigen code alle componenten van een bepaald type opvragen om te starten.

Normaal maak je er dan een Service van en gebruik je bijvoorbeeld BundleContext.getServiceReferences(...) om alle services van een bepaald type op te zoeken. Het makkelijkst is dan wel om een interface te definieren die elke van deze objecten moet implementeren.

edit:
Je kunt trouwens ook prima meerdere versies van een zelfde bundle laden. Je kunt dan bijvoorbeeld Filters gebruiken op de service te vinden die het beste past bij het apparaat wat ingeladen wordt.
De opdracht waarmee ik bezig ben is een deel van mijn thesis. Ik verduidelijk dus even wat meer "wanneer het nodig is". Sorry voor de verwarring:

-ergens in een repository (lokaal of op een server op afstand) moet er een bundle staan die overweg kan met een communicatietechnologie. In mijn geval moet hij dus overweg kunnen met EnOcean.

-de bundel moet nog niet geïnstalleerd worden als er geen EnOcean USB gedetecteerd wordt. Wel moet de Resolver dus weet hebben van de repository waar de bundel zich in bevindt.

-In een andere bundel die wél aanwezig is in het project, een zelfgemaakte bundel dus, zal ik een Component schrijven die de detectie van een EnOcean USB-stick kan waarnemen. Dit is weer terug voor later aangezien ik eerst een dummy variabele zal gebruiken om de 'detectie' van een EnOcean USB-stick waar te nemen.

-Als de detectie waargenomen wordt, dan zal er een nieuwe Requirement moeten worden aangemaakt. Namelijk een Requirement die de eis stelt om de bundel nodig te hebben die weet hoe de communicatie over EnOcean verloopt (de bundel in die repository in mijn eerste streepje dus).

-Als dan eenmaal deze Requirement is aangemaakt, dan moet deze ook voldaan worden: door de Resolver op te roepen en hem het vraagstuk te laten oplossen: dit zijn de requirements, hier zijn de capabilities van de repositories waar er toegang tot is --> welke bundels moeten resolved worden?

-Met het antwoord van de Resolver worden dan al deze bundels geïnstalleerd en bruikbaar gemaakt. Nu zou in principe de EnOcean-technologie binnen het framework moeten werken.

Daarom heb ik nood aan de Resolver handmatig op te roepen vanuit de code, omdat ik de Resolver moet laten lopen nadat ik een nieuwe requirement heb gesteld. Ik keek daarvoor naar de bnd-Github page omdat dat interessant leek aangezien dit gebruik maakt van de (tevens ook de enige Resolver) officiële OSGi resolver, maar dan op een (naar horen zeggen en lezen) gebruiksvriendelijke manier.

Ik wil dus eigenlijk een "biz.aSute.resolve.BndResolver-object aanmaken en hiervan dan de 'resolve'-methode oproepen, zodat er een Resolve-probleem opgelost wordt. Dan moet deze een 'resolveContext' meekrijgen als argument maar ik heb geen idee hoe daaraan te beginnen/hoe daarmee om te gaan (zie afbeelding hieronder). Vandaar dat ik hulp zoek.
[img][img]https://i.imgur.com/8DJcjFX.png[/img][/img]

Alvast bedankt voor de tijd en moeite :)

Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 17:31
BramVanha schreef op maandag 1 april 2019 @ 16:29:
[...]


De opdracht waarmee ik bezig ben is een deel van mijn thesis. Ik verduidelijk dus even wat meer "wanneer het nodig is". Sorry voor de verwarring:

-ergens in een repository (lokaal of op een server op afstand) moet er een bundle staan die overweg kan met een communicatietechnologie. In mijn geval moet hij dus overweg kunnen met EnOcean.

-de bundel moet nog niet geïnstalleerd worden als er geen EnOcean USB gedetecteerd wordt. Wel moet de Resolver dus weet hebben van de repository waar de bundel zich in bevindt.

-In een andere bundel die wél aanwezig is in het project, een zelfgemaakte bundel dus, zal ik een Component schrijven die de detectie van een EnOcean USB-stick kan waarnemen. Dit is weer terug voor later aangezien ik eerst een dummy variabele zal gebruiken om de 'detectie' van een EnOcean USB-stick waar te nemen.

-Als de detectie waargenomen wordt, dan zal er een nieuwe Requirement moeten worden aangemaakt. Namelijk een Requirement die de eis stelt om de bundel nodig te hebben die weet hoe de communicatie over EnOcean verloopt (de bundel in die repository in mijn eerste streepje dus).

-Als dan eenmaal deze Requirement is aangemaakt, dan moet deze ook voldaan worden: door de Resolver op te roepen en hem het vraagstuk te laten oplossen: dit zijn de requirements, hier zijn de capabilities van de repositories waar er toegang tot is --> welke bundels moeten resolved worden?

-Met het antwoord van de Resolver worden dan al deze bundels geïnstalleerd en bruikbaar gemaakt. Nu zou in principe de EnOcean-technologie binnen het framework moeten werken.

Daarom heb ik nood aan de Resolver handmatig op te roepen vanuit de code, omdat ik de Resolver moet laten lopen nadat ik een nieuwe requirement heb gesteld. Ik keek daarvoor naar de bnd-Github page omdat dat interessant leek aangezien dit gebruik maakt van de (tevens ook de enige Resolver) officiële OSGi resolver, maar dan op een (naar horen zeggen en lezen) gebruiksvriendelijke manier.

Ik wil dus eigenlijk een "biz.aSute.resolve.BndResolver-object aanmaken en hiervan dan de 'resolve'-methode oproepen, zodat er een Resolve-probleem opgelost wordt. Dan moet deze een 'resolveContext' meekrijgen als argument maar ik heb geen idee hoe daaraan te beginnen/hoe daarmee om te gaan (zie afbeelding hieronder). Vandaar dat ik hulp zoek.
[[URL="\\[img=800,766]https://i.imgur.com/8DJcjFX.png\\[/img]"]Afbeelding[/URL]]

Alvast bedankt voor de tijd en moeite :)
Dan moet je echt in de code duiken van BndTools om te zoeken hoe deze objecten gebruikt worden. Ze zijn echter gemaakt om tijdens het compilen te werken, dus ik verwacht dat je een ResolveContext moet aanmaken met requirements zoals je in Eclipse doet. Of dit de goede weg is vraag ik me nog steeds wel af.

Volgens mij is het makkelijker om te kijken of je ook remote bundles kunt laden en dat je bijhoudt welke services in welke bundle zitten. Het is namelijk in OSGi ook heel makkelijk om remote bundles te laden vanaf een willekeurige InputStream (dus ook via HTTP). Je kunt kijken of je voor de het protocol iets van Bnd kunt gebruiken, maar daar moet je dan verder in duiken. Dit is dan ook het onderdeel uitzoeken voor jouw thesis.

Acties:
  • 0 Henk 'm!

  • BramCoding
  • Registratie: Maart 2016
  • Laatst online: 03-10 15:43
Marcj schreef op maandag 1 april 2019 @ 18:51:
[...]


Dan moet je echt in de code duiken van BndTools om te zoeken hoe deze objecten gebruikt worden. Ze zijn echter gemaakt om tijdens het compilen te werken, dus ik verwacht dat je een ResolveContext moet aanmaken met requirements zoals je in Eclipse doet. Of dit de goede weg is vraag ik me nog steeds wel af.

Volgens mij is het makkelijker om te kijken of je ook remote bundles kunt laden en dat je bijhoudt welke services in welke bundle zitten. Het is namelijk in OSGi ook heel makkelijk om remote bundles te laden vanaf een willekeurige InputStream (dus ook via HTTP). Je kunt kijken of je voor de het protocol iets van Bnd kunt gebruiken, maar daar moet je dan verder in duiken. Dit is dan ook het onderdeel uitzoeken voor jouw thesis.
Klopt, die code probeer ik nu wat te begrijpen.

Remote bundles inladen, wat bedoel je hier dan precies mee? Het pas inladen van de bundles wanneer aan bepaalde eisen voldaan is? Zijn deze bundles dan wel al Resolved als je ze gewoon in laadt?

Begrijp me niet verkeerd, heel tevreden met de hulp/tips, ben gewoon maar aan het denken.

Acties:
  • +1 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 17:31
BramVanha schreef op dinsdag 2 april 2019 @ 19:30:
[...]


Klopt, die code probeer ik nu wat te begrijpen.

Remote bundles inladen, wat bedoel je hier dan precies mee? Het pas inladen van de bundles wanneer aan bepaalde eisen voldaan is? Zijn deze bundles dan wel al Resolved als je ze gewoon in laadt?

Begrijp me niet verkeerd, heel tevreden met de hulp/tips, ben gewoon maar aan het denken.
Lees BundleContext.installBundle(...) maar eens door. Je kunt van een willekeurige InputStream een nieuwe bundle laden.
Pagina: 1