Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Mark Raynsford
On 2017-07-22T17:46:56 +0100
Neil Bartlett  wrote:
> > On 22 Jul 2017, at 14:23, Mark Raynsford  wrote:
> >
> > Yes, as am I. I used the example of multiple versions of the same jar
> > resulting in multiple conflicting registrations of services trying to
> > use the same name because having multiple versions of the same jar is
> > the primary "error" case where this can happen. If we ignore the case
> > where two unrelated jars or bundles publish services that just happen
> > to pick conflicting names, then that just leaves us with the case where
> > two versions of the *same* jar attempt to publish services with
> > conflicting names.  
> 
> But why ignore that case? It’s the primary problem. As you said, the case of 
> having multiple versions of the same module already has some protections 
> around it — in fact it’s only really possible in OSGi.

That probably should have read "if we ignore the case (for the purposes
of this discussion)". We can't ignore it in practice for the reasons
stated by you and others (including myself).

> > So, with that in mind: In Java < 9, having multiple versions of the
> > same jar on the classpath is discouraged and considered to be bad
> > practice, so this situation is _possible_ but _somewhat less likely_ to
> > occur with ServiceLoader. In Java 9, there are VM-level checks in place
> > to prevent conflicting modular jars from being loaded, so this
> > particular error case can't happen. In OSGi however, as I said, it's
> > possible if not encouraged to have two different versions of a bundle
> > installed, so this error case *can* occur. That's not a disadvantage of
> > OSGi at all, quite the opposite, but it does mean that classes that do
> > that kind of centralized registration of services have to be able to
> > cope with it.  
> 
> I don’t know what kind of VM-level checks you’re talking about here, and as 
> one of the experts on the JSR 376 Expert Group, I suppose that I really 
> should know.

I was referring to the fact that if two modular jars export the same
package, the VM won't allow them to coexist in the same ModuleLayer. I
was working from the assumption that, if a given module M exports a
package P and a service S, then another version of M (call it M') will
probably export the same package P, and therefore M and M' can't
coexist. My point was that, in the common case, Java 9 would probably
prevent that specific error case as a side effect of the export
restrictions.

I'm well aware that modules aren't required to export any packages, but
I imagine it's going to be quite a while before that becomes recognized
as a best practice. :)

> I think you may also be touching on the philosophical difference between a 
> service and a library in OSGi.
> 
> There are some degrees of grey between these opposites, such as when you 
> request an ImageFormatter with a specific name, or a MigestDigest with a 
> specific algorithm, etc.

Yeah, I understand and appreciate all of the things you mentioned. It's
this grey area that prompted the original email. As I said, (and I
think we're beating a dead horse somewhat, I've restated this
repeatedly), I was asking how experienced OSGi developers would handle
implementing an API like ImageIO.read() (not how they'd replace it
with a much better API that's OSGi-aware), and that question has been 
answered to my satisfaction!

-- 
Mark Raynsford | http://www.io7m.com


pgps7hnlgL9mW.pgp
Description: OpenPGP digital signature
___
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Neil Bartlett
Hi Justin,

That’s exactly where I was going with that analogy. The equivalent of 
service.ranking for plumbers would presumably be their Yelp rating. And if you 
have multiple plumbers all with 5-star reviews then just pick any, it doesn’t 
matter!

Neil

> On 22 Jul 2017, at 14:04, Justin Edelson  wrote:
> 
> Obviously you should pick the plumber with the highest service.ranking. 
> 
> Sorry, couldn't resist.
> 
> On Sat, Jul 22, 2017 at 7:39 AM Neil Bartlett  > wrote:
> I'm not talking at all about multiple versions of the same jar. I'm talking 
> about multiple providers of the same service, possibly even from different 
> vendors. This happens just as easily under Service Loader as under OSGi. 
> 
> In your original email you asked: why does the consumer of PNG have to care 
> which PNG provider to choose. Well isn't that just a fact of life? I need a 
> plumber to fix my toilet... there are ten plumbers in my town, which should I 
> choose? Why do I have to care about plumbers?!
> 
> Having choices can suck, but not as much as having no choice. 
> 
> Neil
> 
> On 22 Jul 2017 10:44 am, "Mark Raynsford"  > wrote:
> On 2017-07-22T00:22:31 +0100
> Neil Bartlett > wrote:
> 
> > Hello Mark,
> 
> 'Ello.
> 
> >
> > Tell me, why is this problem any harder under OSGi than with 
> > ServiceLoader?? In both cases, anybody can install a bundle or a JAR that 
> > provides a service with a name, and those names can collide.
> 
> In Java < 9, it's not so much that it can't happen, but more that
> having two different versions of the same jar file on the classpath is
> considered a mistake, and build tools like Maven will (via the Enforcer
> plugin) try to prevent that from happening. In Java 9, it's explicitly
> an error for two modular jars in the same ModuleLayer to export the
> same package, so the program won't even start up if you try it. In
> OSGi, having multiple versions of a bundle installed and running is not
> considered an error (although it's probably not exactly encouraged
> either), so the hypothetical ImageFormats class that tracks providers
> by name would give inconsistent results in that situation.
> 
> > In both ServiceLoader and OSGi there is a simple rule for selecting a 
> > single instance of a service where many are available. Under ServiceLoader 
> > it is just the first JAR on the classpath. With OSGi you can attach a 
> > service.ranking property to any service. This can be done by the developer 
> > of the service, or supplied/overridden at runtime using Config Admin. Note 
> > that even with service.ranking, it is possible to have multiple service 
> > with the same high ranking. In this case OSGi picks the service with the 
> > lowest service.id , which in effect usually means the 
> > one that was registered first.
> 
> Yes, I'm aware. As I mentioned in the other message to this list, using
> the service ranking and ID would *probably* be fine given a very
> long-running framework instance, because the ordering of service.id 
>  will
> most likely reflect the order in which a given set of bundle versions
> were installed. However, if you start up a new framework instance with
> a set of bundles already in the bundle cache, there's nothing that
> guarantees that the older bundle versions will get lower service IDs,
> right?
> 
> > By the way it is generally bad practice to provide a service name via a 
> > method on the service interface. Better to add this as a property to the 
> > service metadata, so that it can be selected using declarative filters. For 
> > example:
> >
> >   @Component(property = “name=JPEG”)
> >   public class JPEGImageFormat implements ImageFormat { … }
> >
> >   @Component
> >   public class PaintProgram {
> >   @Reference(target = “(name=JPEG)”)
> >   ImageFormat formatter;
> >   // ...
> >   }
> 
> I'd tend to agree, but I did make this point:
> 
> > Sometimes, though, a class analogous to ImageFormats
> > is necessary, particularly when you expect callers to be OSGi-unaware
> ^^^
> > and/or you only have very simple selection criteria (like a "PNG"
> > string).
> 
> In other words, if you're writing code that is expected to work both
> when running in an OSGi framework and when running on the classpath or
> module path, you may want/need to abstract over the registration of
> ImageFormats. In other words, you might want to provide a hypothetical
> ImageFormatRegistry interface that _both OSGi and non-OSGi consumers_
> can make calls into to find image formats (to avoid having to write
> one code path for OSGi, and one code path for everyone else). Outside of
> OSGi, the best-practice rules for Java < 9 make 

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Neil Bartlett
Hi Mark,

> On 22 Jul 2017, at 14:23, Mark Raynsford  wrote:
> 
> 'Ello.
> 
> I suspect we're in agreement, but I think there may've been a slight
> miscommunication somewhere...
> 
> On 2017-07-22T12:39:41 +0100
> Neil Bartlett  wrote:
>> 
>> I'm not talking at all about multiple versions of the same jar. I'm talking
>> about multiple providers of the same service, possibly even from different
>> vendors. This happens just as easily under Service Loader as under OSGi.
> 
> Yes, as am I. I used the example of multiple versions of the same jar
> resulting in multiple conflicting registrations of services trying to
> use the same name because having multiple versions of the same jar is
> the primary "error" case where this can happen. If we ignore the case
> where two unrelated jars or bundles publish services that just happen
> to pick conflicting names, then that just leaves us with the case where
> two versions of the *same* jar attempt to publish services with
> conflicting names.

But why ignore that case? It’s the primary problem. As you said, the case of 
having multiple versions of the same module already has some protections around 
it — in fact it’s only really possible in OSGi.

The fundamental problem, it seems to be, is that you simply cannot *stop* two 
or more people providers from saying, “hey I have an ImageFormatter for PNG 
files”. That is true under Java <9 without OSGi, it’s true under OSGi, and it’s 
true in Java 9, so all of those things seem to be distractors.

> 
> So, with that in mind: In Java < 9, having multiple versions of the
> same jar on the classpath is discouraged and considered to be bad
> practice, so this situation is _possible_ but _somewhat less likely_ to
> occur with ServiceLoader. In Java 9, there are VM-level checks in place
> to prevent conflicting modular jars from being loaded, so this
> particular error case can't happen. In OSGi however, as I said, it's
> possible if not encouraged to have two different versions of a bundle
> installed, so this error case *can* occur. That's not a disadvantage of
> OSGi at all, quite the opposite, but it does mean that classes that do
> that kind of centralized registration of services have to be able to
> cope with it.

I don’t know what kind of VM-level checks you’re talking about here, and as one 
of the experts on the JSR 376 Expert Group, I suppose that I really should know.

You may be confused with the multiple export restriction? Which says you can’t 
have multiple modules exporting the same package in the same JPMS Layer. 
However that’s not relevant because a service provider doesn’t need to export 
anything at all. There only needs to be one export of the service API package — 
that is, the ImageFormatter interface. All of the providers simply import that 
package and implement the interface. Obviously in Java you can have multiple 
implementations of an interface.

> 
>> In your original email you asked: why does the consumer of PNG have to care
>> which PNG provider to choose. Well isn't that just a fact of life? I need a
>> plumber to fix my toilet... there are ten plumbers in my town, which should
>> I choose? Why do I have to care about plumbers?!
>> 
>> Having choices can suck, but not as much as having no choice.
> 
> Again, I agree. However, I gave the example of the ImageIO interface as
> a general example of a problem: You have multiple providers, those
> providers are essentially hidden from you, and you only have a
> mindlessly simple selection criteria such as "PNG" to pick a provider.
> Under traditional Java, the problem is slightly diminished in some
> sense because of the primitive nature of ServiceLoader, the
> generally static nature of module deployments, and in Java 9, the
> VM-level ModuleLayer checks. Under OSGi, the situation is more complex,
> and I was asking how experienced OSGi people tended to deal with the
> situation. Nothing more!


I think you may also be touching on the philosophical difference between a 
service and a library in OSGi. With a service, you just want an implementation 
of an interface and — though you can influence the choice to some extent — you 
don’t ultimately care which implementation you get. This has the huge advantage 
of decoupling consumers from providers but it does occasionally leave you in 
the situation of needing to arbitrarily choose between multiple providers that 
seem to be equally valid. But that’s okay because… remember… you don’t care 
which implementation you get.

In the case of a library, you directly instantiate a particularly class because 
you really need that particular implementation. For example when you create a 
Base64Encoder you really don’t want OSGi or anybody else to substitute a 
different encoding! This requires coupling to a concrete class but it 
guarantees you always get exactly what you want.

There are some degrees of grey between these opposites, such as when you 
request an 

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Mark Raynsford
On 2017-07-22T13:04:15 +
Justin Edelson  wrote:

> Obviously you should pick the plumber with the highest service.ranking.
> 
> Sorry, couldn't resist.

http://academic.depauw.edu/aevans_web/HONR101-02/WebPages/Fall%202007/Kate%20W/Brazil%20the%20third/images/CS.jpg

-- 
Mark Raynsford | http://www.io7m.com


pgp7i7Aa69IVt.pgp
Description: OpenPGP digital signature
___
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Mark Raynsford
'Ello.

I suspect we're in agreement, but I think there may've been a slight
miscommunication somewhere...

On 2017-07-22T12:39:41 +0100
Neil Bartlett  wrote:
>
> I'm not talking at all about multiple versions of the same jar. I'm talking
> about multiple providers of the same service, possibly even from different
> vendors. This happens just as easily under Service Loader as under OSGi.

Yes, as am I. I used the example of multiple versions of the same jar
resulting in multiple conflicting registrations of services trying to
use the same name because having multiple versions of the same jar is
the primary "error" case where this can happen. If we ignore the case
where two unrelated jars or bundles publish services that just happen
to pick conflicting names, then that just leaves us with the case where
two versions of the *same* jar attempt to publish services with
conflicting names.

So, with that in mind: In Java < 9, having multiple versions of the
same jar on the classpath is discouraged and considered to be bad
practice, so this situation is _possible_ but _somewhat less likely_ to
occur with ServiceLoader. In Java 9, there are VM-level checks in place
to prevent conflicting modular jars from being loaded, so this
particular error case can't happen. In OSGi however, as I said, it's
possible if not encouraged to have two different versions of a bundle
installed, so this error case *can* occur. That's not a disadvantage of
OSGi at all, quite the opposite, but it does mean that classes that do
that kind of centralized registration of services have to be able to
cope with it.

> In your original email you asked: why does the consumer of PNG have to care
> which PNG provider to choose. Well isn't that just a fact of life? I need a
> plumber to fix my toilet... there are ten plumbers in my town, which should
> I choose? Why do I have to care about plumbers?!
> 
> Having choices can suck, but not as much as having no choice.

Again, I agree. However, I gave the example of the ImageIO interface as
a general example of a problem: You have multiple providers, those
providers are essentially hidden from you, and you only have a
mindlessly simple selection criteria such as "PNG" to pick a provider.
Under traditional Java, the problem is slightly diminished in some
sense because of the primitive nature of ServiceLoader, the
generally static nature of module deployments, and in Java 9, the
VM-level ModuleLayer checks. Under OSGi, the situation is more complex,
and I was asking how experienced OSGi people tended to deal with the
situation. Nothing more!

--
Mark Raynsford | http://www.io7m.com


pgpsMftRW5X8e.pgp
Description: OpenPGP digital signature
___
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Justin Edelson
Obviously you should pick the plumber with the highest service.ranking.

Sorry, couldn't resist.

On Sat, Jul 22, 2017 at 7:39 AM Neil Bartlett  wrote:

> I'm not talking at all about multiple versions of the same jar. I'm
> talking about multiple providers of the same service, possibly even from
> different vendors. This happens just as easily under Service Loader as
> under OSGi.
>
> In your original email you asked: why does the consumer of PNG have to
> care which PNG provider to choose. Well isn't that just a fact of life? I
> need a plumber to fix my toilet... there are ten plumbers in my town, which
> should I choose? Why do I have to care about plumbers?!
>
> Having choices can suck, but not as much as having no choice.
>
> Neil
>
> On 22 Jul 2017 10:44 am, "Mark Raynsford"  wrote:
>
>> On 2017-07-22T00:22:31 +0100
>> Neil Bartlett  wrote:
>>
>> > Hello Mark,
>>
>> 'Ello.
>>
>> >
>> > Tell me, why is this problem any harder under OSGi than with
>> ServiceLoader?? In both cases, anybody can install a bundle or a JAR that
>> provides a service with a name, and those names can collide.
>>
>> In Java < 9, it's not so much that it can't happen, but more that
>> having two different versions of the same jar file on the classpath is
>> considered a mistake, and build tools like Maven will (via the Enforcer
>> plugin) try to prevent that from happening. In Java 9, it's explicitly
>> an error for two modular jars in the same ModuleLayer to export the
>> same package, so the program won't even start up if you try it. In
>> OSGi, having multiple versions of a bundle installed and running is not
>> considered an error (although it's probably not exactly encouraged
>> either), so the hypothetical ImageFormats class that tracks providers
>> by name would give inconsistent results in that situation.
>>
>> > In both ServiceLoader and OSGi there is a simple rule for selecting a
>> single instance of a service where many are available. Under ServiceLoader
>> it is just the first JAR on the classpath. With OSGi you can attach a
>> service.ranking property to any service. This can be done by the developer
>> of the service, or supplied/overridden at runtime using Config Admin. Note
>> that even with service.ranking, it is possible to have multiple service
>> with the same high ranking. In this case OSGi picks the service with the
>> lowest service.id, which in effect usually means the one that was
>> registered first.
>>
>> Yes, I'm aware. As I mentioned in the other message to this list, using
>> the service ranking and ID would *probably* be fine given a very
>> long-running framework instance, because the ordering of service.id will
>> most likely reflect the order in which a given set of bundle versions
>> were installed. However, if you start up a new framework instance with
>> a set of bundles already in the bundle cache, there's nothing that
>> guarantees that the older bundle versions will get lower service IDs,
>> right?
>>
>> > By the way it is generally bad practice to provide a service name via a
>> method on the service interface. Better to add this as a property to the
>> service metadata, so that it can be selected using declarative filters. For
>> example:
>> >
>> >   @Component(property = “name=JPEG”)
>> >   public class JPEGImageFormat implements ImageFormat { … }
>> >
>> >   @Component
>> >   public class PaintProgram {
>> >   @Reference(target = “(name=JPEG)”)
>> >   ImageFormat formatter;
>> >   // ...
>> >   }
>>
>> I'd tend to agree, but I did make this point:
>>
>> > Sometimes, though, a class analogous to ImageFormats
>> > is necessary, particularly when you expect callers to be OSGi-unaware
>> ^^^
>> > and/or you only have very simple selection criteria (like a "PNG"
>> > string).
>>
>> In other words, if you're writing code that is expected to work both
>> when running in an OSGi framework and when running on the classpath or
>> module path, you may want/need to abstract over the registration of
>> ImageFormats. In other words, you might want to provide a hypothetical
>> ImageFormatRegistry interface that _both OSGi and non-OSGi consumers_
>> can make calls into to find image formats (to avoid having to write
>> one code path for OSGi, and one code path for everyone else). Outside of
>> OSGi, the best-practice rules for Java < 9 make multiple registrations
>> of an ImageFormat less likely. The strict Java 9 rules regarding
>> conflicting package exports make multiple registrations impossible, at
>> least when those registrations come from two different versions of the
>> same modular jar. In an OSGi framework, however, the situation is
>> slightly more permissive than the Java < 9 case; multiple installed
>> versions of a bundle are a reality, and complicate the implementation of
>> ImageFormatRegistry 

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Neil Bartlett
I'm not talking at all about multiple versions of the same jar. I'm talking
about multiple providers of the same service, possibly even from different
vendors. This happens just as easily under Service Loader as under OSGi.

In your original email you asked: why does the consumer of PNG have to care
which PNG provider to choose. Well isn't that just a fact of life? I need a
plumber to fix my toilet... there are ten plumbers in my town, which should
I choose? Why do I have to care about plumbers?!

Having choices can suck, but not as much as having no choice.

Neil

On 22 Jul 2017 10:44 am, "Mark Raynsford"  wrote:

> On 2017-07-22T00:22:31 +0100
> Neil Bartlett  wrote:
>
> > Hello Mark,
>
> 'Ello.
>
> >
> > Tell me, why is this problem any harder under OSGi than with
> ServiceLoader?? In both cases, anybody can install a bundle or a JAR that
> provides a service with a name, and those names can collide.
>
> In Java < 9, it's not so much that it can't happen, but more that
> having two different versions of the same jar file on the classpath is
> considered a mistake, and build tools like Maven will (via the Enforcer
> plugin) try to prevent that from happening. In Java 9, it's explicitly
> an error for two modular jars in the same ModuleLayer to export the
> same package, so the program won't even start up if you try it. In
> OSGi, having multiple versions of a bundle installed and running is not
> considered an error (although it's probably not exactly encouraged
> either), so the hypothetical ImageFormats class that tracks providers
> by name would give inconsistent results in that situation.
>
> > In both ServiceLoader and OSGi there is a simple rule for selecting a
> single instance of a service where many are available. Under ServiceLoader
> it is just the first JAR on the classpath. With OSGi you can attach a
> service.ranking property to any service. This can be done by the developer
> of the service, or supplied/overridden at runtime using Config Admin. Note
> that even with service.ranking, it is possible to have multiple service
> with the same high ranking. In this case OSGi picks the service with the
> lowest service.id, which in effect usually means the one that was
> registered first.
>
> Yes, I'm aware. As I mentioned in the other message to this list, using
> the service ranking and ID would *probably* be fine given a very
> long-running framework instance, because the ordering of service.id will
> most likely reflect the order in which a given set of bundle versions
> were installed. However, if you start up a new framework instance with
> a set of bundles already in the bundle cache, there's nothing that
> guarantees that the older bundle versions will get lower service IDs,
> right?
>
> > By the way it is generally bad practice to provide a service name via a
> method on the service interface. Better to add this as a property to the
> service metadata, so that it can be selected using declarative filters. For
> example:
> >
> >   @Component(property = “name=JPEG”)
> >   public class JPEGImageFormat implements ImageFormat { … }
> >
> >   @Component
> >   public class PaintProgram {
> >   @Reference(target = “(name=JPEG)”)
> >   ImageFormat formatter;
> >   // ...
> >   }
>
> I'd tend to agree, but I did make this point:
>
> > Sometimes, though, a class analogous to ImageFormats
> > is necessary, particularly when you expect callers to be OSGi-unaware
> ^^^
> > and/or you only have very simple selection criteria (like a "PNG"
> > string).
>
> In other words, if you're writing code that is expected to work both
> when running in an OSGi framework and when running on the classpath or
> module path, you may want/need to abstract over the registration of
> ImageFormats. In other words, you might want to provide a hypothetical
> ImageFormatRegistry interface that _both OSGi and non-OSGi consumers_
> can make calls into to find image formats (to avoid having to write
> one code path for OSGi, and one code path for everyone else). Outside of
> OSGi, the best-practice rules for Java < 9 make multiple registrations
> of an ImageFormat less likely. The strict Java 9 rules regarding
> conflicting package exports make multiple registrations impossible, at
> least when those registrations come from two different versions of the
> same modular jar. In an OSGi framework, however, the situation is
> slightly more permissive than the Java < 9 case; multiple installed
> versions of a bundle are a reality, and complicate the implementation of
> ImageFormatRegistry class.
>
> --
> Mark Raynsford | http://www.io7m.com
>
___
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread elias vasylenko
It still feels to me like you're putting the focus in the wrong place. The
problem in this example is still fundamentally being caused by a poorly
configured deployment containing unnecessary duplicates, so to me it sounds
like you're saying that you want the system to be forgiving to bad
configuration because user error is expected.

I can understand that, but if a user is doing things like installing
multiple superfluous versions of the same bundle, it's only to be expected
that their experience is not going to be perfect. Rather than trying to
work around users who don't know how to configure their installation and
organise their mods properly, isn't it better to think about how to make it
easier for them so they won't/can't make these mistakes in the first place?

For example, you say that there is nothing stopping them from
(unnecessarily) installing the same bundle twice, but why?

First of all, what actually constitutes the fundamental installation unit
of a mod? I assume it's either a special bundle (marked as a mod by some
particular capability/manifest header or contained file) or just a file
containing whatever meta-data describes the mod and a set of requirements
for the resolver?

Whatever the case, since you say there is a friendly UI I assume users are
not forced to manage naked bundles, right? So then they should only have to
deal with selecting "mods", with resolution/installation (and conflict
reporting) of dependency bundles managed transparently as a side-effect of
their mod selection.

In this case I'm still convinced there's no point in worrying about
superfluous duplicates. Just disallow selecting different versions of the
same mod as a primary unit of installation, and trust that any duplicates
amongst the set of bundles resolved to satisfy the requirements of those
mods are only those duplicates which are necessary. In other words they
should avoid the problem described as according to the end of my previous
email.

On Sat, 22 Jul 2017 at 10:16 Mark Raynsford  wrote:

> On 2017-07-21T20:14:51 +
> elias vasylenko  wrote:
> >
> > As for multiple versions of the same bundle providing the same service,
> > well they would probably share the same service-ranking so that's no
> longer
> > a solution ... but then you have to wonder about the design choices which
> > might allow this situation to happen.
>
> In my case, I'm producing a game engine where the game itself is a set
> of bundles, and third party modifications to the game (new levels, new
> creatures, etc) are also bundles. Users install new bundles via a
> friendly UI, and although I can automate the installation of dependency
> bundles via the repository and resolver services, there's nothing to
> stop a user from installing two different versions of the same bundle.
>
> --
> Mark Raynsford | http://www.io7m.com
> ___
> 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

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Mark Raynsford
On 2017-07-22T00:22:31 +0100
Neil Bartlett  wrote:

> Hello Mark,

'Ello.

> 
> Tell me, why is this problem any harder under OSGi than with ServiceLoader?? 
> In both cases, anybody can install a bundle or a JAR that provides a service 
> with a name, and those names can collide.

In Java < 9, it's not so much that it can't happen, but more that
having two different versions of the same jar file on the classpath is
considered a mistake, and build tools like Maven will (via the Enforcer
plugin) try to prevent that from happening. In Java 9, it's explicitly
an error for two modular jars in the same ModuleLayer to export the
same package, so the program won't even start up if you try it. In
OSGi, having multiple versions of a bundle installed and running is not
considered an error (although it's probably not exactly encouraged
either), so the hypothetical ImageFormats class that tracks providers
by name would give inconsistent results in that situation.

> In both ServiceLoader and OSGi there is a simple rule for selecting a single 
> instance of a service where many are available. Under ServiceLoader it is 
> just the first JAR on the classpath. With OSGi you can attach a 
> service.ranking property to any service. This can be done by the developer of 
> the service, or supplied/overridden at runtime using Config Admin. Note that 
> even with service.ranking, it is possible to have multiple service with the 
> same high ranking. In this case OSGi picks the service with the lowest 
> service.id, which in effect usually means the one that was registered first.

Yes, I'm aware. As I mentioned in the other message to this list, using
the service ranking and ID would *probably* be fine given a very
long-running framework instance, because the ordering of service.id will
most likely reflect the order in which a given set of bundle versions
were installed. However, if you start up a new framework instance with
a set of bundles already in the bundle cache, there's nothing that
guarantees that the older bundle versions will get lower service IDs,
right?

> By the way it is generally bad practice to provide a service name via a 
> method on the service interface. Better to add this as a property to the 
> service metadata, so that it can be selected using declarative filters. For 
> example:
> 
>   @Component(property = “name=JPEG”)
>   public class JPEGImageFormat implements ImageFormat { … }
> 
>   @Component
>   public class PaintProgram {
>   @Reference(target = “(name=JPEG)”)
>   ImageFormat formatter;
>   // ...
>   }

I'd tend to agree, but I did make this point:

> Sometimes, though, a class analogous to ImageFormats
> is necessary, particularly when you expect callers to be OSGi-unaware
^^^
> and/or you only have very simple selection criteria (like a "PNG"
> string).

In other words, if you're writing code that is expected to work both
when running in an OSGi framework and when running on the classpath or
module path, you may want/need to abstract over the registration of
ImageFormats. In other words, you might want to provide a hypothetical
ImageFormatRegistry interface that _both OSGi and non-OSGi consumers_
can make calls into to find image formats (to avoid having to write
one code path for OSGi, and one code path for everyone else). Outside of
OSGi, the best-practice rules for Java < 9 make multiple registrations
of an ImageFormat less likely. The strict Java 9 rules regarding
conflicting package exports make multiple registrations impossible, at
least when those registrations come from two different versions of the
same modular jar. In an OSGi framework, however, the situation is
slightly more permissive than the Java < 9 case; multiple installed
versions of a bundle are a reality, and complicate the implementation of
ImageFormatRegistry class.

-- 
Mark Raynsford | http://www.io7m.com


pgpBwD4wj7x6x.pgp
Description: OpenPGP digital signature
___
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Mark Raynsford
On 2017-07-21T16:57:20 -0400
Raymond Auge  wrote:
>
> I hate to say it because I've done exactly this on several occasions...

:)

> you get a List of tuples you can iterate over which will hold true to the
> natural ordering of the services (via ServiceReference.compareTo)
> 
> Then using a Filter (yes this part pulls in OSGi API, but very little) you
> can use the streaming API to find "the best" match in the List (if one
> exists):
> 
> Filter filter = FrameworkUtil.createFilter("(format=PNG)");
> 
> Optional bestMatch = _formats.stream().sorted(
> Collections.reverseOrder() // not totally sure you need this,

I'm not sure about this. The compareTo call would give results in order
of service ranking order, tiebreaking by selecting the service with the
lowest ID (the oldest service). In the case of multiple versions of the
same bundle being available, there's no guarantee that the bundle with
the lower service ID is the older version. That's more likely to happen
if the framework is running 24/7 (because a user might have installed a
newer version of a bundle at some point and not uninstalled the old
one), but for short-lived programs it doesn't necessarily hold.

-- 
Mark Raynsford | http://www.io7m.com


pgpcW4qM3ZyA9.pgp
Description: OpenPGP digital signature
___
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-22 Thread Mark Raynsford
On 2017-07-21T20:14:51 +
elias vasylenko  wrote:
>
> As for multiple versions of the same bundle providing the same service,
> well they would probably share the same service-ranking so that's no longer
> a solution ... but then you have to wonder about the design choices which
> might allow this situation to happen.

In my case, I'm producing a game engine where the game itself is a set
of bundles, and third party modifications to the game (new levels, new
creatures, etc) are also bundles. Users install new bundles via a
friendly UI, and although I can automate the installation of dependency
bundles via the repository and resolver services, there's nothing to
stop a user from installing two different versions of the same bundle.

-- 
Mark Raynsford | http://www.io7m.com


pgpgQSZwoOQ8K.pgp
Description: OpenPGP digital signature
___
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-21 Thread Neil Bartlett
Hello Mark,

Tell me, why is this problem any harder under OSGi than with ServiceLoader?? In 
both cases, anybody can install a bundle or a JAR that provides a service with 
a name, and those names can collide.

In both ServiceLoader and OSGi there is a simple rule for selecting a single 
instance of a service where many are available. Under ServiceLoader it is just 
the first JAR on the classpath. With OSGi you can attach a service.ranking 
property to any service. This can be done by the developer of the service, or 
supplied/overridden at runtime using Config Admin. Note that even with 
service.ranking, it is possible to have multiple service with the same high 
ranking. In this case OSGi picks the service with the lowest service.id, which 
in effect usually means the one that was registered first.

By the way it is generally bad practice to provide a service name via a method 
on the service interface. Better to add this as a property to the service 
metadata, so that it can be selected using declarative filters. For example:

@Component(property = “name=JPEG”)
public class JPEGImageFormat implements ImageFormat { … }

@Component
public class PaintProgram {
@Reference(target = “(name=JPEG)”)
ImageFormat formatter;
// ...
}

Regards,
Neil


> On 21 Jul 2017, at 19:26, Mark Raynsford  wrote:
> 
> Hello.
> 
> Consider an API like ImageIO. To write an image in the PNG format, one
> calls:
> 
>  ImageIO.write(image, "PNG", output);
> 
> The implementation of the write() method gets a list of the available
> formats via ServiceLoader and picks the one named "PNG". The "PNG"
> value is the sole criteria used to pick an image format provider.
> 
> In OSGi, we'd use the whiteboard pattern (probably with declarative
> services) to implement this. The implementation might look something
> like:
> 
>  interface ImageFormat
>  {
>String name();
>...
>  }
> 
>  @Component
>  public final class ImageFormats
>  {
>private final ConcurrentHashMap formats =
>  new ConcurrentHashMap();
> 
>@Reference(
>  cardinality = ReferenceCardinality.MULTIPLE,
>  policy = ReferencePolicy.DYNAMIC,
>  unbind = "onFormatUnregister")
>public void onFormatRegister(
>  final ImageFormat format)
>{
>  this.formats.put(format.name(), format);
>}
> 
>public void onFormatUnregister(
>  final ImageFormat format)
>{
>  this.formats.remove(format.name(), format);
>}
> 
>...
>  }
> 
> This would work perfectly well, but what happens if two bundles
> try to register a format with the same name? We could check for
> and reject registrations with overlapping names, but that might
> leave developers/users stuck with a format implementation that
> they don't like. What if two different versions of the same bundle
> are installed, and both try to register themselves?
> 
> This is a problem that seems to come up in various guises each
> time I work with OSGi, and I've not really seen a satisfactory
> solution to it. Many solutions involve bubbling up the entirely
> internal concern of there being multiple versions of a format
> provider present to the API, and although this can work, it does
> mean that users are then forced to intelligently pick providers
> ("I just want PNG, why do I have to care which of the providers
> I end up with?! Isn't the ImageFormats class supposed to pick
> for me?!"). Part of this problem is caused by the fact that the
> ImageFormats class exists at all; users could, for example,
> search for services providing ImageFormat themselves via DS or
> the OSGi APIs. Sometimes, though, a class analogous to ImageFormats
> is necessary, particularly when you expect callers to be OSGi-unaware
> and/or you only have very simple selection criteria (like a "PNG"
> string).
> 
> How do people that know more about OSGi than I do usually handle
> this?
> 
> -- 
> Mark Raynsford | http://www.io7m.com
> ___
> 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

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-21 Thread Raymond Auge
I hate to say it because I've done exactly this on several occasions...

But that is a bad design for the reasons you mentioned! However it happens
enough that DS has something that can get your pretty close.

The most recent version of the DS spec which added Field injection and in
particular tuples. If you create a injected field like so:

@Reference(
cardinality = ReferenceCardinality.MULTIPLE,
policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY
)
private volatile List, ImageFormat>>
_formats;

you get a List of tuples you can iterate over which will hold true to the
natural ordering of the services (via ServiceReference.compareTo)

Then using a Filter (yes this part pulls in OSGi API, but very little) you
can use the streaming API to find "the best" match in the List (if one
exists):

Filter filter = FrameworkUtil.createFilter("(format=PNG)");

Optional bestMatch = _formats.stream().sorted(
Collections.reverseOrder() // not totally sure you need this,
but I think so
).filter(
entry -> filter.matches(entry.getKey())
).map(
Map.Entry::getValue
).findFirst();

- Ray

On Fri, Jul 21, 2017 at 2:26 PM, Mark Raynsford 
wrote:

> Hello.
>
> Consider an API like ImageIO. To write an image in the PNG format, one
> calls:
>
>   ImageIO.write(image, "PNG", output);
>
> The implementation of the write() method gets a list of the available
> formats via ServiceLoader and picks the one named "PNG". The "PNG"
> value is the sole criteria used to pick an image format provider.
>
> In OSGi, we'd use the whiteboard pattern (probably with declarative
> services) to implement this. The implementation might look something
> like:
>
>   interface ImageFormat
>   {
> String name();
> ...
>   }
>
>   @Component
>   public final class ImageFormats
>   {
> private final ConcurrentHashMap formats =
>   new ConcurrentHashMap();
>
> @Reference(
>   cardinality = ReferenceCardinality.MULTIPLE,
>   policy = ReferencePolicy.DYNAMIC,
>   unbind = "onFormatUnregister")
> public void onFormatRegister(
>   final ImageFormat format)
> {
>   this.formats.put(format.name(), format);
> }
>
> public void onFormatUnregister(
>   final ImageFormat format)
> {
>   this.formats.remove(format.name(), format);
> }
>
> ...
>   }
>
> This would work perfectly well, but what happens if two bundles
> try to register a format with the same name? We could check for
> and reject registrations with overlapping names, but that might
> leave developers/users stuck with a format implementation that
> they don't like. What if two different versions of the same bundle
> are installed, and both try to register themselves?
>
> This is a problem that seems to come up in various guises each
> time I work with OSGi, and I've not really seen a satisfactory
> solution to it. Many solutions involve bubbling up the entirely
> internal concern of there being multiple versions of a format
> provider present to the API, and although this can work, it does
> mean that users are then forced to intelligently pick providers
> ("I just want PNG, why do I have to care which of the providers
> I end up with?! Isn't the ImageFormats class supposed to pick
> for me?!"). Part of this problem is caused by the fact that the
> ImageFormats class exists at all; users could, for example,
> search for services providing ImageFormat themselves via DS or
> the OSGi APIs. Sometimes, though, a class analogous to ImageFormats
> is necessary, particularly when you expect callers to be OSGi-unaware
> and/or you only have very simple selection criteria (like a "PNG"
> string).
>
> How do people that know more about OSGi than I do usually handle
> this?
>
> --
> Mark Raynsford | http://www.io7m.com
>
> ___
> OSGi Developer Mail List
> osgi-dev@mail.osgi.org
> https://mail.osgi.org/mailman/listinfo/osgi-dev
>



-- 
*Raymond Augé* 
 (@rotty3000)
Senior Software Architect *Liferay, Inc.* 
 (@Liferay)
Board Member & EEG Co-Chair, OSGi Alliance  (@OSGiAlliance)
___
OSGi Developer Mail List
osgi-dev@mail.osgi.org
https://mail.osgi.org/mailman/listinfo/osgi-dev

Re: [osgi-dev] Names in the presence of multiple bundle versions

2017-07-21 Thread elias vasylenko
Hi,

The normal strategy here would be to give priority to the ImageFormat
service with the highest *service-ranking* and ignore others with the same
name. Depending on how you set up your ImageFormats class you can even have
DS inject services in ranking order to make it easier. Anyway there are
better sources than me to explain it once you know what to search for so
I'll leave it at that.

As for multiple versions of the same bundle providing the same service,
well they would probably share the same service-ranking so that's no longer
a solution ... but then you have to wonder about the design choices which
might allow this situation to happen.

Typically if you have to deploy multiple versions of the same service
provider, it's because they are implementing different versions of an API.
In other words, you may have some bundles consuming e.g. the image format
1.0.0 API and others consuming the image format 2.0.0 API, such that you
need to deploy a PNG ImageFormat service implementing each one. In this
case they're not actually going to mix, as you will also need two
respective versions of the ImageFormats component which will pick them up
separately.

Sure, it's possible to imagine a situation where the two PNG ImageFormat
services would both need to be deployed even though they implement the
*same* API version, but if this is actually happening it almost certainly
should have been avoided. Perhaps by having a cleaner versioning strategy
and not over-burdening the bundle which provides the PNG ImageFormat
service with too many independent responsibilities.

On Fri, 21 Jul 2017 at 19:26 Mark Raynsford  wrote:

> Hello.
>
> Consider an API like ImageIO. To write an image in the PNG format, one
> calls:
>
>   ImageIO.write(image, "PNG", output);
>
> The implementation of the write() method gets a list of the available
> formats via ServiceLoader and picks the one named "PNG". The "PNG"
> value is the sole criteria used to pick an image format provider.
>
> In OSGi, we'd use the whiteboard pattern (probably with declarative
> services) to implement this. The implementation might look something
> like:
>
>   interface ImageFormat
>   {
> String name();
> ...
>   }
>
>   @Component
>   public final class ImageFormats
>   {
> private final ConcurrentHashMap formats =
>   new ConcurrentHashMap();
>
> @Reference(
>   cardinality = ReferenceCardinality.MULTIPLE,
>   policy = ReferencePolicy.DYNAMIC,
>   unbind = "onFormatUnregister")
> public void onFormatRegister(
>   final ImageFormat format)
> {
>   this.formats.put(format.name(), format);
> }
>
> public void onFormatUnregister(
>   final ImageFormat format)
> {
>   this.formats.remove(format.name(), format);
> }
>
> ...
>   }
>
> This would work perfectly well, but what happens if two bundles
> try to register a format with the same name? We could check for
> and reject registrations with overlapping names, but that might
> leave developers/users stuck with a format implementation that
> they don't like. What if two different versions of the same bundle
> are installed, and both try to register themselves?
>
> This is a problem that seems to come up in various guises each
> time I work with OSGi, and I've not really seen a satisfactory
> solution to it. Many solutions involve bubbling up the entirely
> internal concern of there being multiple versions of a format
> provider present to the API, and although this can work, it does
> mean that users are then forced to intelligently pick providers
> ("I just want PNG, why do I have to care which of the providers
> I end up with?! Isn't the ImageFormats class supposed to pick
> for me?!"). Part of this problem is caused by the fact that the
> ImageFormats class exists at all; users could, for example,
> search for services providing ImageFormat themselves via DS or
> the OSGi APIs. Sometimes, though, a class analogous to ImageFormats
> is necessary, particularly when you expect callers to be OSGi-unaware
> and/or you only have very simple selection criteria (like a "PNG"
> string).
>
> How do people that know more about OSGi than I do usually handle
> this?
>
> --
> Mark Raynsford | http://www.io7m.com
> ___
> 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