Skip to content
This repository has been archived by the owner on Dec 4, 2020. It is now read-only.

[core] Add Map/Dictionary converter to the org.osgi.framework APIs #2949

Open
bjhargrave opened this issue Jun 29, 2018 · 36 comments
Open

[core] Add Map/Dictionary converter to the org.osgi.framework APIs #2949

bjhargrave opened this issue Jun 29, 2018 · 36 comments
Assignees

Comments

@bjhargrave
Copy link
Member

Original bug ID: BZ#3081
From: @rinswind
Reported version: R7

See also: BZ#3091

@bjhargrave
Copy link
Member Author

Comment author: @rinswind

On the equinox-dev mailing list someone asked why don't we add Map<String, Object> flavors of the methods that use Dictionary. E.g. BundleContext.registerService();

http://dev.eclipse.org/mhonarc/lists/equinox-dev/msg08867.html

I found Bug BZ#974, where BJ states that Map's will be used in "org.osgi.framework; version=2.0". This was in 2008.

Maybe as suggested in equinox-dev we should deprecate the old versions and add Map-flavoured versions. We seem to have decided that breaking compatibility of the core APIs is too dangerous.

In the same vane I was not present when the decision was made to add
ServiceReference.getProperties() with return type Dictionary. Why was this done?

Generally why Dictionary was retained even in "org.osgi.framework; version=1.6" when generics were added and we had the change to do it right?

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

We use Dictionary for historical reasons since we needed OSGi to run on Java ME CDC and older versions of Java.

With the addition of DI systems like DS, Blueprint and soon CDI, there is little reason to override the low level API which takes Dictionary with versions which take Map. It could certainly be done at the cost of making the API much wider.

I also would not support deprecating the methods which take Dictionary as Dictionary is not a deprecated type. While it may be listed as obsolete, it is not deprecated and is still fully supported in Java.

An easier solution may be to define a static utility method, e.g.

<K,V> Dictionary<K,V> FrameworkUtil.asDictionary(Map<K,V> map)

which could be use to wrap a map into a dictionary.

I think the utility method is the simplest solution since it allows users to pass their Map, after wrapping, to the low level API and does not "pollute" the API with duplicate methods which vary only be Dictionary/Map.

This "issue" is just a "style" issue. People see Dictionary and are somehow upset :-) There is nothing wrong with Dictionary. It is just an older type. Somehow Date does not upset people as much even though it has been obsoleted by newer types!

@bjhargrave
Copy link
Member Author

Comment author: @rotty3000

I agree, but might I suggest that if we make such a utility function Map->Dictionary, that we also have Dictionary->Map since OSGi has methods (including brand new ones) which return Dictionary (e.g. ServiceReference.getProperties, etc.)

@bjhargrave
Copy link
Member Author

Comment author: @tjwatson

(In reply to Raymond Auge from comment BZ#2)

I agree, but might I suggest that if we make such a utility function
Map->Dictionary, that we also have Dictionary->Map since OSGi has methods
(including brand new ones) which return Dictionary (e.g.
ServiceReference.getProperties, etc.)

I agree with BJ that an asDictionary could be generally useful and likely small. We likely have internal implementations for such things as Filter.match(Map) Converting Dictionary->Map could also be useful, but would like to see the concrete usecase with OSGi APIs that would warrant the addition. Map has a much bigger API footprint so the wrapping class will have more to implement and test.

@bjhargrave
Copy link
Member Author

Comment author: @pkriens

I am not sure I understand the argumentation to not fully support Map. Methods making the existing API more modern have tremendous marketing value for something like OSGi that is already suspect in many cases. Let's face it, if you see a Dictionary in an API you do not get the impression that this is a fresh new active nice API?

Let's face it, using Dictionary with its enumeration is a pain in the ass to work with nowadays.

So I think we should modernize the API and declare the old methods obsolete. A static conversion method is the absolute wrong direction to go imho.

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

(In reply to Peter Kriens from comment BZ#4)

Let's face
it, if you see a Dictionary in an API you do not get the impression that
this is a fresh new active nice API?

I am unmotivated by the argument that an API which has Dictionary in its signature is old fashioned or unhip. I am, however, motivated by an argument that says a developer has a Map object and needs to call an OSGi API which takes a Dictionary or a developer receives a Dictionary object from an OSGi API but needs to pass a Map to some other method. This latter argument can be addressed by utility methods which can wrap a Dictionary as a Map or a Map as a Dictionary. (And since some framework Dictionary implementations are extends Dictionary implements Map, the utility methods can do an instanceof check and simply cast. https://osgi.org/gitweb/build.git/blob/refs/heads/core:/org.osgi.test.support/src/org/osgi/test/support/dictionary/DictionaryMap.java#l31)

I searched the org.osgi.framework package for Dictionary in method signatures. I removed Filter (and FrameworkUtil) since Filter already has Map overloads:

Bundle.java (2 matches)
Dictionary<String, String> getHeaders();
Dictionary<String, String> getHeaders(String locale);

BundleContext.java (4 matches)
ServiceRegistration registerService(String[] clazzes, Object service, Dictionary properties);
ServiceRegistration registerService(String clazz, Object service, Dictionary properties);
ServiceRegistration registerService(Class clazz, S service, Dictionary<String, ?> properties);
ServiceRegistration registerService(Class clazz, ServiceFactory factory, Dictionary<String, ?> properties);

ServiceReference.java
public Dictionary<String,Object> getProperties();

ServiceRegistration.java
public void setProperties(Dictionary<String, ?> properties);

So for Bundle, we would need a new method to return the headers as a Map. (We dont need a no-params overload for Map.)

For BundleContext, we already have 4 registerService method overloads. So we would need 4 more methods which take Map as an argument. So that would be 8 registerService methods. That does not look like a "fresh new active nice API". It would look like a dog's dinner. :-)

For ServiceReference, we would need a new method that returns a Map

For ServiceRegistration, we would need an overload that takes a Map.

It is also not safe to simply overload the methods which take Dictionary since the overloads would be not source compatible for code which passes a Hashtable as the Dictionary argument. This is likely the most common case since Hashtable is the only Dictionary implementation in the JRE. Since Hashtable also implements Map, it is ambiguous as to which method the compiler should select. (We saw this problem when we long ago attempted org.osgi.framework-2.0). So any overload methods to take Map would need to have a different method name to avoid this source incompatibility problem. registerService2 anyone?

So, for the org.osgi.framework package alone, this is 7 new methods which don't add any new function to the framework. To, me such a change does not carry its weight.

Note, I only looked in org.osgi.framework for the above, the following other packages also reference Dictionary and would need some consideration.

org.osgi.application
org.osgi.jmx
org.osgi.service.cm
org.osgi.service.component
org.osgi.service.condpermadmin
org.osgi.service.dal
org.osgi.service.device
org.osgi.service.dmt
org.osgi.service.event
org.osgi.service.http
org.osgi.service.provisioning
org.osgi.service.remoteserviceadmin
org.osgi.service.upnp
org.osgi.service.useradmin
org.osgi.service.wireadmin
org.osgi.util.converter

So I still would rather see that we add an org.osgi.util.dictionary package (rather than putting in FrameworkUtil so users do not have to couple to the framework package) with static utility methods to wrap Dictionary objects as Maps and Maps as Dictionarys. This would be equally useful for framework API users as well as users of any other OSGi API which takes or consumes Dictionary.

See https://osgi.org/gitweb/build.git/blob/refs/heads/core:/org.osgi.test.support/src/org/osgi/test/support/dictionary/DictionaryMap.java for such a utility class for wrapping a Dictionary in a Map. I use this in a CT, https://osgi.org/gitweb/build.git/blob/refs/heads/core:/org.osgi.test.cases.bundle.annotations/src/org/osgi/test/cases/bundle/annotations/junit/HeaderAnnotationsTestClass.java#l28, to take the Dictionary returned by Bundle.getHeaders and pass it, as a Map, to a method.

@bjhargrave
Copy link
Member Author

Comment author: @rinswind

Why did we not make the newer methods use Maps in the first place?
E.g.
ServiceRegistration registerService(Class type, T service, Map<String, Object> props);

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

(In reply to Todor Boev from comment BZ#6)

Why did we not make the newer methods use Maps in the first place?
E.g.
ServiceRegistration registerService(Class type, T service,
Map<String, Object> props);

I would assume for consistency with the existing methods. And also since we still probably needed to support OSGi Minimum EE at the time those methods were added.

@bjhargrave
Copy link
Member Author

Comment author: @timothyjward

There is an important API difference that has not been taken into account.

The Map interface is very permissive, it allows keys to be associated with null values, and for null to be used as a key. Both of these things would be very bad for Service Properties and for Configuration Admin.

Dictionary, on the other hand, does not permit these things, and so prevents a large amount of checking/copying/error cases that might otherwise occur.

@bjhargrave
Copy link
Member Author

Comment author: @pkriens

I was at a customer today and during lunch asked them about Dictionary ...

Ever been in an occasion where your fly was accidentally open? That was how it felt. They clearly had made fun of Dictionary among themselves and did not want to emberras me. They really could not understand how on earth we still used this a the mainstream type. Very much in agreement with Lars Vogel's remarks. I do expect this is actually makes us lose 'customers'.

I find almost all of the argument putting the implementers/specifiers first and application developers second. Which, imho, is putting the cart in front of the horse imho.

One way out of this conundrum is if we add adapt(Class<T>) to BundleContext and then provide a more modern version of BundleContext designed from scratch. (I am perfectly ok with BundleContext2*) This BundleContext2 should then also be acceptable in the DS and CDI injection sites. (I do not think it is worth to add a new BundleActivator.)

About null, Hashtable does not accept null and is also a Map. So Java seems to allow restricting keys and values for implementations?

  • Golang is not versioning packages for major changes because they decided to add a version in the name. I.e. foo.bar.v2.baz. I can see this reduces a lot of complexity and one gets easily used to this model over time I think.

@bjhargrave
Copy link
Member Author

Comment author: @pkriens

I did a bit of experimenting with BundleContext2. It is clear that BundleContext is not cohesive. It consists of:

  • the context of the bundle (data file, get the bundle, object, etc.)
  • service registry
  • bundle management

So we could use this to split this up in different interfaces

BundleContext2:

Map<String,String> getProperties();
Path getDataFile(String filename);
Bundle getBundle();

ManagementAgent:

Bundle installBundle(URI location, InputStream input) throws BundleException;
Bundle installBundle(URI location) throws BundleException;
Bundle getBundle(long id);
List<Bundle> getBundles();
Bundle getBundle(URI location);
Closeable addBundleListener(BundleListener listener);
Closeable addFrameworkListener(FrameworkListener listener);

ServiceRegistry:

<S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Map<String, ?> properties, Class<?> ... moreClasses);
<S> ServiceRegistration<S> registerService(Class<S> clazz, ServiceFactory<S> factory, Map<String, ?> properties);
<S> ServiceReference<S> getServiceReference(Class<S> clazz);
<S> List<ServiceReference<S>> getAllServiceReferences(Class<S> clazz, String filter);
<S> List<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter) throws InvalidSyntaxException;
<S> S getService(ServiceReference<S> reference);
boolean ungetService(ServiceReference<?> reference);
<S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference);
Closeable addServiceListener(ServiceListener listener, String filter) ;
Closeable addServiceListener(ServiceListener listener);

Hmmm:

Filter createFilter(String filter);

@bjhargrave
Copy link
Member Author

Comment author: @rotty3000

I have also witnessed this type of scenario on several occasions where the thinking is:

OSGi is old and we need to work around it's old-ness

It results in a scenario where we lose a lot of good will for very little benefit.

Now, we certainly cannot fault OSGi in any way for being so damn resilient to change while continuing to achieve the extraordinary level of function year after year. But just like in human language which I'm sure any linguist from 200 years ago would have argued that the language of the time was good enough to do everything it needed to do. Ultimately it still had to change as we all know.

OSGi is bloody fantastic, but it still has to change regardless, or it will simply fade out of memory.

The type of change we're talking here is precisely the type of "period" change required to keep it fresh. Yes, it's not functional, it's not perfect, it's not even needed technically, but it's needed for perception and acceptance and to stay relevant.

@bjhargrave
Copy link
Member Author

Comment author: @rotty3000

@ Peter, what about making most, if not all exceptions unchecked?

@bjhargrave
Copy link
Member Author

Comment author: @pkriens

I did it for the horrible IllegalSyntaxException, forgot I could also do this with the BundleException ...

@bjhargrave
Copy link
Member Author

Comment author: @rinswind

About 12 years ago I tried to hack felix to replace the org.osgi.framework APIs with something almost identical to what Peter proposed. Especially the BundleContext split into pretty much the same pieces. I did not have the time to complete the work.

I think we all like to see a modernised core APIs, because we code infrastructure or low level functionality.

I think it is not true that the core API is hidden from everyday developers. Every developer who approaches OSGi goes to the core APIs to see what it is all about. I sure do this king of digging into projects when I start using them. Also training materials/books on OSGi have to contain large sections with the core APIs. OSGi was always a hard sell and now with the Java modules released and all the dramatic changes to the language since Java 8 the core APIs are one more thing to turn people away from OSGi.

Developing an "org.osgi.framework;version:=2.0" is a massive undertaking that I am sure was considered many times and there were good reasons to not attempt it. However it may have become a matter of survival to do the transition. This may be the major feature of R8.

To make this discussion productive at all I think we should re-visit the arguments against modernisation. The conditions now may be more permissive.

As a final note I can say that it is frustrating that in a modular system with strong versioning that is precisely designed to support this king of change we can't make use of our own core features to change the core.

1 similar comment
@bjhargrave
Copy link
Member Author

Comment author: @rinswind

About 12 years ago I tried to hack felix to replace the org.osgi.framework APIs with something almost identical to what Peter proposed. Especially the BundleContext split into pretty much the same pieces. I did not have the time to complete the work.

I think we all like to see a modernised core APIs, because we code infrastructure or low level functionality.

I think it is not true that the core API is hidden from everyday developers. Every developer who approaches OSGi goes to the core APIs to see what it is all about. I sure do this king of digging into projects when I start using them. Also training materials/books on OSGi have to contain large sections with the core APIs. OSGi was always a hard sell and now with the Java modules released and all the dramatic changes to the language since Java 8 the core APIs are one more thing to turn people away from OSGi.

Developing an "org.osgi.framework;version:=2.0" is a massive undertaking that I am sure was considered many times and there were good reasons to not attempt it. However it may have become a matter of survival to do the transition. This may be the major feature of R8.

To make this discussion productive at all I think we should re-visit the arguments against modernisation. The conditions now may be more permissive.

As a final note I can say that it is frustrating that in a modular system with strong versioning that is precisely designed to support this king of change we can't make use of our own core features to change the core.

@bjhargrave
Copy link
Member Author

Comment author: @tverbele

Why should this be a BundleContext replacement / addition ... Another solution would be to have the framework expose additional services, e.g. a ServiceRegistry service that gives a more modern API to register/find services?

Similarly, we already have a FrameworkManager service defined in the ClusterInfo spec that exposes some of the BundleContext functionality.

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

(In reply to Todor Boev from comment BZ#15)

Developing an "org.osgi.framework;version:=2.0" is a massive undertaking
that I am sure was considered many times and there were good reasons to not
attempt it. However it may have become a matter of survival to do the
transition. This may be the major feature of R8.

To make this discussion productive at all I think we should re-visit the
arguments against modernisation. The conditions now may be more permissive.

The main reason we abandoned "org.osgi.framework;version=2.0" was that it basically causes every bundle in existence to become obsolete. "org.osgi.framework;version=2.0" also bleeds through to many other OSGi specifications which use an org.osgi.framework type like Filter, BundleContext, etc. in its API. So it essentially created a parallel universe which is all version 2.0 and incompatible with the existing universe.

Since OSGi already struggles with acceptance, creating a fork in the bundle space was not a great idea and thus abandoned. A lot of effort was put into 2.0, including public presentations discussion it, before we abandoned it. We also abandoned a change to the OSGi version format for similar reasons as well as tooling compatibility concerns.

We are basically complaining that the OSGi API does not have a fashionable haircut by today's fashion standards. (It was an OK haircut at the time.) So now people want to get it a new haircut but the haircut does not add any function, it just moves the hair around.

My preferred answer to this it a util package (a "hat") which provides wrappers for Map->Dictionary, Dictionary->Map and even a full "extends Dictionary implements Map" implementation.

Next best would to be to add methods to the current framework API to support using Map ("hair extensions") but staying at "org.osgi.framework;version=1.0".

I think it is a bad idea to go about refactoring the framework API to make it more pleasing to the modern eye. It begins to reek of second system syndrome and will ripple through many of the other OSGi specifications. I am very much against an "org.osgi.framework;version=2.0".

In any case, we are not going to do anything significant directly via this bug. Next step, an RFC (or competing RFCs) must be made and then the discussion can continue from concrete proposals.

@bjhargrave
Copy link
Member Author

Comment author: @rinswind

(In reply to Tim Verbelen from comment BZ#16)

Why should this be a BundleContext replacement / addition ... Another
solution would be to have the framework expose additional services, e.g. a
ServiceRegistry service that gives a more modern API to register/find
services?

Similarly, we already have a FrameworkManager service defined in the
ClusterInfo spec that exposes some of the BundleContext functionality.

The ultimate solution I was working on at the time gave to BundleActivator an object that allowed only service registration/unregistration/lookup. A "ServiceContext". This was the absolute minimum needed to bootstrap the access to services. Furthermore there were simplifications like providing registrations only of ServiceFactory in recognition that "bundle.scope=singleton" is a corner case of this. Every other function was implemented as service factories provided from the system bundle or via whiteboard. E.g. register a ServiceListener with the LDAP filer as a service property. E.g. a bundle could get access to it's own Bundle object by getting an "org.osgi.framework.Bundle" service and because you have a factory on the other end the framework will know exactly which object to return.

I found counter arguments to this extreme design, but can't remember them now. It had something to do with implementing extenders.

Anyway there is no use in discussing more details here, other than arguments for/against the introduction of "org.osgi.farmework;version=2.0". Or moving the entire discussion in to an RFP/RFC like BJ says.

@bjhargrave
Copy link
Member Author

Comment author: @rinswind

The ultimate solution I was working on at the time gave to BundleActivator
an object that allowed only service registration/unregistration/lookup. A
"ServiceContext". This was the absolute minimum needed to bootstrap the
access to services. Furthermore there were simplifications like providing
registrations only of ServiceFactory in recognition that
"bundle.scope=singleton" is a corner case of this. Every other function was

I mean "service.scope=singleton|bundle|prototype" of course.

@bjhargrave
Copy link
Member Author

Comment author: @pkriens

Thinking more about the problem I starting to really warm up to the Golang idea to version packages with a major version in their name. This approach will make it trivial to support OSGi 'classic' and OSGi v2.

org.osgi.framework.v2

An interesting approach for the implementers is to support the old API via a compatibility bundle. This makes the cost of hanging on to old versions been borne by the laggards and not the companies that want to keep up to date.

This would actually save a VERY big problem at one of my customers.

We can do the same for the service APIs. This Golang idea will significantly lower the cost of making breaking API changes.

Interesting, the only drawback is a feeling of disgust of using a version number in a name. However, as the Golang guys decided, that has very little to do with actual arguments. You likely get used it quickly.

@bjhargrave
Copy link
Member Author

Comment author: @pkriens

Reference to Golang discussions about this subject: https://research.swtch.com/vgo-import

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

(In reply to Peter Kriens from comment BZ#20)

Thinking more about the problem I starting to really warm up to the Golang
idea to version packages with a major version in their name. This approach
will make it trivial to support OSGi 'classic' and OSGi v2.

org.osgi.framework.v2

This basically argues against the whole idea of semver. That is, major is always and only "1" since you always move to a new package name for an incompatible change.

Can you please provide a reference to the Go Lang spec/recommendation on package versioning?

Also, the practice of including a version number in module names has been put forth as a bad idea for JPMS modules.

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

(In reply to Peter Kriens from comment BZ#21)

Reference to Golang discussions about this subject:
https://research.swtch.com/vgo-import

Oops, a link was in your next comment!

@bjhargrave
Copy link
Member Author

Comment author: @pkriens

It argues partially against semver in the same way dependency injection argued against access protection. I think it is called life to get insight how things really work.

Partially because it does invalidate all of the semver.org argument but not OSGi's semantic versioning rules. Basically in the propose model we remove the major version out of the package/bundle version.

However, the OSGi semantic version is much richer than semver.org. (I did make a futile attempt to get in there.) In OSGi we (try to) depend on API. This is the reason we have providers and consumers (of the API). We accept breaking providers on minor changes but protect consumers. I.e. the subtlety that is so hard to get for many is that OSGi allowed providers to be broken by a minor change.

I think we both realized we could never use a breaking version change when we tried to create framework 2.0. What Golang does is for me similar to what Linus Torvald did with Git. Before Git I'd never dared use a SHA as a primary key because of the possible collisions, Linus made it acceptable. I'd never dared to propose a v2 in a package name because this was scandalized by Windows in their COM. Real programmers would NEVER use a version number in a class/package name!

However, taking a step back it is really hard to argue against the Golang arguments. It does remove an enormous class of problems in versioning. The idea you do not have to thump (was that the name?) through incompatible classes seems to lower the price of incompatible changes significantly. And looking back at our 20 years history this year, it is clear we never found the courage to make an incompatible change so far. That should tell us something ...

Adding a v2 to a package seems an extremely low price.

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

(In reply to Peter Kriens from comment BZ#24)

Adding a v2 to a package seems an extremely low price.

OK, I read the paper at the link and watched the linked video of the presentation by Rich Hickey (https://www.youtube.com/watch?v=oyLBGkS5ICk). I am persuaded. I can see now that the major version portion of semver is ultimately a bad idea. The comparisons to functional programming resonated with me. A package name must only accrete. To break, you move to a new package name. (As a side note: we did exactly this when info.dmtree;version=1.0 was changed to org.osgi.service.dmt;version=2.0 between R4V42 and R4V43.)

However, I am still not convinced that we need to or should do a framework v2 API. Adding some utility methods/classes for Map<->Dictionary is still my first preference.

Adding additional methods which take Map arguments is my second preference. If our goal (as stated in this bug title) is provide support for Map instead of Dictionary, then adding methods which only bump the minor version of the framework package is the the minimal change required to support that goal. And this is fully inline with the paper and the Rich Hickey presentation (accretion at the right level).

I really don't want to use this (supporting Map instead of Dictionary) as an excuse to open up the entire framework API up for a redesign to org.osgi.framework.v2. There are many knock-on effects from this. It would require all the framework implementations to support both org.osgi.framework and org.osgi.framework.v2 simultaneously for some period of time without adding any real new function. This would be a non-trivial change to the framework implementations. It is much easier for the framework implementations to support new methods on existing types. Furthermore, tools like Bnd will also need non-trivial updates to support both framework packages.

So now, I think we wait for the RFC(s) to roll in...

@bjhargrave
Copy link
Member Author

Comment author: @pkriens

I do not think Frameworks will have to implement v1 and v2. Actually, I would recommend against that. Since these are now different namespaces, the framework should only support v2. Compatibility can then be achieved with a compatibility bundle.

Apple taught me that you should never let the new adopters pay the price for compatibility. The laggards want to hold back so they should pay. This allows the product to really take advantage of new features.

I'd love to write an RFC but I would have to find a customer that pays those hours ...

@bjhargrave
Copy link
Member Author

Comment author: Bruce Jackson <bruce.jackson@thingstream.io>

I have to say, I struggle with the rationale for a huge overhaul of the core platform, especially when this adds no functionality but is rather driven by Dictionary being old school.

In reality, comparing:

Dictionary<String, ?> dict = ctx.getProperties();
for(Enumeration<?> e = dict.keys(); e.hasMoreElements(); ) {

Object o = dict.get(e.nextElement());
// do something here

}

...and:

for(Object key : map.keySet()) {

if(key != null) {
			
	Object o = map.get(key);
	if(o != null) {
		// do something here
	}
			
}

}

Is it that much better, or that much of a pain in the ass? Sure, it's not hipster, but if we were all totally bought into removing as much boiler-plate as possible we'd all be using Scala ;-)

	}

@bjhargrave
Copy link
Member Author

Comment author: @rinswind

On the Jena F2F we decided:

  • To open a new issue to introduce a utility to convert between dictionary and map
  • To make a whitepaper regarding our new thinking about versions.

Where is the best place to keep track of any discussions regarding the whitepaper? Another issue?

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

(In reply to Todor Boev from comment BZ#28)

Where is the best place to keep track of any discussions regarding the
whitepaper? Another issue?

The whitepaper is bug BZ#3086.

@bjhargrave
Copy link
Member Author

Comment author: @rinswind

(In reply to BJ Hargrave from comment BZ#29)

(In reply to Todor Boev from comment BZ#28)

Where is the best place to keep track of any discussions regarding the
whitepaper? Another issue?

The whitepaper is bug BZ#3086.

This is the whitepaper about how non-OSGi projects can be OSGi friendly.

I am talking about a new whitepaper, about our (changed?) thinking with respect to introducing breaking changes.
For example:
Replace major version changes with new namespaces

  • org.example.foo; version=0.0.1 - The prototype period when the meaning is first being defined. Breakage is allowed now and only now.
  • org.example.foo; version=1.0.0 - The meaning of the package name becomes locked down.
  • org.example.foo; version=1.0.1 - The meaning is unchanged.
  • org.example.foo; version=1.1.0 - The meaning enriched, but not invalidated.
  • org.example.foo; version=2.0.0 - ILLEGAL: the meaning is invalidated.
  • org.example.foo.v2; version=1.0.0 - new package name bound to the new meaning.

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

OK, then you are talking about an update to the Semantic Versioning whitepaper. So that would need a new bug.

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

(In reply to Todor Boev from comment BZ#30)

  • org.example.foo; version=2.0.0 - ILLEGAL: the meaning is invalidated.

I would not say illegal but if there is a major version of the package less than this major version, then highly discouraged.

  • org.example.foo.v2; version=1.0.0 - new package name bound to the new
    meaning.

This new package name could start with any major version. I would even say it should be 2.0.0 so the second version-ness of it is reflected in the major version. The new package name does not have to have a number in it. It could be

  • org.example.fooplus; version=2.0.0

@bjhargrave
Copy link
Member Author

Comment author: @rinswind

(In reply to BJ Hargrave from comment BZ#32)

(In reply to Todor Boev from comment BZ#30)

  • org.example.foo; version=2.0.0 - ILLEGAL: the meaning is invalidated.

I would not say illegal but if there is a major version of the package less
than this major version, then highly discouraged.

  • org.example.foo.v2; version=1.0.0 - new package name bound to the new
    meaning.

This new package name could start with any major version. I would even say
it should be 2.0.0 so the second version-ness of it is reflected in the
major version. The new package name does not have to have a number in it. It
could be

  • org.example.fooplus; version=2.0.0

I opened Bug BZ#3090 and more or less replied to your remarks

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

CPEG call: BJ will add static asMap and asDictionary methods to FrameworkUtil for R8.

All other items discussed in this bug are handled by other bugs now.

@bjhargrave
Copy link
Member Author

Comment author: @bjhargrave

Added impl and tests with https://osgi.org/gitweb/build.git/commit/4711589eca1bf2f67612f9264e2df82b8801fd66

The Framework RI now needs to be updated with the modified FrameworkUtil class to pass the CT. Assigning to Tom for the RI part.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants