Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

How to correctly add an optional OSGi import from another plugin (GreenHopper) and make UPM re-resolve my plugin bundle when the imported bundle is installed?

Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012

Our plugin Structure integrates with GreenHopper by optionally importing API packages through Import-Package OSGi instruction. Everything works fine - but only if plugins are installed in the correct order.

If GreenHopper is installed first, and then Structure is installed, the packages are successfully imported. If Structure is installed first, package import is not done and Structure cannot talk to GreenHopper. Disable/enable does not help - the only thing that helps is reinstall of Structure or JIRA restart, because then all bundles will be re-resolved.

I think it used to work in the previous versions of the UPM, but with UPM 2.7.6 (JIRA 5.2-rc1) it no longer works.

It there any gotchas to make this happen or at least an API to force re-resolution of a bundle?

For the record, here are our our OSGi instructions:

<instructions>
            <Export-Package>
              com.almworks.jira.structure.api*;version="${structure.api.version}",
              com.almworks.jira.structure.util;version="${structure.api.version}",
              com.almworks.integers*;version="${integers.version}",
              org.jetbrains.annotations;version="${jetbrains.annotations.version}"
            </Export-Package>

            <!-- Important: the only reason to import com.atlassian.upm.api.util is
               - to force dependency on the UPM plugins, which is a workaround for the issue
               - http://jira.almworks.com/browse/HJ-680
               -->
            <Import-Package>
              com.almworks.integers*;version="${integers.version}",
              com.almworks.jira.structure.api*;version="${structure.api.version}",
              com.almworks.jira.structure.util;version="${structure.api.version}",
              org.jetbrains.annotations;version="${jetbrains.annotations.version}";resolution:=optional,

              javax.ws.rs*;version="[1,2)",
              javax.servlet*;version="[2.3,3)",
              javax.xml.bind*;version="[2.1,3)",

              com.atlassian.greenhopper.service;version="5.8";resolution:=optional,
              com.atlassian.greenhopper.service.rank;version="5.8";resolution:=optional,
              com.atlassian.greenhopper.model.validation;version="5.8";resolution:=optional,
              com.atlassian.greenhopper.api.rank;version="5.10.6";resolution:=optional,

              com.atlassian.upm.api.util;version="0";resolution:=optional,

              *;version="0";resolution:=optional
            </Import-Package>
            <Spring-Context>*;timeout:=60</Spring-Context>
          </instructions>

2 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

6 votes
Answer accepted
Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 9, 2012

Ok, after some source digging, here's how I solved this. I hoped it would be something easier.

Let's say plugin B depends on plugin A: B => A, and the dependency is optional.

1. The problem happens if plugin A is installed (not upgraded) when plugin B is already installed, and the B's bundle is resolved. (And optional packages from A are not resolved.)

2. The problem does not happen if A and B are installed and wired, and then A is getting uninstalled. The plugin manager (as of JIRA 5.1) is smart enough it stop plugin B too and refresh the framework.

3. Part of the problem is that the admin does not have a simple way to re-resolve the plugin - only JIRA restart or plugin B reinstallation.

4. Solution (entirely within plugin B) includes two parts: a) detecting that the B should be re-resolved (refreshed); b) refreshing B.

5. Detecting that B should be refreshed: I) we take a sample package that we import from A and verify through org.osgi.service.packageadmin.PackageAdmin that, if an export of that package exists, our bundle B imports it; II) the check is made on B start and also when plugin events like PluginEnabledEvent are received; III) the instances of Plugin need to be case to OsgiPlugin to get a hold of Bundle and underlying framework.

6) Refreshing B: I) start a new thread for that; II) disable the plugin through PluginController; III) get a hold of PackageAdmin and call refreshPackages() passing your bundle; IV) enable plugin back. Note that before anything you'll need to preload all classes that you will need later in that thread because the classloader won't be able to load anything new.

Luckily, PluginManager manages transitive dependencies and stops all other plugins that depend on B when B stops, otherwise it would be a lot more work.

Phew. I hope this helps someone.

Cheers,
Igor

Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 18, 2012

Hey Igor, meant to reply to this, it is surely to come in handy, er, for me actually, as I will probably come accross this in the near future, the description is great a good walkthrough, can you post anything, would be a timesaver!?

Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
March 10, 2013

Hi Andy - sorry I just saw your comment! If you mean posting the source, yes, I think that's a good idea - I'll think about how we can share pieces of source on our website. Meanwhile I can send it to you directly if you need it.

2 votes
Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012
Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012

Hey Andy, thanks for the pointers. Good instructions from Don there, we'll try those if nothing better comes up. (Although not DynamicImport, but a ServiceTracker should help.)

My point is, it used to work fine with the normal imports with the earlier UPM - somehow it figured out our plugin also had to be rewired after GH installation. I think it is much better way than using ServiceTracker.

Andy Brook [Plugin People]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012

Yes, I think more visibility of changes affecting dependency resolution workings would be good, its not really doucmented AFAICT (sure, could look at the source, but ...) . I had some breakages in 5.2rc1 (JRA-30451) but details were thin on the ground, and it was platform specific, not GH. When you say it worked before, was that in 5.1.x ? that was my experience, wonder if its related.

Igor Sereda [ALM Works]
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
November 8, 2012

Last time we checked with 5.0.x, I believe.

One other thought about dynamic linking via ServiceTracker - then we'll have to use reflection, which sucks. GreenHopper has published API artifact, which I'm happy to use - but cannot if we use ServiceTracker, and therefore are ready for the service to come and go.

TAGS
AUG Leaders

Atlassian Community Events