Hi Scott,

As the author of the Transaction Control specification I can attempt to explain 
to you the reasoning for the example that is confusing you.

In the Transaction Control specification there are three primary sets of actors:

People implementing the core TransactionControl service (i.e. the transaction 
management piece)
People implementing Transactional Resources (e.g. JDBC wrappers, JPA wrappers, 
JMS wrappers, Transaction Scoped objects)
People using the Transaction Control Service to do transactional work

In many cases there will be overlaps in these groups, but broadly speaking the 
intent of the specification is that people providing transactional resources 
are different from people providing the core transaction service. It is also 
expected (hoped) that there will be many more people providing transactional 
resource providers than there are providing Transaction Control Services. 

For these reasons the generic ResourceProvider interface is annotated with 
@ConsumerType, specifically so users can provide their own custom resource 
providers without becoming providers of the Transaction Control specification.

Now, to answer your question - if you have a specialisation of a @ConsumerType 
interface (as JDBCConnectionProvider and JPAEntityManagerProvider both are) 
then what should the status of that interface be? The general wisdom is that 
Transaction Control Resource Provider specialisations are explicitly supposed 
to be used for reifying the type of the ResourceProvider. This doesn’t change 
the usage intent of the ResourceProvider, and therefore we don’t change the 
@ConsumerType.

On the other hand the various ResourceProvider Factory services *do* feature in 
the specification in the way that other “provider” services do - there are 
rules about what properties you need to support in the configuration maps etc. 
Also, unlike the ResourceProvider interfaces, it’s possible to implement the 
factory service without implementing other Transaction Control interfaces 
(implementing JDBCConnectionProvider requires implementing ResourceProvider). 
We very much want to avoid coupling which would mean that existing Resource 
Provider implementations would not work with a version 1.1 of the Transaction 
Control specification.

In summary - JDBCConnectionProvider is @ConsumerType because ResourceProvider 
is @ConsumerType. ResourceProvider is @ConsumerType because providing a 
transactional resource is not the same as providing a Transaction Control 
service. JDBCConnectionProviderFactory is @ProviderType because by implementing 
it you are a provider of the standardised configuration factory for 
Transactional JDBC resources.

I hope this makes sense.

All the best,

Tim

> On 24 Oct 2019, at 03:53, Leschke, Scott via osgi-dev 
> <osgi-dev@mail.osgi.org> wrote:
> 
> First I’d like to thank everybody for their thoughtful responses. I’m sorry 
> that this response was so long in coming. Unfortunately, the demands of my 
> day-to-day, which is unrelated to anything OSGi, has taken quite a bit of my 
> time lately.
>  
> I found all the responses very helpful but I must say that I found Peter’s 
> response below to be extremely helpful especially the last two paragraphs. I 
> do a few question have a specific example taken from the R7 OSGi Compendium 
> spec that I still find confusing though.
>  
> Package org.osgi.service.transaction.control.jdbc provides two interfaces, 
> JDBCConnectionProvider and JDBCConnectionProviderFactory.  The latter is 
> @ProviderType as I’d expect but the former is @ConsumerType.  As a consumer 
> of this API package, my expectation is that I won’t be implementing 
> JDBCConnectionProvider but the API provider, Apache Aries for example, will 
> be so that it should be @ProviderType instead of @ConsumerType since adding 
> methods to this interface won’t impact me as a consumer.
>  
> Am I making any sense? Is it possible for an API to expose an @ConsumerType 
> that isn’t implemented or extended by the consumer role? It would seem not. 
> If that’s the case, is the primary reason the default is @ConsumerType 
> (rather than @ProviderType) because it’s the more conservative choice, rather 
> than the more common one because in my experience, the vast majority of types 
> in an API are implemented by the provider rather than the consumer.
>  
> Thanks so much, I hope I’m not wasting anybody’s time here.
>  
> Scott
>  
> From: Peter Kriens <peter.kri...@aqute.biz> 
> Sent: Thursday, October 17, 2019 12:17 PM
> To: Leschke, Scott <slesc...@medline.com>; OSGi Developer Mail List 
> <osgi-dev@mail.osgi.org>
> Subject: Re: [osgi-dev] @ConsumerType vs @ProviderType
>  
> It is surprisingly simple. :-)
>  
> Let's assume Oracle adds a new method to `java.nio.file.Path`. Would you 
> care? Unless you work for Azul, you'd like couldn't give a rats ass. Once you 
> use that new method you care, but before that moment it is irrelevant to you. 
> That makes you a _consumer_ of the `java.nio.file` package. Azul and Oracle 
> are, however, _providers_ of this package. Oracle and Azul do care when this 
> method gets added because you would be very upset if the method is not there. 
> However, if Oracle added a method to `java.io.Serializable` you would likely 
> be pretty upset because you are a _consumer_ of the `java.io 
> <https://urldefense.proofpoint.com/v2/url?u=http-3A__java.io&d=DwMFaQ&c=ZyuC0pi8BQ0JtN0UhY3DPMRPQOzp-0mvXzAggKz74wI&r=bjaNw_Ip6Cns5Gp3HC6K_oF-NLagO9fLr68IUFiG2XI&m=4j5tN615t0CCQkj0qKIfs7DsTPHcY6IZTKcyRWR3-x4&s=d1IEUgm1-X61sZi0T8Znk33Xo7ggGqLRmuWrUSlYF6k&e=>`
>  package.
>  
> When you make a change to an API package you might break users of that 
> package. To distinguish between the Azuls and Oracles of this world and mere 
> mortals OSGi/bnd allows you to mark a type to be **only** affecting 
> _providers_. I.e. the Path interface would be a _provider type_. (The 
> @ConsumerType is default and just breaks everybody when you make a binary 
> incompatible change.)
>  
> The archetypical example is Event Admin. If we add a method to the EventAmin 
> interface we only break the 5 or 6 implementations of Event Admin. And we 
> should break those implementation because they need to implement this new 
> method. However, the 50 million bundles that depend on Event Admin are not 
> affected since this change is fully backward compatible for them. However, if 
> we add a method to Event Handler then we break all those 50 million bundles 
> that implement Event Handler. That is why  the `EventHandler` interface is a 
> @ConsumerType.
>  
> So the sole purpose of the @ProviderType annotation is to make a breaking 
> change but indicate that only, the usually smaller number of, bundles that 
> _provide_ the API should be broken instead of the majority of bundles that 
> only _consume_ this API.
>  
> The key thing to realize is that provider/consumer is about the API 
> **package** and not an interface. If you make a binary incompatible change, 
> the key question is does it affect everybody (consumer and providers) or can 
> I limit it to a smaller number of bundles (providers)?
>  
> PK
>  
> On 16 Oct 2019, at 21:15, Leschke, Scott via osgi-dev <osgi-dev@mail.osgi.org 
> <mailto:osgi-dev@mail.osgi.org>> wrote:
>  
> I’m trying to wrap my head around these two annotations and I’m struggling a 
> bit. Is the perspective of the provider and consumer roles from a bundle 
> perspective or an application perspective?
> I’ve read the Semantic Versioning whitepaper a number of times and it doesn’t 
> really clear things up for me definitely.
>  
> If an application has an API bundle that only exposes Interfaces and Abstract 
> classes, and those interfaces are implemented by other bundles in the app, 
> are those bundles providers or consumers? My inclination is that they’re 
> providers but then when does a bundle become a consumer?  Given that API 
> bundles are compile only (this is the rule right?), would a good rule be that 
> if you implement the interface and export the package it’s in, that type 
> would be @ProviderType, if you don’t implement it it’s @ConsumeType?
>  
> It would seem to me that @ProviderType would be the default using this logic, 
> as opposed to @ConsumerType, which leads me to believe that I’m thinking 
> about this wrong.
>  
> Any help appreciated as always.
>  
> Regards,
>  
> Scott Leschke
> _______________________________________________
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org <mailto:osgi-dev@mail.osgi.org>
> https://mail.osgi.org/mailman/listinfo/osgi-dev 
> <https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.osgi.org_mailman_listinfo_osgi-2Ddev&d=DwMFaQ&c=ZyuC0pi8BQ0JtN0UhY3DPMRPQOzp-0mvXzAggKz74wI&r=bjaNw_Ip6Cns5Gp3HC6K_oF-NLagO9fLr68IUFiG2XI&m=4j5tN615t0CCQkj0qKIfs7DsTPHcY6IZTKcyRWR3-x4&s=oBOK5YFs59FcQQf9pSe_17TyLfgRykUb46b0ght36Yk&e=>
>  
> _______________________________________________
> 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