polygene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Paul Merlin <paulmer...@apache.org>
Subject Re: Default assemblers (Re: Issue with null association)
Date Mon, 22 May 2017 15:43:24 GMT
Addendum:

- s/polygene-runtime/polygene-support
- Tibor, you could try the branch with your application, I hope it'll 
fix your IdentityGenerator issue


Le 2017-05-22 17:38, Paul Merlin a écrit :
> Gang,
> 
> Le 2017-05-21 19:45, Tibor Mlynarik a écrit :
>> I have another one. Is it ok to report here or better create JIRA 
>> issue ?
> 
> What Niclas said, JIRAs are better. Keep them coming Tibor!
> 
> 
>> My custom IdentityGenerator ( inherited from layer hierarchy ) is
>> probably overwritten with default one.
>> My guess is that ModuleAssemblyImpl.addDefaultAssemblers() is not
>> respecting hierarchy inheritance.
>> 
>> I have custom IdentityGenerator declared in BottomLayer but used in 
>> UpperLayer.
> 
> 
> The issue is not about type hierarchy but structure and visibility.
> 
> Default assemblers are added to ALL modules for
> - IdentityGenerator,
> - Serialization
> - and UnitOfWorkFactory
> if no service assignable to each was assembled.
> 
> This makes sense for UnitOfWorkFactory, UnitOfWorkFactory is bound to
> its module and one always create an uow from a given
> module.
> But it doesn't for the two other types for which one will want to get
> the closest in the app structure instead.
> 
> I think this mixes two use cases.
> 
> Assembly of all modules must contain a service of a given type. That's
> the UnitOfWorkFactory case and current
> "default assemblers" do the job.
> 
> If a service of a given type cannot be found, then fallback to a
> framework default. That's the IdentityGenerator and
> Serialization cases. Both because they are core api services (e.g. in
> Module) and almost all extensions and a bunch
> of libraries use them. But assembling them in all modules prevent
> reasonable assemblies, as I see it it's a
> regression. And requiring users to assemble some special services in
> all their modules feels wrong.
> 
> In 2.1, serialization and metrics have a fallback, identity generation 
> doesn't:
> - Module.identityGenerator() throws NoSuchServiceException if not found
> - Module.valueSerialization() instantiate OrgJsonValueSerialization
> directly and cache
> - Module.metricsProvider() is package protected, it instantiate
> MetricsProviderAdapter directly and cache
> 
> On develop: metrics have a fallback, the others don't:
> - Module.identityGenerator() throws NoSuchServiceException if not
> found, but is always found (default assemblers)
> - Module.serialization() throws NoSuchServiceException if not found,
> but is always found (default assemblers)
> - Module.metricsProvider() instantiate MetricsProviderAdapter directly 
> and cache
> but the first two are assembled in all modules anyway.
> 
> A noop implementation is a good fit for metrics.
> UuidGeneratorMixin is core and a simple class so it could easily be
> instantiated directly as a fallback.
> Our default serialization requires composition but it could be
> reworked to be instantiatable, requiring injection.
> 
> But these services are not bound to their assembly module, so they
> could be shared across modules.
> Declaration in all modules is cheap, but it pollutes the application
> model in all modules, which is not nice.
> 
> And returning plain Objects where one would expect services feels
> weird to me. Plus it makes getting these core
> services injected in composites impossible.
> 
> If my assembly misses these core services, it's very easy to fall into
> the cryptic assembly error trap.
> In most cases you want to fix the assembly issue holistically
> according to your application needs.
> That's how 2.x works.
> 
> The intent of "default assemblers" for IdentityGenerator and
> Serialization is convenience.
> When starting an application or writing Polygene tests one wants
> simple defaults.
> But the way they are done now gets in the way when assembling non
> trivial applications.
> 
> One way to provide these fallbacks while respecting the structure and
> visibility concept, for the sake of least
> surprise, would be to add an arbitrary layer with these default
> services with application visibility and make all
> other "leaf" layers use this arbitrary layer. Effectively making these
> default services visible to the whole
> application while allowing any custom implementations assembled to
> override them.
> 
> We could also add a way to opt-out of this during assembly, for a
> stricter structure.
> 
> Metrics could then work the same way for the sake of least surprise
> again, still providing a noop implementation.
> 
> I gave the idea a try in the `pm/bootstrap/support-layer` branch, it
> passes the whole test suite.
> I opened a GitHub PR so it's easier to look at:
> https://github.com/apache/polygene-java/pull/6/files
> 
> The controversial aspect of this solution is that it automatically
> adds an arbitrary layer to support Polygene
> core services that an application can override.
> But I feel that's far less invasive than adding several assembly
> declarations to all modules.
> And it makes structure reflect the real intent.
> 
> Here are some Envisage screenshots to illustrate the change:
> - current `develop` behaviour: https://pasteboard.co/9hJfzPf4r.png
> - with the added `polygene-runtime` layer: 
> https://pasteboard.co/9hJJnHL4h.png
> - with explicit assembly of base services in the application assembly,
> the `polygene-runtime` layer is not needed so
> it is not added to the assembly: https://pasteboard.co/9hKatWHMc.png
> 
> WDYAT?


Mime
View raw message