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

E4 application model fragments applied in wrong order when supplied with Model-Fragment manifest header #2530

Open
1 of 2 tasks
SaschaRiemer opened this issue Nov 21, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@SaschaRiemer
Copy link

SaschaRiemer commented Nov 21, 2024

When different fragments are applied to build the full application model, it is important that they are applied in the correct order. Otherwise, the following errors can occur while the model fragment is applies:

  • The to-be-extended element, specified by its ID, can not be found, because it is not yet available
  • An imported element can not be found, because it is not yet available

There is some code in the ModelAssembler which sorts the fragments to avoid these issues, but from my understanding it is incomplete:

  • It does not consider imports at all
  • It only considers top-level elements. If a contributed element contains somewhere nested an element with another ID, then that nested element is not considered.

When the model fragments are contributed with a plugin.xml extension, there is a workaround: By specifying a dependency between bundles, the order in which bundles are activated can be influenced, and this affects the order in which the extensions are processed. But when the model fragment is contributed with the Manifest, this does not work.
There is a BundleTracker installed which collects all bundles which have been activated until the extensions are processed and checks if they have the Model-Fragment header. But because the BundleTracker internally uses a HashMap, the order in which bundles and their model fragments are returned is mixed up. It is actually pretty stable, but it's not the order in which the bundles were activated.

Steps to reproduce

Difficult to describe reliable steps to reproduce this problem since it depends on the state of a HashMap.
However, in general you need the following components:

  • Create a plugin in which you contribute a command through an e4 model fragment. Add a handler to that command so it can be observed when the command is executed.
  • Create a second plugin where you import that command and add it to a menu. This plugin should have a Require-Bundle dependency on the first plugin.

Depending on the order in which these two fragments are applied, either the menu entry triggers the expected functionality, or not.

Expected behavior:
Whether fragments are contributed with a plugin.xml extension or with the Model-Fragment manifest header, the dependencies between the fragments are considered correctly when applying the fragments to the application model.

Tested under this environment:

  • OS & version: Windows 10
  • Eclipse 2024-09 / 4.33

Community

  • I understand reporting an issue to this OSS project does not mandate anyone to fix it. Other contributors may consider the issue, or not, at their own convenience. The most efficient way to get it fixed is that I fix it myself and contribute it back as a good quality patch to the project.
@SaschaRiemer SaschaRiemer added the bug Something isn't working label Nov 21, 2024
@laeubi
Copy link
Contributor

laeubi commented Nov 21, 2024

I don't think that activation order is actually what is desired, but one would more sort them depending on their dependencies (e.g. Wires).

@SaschaRiemer
Copy link
Author

That means enhancing the existing sort to

  • consider imports
  • consider nested IDs

Also sounds like the better approach to me. Especially considering that we could not sort extension-provided and manifest-provided fragments together.

  • How would one then handle cyclic dependencies?
  • What about bundles which are activated later? If their fragments are depending on each other, then the bundle order must also respect that, because in this case the fragments are applied one by one. This suggests to me, that, while the bundle dependencies should not be used to sort how the fragments are applied, it must still be configured that way.

@laeubi
Copy link
Contributor

laeubi commented Nov 22, 2024

Especially considering that we could not sort extension-provided and manifest-provided fragments together

I think regarding dependencies it does not make much of a difference, as a rough recipe one should do:

  1. Get the Bundle of the extension (regardless of extension or Manifest)
  2. Get the BundleWiring and fetch all required wires
  3. Create a set of Bundles from the wires
  4. put it on a map so we can lookup them
  5. now filter all requires to only retain those that are having model fragments

Now one should iteratively work on the data structure in the following way:

  1. remove one of the items that has no dependencies (if no such thing exits this is likely an error and we can give a warning and just pick a random one, one with the lowest dependencies count, lowest bundle id, ...)
  2. Apply the fragment and remove this bundle from all other dependencies set
  3. repeat until map is empty

How would one then handle cyclic dependencies?

Actually OSGi should already handle cyclic dependencies, but if its the case we can assume it as an error and then something happens (e.g. even random order)

What about bundles which are activated later?

Activation actually do not matter, if you mean "installed later, they should be applied at install time, I don't think there is much other option but this case is quite rare and at worst requires a restart of Eclipse to properly work.

@SaschaRiemer
Copy link
Author

SaschaRiemer commented Nov 22, 2024

Ah, sorry, misunderstood you there in the first place. You are actually in favor of considering the bundle dependencies, and not the imports and IDs inside the fragments. In that case, yes your outlined approach should work, except that it is somewhat inconvenient that one would have to reimplement things which OSGi has already done, i.e. the bundle wiring, and transitive dependencies.

Activation actually do not matter, if you mean "installed later, they should be applied at install time, I don't think there is much other option but this case is quite rare and at worst requires a restart of Eclipse to properly work.

I think I meant activation.
If a bundle is missing the "Bundle-ActivationPolicy: lazy" header, its fragment is not applied when the application starts, but possibly later, when the bundle is activated. At least that is how I understand this comment on the issue, where the feature was originally introduced: https://bugs.eclipse.org/bugs/show_bug.cgi?id=571866#c2
However, given that the approach should be to consider the bundle dependencies, that should not be a problem, OSGi should take care of activating the dependencies first I think.

Let me see if I can get something working here...

@laeubi
Copy link
Contributor

laeubi commented Nov 22, 2024

You don't need to reimplement it you can use Bundle Wiring Api, but the interpretation needs to be done by the software. Of course if we can additionally discover requirements not expressed in terms of OSGi that would be quite handy, needing requirements on other bundles is always a bit odd when working in E4...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants