The main reason an interface would change from consumer to provider is if
the fact that it is a consumer interface is a bug that needs correction.
Since the current proposal is to make consumer type the default, it is
likely that developers will forget to add the @ProviderType annotation.
There is no build failure and the code works perfectly when tested, so the
code might be released with the bug present.
Suppose we have
public interface Model {
public String getSomeField();
}
out in version 1.0. With the current default applied, clients implementing
the interface would have imports saying version:="[1.0;2.0)". Now we
realize this was a mistake (perhaps we want to add another method).
Changing Model to a @ProviderType cannot be done in version 1.1, since if
there were any old clients implementing it, they would break when a method
is added.
Now consider
public interface Listener {
public String handle();
}
out in version 1.0. For a moment, assume that provider type is default, ie.
the Listener has a bug in that it was not declared @ConsumerType. Clients
implementing the interface would get imports saying version:="[1.0,1.1)".
Adding the missing @ConsumerType annotation can be safely done in version
1.1 (at least relative to versions). It could even be done in version
1.0.1, since the API did not change.
So it is easier to go from provider type to consumer type than from
consumer type to provider type.
Best regards,
Henning
On Mon, Apr 15, 2013 at 10:30 PM, Neil Bartlett <[email protected]>wrote:
> Predictably, I disagree.
>
> On Mon, Apr 15, 2013 at 8:46 PM, Henning Andersen
> <[email protected]>wrote:
>
>> Regarding 2 and 3 below, my point is that a client bundle should declare
>> whether it is consumer or provider of an imported package (default
>> consumer). With that knowledge, building a bundle that consumes a package
>> from another bundle should fail if the client contains any implementations
>> of provider-type interfaces.
>>
>> If the client cannot declare consumer or provider role/policy, a build
>> cannot fail when a (consumer) client (by mistake) implements both consumer
>> and provider types.
>>
>> Switching between consumer and provider policy automatically based on
>> whether the client implements provider type interfaces is too much
>> automation in my view. Getting a provider policy instead of a consumer
>> policy unnoticed will introduce major problems later due to not being able
>> to upgrade bundles individually.
>>
>
> My experience is the opposite. Developers of component bundles will
> probably not stop to consider whether they are a consumer or a provider of
> a particular API, so there will be nothing to check.
>
> The philosophy of bnd to extract as much information as possible out of
> the code itself; hence generating Import-Package from classfile analysis
> and so on. The same applies to the consumer/provider relationship: it can
> be derived from the code using a simple check to see whether it implements
> a provider type. Although a hint is needed in the form of the annotation,
> this only needs to be done once in the API and is then consistently applied
> to all importers. Hence there is a greater chance of it being applied
> widely and consistently.
>
> If this is too much automation in your view, you are of course free to use
> an alternative tool.
>
>
>
>> Given the above, provider type becomes the obvious default, since it
>> really is the more restrictive one, clients can only implement a provider
>> type interface if they are declared as providers of the containing package.
>>
>
> Since I disagree with the premise, I cannot agree with the conclusion :-)
>
>
> Notice that changing an interface from provider to consumer type is safe
>> in a minor version (regardless of the above), since clients build against
>> the type when it was a provider type will be incompatible (if they
>> implement the type). The reverse is not true, going from consumer to
>> provider type will require a major version update of the package. This
>> again favors that provider type is the default.
>>
>
> I don't understand this at all. How can an interface change from provider
> to consumer type or vice versa? This is an intrinsic characteristic of the
> interface; if it changes then it just isn't the same interface. It would be
> a major change in all cases.
>
>
> Regarding the annotation indirection, defining the ability to use a
>> different annotation scheme in the spec could free us from problems getting
>> the consumer/provider type annotation right (plus this would be the only
>> osgi-dependency for most of our code). In our case, we do have a hard rule
>> that certain annotations dictate consumer type. The easiest way to enforce
>> this would be to declare it on our annotation(s) so that developers only
>> need to apply the one annotation, not both. The other way we have is to add
>> a compilation check ourselves that validates that the rule is not broken.
>>
>
> Sounds like a case of "everything can be solved with one more level of
> indirection". Again, why go down the rabbit hole of meta-annotations when
> you can already apply your tool's own interpretation to the existing
> (proposed) annotations?
>
> Neil
>
>
>
>> Thanks,
>>
>> Henning
>>
>>
>>
>> On Mon, Apr 15, 2013 at 9:46 AM, Peter Kriens <[email protected]>wrote:
>>
>>> There are a number of issues with this opinion:
>>>
>>> 1) The whiteboard pattern in general requires a consumer type. So it is
>>> absolutely NOT the normal case to be a Provider Type, look at the OSGi
>>> compendium. I do not think there is any package without a Consumer Type.
>>>
>>> 2) The frequency of Consumer type/Provider type is irrelevant since
>>> they're aggregated in the package. Assuming everything is a Provider Type
>>> will break any client when one of the Consumer type changes, regardless of
>>> their ratio.
>>>
>>> 3) The package level provide: directive was a hack to make some of this
>>> stuff work when there are no Consumer/Provider Type annotations. In the
>>> future bnd should detect this information from the annotations because that
>>> is less error prone. And though it might be useful on imports, its primary
>>> intention is on the export.
>>>
>>> 4) It is another example, pervasive in enterprise software, of being
>>> 'nice' by trying to hide reality (Damping anyone?) because it is 'easier'.
>>> You first make it right, then make it easier. The other way around usually
>>> ends up in trading development time for lots of debug time. In general it
>>> is good to be lazy as a developer but it should never cause solutions that
>>> are not correct all the time. In the embedded world, these kind of
>>> suggestions would be considered, well, eh, flabbergasting :-)
>>>
>>> About the indirection of annotated annotations, this seems like things
>>> become a lot harder to read. I also expect that it will result in the
>>> proposed effect of 'well most of the time this existing annotation is ...',
>>> having the same problems as sketched before. I would suggest to keep it
>>> highly cohesive and simple.
>>>
>>> Kind regards,
>>>
>>> Peter Kriens
>>>
>>>
>>>
>>> On 14 apr. 2013, at 21:26, Henning Andersen wrote:
>>>
>>> I certainly agree with Emily that having a default of @ProviderType is
>>> sensible, since the normal case for most APIs is to call methods on it, not
>>> to implement interfaces of it.
>>>
>>> bnd already has a similar default regarding its imports, where clients
>>> should specify provide:=true when the client is a provider of the API.
>>>
>>> I think this makes perfect sense also from a tooling standpoint, in that
>>> a tool could break the build if a client tries to implement a @ProviderType
>>> interface without having declared provide:=true on the corresponding import
>>> statement. That way, there is no unsafety (except naturally purely semantic
>>> changes to implementation).
>>>
>>> A sidenote on the RFC 197: I think naming these annotations more
>>> explicitly like "ProviderImplemented" and "ConsumerImplemented" would
>>> reduce confusion on which to use when. Also, it would be really nice if the
>>> RFC would allow specifying other annotations as having the same semantics,
>>> for instance by again annotating those annotations. Allowing us to write:
>>>
>>> @MyCustomAnnotation
>>> public interface Xyz {}
>>>
>>> and giving provider or consumer role to the interface with the
>>> annotation. We certainly have cases where this would allow us to not add
>>> yet another annotation to all our consumer implemented interface.
>>>
>>> Best Regards,
>>>
>>> Henning
>>>
>>>
>>>
>>> On Sun, Apr 14, 2013 at 4:17 PM, Neil Bartlett <[email protected]>wrote:
>>>
>>>>
>>>> On Sun, Apr 14, 2013 at 2:38 PM, BJ Hargrave <[email protected]>wrote:
>>>>
>>>>> > And even that guess is not really safe. I always use the following
>>>>> > example to explain. If you have an interface A:
>>>>> >
>>>>> > /* version 1.0 */
>>>>> > interface A {
>>>>> > /* returns true in a certain condition */
>>>>> > boolean check();
>>>>> > }
>>>>> >
>>>>> > And in a new version, this interface has been changed like this:
>>>>> >
>>>>> > /* version ??? */
>>>>> > interface A {
>>>>> > /* returns false in a certain condition */
>>>>> > boolean check();
>>>>> > }
>>>>> >
>>>>> > Then, even though the method signature has not changed in any way,
>>>>> > the semantics of this interface have changed in an incompatible way
>>>>> > and a major bump in versioning is required. There is just no way
>>>>> > tools are going to pick up on this as long as they're just based on
>>>>> > Java (byte)code, you actually need to understand the documentation
>>>>> > to understand this. So this is another instance where you might be
>>>>> > in for some unpleasant surprises if you blindly use the output of
>>>>> > such versioning tools.
>>>>>
>>>>> Yes. Tools can only analyze syntactic changes to find semantic
>>>>> differences. Other (non-syntactic) semantic changes need humans to
>>>>> participate in the version change decision.
>>>>>
>>>>
>>>> The conclusion seems to be that tools will differ in their approach to
>>>> interpreting defaults. Tools in the future could even attempt to go further
>>>> and analyze actual method behaviour in addition to signatures. This is fine
>>>> because RFC 197 does not place any constraints on tool developers, it
>>>> merely defines the existence and meaning of the @Consumer/ProviderType
>>>> annotations.
>>>>
>>>>
>>>>
>>>>> --
>>>>>
>>>>> *BJ Hargrave*
>>>>>
>>>>> Senior Technical Staff Member, IBM
>>>>> OSGi Fellow and CTO of the *OSGi Alliance* <http://www.osgi.org/>*
>>>>> **[email protected]* <[email protected]>
>>>>>
>>>>> office: +1 386 848 1781
>>>>> mobile: +1 386 848 3788
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> OSGi Developer Mail List
>>>>> [email protected]
>>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> OSGi Developer Mail List
>>>> [email protected]
>>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>>>
>>>
>>> _______________________________________________
>>> OSGi Developer Mail List
>>> [email protected]
>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>>
>>>
>>>
>>> _______________________________________________
>>> OSGi Developer Mail List
>>> [email protected]
>>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>>
>>
>>
>> _______________________________________________
>> OSGi Developer Mail List
>> [email protected]
>> https://mail.osgi.org/mailman/listinfo/osgi-dev
>>
>
>
> _______________________________________________
> OSGi Developer Mail List
> [email protected]
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>
_______________________________________________
OSGi Developer Mail List
[email protected]
https://mail.osgi.org/mailman/listinfo/osgi-dev