eclipse-m2e / m2e-core

Eclipse Public License 2.0
111 stars 113 forks source link

OSGi bundles referenced in target file with type="Maven" are not automatically started #945

Closed kwin closed 2 years ago

kwin commented 2 years ago

I have referenced an OSGi bundle dependency in my target file like outlined in https://xn--lubisoft-0za.gmbh/en/articles/using-maven-artifacts-in-pde-rcp-and-tycho-builds/. Despite the fact that this OSGi bundle does not have a Bundle-ActivationPolicy header it is not started automatically but stays in Resolved state when launching an Eclipse Application based on the given target (without any manual configuration). Starting it manually with the Gogo Console works without issues, but I need this bundle to be started eagerly as it carries some crucial declarative services.

I am referencing the declarative service with an ServiceTracker. Should that start all OSGi bundles automatically if they provide services of the tracked interfaces?

laeubi commented 2 years ago

Despite the fact that this OSGi bundle does not have a Bundle-ActivationPolicy header it is not started automatically but stays in Resolved state when launching an Eclipse Application based on the given target (without any manual configuration).

That is the expected behavior and is not related to target handling at all. This will happen to any Bundle regardless of its a directory, IU or maven location.

Starting it manually with the Gogo Console works without issues, but I need this bundle to be started eagerly as it carries some crucial declarative services.

The usual way is to mention the bundle in the product configuration and mark it with a start level and autostart = true

If you are not in control of that application, but your code is usually installed through P2 you can use a p2.inf, see: https://wiki.eclipse.org/Equinox/p2/Setting_Start_Levels

I am referencing the declarative service with an ServiceTracker. Should that start all OSGi bundles automatically if they provide services of the tracked interfaces?

No this is not enough, the general rule is, that a bundle that is not started, nor marked as lazy-activate can load classes from but do not have any active services. If you want to do that programmatically you can iterate through the BundleContext#getBundles() and start the bundle before (or after) open the ServiceTracker. But be aware that this is actually bad, what bundles are installed, what bundles are started and so on is actually the responsibility of the "Management Agent", so if your bundle should be used in different context you might get complains from users that by intentd don't want that bundle started (or don't have it installed at all).

kwin commented 2 years ago

Well at least if the bundle contains immediate declarative services I would expect that the bundle is started ASAP automatically, at least that is what Apache Felix is doing. Is there no other way to force a bundle to be eagerly started than dealing with p2 start levels? No Equinox specific bundle manifest header, maybe?

laeubi commented 2 years ago

Well at least if the bundle contains immediate declarative services I would expect that the bundle is started ASAP automatically

The expectation is wrong.

at least that is what Apache Felix is doing

Then Felix violates the OSGi specification, you are referring to some other Felix functionality (Eclipse/Equinox uses Felix DS under the hood), or there is something configured differently.

No Equinox specific bundle manifest header, maybe?

As said Bundle-ActivationPolicy ::= lazy is already there, so no need for a custom header at all.

laeubi commented 2 years ago

For reference these are the relevant parts from the spec: http://docs.osgi.org/specification/osgi.cmpn/7.0.0/service.component.html#service.component-component.lifecycle

A component cannot be enabled unless the component's bundle is started. See Starting Bundles in OSGi Core Release 7]. All components in a bundle become disabled when the bundle is stopped. So the life cycle of a component is contained within the life cycle of its bundle.

kwin commented 2 years ago

A component cannot be enabled unless the component's bundle is started.

Right, what I meant is that the container bundle is automatically started which leads to service registration immediately afterwards.

According to https://docs.osgi.org/specification/osgi.core/7.0.0/framework.lifecycle.html#i3270328

A started bundle may need to be automatically started again by the framework after a restart or changes in the start level. The framework therefore maintains a persistent autostart setting for each bundle. This autostart setting can have the following values:

Stopped - The bundle should not be started.

Started with eager activation - The bundle must be started once it is ready and it must then be eagerly activated.

Started with declared activation - The bundle must be started once it is ready and it must then be activated according to its declared activation policy. See Activation Policies.

I think for every value but "stopped" it is reasonable to assume that the bundle is started eagerly (if it does not carry a the bundle header Bundle-ActivationPolicy). For value "Stopped" I would expect the bundle to never be automatically started by the framework. I am really wondering which of those settings equinox is using by default.

laeubi commented 2 years ago

I think for every value but "stopped" it is reasonable to assume that the bundle is started eagerly (if it does not carry a the bundle header Bundle-ActivationPolicy).

No, this is wrong, please read the mentioned doc that states:

A bundle can be started by calling one of the start methods on its Bundle object or the Framework can automatically start the bundle if the bundle is ready and the autostart setting of the bundle indicates that it must be started.

Both things must be performed "on purpose" so you either do it manually ("gogo console way") or you configure it explicitly (p2.inf way) or some other actor do so.

Nerveless,, the target-platform has nothing to do nor can do anything here as these only configures what bundles are available for dependency resolution and those can be used in a variety of configurations including those where the bundle is marked as auto-starting,

kwin commented 2 years ago

OSGi Core spec defines 3 values for autostart:

  1. Stopped
  2. Started with eager activation
  3. Started with declared activation

In Eclipse Launch Configuration for an Application I only see true or false as autostart settings. If that is value 2 and 3. from the spec both should lead to eager activation of bundles not carrying the Bundle-ActivationPolicy=lazy!

laeubi commented 2 years ago

In Eclipse Launch Configuration for an Application I only see true or false as autostart settings

What has "false" as default, beside that, for each bundle you can declare three values:

  1. "default" (see above)
  2. "true" always start regardless of default settings
  3. "false" never start regardless of default settings

All of this has nothing to do with the state you see, you can always stop a default or eager activated bundle afterwards...

So if you see a bundle in RESOLVED it will have no BundleContext and will not have therefore any service and then can not have any DS components. If it is in STARTING then it has lazy activation policy, no bundle context, but loading a class or requesting a DS component or having an immediate DS component will activate the bundle.

kwin commented 2 years ago

In fact adding Bundle-ActivationPolicy: lazy leads to eager(!) activation of the bundle, while with no policy (eager activation) the bundle won't be started at all. That is really confusing and to me this contradicts https://docs.osgi.org/specification/osgi.core/7.0.0/framework.lifecycle.html#i3270445. where the lazy policy only differ from the eager one by potentially deferring(!) activation (introducing additional states but using all states from eager). But in this case Equinox is actually only then starting the bundle automatically at all if lazy is being used.

I am not a native speaker but this is the opposite from what I would expect from lazy vs. eager!

laeubi commented 2 years ago

That is really confusing and to me this contradicts I am not a native speaker but this is the opposite from what I would expect from lazy vs. eager!

If you like you can discuss this with the OSGi people here, that is where the spec lives: https://github.com/osgi/osgi

But I think you simply mix-up things! This lazy/eager has nothing to do with starting a bundle! From the spec:

A Bundle Activator must be created when a Bundle is started, implying the creation of a class loader. For larger systems, this greedy strategy can significantly increase startup times and unnecessarily increase the memory footprint. Mechanisms such as the Service Component Runtime and activation policies can mitigate these problems.

and later on

A lazy activation policy indicates that the bundle, once started, must not be activated until it receives the first request to load a class.

So starting a lazy-bundle will not activate it, unless a class is loaded from the bundle (that can be done from any bundle that is resolved). So the eager/greedy default here only means that if you start the bundle it get immediately activated that is, a Classloader is created for that bundle and its BundleActivator code (if any) is run, while with lazy strategy this part is delayed until a class is actually loaded from the bundle!

kwin commented 2 years ago

This is all fine, but what I see is that the bundle is started by Equinox automatically if it carries "Bundle-ActivationPolicy: lazy", but isn't if it doesn't carry an explicit policy (i.e. means policy eager). In both cases with the same default auto-start setting. This is plain wrong!

laeubi commented 2 years ago

This is all fine, but what I see is that the bundle is started by Equinox automatically if it carries "Bundle-ActivationPolicy: lazy", but isn't if it doesn't carry an explicit policy (i.e. means policy eager). In both cases with the same default auto-start setting. This is plain wrong!

https://github.com/eclipse-equinox/equinox

kwin commented 2 years ago

FTR: I raised this now in https://www.eclipse.org/lists/osgi-users/msg00117.html.