You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@aries.apache.org by Holly Cummins <ho...@googlemail.com> on 2012/04/18 18:58:34 UTC

Which implementors of application interfaces are providers?

Hi all,

Once we're using version numbers 1.0.0 and above for our packages, we need
to think a bit about when we're importing a package to provide it, and when
we're doing a normal import. In the provider case we want to use a
[1.0,1.1) range and in the more general case we'll want [1.0,2). I'm
sifting through all the classes which implement or extend an
org.apache.aries.* interface or class to try and get the metadata right.

(I haven't looked at classes in src/test, since I don't know of any
sensible way of configuring their package imports, and since I think
they're unlikely to be used outside our well-defined build environment, and
it's just too darn hard.)


I've had an initial pass at the org.apache.aries.application.* packages,
and come up with a list of bundles which provide them. In most cases these
interfaces were implemented by other classes within the application module,
and they were clearly being provided. In a few cases, I decided it looked
like they were being consumed, and in one case, ejb modelling, I wasn't
sure whether something which implemented an interface was providing it or
consuming it.


However, the fact that I had such a hard time working out when interfaces
were being provided and consumed made me a bit nervous about whether we'd
get the version increments right when we change a package. For example, I
decided that our use of the UpdateStrategy.UpdateInfo in
the org.apache.aries.runtime.deployment.management bundle was consumption,
not provision. However, will we really remember this decision if we change
that interface, and bump the package version up by a major increment?


Adopting a blanket policy where we say any implementation of a package
within the same module (for example, application) is provision, and we use
the narrower version ranges, has some advantages. It's way easier for us to
remember than my complex list below, which might make it easier for us to
ensure we get changes to our package versions right. It would also save me
a lot of work trying to make fine-grained decisions about each implementer.
However, it doesn't help us with remembering to bump packages which have
implementations outside a module up by a major increment when we change
them. It might also compromise release-by-bundle by restricting different
versions of bundles from the same module from working together.


Thoughts?


This is the list of providers and consumers I've come up with for the
org.apache.aries.application.* packages.



--------------------------------------------------

PACKAGE org.apache.aries.application

PROVIDED BY

- org.apache.aries.application.utils


--------------------------------------------------

PACKAGE org.apache.aries.application.management


No 'outside-bundle' implementors


--------------------------------------------------

PACKAGE org.apache.aries.application.modelling


PROVIDED BY


- org.apache.aries.application.modeller
- org.apache.aries.application.resolve.transform.cm

    private static class ConfigAwareDeployedBundles implementsDeployedBundles

- org.apache.aries.application.resolve.obr

     public class ModelledBundleResource implements ModelledResource {

UNSURE

- org.apache.aries.ejb.modeller

    public class EJBServiceExport implements ExportedService {

--------------------------------------------------

PACKAGE org.apache.aries.application.management.spi.convert


PROVIDED BY


- org.apache.aries.application.converters
public class WabConverterService implements BundleConverter {


--------------------------------------------------

PACKAGE org.apache.aries.application.management.spi.framework


PROVIDED BY

- org.apache.aries.application.runtime.framework

- org.apache.aries.application.runtime.framework.management

- org.apache.aries.application.runtime.isolated



--------------------------------------------------

PACKAGE org.apache.aries.application.management.spi.repository


PROVIDED BY

- org.apache.aries.application.management

- org.apache.aries.application.resolver.obr

- org.apache.aries.application.runtime.repository


--------------------------------------------------

PACKAGE org.apache.aries.application.management.spi.resolve


PROVIDED BY

- org.apache.aries.application.deployment.management

- org.apache.aries.application.management

- org.apache.aries.application.resolve.transform.cm

- org.apache.aries.application.resolver.noop

- org.apache.aries.application.resolver.obr

CONSUMED BY

- org.apache.aries.application.framework.runtime.management
   public class SharedFrameworkPreResolveHook implements PreResolveHook

--------------------------------------------------

PACKAGE org.apache.aries.application.management.spi.runtime


PROVIDED BY

- org.apache.aries.application.runtime.default.local.platform

- org.apache.aries.application.runtime

- org.apache.aries.application.runtime.isolated


--------------------------------------------------

PACKAGE org.apache.aries.application.management.spi.update

CONSUMED BY org.apache.aries.runtime.deployment.management

      strategy.update(new UpdateStrategy.UpdateInfo() {


--------------------------------------------------

PACKAGE org.apache.aries.application.modelling.utils


No 'outside-bundle' implementors

Re: Which implementors of application interfaces are providers?

Posted by David Jencks <da...@yahoo.com>.
I hope we can either keep the text package.info files (I expect easy) or find a way that the semantic version checker plugin can deal with the package-info.java files (a lot harder since we'd have to parse pretty much the entire file?).

BTW IIRC you need to configure separate patterns for version ranges for consumer and producer, maybe that's why it doesn't appear to be working yet?

thanks
david jencks

On Apr 19, 2012, at 9:08 AM, Holly Cummins wrote:

> Felix wrote:
> 
> 
> IIRC bnd (and thus the bundle plugin) in recent versions is able to find
>> this out and generate the import version ranges appropriately.
>> 
> 
> I wrote:
> 
> 
>> Ah, now that would be handy! I've just checked and it's not doing it in
>> our current build but I'll have an explore of more recent bnd versions and
>> see if I can make it work, since it would save me a lot of time. The bnd
>> docs seem to indicate it's a manual process:
>> 
>> "How does bnd know if a bundle is a provider or a consumer of a specific
>> package? Well, the default is the consumer policy but this can be
>> overridden with the provide:=true directive that works on the
>> Import-Package clauses as well as on the Export-Package clauses." (
>> http://www.aqute.biz/Bnd/Versioning)
>> 
>> However, I'll look around and see if there's an automated detection which
>> isn't referenced from that page. Thanks!
>> 
> 
> Ah, found it, just after hitting 'send'! I think it only works with the
> ProviderType and ConsumerType annotations you mentioned:
> https://github.com/bndtools/bnd/issues/112
> 
> So they'll probably be a good way of getting the versioning right without
> having to hand-sift all our POMs (although it will be a lot of java
> changes).
> 
> Holly
> 
> Holly


Re: Which implementors of application interfaces are providers?

Posted by Holly Cummins <ho...@googlemail.com>.
Felix wrote:


IIRC bnd (and thus the bundle plugin) in recent versions is able to find
> this out and generate the import version ranges appropriately.
>

I wrote:


> Ah, now that would be handy! I've just checked and it's not doing it in
> our current build but I'll have an explore of more recent bnd versions and
> see if I can make it work, since it would save me a lot of time. The bnd
> docs seem to indicate it's a manual process:
>
> "How does bnd know if a bundle is a provider or a consumer of a specific
> package? Well, the default is the consumer policy but this can be
> overridden with the provide:=true directive that works on the
> Import-Package clauses as well as on the Export-Package clauses." (
> http://www.aqute.biz/Bnd/Versioning)
>
> However, I'll look around and see if there's an automated detection which
> isn't referenced from that page. Thanks!
>

Ah, found it, just after hitting 'send'! I think it only works with the
ProviderType and ConsumerType annotations you mentioned:
https://github.com/bndtools/bnd/issues/112

So they'll probably be a good way of getting the versioning right without
having to hand-sift all our POMs (although it will be a lot of java
changes).

Holly

Holly

Re: Which implementors of application interfaces are providers?

Posted by Holly Cummins <ho...@googlemail.com>.
Hi Felix,

Thanks for the comments.

On Thu, Apr 19, 2012 at 3:54 AM, Felix Meschberger <fm...@adobe.com>wrote:

[snip]

>
> I think key are the "implements XXX" and "extends XXX" clauses (and
> similar anonymous classes). As soon as you have something like that in your
> code, it is "providing" and the narrow version range applies.


My understanding was that it was a bit more subtle than this, because some
APIs, like javax.http.HttpServlet, for example, are intended to be
subclassed by consumers of the API. So adding an extra method onto this API
would be a breaking change for consumers, even though it would normally
only be a minor-increment change.

However, avoiding such subtlety/tortuousness in our internal versioning
would clearly have some advantages, particularly if that understanding of
'provider' isn't universal.

IIRC bnd (and thus the bundle plugin) in recent versions is able to find
> this out and generate the import version ranges appropriately.
>

Ah, now that would be handy! I've just checked and it's not doing it in our
current build but I'll have an explore of more recent bnd versions and see
if I can make it work, since it would save me a lot of time. The bnd docs
seem to indicate it's a manual process:

"How does bnd know if a bundle is a provider or a consumer of a specific
package? Well, the default is the consumer policy but this can be
overridden with the provide:=true directive that works on the
Import-Package clauses
as well as on the Export-Package clauses." (
http://www.aqute.biz/Bnd/Versioning)

However, I'll look around and see if there's an automated detection which
isn't referenced from that page. Thanks!

>
> As for package exports, I started using the package-info.java file with
> basically these BND annotations
>
>   @Version("1.0")
>   @Export(optional = "provide:=true")
>   package xxx.xxx.xxx;
>
> Where the "provide:=true" is added if there is at least one
> interface/class implemented or extended within the same bundle.
>

I don't think we have any of these annotations, and I can see they'd be
very useful, so I'll put adding them onto my to do list.  I guess doing so
would mean switching from the text package info files to java ones. Are
there any opinions about doing this, one way or another?

>
> Also, I find it helpful to use the @ProviderType (provided by the
> exporting bundle) and @ConsumerType (consumed by the exporting bundle) BND
> annotations.
>

I'll have a look at these as well. Thanks.

Holly

Re: Which implementors of application interfaces are providers?

Posted by Felix Meschberger <fm...@adobe.com>.
Hi,

Am 18.04.2012 um 18:58 schrieb Holly Cummins:

> Hi all,
> 
> Once we're using version numbers 1.0.0 and above for our packages, we need
> to think a bit about when we're importing a package to provide it, and when
> we're doing a normal import. In the provider case we want to use a
> [1.0,1.1) range and in the more general case we'll want [1.0,2). I'm
> sifting through all the classes which implement or extend an
> org.apache.aries.* interface or class to try and get the metadata right.
> 
> (I haven't looked at classes in src/test, since I don't know of any
> sensible way of configuring their package imports, and since I think
> they're unlikely to be used outside our well-defined build environment, and
> it's just too darn hard.)

Unless you create a bundle with test cases for deployment in a testing environment, tests generally are not even deployed as binary artifacts. So there is IMHO no use in trying to come up with sensible imports.

> 
> 
> I've had an initial pass at the org.apache.aries.application.* packages,
> and come up with a list of bundles which provide them. In most cases these
> interfaces were implemented by other classes within the application module,
> and they were clearly being provided. In a few cases, I decided it looked
> like they were being consumed, and in one case, ejb modelling, I wasn't
> sure whether something which implemented an interface was providing it or
> consuming it.
> 
> 
> However, the fact that I had such a hard time working out when interfaces
> were being provided and consumed made me a bit nervous about whether we'd
> get the version increments right when we change a package. For example, I
> decided that our use of the UpdateStrategy.UpdateInfo in
> the org.apache.aries.runtime.deployment.management bundle was consumption,
> not provision. However, will we really remember this decision if we change
> that interface, and bump the package version up by a major increment?
> 
> 
> Adopting a blanket policy where we say any implementation of a package
> within the same module (for example, application) is provision, and we use
> the narrower version ranges, has some advantages. It's way easier for us to
> remember than my complex list below, which might make it easier for us to
> ensure we get changes to our package versions right. It would also save me
> a lot of work trying to make fine-grained decisions about each implementer.
> However, it doesn't help us with remembering to bump packages which have
> implementations outside a module up by a major increment when we change
> them. It might also compromise release-by-bundle by restricting different
> versions of bundles from the same module from working together.
> 
> 
> Thoughts?

I think key are the "implements XXX" and "extends XXX" clauses (and similar anonymous classes). As soon as you have something like that in your code, it is "providing" and the narrow version range applies. IIRC bnd (and thus the bundle plugin) in recent versions is able to find this out and generate the import version ranges appropriately.

As for package exports, I started using the package-info.java file with basically these BND annotations

   @Version("1.0")
   @Export(optional = "provide:=true")
   package xxx.xxx.xxx;

Where the "provide:=true" is added if there is at least one interface/class implemented or extended within the same bundle.

Also, I find it helpful to use the @ProviderType (provided by the exporting bundle) and @ConsumerType (consumed by the exporting bundle) BND annotations.

As for the concrete example:

> PACKAGE org.apache.aries.application.modelling
> - org.apache.aries.ejb.modeller
> 
>    public class EJBServiceExport implements ExportedService {

I would say, that this class "implements" the interface and thus the import must be using the narrow range.

At the end of the day, API is extremely important and IMHO it is a good thing, to make changes to the API as complex as possible for developers as an additional barrier to changing too light-heartedly.

Just my $.02

Regards
Felix