Hi Thomas, A better design would be to implement a whiteboard pattern rather than an extender. Rather than to track and scan bundles it is better to track OSGi services that extend Component and plug those into Vaadin directly.
To make sure Vaadin gets a fresh object every time it needs you can recommend to your users to register their services with a property "service.scope=prototype". This property instructs the OSGi framework to create a new object every time an attempt is made to grab the service. Your OSGiInstantiator will then just grab the service every time it is asked to create an object. The users may still choose to use a singleton object if it is stateless for example. In this design you abstract away how the users choose to create and register their service. In the case when they choose Declarative Services they will create a regular DS component with "service.scope=prototype". No need of a component factory. The OSGiInstantiator has to hold on to objects of this type: https://osgi.org/javadoc/osgi.core/7.0.0/org/osgi/framework/ServiceObjects.html Which are obtained like this: https://osgi.org/javadoc/osgi.core/7.0.0/org/osgi/framework/BundleContext.html#getServiceObjects-org.osgi.framework.ServiceReference - It has to store the service instances it creates and release them when appropriate. The principles of this design are tried and tested in OSGi specifications like the Http integration - where the core gathers Servlet and Filter services or the JAX-RS integration where the core gathers resources. In my opinion the major technical issues you face are: 1. You likely have to pass to Vaadin all classes that it needs to plug into the web app ahead of time. This means you need to inspect each Component service when it arrives to get it's concrete class. Basically probe the service by getting one instance then getting it's class then releasing the instance. Then you may need to reboot the Vaadin application with the new class added. 2. The OSGiInstantiator is created through ServiceLoader. This means you can not initialize it with the concrete OSGi service object. It may have to pass through static fields that are populated with the Component services by other parts of your whiteboard. This can also introduce lifecycle issues since the OSGiIntantiator may be created before a service it needs is added so it may need to block for a period of time. If you can pass a ready made OSGiInstantiator to Vaadin it will be ideal. These implementation complications are well worth the power/simplicity you give the users to completely control the lifecycle and implementation style of their components. P.S. With all that said I think there is a real issue with DS and programmatic creation of components. Since component factories are frowned upon the next best thing is to register "service.scope=prototype" services that may need setters or initializtion methods. The party that needs to make programmatically the component can grab a fresh instance and the customize it. Another pattern I have used is to just add configurations to ConfigAdmin. Hope this helps, Todor On Mon, 2019-02-11 at 09:12 +0000, Thomas Driessen via osgi-dev wrote: > Hi Ray, > > thanks for your time and advice. > > Regarding your question: > > The classes are annotated by whoever wants to register a @Route in Vaadin. > Routes in Vaadin are > usually a specific location within a web application. Classes that are > annotated with @Route are > extending Vaadin's Component class and are instantiated by Vaadin whenever a > new client requests > the respective part of the web application. Vaadin delegates the > instantiation of the class to an > Instantiator, this is usually the DefaultInstantiator class in Vaadin. > > I try to delegate this instantiation to OSGi by extending Vaadins > DefaultInstantiator and > registering the new OSGiInstantiator via ServiceLoader mechanism which is > internally used by > Vaadin to find its Instantiators. > Whenever Vaadin calls an Instantiator it passes a class that has to be > instantiated. > This is the place where I'm using ComponentFactory to create instances of > those classes. > > You can also have a look on all of these classes and additional information > about the intended > logic flow at my repository: > https://github.com/Sandared/flow-osgi > > Kind regards, > Thomas > > > ------ Originalnachricht ------ > Von: "Raymond Auge" <raymond.a...@liferay.com> > An: "Thomas Driessen" <thomas.driessen...@gmail.com> > Cc: "OSGi Developer Mail List" <osgi-dev@mail.osgi.org> > Gesendet: 10.02.2019 18:05:56 > Betreff: Re: [osgi-dev] Programmatically creating DS components > > > > > On Sun, Feb 10, 2019 at 11:20 AM Thomas Driessen > > <thomas.driessen...@gmail.com> wrote: > > > Hi Ray, > > > > > > I'm not defining any additional manifest header if that's what you mean. > > > I have no real > > > control over the bundles I need to scan. > > > > > > What I do is registering a BundleTracker that scans a bundle's classes if > > > its wiring states it > > > is importing the package of the annotation I'm looking for. > > > (Can be seen here: > > > https://github.com/Sandared/flow-osgi/blob/master/flow.osgi.integration/src/main/java/io/jatoms/flow/osgi/integration/FlowOsgiRouteTracker.java > > > ) > > > > > > > This is precisely the "extender pattern" [1]. > > > > > Those classes usually look something like this: > > > > > > @Route("") > > > @Component(factory="fqcn") > > > public class MyFancyUI extends Component { > > > @Reference > > > SomeService service; > > > ... > > > } > > > > > > So I'm looking into the wiring of the bundle if it has imported the > > > package > > > "com.vaadin.flow.router" . If so I then scan the bundle's classes for the > > > @Route annotation > > > (and @RouteAlias). > > > Classes that have this annotation can later on be instantiated via > > > ComponentFactory. > > > > > > Can I instantiate such a component with the Apache Aries approach and if > > > so will its reference > > > be injected? I'm not sure if this is done if I'm registering the instance > > > just as a service. > > > > > > > Let's start with how the classes came to be annotated with @Component, and > > why that isn't > > already enough. > > > > - Ray > > > > [1] https://blog.osgi.org/2007/02/osgi-extender-model.html > > > > > Kind regards, > > > Thomas > > > > > > Am So., 10. Feb. 2019 um 15:38 Uhr schrieb Raymond Auge > > > <raymond.a...@liferay.com>: > > > > Are you implementing this using the extender pattern? If so, I would > > > > not use DS. I would use > > > > something lower level. > > > > > > > > There are plenty of good alternatives for doing this, but I would > > > > suggest looking at Apache > > > > Aries Component DSL [1] (it's what is used to implement Aries JAXRS > > > > Whiteboard). > > > > > > > > - Ray > > > > > > > > [1] https://github.com/apache/aries/tree/trunk/component-dsl > > > > > > > > On Sun, Feb 10, 2019 at 8:01 AM Thomas Driessen via osgi-dev > > > > <osgi-dev@mail.osgi.org> wrote: > > > > > Hi, > > > > > > > > > > I'm currently trying to sketch out a possible better OSGi integration > > > > > for Vaadin 10+. > > > > > > > > > > For this I need to programmatically create DS components in order to > > > > > make @ > > > > > Route/@RouteAlias annotated classes also DS components. > > > > > > > > > > Right now I'm doing this via ComponentFactory and the assumption that > > > > > all @Route annotated > > > > > classes are also annotated with > > > > > @Component(factory="fully qualified class name") > > > > > > > > > > I don't think this is the best way to do this. Having to type the > > > > > fqcn seems rather > > > > > errorprone to me and therefore I wanted to ask if there is a better > > > > > way (maybe even a > > > > > typesafe way) to do this? > > > > > > > > > > The code instantiating a component can be seen here: > > > > > https://github.com/Sandared/flow-osgi/blob/master/flow.osgi.integration/src/main/java/io/jatoms/flow/osgi/integration/FlowOsgiInstantiator.java > > > > > The class that shall be instantiated can be seen here: > > > > > https://github.com/Sandared/flow-osgi/blob/master/flow.osgi.simpleui/src/main/java/io/jatoms/flow/osgi/simpleui/MainView.java > > > > > > > > > > Any advice is highly appreciated. > > > > > > > > > > Kind regards, > > > > > Thomas > > > > > _______________________________________________ > > > > > OSGi Developer Mail List > > > > > osgi-dev@mail.osgi.org > > > > > https://mail.osgi.org/mailman/listinfo/osgi-dev > > > > > > > > > > > > -- > > > > Raymond Augé (@rotty3000) > > > > Senior Software Architect Liferay, Inc. (@Liferay) > > > > Board Member & EEG Co-Chair, OSGi Alliance (@OSGiAlliance) > > > > > > _______________________________________________ > > OSGi Developer Mail List > > osgi-dev@mail.osgi.org > > https://mail.osgi.org/mailman/listinfo/osgi-dev _______________________________________________ OSGi Developer Mail List osgi-dev@mail.osgi.org https://mail.osgi.org/mailman/listinfo/osgi-dev