[ODLGUICE-7] javax.inject exported twice by two different bundles Created: 11/Sep/19  Updated: 03/Oct/20

Status: Confirmed
Project: odlguice
Component/s: None
Affects Version/s: None
Fix Version/s: Silicon

Type: Bug Priority: High
Reporter: Kevin Smokowski Assignee: Tejas Nevrekar
Resolution: Unresolved Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Epic Link: Silicon Updates - ODL-Guice

 Description   

Do we agree that a package should be exported only by a single bundle?

On my local fluorine I see conflicts that I believe are related to infra-utils & aaa.

nullop:/opt/sdn/controller/system$ cat ./org/opendaylight/aaa/odl-aaa-web/0.8.1/odl-aaa-web-0.8.1-features.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="odl-aaa-0.8.1">
    <repository>mvn:org.opendaylight.odlparent/odl-karaf-feat-jetty/3.1.4/xml/features</repository>
    <repository>mvn:org.opendaylight.odlparent/odl-guava-23/3.1.4/xml/features</repository>
    <repository>mvn:org.opendaylight.yangtools/odl-yangtools-util/2.0.12/xml/features</repository>
    <feature name="odl-aaa-web" description="ODL :: aaa :: odl-aaa-web" version="0.8.1">
        <details>OpenDaylight is leading the transformation to Open Software Defined Networking (SDN). For more information, please see https://www.opendaylight.org</details>
        <feature version="[3.1.0,4)" prerequisite="false" dependency="false">odl-karaf-feat-jetty</feature>
        <feature version="[3.1.0,4)" prerequisite="false" dependency="false">odl-guava-23</feature>
        <feature version="[2.0.10,3)" prerequisite="false" dependency="false">odl-yangtools-util</feature>
        <bundle>mvn:org.opendaylight.aaa.web/web-osgi-impl/0.8.1</bundle>
        <bundle>mvn:org.opendaylight.aaa.web/web-api/0.8.1</bundle>
        <bundle>mvn:javax.servlet/javax.servlet-api/3.1.0</bundle>
        <bundle>mvn:org.ops4j.pax.web/pax-web-api/6.0.9</bundle>
        <bundle>mvn:org.opendaylight.aaa.web/servlet-jersey2/0.8.1</bundle>
        <bundle>mvn:org.opendaylight.aaa.web/servlet-api/0.8.1</bundle>
        <bundle>mvn:javax.ws.rs/javax.ws.rs-api/2.0.1</bundle>
        <bundle>mvn:org.glassfish.jersey.containers/jersey-container-servlet/2.8</bundle>
        <bundle>mvn:org.glassfish.jersey.containers/jersey-container-servlet-core/2.25.1</bundle>
        <bundle>mvn:org.glassfish.jersey.core/jersey-common/2.25.1</bundle>
        <bundle>mvn:javax.annotation/javax.annotation-api/1.2</bundle>
        <bundle>mvn:org.glassfish.hk2/osgi-resource-locator/1.0.1</bundle>
        <bundle>mvn:org.glassfish.jersey.core/jersey-server/2.25.1</bundle>
        <bundle>mvn:org.glassfish.jersey.media/jersey-media-jaxb/2.25.1</bundle>
        <bundle>mvn:javax.validation/validation-api/1.1.0.Final</bundle>
        <bundle>mvn:org.glassfish.jersey.core/jersey-client/2.25.1</bundle>
        <bundle>mvn:org.glassfish.hk2/hk2-api/2.5.0-b32</bundle>
        <bundle>mvn:org.glassfish.hk2/hk2-utils/2.5.0-b32</bundle>
        <bundle>mvn:org.glassfish.hk2.external/aopalliance-repackaged/2.5.0-b32</bundle>
        <bundle>mvn:org.glassfish.hk2.external/javax.inject/2.5.0-b32</bundle>
        <bundle>mvn:org.glassfish.hk2/hk2-locator/2.5.0-b32</bundle>
        <bundle>mvn:org.javassist/javassist/3.23.1-GA</bundle>
        <bundle>mvn:org.glassfish.jersey.bundles.repackaged/jersey-guava/2.25.1</bundle>
    </feature>
</features>
nullop:/opt/sdn/controller/system$ cat ./org/opendaylight/infrautils/odl-infrautils-inject/1.4.1/odl-infrautils-inject-1.4.1-features.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="odl-infrautils-inject">
    <feature name="odl-infrautils-inject" description="OpenDaylight :: Infrautils :: @Inject" version="1.4.1">
        <details>OpenDaylight is leading the transformation to Open Software Defined Networking (SDN). For more information, please see https://www.opendaylight.org</details>
        <feature prerequisite="true" dependency="false">wrap</feature>
        <bundle>mvn:org.opendaylight.infrautils/inject/1.4.1</bundle>
        <bundle>wrap:mvn:javax.inject/javax.inject/1</bundle>
        <bundle>wrap:mvn:com.google.errorprone/error_prone_annotations/2.3.1</bundle>
    </feature>
</features>

The part that stands out to me is

        <bundle>wrap:mvn:javax.inject/javax.inject/1</bundle>
        <bundle>mvn:org.glassfish.hk2.external/javax.inject/2.5.0-b32</bundle>

I see this when changing package exports and running bundles

nullop@root>bundle:list | grep javax.inject
276 | Active   |  80 | 2.5.0.b32                              | javax.inject:1 as OSGi bundle
530 | Active   |  80 | 0                                      | wrap_file__opt_app_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar
nullop@root>package:exports | grep javax.inject                            
javax.inject                                                                                                                                                                                                                                                                        │ 0.0.0                                  │ 530 │ wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar
javax.inject                                                                                                                                                                                                                                                                        │ 1.0.0                                  │ 276 │ org.glassfish.hk2.external.javax.inject

If I check the headers I do see the package is being exported in each bundle

nullop@root>bundle:headers 530wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar (530)
---------------------------------------------------------------------------------------------
Bnd-LastModified = 1568232244101
Created-By = 1.8.0_162 (Oracle Corporation)
Generated-By-Ops4j-Pax-From = wrap:file:/sdncopt/sdn/controller/system/javax/inject/javax.inject/1/javax.inject-1.jar
Manifest-Version = 1.0
Tool = Bnd-2.3.0.201405100607Bundle-ManifestVersion = 2
Bundle-Name = wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar
Bundle-SymbolicName = wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar
Bundle-Version = 0Require-Capability = 
	osgi.ee;filter:=(&(osgi.ee=JavaSE)(version=1.5))Export-Package = 
	javax.inject
nullop@root>bundle:headers 276javax.inject:1 as OSGi bundle (276)
-----------------------------------
Archiver-Version = Plexus Archiver
Bnd-LastModified = 1484762462222
Build-Jdk = 1.7.0_79
Built-By = java_re
Created-By = Apache Maven Bundle Plugin
Implementation-Version = 1
Manifest-Version = 1.0
Tool = Bnd-2.1.0.20130426-122213Bundle-Description = Injection API (JSR 330) version ${javax.inject.version} repackaged as OSGi bundle
Bundle-DocURL = http://www.oracle.com
Bundle-License = https://glassfish.java.net/nonav/public/CDDL+GPL_1_1.html
Bundle-ManifestVersion = 2
Bundle-Name = javax.inject:1 as OSGi bundle
Bundle-SymbolicName = org.glassfish.hk2.external.javax.inject
Bundle-Vendor = Oracle Corporation
Bundle-Version = 2.5.0.b32Export-Package = 
	javax.inject;version=1

If I turn the logs up I was seeing this make a package loop for about 20 minutes with this message

Chain 1:
  wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar [wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar/0.0.0]
    import: (osgi.wiring.package=javax.inject)
     |
    export: osgi.wiring.package: javax.inject
  wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar [wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar/0.0.0]Chain 2:
  wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar [wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar/0.0.0]
    import: (osgi.wiring.package=org.glassfish.jersey.internal.l10n)
     |
    export: osgi.wiring.package=org.glassfish.jersey.internal.l10n; uses:=javax.inject
  org.glassfish.jersey.core.jersey-common [org.glassfish.jersey.core.jersey-common/2.25.1]
    import: (&(osgi.wiring.package=javax.inject)(version>=1.0.0)(!(version>=2.0.0)))
     |
    export: osgi.wiring.package: javax.inject
  org.glassfish.hk2.external.javax.inject [org.glassfish.hk2.external.javax.inject/2.5.0.b32])
2019-09-10T17:38:06,336 | DEBUG | features-1-thread-1 | ResolverImpl                     | 8 - org.apache.karaf.features.core - 4.1.6 |  -   | Candidate permutation failed due to a conflict between imports; will try another if possible. (Uses constraint violation. Unable to resolve resource wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar [wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar/0.0.0] because it is exposed to package 'javax.inject' from resources wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar [wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar/0.0.0] and org.glassfish.hk2.external.javax.inject [org.glassfish.hk2.external.javax.inject/2.5.0.b32] via two dependency chains.Chain 1:
  wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar [wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar/0.0.0]
    import: (osgi.wiring.package=javax.inject)
     |
    export: osgi.wiring.package: javax.inject
  wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar [wrap_file__sdncopt_sdn_controller_system_javax_inject_javax.inject_1_javax.inject-1.jar/0.0.0]Chain 2:
  wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar [wrap_file__sdncopt_sdn_controller_system_org_glassfish_jersey_security_oauth1-signature_2.25.1_oauth1-signature-2.25.1.jar/0.0.0]
    import: (osgi.wiring.package=org.glassfish.jersey.internal.l10n)
     |
    export: osgi.wiring.package=org.glassfish.jersey.internal.l10n; uses:=org.glassfish.hk2.api
  org.glassfish.jersey.core.jersey-common [org.glassfish.jersey.core.jersey-common/2.25.1]
    import: (&(osgi.wiring.package=org.glassfish.hk2.api)(version>=2.5.0)(!(version>=3.0.0)))
     |
    export: osgi.wiring.package=org.glassfish.hk2.api; uses:=javax.inject
  org.glassfish.hk2.api [org.glassfish.hk2.api/2.5.0.b32]
    import: (osgi.wiring.package=javax.inject)
     |
    export: osgi.wiring.package: javax.inject
  org.glassfish.hk2.external.javax.inject [org.glassfish.hk2.external.javax.inject/2.5.0.b32])
2019-09-10T17:38:06,481 | DEBUG | features-1-thread-1 | ResolverImpl                     | 8 - org.apache.karaf.features.core - 4.1.6 |  -   | Candidate permutation failed due to a conflict between imports; will try another if possible. (Uses constraint violation. Unable to resolve resource org.glassfish.jersey.core.jersey-client [org.glassfish.jersey.core.jersey-client/2.25.1] because it is exposed to package 'javax.inject' from resources org.glassfish.hk2.external.javax.inject [org.glassfish.hk2.external.javax.inject/2.5.0.b32] and org.glassfish.hk2.external.javax.inject [org.glassfish.hk2.external.javax.inject/2.5.0.b32] via two dependency chains.


 Comments   
Comment by Michael Vorburger [ 12/Sep/19 ]

> Do we agree that a package should be exported only by a single bundle?

yes!

This javax.inject/javax.inject/1 VS org.glassfish.hk2.external/javax.inject/2.5.0-b32 business rings a (vague) bell in my mind... search JIRA and Gerrit for anything related, https://git.opendaylight.org/gerrit/q/javax.inject, note e.g. https://git.opendaylight.org/gerrit/c/aaa/+/77654/2/web/servlet-jersey2/pom.xml - you may want to do something similar, somewhere?

Unassigned this issue from myself, just to clarify that I no longer actively work on OpenDaylight, by day; I'm still happy to occasionally answer Qs such as this, by night.

Gerrit changes from you to fix this problem are, of course, very welcome. (I'd still try to find a moment to review and merge anything like this.)

Comment by Kevin Smokowski [ 12/Sep/19 ]

vorburger thanks for your reply. I believe Jira has you as the default assignee still so I let that option flow through, didn't mean to directly target you.

I'm thinking that perhaps AAA might need the fix? I'm trying to think of what is actually correct.

For example should org.glassfish.hk2.external.javax.inject import javax.inject and not export it?

It would seem odd for infrautils to import this package from org.glassfish.hk2.external.javax.inject instead of something like the wrapped javax.inject jar.

I saw you did some PoC on removing Karaf. Karaf has many complicated pains such as this one

Comment by Robert Varga [ 23/Jul/20 ]

Well, javax.inject should always be scope=provided in all our artifacts which make it to OSGi, simply because we do not rely on javax.inject for actual wiring in OSGi. That is not true for Jersey, though, which needs HK2 for wiring, which in turn requires javax.inject package – and the place they are getting is their own packaging (because javax.inject-1.jar is not a bundle).

That having been said, there is actually a third party contender, which is Geronimo's atinject – which does exactly the same thing as hk2.external.javax.inject!

Comment by Robert Varga [ 23/Jul/20 ]

Looking through what we are actually shipping, javax.inject is being packaged by odl-infrautils-inject feature and is actively being used by ClassPathScanner.

vorburgerI cannot find anything in terms of documentation of this. Is that even meant to be used in Karaf? If not, then we should actively filter javax.inject from that package, should we not?

Comment by Robert Varga [ 23/Jul/20 ]

Guice wiring, which is the only infrautils thing pulling this in is moving to odlguice. Moving this issue there, so it gets addressed.

Generated at Wed Feb 07 20:26:09 UTC 2024 using Jira 8.20.10#820010-sha1:ace47f9899e9ee25d7157d59aa17ab06aee30d3d.