I'm using a (Maven) dependency which itself depends on xml-apis. Unfortunately, the presence of this package now causes conflicts in our OSGi environment (see below in case it should be relevant).
Looking at the JAR content, I find classes which seem to be present in a current JRE anyways. So, my question: Is it safe to exclude this dependency?
In general: Is there any official documentation about classes which used to be stand alone dependencies and which have been integrated into the JRE now?
Here's the mentioned OSGi error when the created xml-apis bundle is present:
Bundle was not resolved because of a uses contraint violation.
org.osgi.service.resolver.ResolutionException: Uses constraint violation. Unable to resolve resource my.company.plugin [osgi.identity; osgi.identity="my.company.plugin"; type="osgi.bundle"; version:Version="2.0.0.201707131542"; singleton:="true"] because it is exposed to package 'javax.xml.transform' from resources org.eclipse.osgi [osgi.identity; type="osgi.bundle"; version:Version="3.11.1.v20160708-1632"; osgi.identity="org.eclipse.osgi"; singleton:="true"] and xml-apis [osgi.identity; type="osgi.bundle"; version:Version="1.4.1.bnd-vA0Q7A"; osgi.identity="xml-apis"] via two dependency chains.
You can define the xml-apis as an explicit dependency in the pom.xml of your project with the scope "provided". Then it will not be part of the runtime dependencies.
Related
I am trying to get Log4J2 working via Pax Logging but online docs focus on Log4J (v1). My project is Java, Gradle with BND plugin for OSGi bundles aimed at the Equinox environment.
I am using Gradle 6.8.3
I have my build.gradle file for an OSGi bundle that aims to expose logging functionality to other bundles using:
implementation 'org.ops4j.pax.logging:pax-logging-api:2.1.0'
implementation 'org.ops4j.pax.logging:pax-logging-log4j2:2.1.0'
In my BND file, I include the following imports:
Import-Package: org.apache.logging.log4j;version="2.17.1";provider=paxlogging, org.apache.commons.logging;version="[1.1.1,2)";provider=paxlogging, org.apache.logging.log4j.core;version="2.17.1";provider=paxlogging
Since my project has file appenders defined, which don't form part of the Log4J2 API, but Log4J2 Core, I therefore export the following from the same bundle to enable Log4J2 Core classes to have visibility in other bundles that depend on the logging bundle:
Export-Package: com.mycompany.loggingbundle, org.apache.logging.log4j, org.apache.logging.log4j.message, org.apache.logging.log4j.util, org.apache.logging.log4j.core;version="2.17.1", org.apache.logging.log4j.core.appender;version="2.17.1", org.apache.logging.log4j.core.filter;version="2.17.1", org.apache.logging.log4j.core.impl;version="2.17.1", org.apache.logging.log4j.spi;version="2.17.1"
Everything compiles, builds and install fine.
At runtime, I have an issue:
org.osgi.framework.BundleException: Could not resolve module: com.mycompany.otherbundle [1306]
Unresolved requirement: Require-Bundle: com.mycompany.loggingbundle
-> Bundle-SymbolicName: com.mycompany.loggingbundle; bundle-version="<hidden>"; singleton:="true"
com.mycompany.loggingbundle [1311]
Unresolved requirement: Import-Package: org.apache.logging.log4j.core; provider="paxlogging"; version="2.17.1"
at org.eclipse.osgi.container.Module.start(Module.java:434)
at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1582)
at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.incStartLevel(ModuleContainer.java:1561)
at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.doContainerStartLevel(ModuleContainer.java:1533)
at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1476)
at org.eclipse.osgi.container.ModuleContainer$ContainerStartLevel.dispatchEvent(ModuleContainer.java:1)
at org.eclipse.osgi.framework.eventmgr.EventManager.dispatchEvent(EventManager.java:230)
at org.eclipse.osgi.framework.eventmgr.EventManager$EventThread.run(EventManager.java:340)
Hopefully some OSGi expert knows what I've got wrong because the whole reason to use Pax Logging was to avoid the need to create Log4J2 fragments and have an easier configuration for a multi-bundled environment. Perhaps there is a systematic series of things to look at to resolve this?
Update
I opened up the pax-logging-log4j2 JAR file to review its manifest and can see it doesn't export anything from org.apache.logging.log4j.core so my re-exporting it from my bundle could never provide the core packages I was hoping.
This still leaves the problem of how to get access to things like a FileAppnder elsewhere in code, but it answers the question as to what is wrong with my approach.
Does OSGI capabilities support versioning and how does it work? Say I have a module with the following declared:
Bundle-SymbolicName: my-module
Implementation-Version: 1.8.1-qualifier
Provide-Capability: org.foo.dependency;nameId="my-module",version="1.8.1-qualifier"
Would I then be able to add this require to get the module above?
Require-Capability: org.foo.dependency;filter:="&(nameId=my-module)(version>=1.8)"
Is there also a way to leverage Implementation-Version on the manifest if it's already specified in the provider module? I see references to osgi.wiring.bundle here. Would I be able to do this instead on the require:
Require-Capability: org.foo.dependency;filter:="(nameId=my.module)",osgi.wiring.bundle;filter:="(bundle-version>=1.8)"
Appreciate any pointers on the subject matter.
1.8.1-qualifier is not a valid OSGi version. 1.8.1.qualifier is a valid OSGi version.
&(nameId=my-module)(version>=1.8) is not a valid OSGi filter expression. You need to surround with parenthesis. (&(nameId=my-module)(version>=1.8))
You cannot use Implementation-Version, but you can use Bundle-Version.
Bundle-SymbolicName: my-module
Bundle-Version: 1.8.1.qualifier
Require-Capability: osgi.wiring.bundle;filter:="(&(osgi.wiring.bundle=my-module)(bundle-version>=1.8))"
See https://docs.osgi.org/specification/osgi.core/8.0.0/framework.namespaces.html#framework.namespaces.osgi.wiring.bundle.
I am compiling my legacy source code using JDK 9.0.1 as follows:
javac --add-modules=java.base,java.xml.ws -cp lib\jsr305.jar;lib\javax.annotation-api-1.2.jar TestJava.java
It gives an error because the annotations defined in jsr305.jar are not visible due to split module issue. The error is as follows:
TestJava.java:3: error: cannot find symbol
import javax.annotation.Nonnull;
^
symbol: class Nonnull
location: package javax.annotation
Here the module java.xml.ws.annotation is getting loaded since it is required for java.xml.ws. So it is ignoring the types in jsr305.jar. I don't want this module to be loaded but refer all its annotation types from javax.annotation-api-1.2.jar. I don't want to do --patch-module either because it would break in future releases.
If I use --limit-module=java.xml.ws.annotation it gives the same error. If I remove java.xml.ws from -add-modules, it compiles successfully but I need to export few APIs from it so can't remove it. Is there any way I can load module java.xml.ws but not java.xml.ws.annotation?
EDIT : I think I have added some confusion by giving an example of split between java.xml.ws.annotaion and jsr305.jar. Though it's my actual problem, I am more interested in knowing - can I avoid loading a transitively dependent module, say loading java.xml.ws without loading java.xml.ws.annotation? As per my understanding in JEP 261 it says,
--limit-modules <module>(,<module>)*
where <module> is a module name. The effect of this option is to limit
the observable modules to those in the transitive closure of the named
modules plus the main module, if any, plus any further modules
specified via the --add-modules option.
So, why isn't --limit-module preventing java.xml.ws.annotation from loading?
I know of no way to prevent resolution of a transitive dependency.
Short-term fix
You should be able to make it work by patching the module with --patch-module java.xml.ws=lib\jsr305.jar:lib\javax.annotation-api-1.2.jar. My opinion: If you just want to get your build working on Java 9, that is a good choice. It's a little dubious but still acceptable if you want to use it in production.
If you're worried about long-term compatibility:
I don't think --patch-module will disappear any time soon - do you have a source for that?
I'm pretty sure java.xml.ws will be removed quite soon - it is already deprecated for removal.
In your place I'd worry about the module more than about patching it.
Long-term solution
So for a long-term solution you should remove your dependency on java.xml.ws. JDK-8189188 has a section on this (with lots of links that I was too lazy to copy):
The Reference Implementations (RIs) of JAX-WS and JAXB are a good starting point because they are complete replacements for the java.xml.ws and java.xml.bind modules in JDK 9. The RIs are available as Maven artifacts: (note that they must be deployed on the classpath)
com.sun.xml.ws : jaxws-ri (JAX-WS, plus SAAJ and Web Services Metadata)
com.sun.xml.bind : jaxb-ri (JAXB)
The tools for JAX-WS and JAXB are also available as Maven artifacts:
wsgen and wsimport: com.sun.xml.ws : jaxws-tools, plus tool scripts
schemagen and xjc: com.sun.xml.bind : jaxb-jxc and com.sun.xml.bind : jaxb-xjc, plus tool scripts
There are also Maven artifacts that contain just the APIs of the Java EE technologies:
javax.xml.ws : jaxws-api (JAX-WS, plus javax.xml.soap : javax.xml.soap-api for SAAJ and javax.xml : webservices-api for Web Services Metadata)
javax.xml.bind : jaxb-api (JAXB)
javax.activation : javax.activation-api (JAF)
javax.annotation : javax.annotation-api (Common Annotations)
Adding either the API JARs or the reference implementations to your class path together with all other javax.annotation-related JARs will work because all class path content ends up in the same module (the unnamed one) and thus split packages are no problem there.
I have the following error:
in text :
Error executing command: Error restarting bundles:
Unable to start bundle 278: Uses constraint violation. Unable to resolve resource demo-persistence-jpa [demo-persistence-jpa [278](R 278.0)] because it is exposed to package 'javax.persistence' from resources javax.persistence [javax.persistence [248](R 248.0)] and org.apache.geronimo.specs.geronimo-jpa_2.0_spec [org.apache.geronimo.specs.geronimo-jpa_2.0_spec [266](R 266.0)] via two dependency chains.
Chain 1:
demo-persistence-jpa [demo-persistence-jpa [278](R 278.0)]
import: (&(osgi.wiring.package=javax.persistence)(version>=2.1.0))
|
export: osgi.wiring.package: javax.persistence
javax.persistence [javax.persistence [248](R 248.0)]
Chain 2:
demo-persistence-jpa [demo-persistence-jpa [278](R 278.0)]
import: (osgi.wiring.package=org.hibernate.proxy)
|
export: osgi.wiring.package=org.hibernate.proxy; uses:=javax.persistence
com.springsource.org.hibernate [com.springsource.org.hibernate [230](R 230.0)]
import: (&(osgi.wiring.package=javax.persistence)(version>=1.0.0)(!(version>=2.0.0)))
|
export: osgi.wiring.package: javax.persistence
org.apache.geronimo.specs.geronimo-jpa_2.0_spec [org.apache.geronimo.specs.geronimo-jpa_2.0_spec [266](R 266.0)] Unresolved requirements: [[demo-persistence-jpa [278](R 278.0)] osgi.wiring.package; (osgi.wiring.package=org.hibernate.proxy)]
as you can see the problem is my bundle demo-persistence-jpa imports the package `javax.persistence which is available via two chains, this I understand
what I don't understand :
My bundle imports within the range version>=2.1.0
org.hibernate.proxy imports within the range (version>=1.0.0)(!(version>=2.0.0))), so there should be no problem
My bundle imports org.hibernate.proxy
so there should be no problem, as the version required by my bundle is not the same as the one required by org.hibernate.proxy
or am I mistaken ?
The problem is
demo-persistence-jpa needs both javax.persistence and org.hibernate.proxy.
hibernate bundle exports org.hibernate.proxy
hibernate bundle states it uses:=javax.persistence
for the resolver this means that whoever uses packages from hibernate bundle has to be wired to the exact same bundle/classloader providing javax.persistence that hibernate bundle is wired to.
If the runtime din't ensure that and each was wired to different bundles/classloders you would get ClassCastException the moment something from hibernate bundle returns you an object from javax.persistence because it will be coming from different classloader.
In the case above, the resolver can no ensure that because hibernate bundle needs javax.persistence version to be lower than 2.0 and demo-persistence-jpa needs the version to be higher than 2.1!
The solution is to either :
use newer version of hibernate (assuming there is one) that works with javax.persistence >= 2.1
make demo-persistence-jpa import javax.persistence < 2.1
I think the problem is that you have two bundles providing the spec in two different versions. This will not work. You have to make sure you can get along with just one jpa spec bundle.
How do you install hibernate and your own bundle? If you use the Apache karaf feature for hibernate it should work.
I have an OSGi Application, that contains 3 bundles -
1 - LoggingWrapper, which acts as a wrapper for log4j and slf4j jars, and exports org.slf4j.* packages.
2 - MyProject, this contains JPA code, and imports the following packages:
Import-Package: javax.management,
javax.naming,
javax.persistence;version="1.1.0",
javax.persistence.criteria;version="1.1.0",
javax.persistence.metamodel;version="1.1.0",
javax.sql;version="0.0.0",
javax.transaction;version="1.1.0",
javax.transaction.xa;version="1.1.0",
org.apache.openjpa.enhance;version="2.2.0",
org.apache.openjpa.util;version="2.2.0",
org.slf4j
Deploying this on the server results in the following error:
[AUDIT ] CWWKZ0404E: An exception was generated when trying to resolve the contents of the application JpaTestApp. The exception text from the OSGi framework is: Uses constraint violation. Unable to resolve resource MyProject [IFileAdapter wrapping file with url file:/D:/programs/WebSphere/liberty/wlp/usr/servers/defaultServer/apps/JpaTestApp.eba/MyProject_1.0.0.jar] because it is exposed to package 'org.slf4j' from resources LoggingWrapper [IFileAdapter wrapping file with url file:/D:/programs/WebSphere/liberty/wlp/usr/servers/defaultServer/apps/JpaTestApp.eba/LoggingWrapper_1.0.0.jar] and com.ibm.ws.slf4j-api.1.7.7 [osgi.identity; osgi.identity="com.ibm.ws.slf4j-api.1.7.7"; type="osgi.bundle"; version:Version="1.0.7.cl50420141211-1039"] via two dependency chains.
Chain 1:
MyProject [IFileAdapter wrapping file with url file:/D:/programs/WebSphere/liberty/wlp/usr/servers/defaultServer/apps/JpaTestApp.eba/MyProject_1.0.0.jar]
import: (&(osgi.wiring.package=org.slf4j)(version>=0.0.0))
|
export: osgi.wiring.package: org.slf4j
LoggingWrapper [IFileAdapter wrapping file with url file:/D:/programs/WebSphere/liberty/wlp/usr/servers/defaultServer/apps/JpaTestApp.eba/LoggingWrapper_1.0.0.jar]
Chain 2:
MyProject [IFileAdapter wrapping file with url file:/D:/programs/WebSphere/liberty/wlp/usr/servers/defaultServer/apps/JpaTestApp.eba/MyProject_1.0.0.jar]
import: (&(osgi.wiring.package=org.apache.openjpa.util)(version>=2.2.0))
|
export: osgi.wiring.package=org.apache.openjpa.util; uses:=org.slf4j
com.ibm.ws.jpa [osgi.identity; osgi.identity="com.ibm.ws.jpa"; type="osgi.bundle"; version:Version="1.0.7.cl50420141211-1039"]
import: (osgi.wiring.package=org.slf4j)
|
export: osgi.wiring.package: org.slf4j
com.ibm.ws.slf4j-api.1.7.7 [osgi.identity; osgi.identity="com.ibm.ws.slf4j-api.1.7.7"; type="osgi.bundle"; version:Version="1.0.7.cl50420141211-1039"]
[AUDIT ] CWWKZ0020I: Application JpaTestApp not updated.
Removing the "LoggingWrapper" bundle from the application, causes the following error:
[AUDIT ] CWWKZ0058I: Monitoring dropins for applications.
[AUDIT ] CWWKZ0404E: An exception was generated when trying to resolve the contents of the application JpaTestApp. The exception text from the OSGi framework is: Unable to resolve IFileAdapter wrapping file with url file:/D:/programs/WebSphere/liberty/wlp/usr/servers/experimentalServer/apps/JpaTestApp.eba/XLetDBUtility_1.0.0.jar: missing requirement org.apache.aries.subsystem.core.archive.ImportPackageRequirement: namespace=osgi.wiring.package, attributes={}, directives={filter=(&(osgi.wiring.package=org.slf4j)(version>=0.0.0))}, resource=IFileAdapter wrapping file with url file:/D:/programs/WebSphere/liberty/wlp/usr/servers/experimentalServer/apps/JpaTestApp.eba/XLetDBUtility_1.0.0.jar
[AUDIT ] CWWKZ0012I: The application JpaTestApp was not started.
How can these errors be resolved?
Although Liberty is designed to insulate applications from open source libraries included in the runtime (such as slf4j), it seems there is a bit of leakage if some of the openjpa packages are imported. You should be able to use JPA in your application without importing the org.apache.openjpa* packages, so your best bet is to avoid them. Switching to dynamic runtime enhancement (rather than build-time enhancement) will save a build step and also allow you to remove the openjpa package imports.