David,

I have experimented with factory configuration and used it in one case. But
what I have not done is used the Extender Pattern with the BundleTracker to
initialize services or here configurations. That is a very good point that
I wasn't aware of. I can see how this could probably replace those "main'
MapData components. Still not sure how well it plays with generics which
are heavily used here.

In this case, I probably won't go any further, since this is a refactoring
to get us moved over from Eclipse extension points and not a redesign or
new services and we need to get done this year and avoid breaking to many
things in the process :)

I can already see uses for the Extender pattern in another part of the
application, great insight.

Cheers,
Alain


On Sun, Aug 12, 2018 at 7:16 PM David Leangen <o...@leangen.net> wrote:

>
> Hi Alain,
>
> >> Since you are annotating classes that are generated, does the generator
> has some configurability?
> > Yes, it is our own.
>
> Ok, great! That will make things easier.
>
>
> >> Is it possible for you to instead generate configurations? The config
> could be a properties file, a JSON, or even a class if necessary.
> > IMHO I am generating the configuration as part of the "main" component
> that I showed. What would be the advantage to put those in a file (we do
> have those for standard config).
>
> I am making a few assumptions here about how your system works, but I
> recommend that you read up on the “Extender Pattern”. Essentially, it
> allows you to automate the creation of a service. The services need to have
> a known structure (which it seems yours do), and have to be configurable
> (which again, it seems yours are).
>
> What you would do using this pattern is output the necessary configuration
> to a file, probably one file per configuration. You could put them all in a
> “known” folder, and include the folder in a bundle. You would use a
> BundleTracker to test for the presence of these configuration files. If a
> folder is detected that contains these files, you would load the
> configuration, one config for each file.
>
> Your component would require a configuration and have a known
> configurationPid. I think the scope should be PROTOTYPE, but you’ll have to
> try it out to be sure, I can’t remember off hand.
>
> Using the ConfigurationAdmin, you would create a factory configuration,
> which would create a new component instance.
>
> I think this approach would be much nicer than handcrafting a new
> component for each generated class, even if you are only doing it once.
>
>
> >> If this is possible, you could for instance use the extender pattern to
> instantiate the services for you, rather than trying to manually build a
> single component for each generated file. Generate the configurations,
> export them to a known folder in a bundle, and when the bundle is deployed,
> read the configs and instantiate the services.
> >>
> >> Right now, it sounds like you are making yourself an extension to the
> generator. If you can reduce the manual work by capturing only what varies
> and automating the repetition, perhaps that would be a more elegant
> solution.
> > At which level. The generator generates the "main" mapData class, the
> table, record and readers/writers. Some of those might have methods marked
> as @notGenerated when manual changes are required. The classes leveraging
> this (like the exporter that I showed), are not generated.
>
> To make this approach work, the configured components should contain only
> the parts that change. I guess you’d have to carefully pull apart what
> changes from what doesn’t.
>
>
> >> One service per generated “class” sounds right to me, but IMO there
> seems to be a bit of a smell to the manual additions to each generated
> file. Think of it from the perspective of your builds. Every time you build
> a new system, you’ll have to do manual work to construct your components.
> Would be better to have an end-to-end build that does not require manual
> intervention. Don’t you think?
> > I don't, there is a fair amount of manual boilerplate involved in the
> non-generated classes, but no further manual intervention.
>
> Well, if it’s one of these things where you invest 2 hours of work, and it
> almost never changes, then maybe you’re doing the right thing. If, however,
> you need to consistently intervene manually, that can be boring and error
> prone. Also, it puts the knowledge into a person, who can forgot or leave
> the company. If the knowledge is instead embedded in the build system, then
> you can concentrate your energies on other things. But like anything, it’s
> always a trade off. YMMV.
>
>
> >> In case you did not now (it was not obvious to me before I first
> discovered it) you can also configure the @References with a “xxx.target”
> configuration property. DS should give you all you need to configure your
> services.
> > Is that different than what I showed with:
> > @Reference(target=BaModelAssetMapData.TARGET_TABLE_NAME)
> >     private ExportTable<BaModelAssetMapTable> exportTable;
>
> That is the effect, but it is done via configuration, not annotation.
>
> Example:
>
>         ConfigurationAdmin cm = ...;
>         Configuration config = cm.createFactoryConfiguration( "some.pid",
> "?" );
>
>         Dictionary<String, Object> properties = new Hashtable<>();
>         properties.put( "XXX.target", "(some.prop=foo)" );
>
>         config.update( properties );
>
>
> The call to config.update(properties) will create a new component with PID
> “some.pid” using the provided configuration.
>
> Cheers,
> =David
>
>
>
_______________________________________________
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Reply via email to