Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Launcher Specification 1.0 #699

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open

Feature Launcher Specification 1.0 #699

wants to merge 12 commits into from

Conversation

timothyjward
Copy link
Contributor

No description provided.

* @return an {@link ArtifactRepository} using the local file system
* @throws IllegalArgumentException if the uri scheme is not
* <code>http</code> or <code>https</code>
* @throws NullPointerException if the path is <code>null</code>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path -> uri?

* <code>http</code> or <code>https</code>
* @throws NullPointerException if the path is <code>null</code>
*/
ArtifactRepository remoteRepository(URI uri, Map<String,Object> props);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ArtifactRepository remoteRepository(URI uri, Map<String,Object> props);
ArtifactRepository remoteRepository(URL uri, Map<String,Object> props);

If we require it to be http/https as an URL is an URI that has a supported scheme (in this case http)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URI is usually preferred over URL as URL has unpleasant behaviours for equals and hashCode, as well as not handling escaping well.

It's easy to convert between them, so my preference would be to encourage the use of the more modern type (still Java 1.4) with nicer construction and support for relativizing/resolving paths against the URI.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this important here? The URI must be convertible into an URL as per contract (especially into an http URL) and every URL can be converted into an URI internally (where the reverse is not true) if desired wanted.

That's why I mentioned that one either should use only createRepository(URI) with maybe that at least http and file scheme must be supported (and it doesn't matter if its local and/or remote) or one should be using URL directly (while its unclear to me the benefit of being restrictive on the factory).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this important here?

Implementations will need to repeatedly resolve paths against the base that they are given (e.g. to get to the artifact folder) and URI provides this natively. It is unlikely that implementations will use URL.openConnection or URL.openStream as much better HTTP clients exist, even in the JDK.

As another data point, even the standard Java HTTP Client uses URIs not URLs - https://docs.oracle.com/en%2Fjava%2Fjavase%2F11%2Fdocs%2Fapi%2F%2F/java.net.http/java/net/http/HttpRequest.html#newBuilder(java.net.URI)

while its unclear to me the benefit of being restrictive on the factory

Some of the benefits are that:

  • It limits what is mandatory for the implementation to support. Small lightweight implementations may not want to try to implement SSH tunnelling!
  • It provides clarity for the user. If I supply a URI of this form then it will work. If not I will get an exception. Optionality is painful because I can never be sure that what I'm doing will work.
  • It doesn't prevent an implementation from providing other ArtifactRepository types that users can instantiate or use, it just makes it clear that they're using something implementation specific when they do.

That's why I mentioned that one either should use only createRepository(URI)

I would be fine to rename the method and also allow file URIs. I would expect to keep a version using a Path as it is extremely common to use a locally accessible file system as a repository and this method simplifies that use case.

@grgrzybek
Copy link
Contributor

Few observations, comments, comparison with Karaf features.

  • is org.osgi.service.featurelauncher.FeatureLauncher not planned to launch a Framework using more than one feature?
  • org.osgi.service.featurelauncher.FeatureLauncher methods don't declare any exceptions and Reader accepting methods assume JSON format by parameter-name only. These methods should (IMO) declare exceptions related to feature itself and the format separately - but that's not that important
  • launching a Framework based on Feature means that this Feature is kind of pre-OSGi/pre-runtime, so it can't benefit from Framework's hooks/services/configurations... In Karaf, feature service comes from one of the early bundles (other non-feature based bundles are fileinstall, configadmin and pax-url-aether (for mvn: protocol)). When this bundle starts, feature service kind of takes over the provisioning of the Framework and while you still can install separate bundles into the framework, usually it's done with features
  • FeatureLauncherConstants are mostly for remote (http(s)) access to some repository (including Bearer token...) instead of for feature launching. Separation of "feature launcher" and "feature locator/repository"? Maybe 132 Repository Service Specification here? Where features are kind of discoverable capabilities? (again - similar to Karaf's features)
  • what about req/cap model of the features? (Karaf has this)
  • I see org.osgi.service.feature.ID is purely Maven based - Karaf supports version ranges as well
  • InstalledConfiguration has String ID (ID.toString() by Javadoc) - shouldn't it stay as ID?
  • looks like InstalledFeature contains a list of other features that also installed a given bundle (which is provided by this feature as well) - usually BundleRevision is better key and also looks like every time you install a feature, you have to review all other installed features to mark yourself as another feature installing given bundle...

Now about Karaf (cc: @jbonofre, @gnodet) - Karaf's most powerful feature (pun intended) is that Features are installed kind of atomically - before their bundles are actually installed (together with configs, libs, ...) there's a resolution step that ensures that everything can be done safely and features' bundles are installed without resolution problems. For example two features installing two different versions of commons-io may end up installing one (newer) version.

Another nice thing is that Karaf's feature service uses maven resolver service which does the fetching/caching of Maven artifacts using bundle URIs with mvn: scheme (pax-url-aether). This allows to extract the fetching/locating mechanisms out of feature service.

I'll add more information when I think about it more ;)

@timothyjward
Copy link
Contributor Author

is org.osgi.service.featurelauncher.FeatureLauncher not planned to launch a Framework using more than one feature?

No, not currently. One of the requirements from the requirements phase is for a "feature merge" operation which can be done at build time or run time. The expectation is that merging happens as a first step, then the merged feature is launched by the feature launcher.

launching a Framework based on Feature means that this Feature is kind of pre-OSGi/pre-runtime, so it can't benefit from Framework's hooks/services/configurations... In Karaf, feature service comes from one of the early bundles (other non-feature based bundles are fileinstall, configadmin and pax-url-aether (for mvn: protocol)). When this bundle starts, feature service kind of takes over the provisioning of the Framework and while you still can install separate bundles into the framework, usually it's done with features

This would be something for the FeatureRuntime. The FeatureLauncher is for initial bootstrapping, you can have the "early bundles" installed by the FeatureLauncher and then use the FeatureRuntime to build the system as a whole.

FeatureLauncherConstants are mostly for remote (http(s)) access to some repository (including Bearer token...) instead of for feature launching. Separation of "feature launcher" and "feature locator/repository"? Maybe 132 Repository Service Specification here? Where features are kind of discoverable capabilities? (again - similar to Karaf's features)

The constants are limited to the specified behaviours. In this case the specification mandates that all implementations understand how to get artifacts from a maven layout repository accessible via HTTP. We don't go any further than that because we want to allow a degree of implementation choice when it comes to dependencies and repository support. The Repository Service Specification is a difficult one - there's no capability that we can use to determine groupId:artifactId:version, which means that the bundle artifact can't be resolved from the repository. If we can find a way to make that work then great.

what about req/cap model of the features? (Karaf has this)
I see org.osgi.service.feature.ID is purely Maven based - Karaf supports version ranges as well

These would both be updates to the Feature Specification (not the launcher). The req/cap model has been discussed but is not currently being taken forward.

InstalledConfiguration has String ID (ID.toString() by Javadoc) - shouldn't it stay as ID?

The FeatureRuntime is trying to follow a similar pattern to the other runtime services by providing DTOs that have a snapshot of the current state. ID is not DTO friendly, and so String is used instead.

looks like InstalledFeature contains a list of other features that also installed a given bundle (which is provided by this feature as well) - usually BundleRevision is better key and also looks like every time you install a feature, you have to review all other installed features to mark yourself as another feature installing given bundle...

I'm not sure that I agree about using BundleRevision as a key - if a resolution update occurs (say due to the uninstallation or update of a different feature) then we don't want to keep a reference to the old revision that has been discarded by the framework.
The caller of the FeatureRuntime does not have to do any marking of bundle ownership. The FeatureRuntime keeps track of all the installed features, and which bundles were "installed" by each feature. It is therefore the actor responsible for keeping the list of features up to date in the

Karaf's most powerful feature (pun intended) is that Features are installed kind of atomically - before their bundles are actually installed (together with configs, libs, ...) there's a resolution step that ensures that everything can be done safely and features' bundles are installed without resolution problems. For example two features installing two different versions of commons-io may end up installing one (newer) version.

The merging portion of the specification text is not yet written, but it is planned for the FeatureRuntime to permit a degree of bundle "consolidation" between Features. A mandatory requirement for a full resolution is unlikely, but I would not want to prohibit it either (that is, a Karaf based implementation should be able to do resolutions as it is doing now and still pass the compliance tests).

Another nice thing is that Karaf's feature service uses maven resolver service which does the fetching/caching of Maven artifacts using bundle URIs with mvn: scheme (pax-url-aether). This allows to extract the fetching/locating mechanisms out of feature service.

This would be an implementation detail. There's no need to specify how fetching/caching is done by the implementation.

@stbischof
Copy link
Contributor

@grgrzybek do you know other Persons we may should Link to this issue?

@grgrzybek
Copy link
Contributor

@stbischof I don't think so ;) The most involved were Guillaume and JBO. I remember @ffang and @gertv were at the start of this initiative, but this was long time ago...

@timothyjward
Copy link
Contributor Author

The most recent update has completed the first draft for the Feature Launcher. Future commits will fill out sections for the Feature Runtime service, as well as incorporating additional feedback.

bosschaert and others added 9 commits April 24, 2024 18:37
Signed-off-by: Tim Ward <timothyjward@apache.org>
Signed-off-by: Tim Ward <timothyjward@apache.org>
Signed-off-by: Tim Ward <timothyjward@apache.org>
Signed-off-by: Tim Ward <timothyjward@apache.org>
Signed-off-by: Tim Ward <timothyjward@apache.org>
* Introduction and terminology sections
* UML diagram of the Feature Launcher Service types
* Description of the Artifact Repository and Artifact Repository Factory
* Description of creating and configuring a FeatureLauncher

Signed-off-by: Tim Ward <timothyjward@apache.org>
* API updates based on feedback from the community
* Description of how OSGi frameworks are located for launching

Signed-off-by: Tim Ward <timothyjward@apache.org>
This commit contains a full first draft of the behaviour for the Feature Launcher, including the normative behaviours required of the implementation and a usage example.

Signed-off-by: Tim Ward <timothyjward@apache.org>
Use bundle metadata as defined in the Feature specification to avoid separating start levels from the bundles they refer to. Allow the final target start level to be set.

Signed-off-by: Tim Ward <timothyjward@apache.org>
@timothyjward
Copy link
Contributor Author

Changes added based on the feedback from today's specification call. I also rebased the commits with --signoff to make the DCO check happy. I had already rebased the original changes from @bosschaert so it would be good to confirm that he is happy with the update and that we have his approval to include that commit history.

@stbischof stbischof self-requested a review April 26, 2024 20:04
* Separate common concepts into an initial section
* Add a description of the Feature Runtime installation process

Signed-off-by: Tim Ward <timothyjward@apache.org>
Convert the FeatureLauncher into a true builder API

Signed-off-by: Tim Ward <timothyjward@apache.org>
Use ID throughout the FeatureRuntime and remove String entries

Signed-off-by: Tim Ward <timothyjward@apache.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants