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

Reply via email to