websphere liberty - SLF4J jars conflicting with websphere internal bundles - java

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.

Related

Export-Package from OSGi bundle with bundled jars

I need some help to access exported packages for an OSGi bundle.
I have a simple OSGi bundle jar which essentially bundles some other non-OSGi jars and exports their packages. This OSGi jar is structured like:
root/
lib/
mylib.jar
META-INF
MANIFEST.MF
It's MANIFEST.MF looks as below. The package mylib.mypackage is available in the bundled jar lib/mylib.jar.
Manifest-Version: 1.0
Bundle-Name: my.osgi.bundle
....
Bundle-ClassPath: .,lib/mylib.jar
Export-Package: mylib.mypackge
I need to access the package mylib.mypackage from a plain Java application. I have tried following construct by leveraging eclipse or equinox:
/*
the installBundle() is used to load the packages & packages from myosgi.jar
because it is not directly added to the class-path
*/
....
EclipseStarter.getSystemBundleContext().installBundle("file:<<path-to>>\\myosgi.jar");
EclipseStarter.run(null);
mylib.mypackge.MySampleClass obj = new mylib.mypackge.MySampleClass();
....
The myosgi.jar is NOT added to the classpath directly and installBundle() API above is intended for class loading for myosgi.jar. Adding myosgi.jar in classpath anyway does not resolve mylib.mypackge.
However the above line fails with error ClassNotFoundException / ClassDefNotFoundError for mylib.mypackge.MySampleClass.
I need some guidance for:
How can I access the classes from the packages from myosgi.jar in a plain Java application? I am fine with initiating an OSGi runtime codefully inside my application.
Is there any way to auto-test the myosgi.jar to check if the packages exported by this jar are getting correctly resolved (in an OSGi env)? I don't have access to maven, we use ant for our builds. I would prefer to have minimal dependencies on any 3rd party jars for testing purpose.
Thanks in advance.
Regards,
Gau

RCP ClassNotFoundException with nested jars

I have an RCP application with the following setup:
my.plugin.jar
|-->META-INF
|-----MANIFEST.MF
|-->A1.jar
|-->A2.jar
|-->A_Dependencies.jar (Jar of jars)
|----->X1.jar,X2.jar,...Xn.jar
When I run it I get ClassNotFoundExceptions relating to the nested jars (X1.jar, X2.jar, etc...)
My Manifests contain (among other things) the following entries:
my.plugin.jar
Bundle-ClassPath: .,A1.jar,A2.jar,A_Dependencies.jar
A1.jar
Bundle-ClassPath: .,A_Dependencies.jar
A2.jar
Bundle-ClassPath: .,A1.jar
A_Dependencies.jar
Bundle-ClassPath: X1.jar, X2.jar,...Xn.jar
Export-Package: (All the appropriate packages)
How do I properly set up the manifest to resolve these? A sample error would look like:
Caused by: java.lang.ClassNotFoundException: some.package.some.classfile cannot be found by my.plugin
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:439)
OSGi bundles nested inside another bundle are just considered ordinary jar files. Their manifest will not be picked up, and hence Bundle-ClassPath will not work. If you want to deploy all jars inside one bundle (why not deploy all bundles separately?), you need to flatten the structure so that all your dependency jars are directly under your bundle, and added to the Bundle-ClassPath of your manifest:
my.plugin.jar
Bundle-ClassPath: .,A1.jar,A2.jar,X1.jar,...,Xn.jar
From the error message, it seems your are running Equinox. I'm more familiar with Felix, and the maven-bundle-plugin, which can be configured to embed dependencies and add them to the classpath. The bundles created by the plugin are not tied to Felix, so you could take a look at that instead of manually write bundle manifests.

Avoid loading a transitively dependent module

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.

xml-apis JAR file necessary?

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.

Programatically resolving POM dependency using ivy, but not source and javadoc

Using this method, I could successfully resolve (but NOT retrieve the actual jars) all dependencies of a library when its organization, name and revision are given, all programatically using Apache Ivy.
During the resolution process, it parses given library's POM and finds a parent POM if specified, and Ivy's POM parser always tries to resolve sources and javadoc, which generally doesn't exist for parent POMs.
The problem is that when a non-existing jar's URL is queried to our local artifactory, it takes 2~3 seconds to refresh its cache, adding up tens of minutes to total dependency resolution time when I have many transitive dependencies having parent POMs.
For example, the following is the log message I get when I try to resolve Google Guava 17.0:
:: loading settings :: url = jar:file:.ivy2/cache/org.apache.ivy/ivy/jars/ivy-2.3.0.jar!/org/apache/ivy/core/settings/ivysettings.xml
:: resolving dependencies :: com.google.guava#guava-envelope;17.0 [not transitive]
confs: [default]
validate = true
refresh = false
resolving dependencies for configuration 'default'
== resolving dependencies for com.google.guava#guava-envelope;17.0 [default]
== resolving dependencies com.google.guava#guava-envelope;17.0->com.google.guava#guava;17.0 [default->master]
tried http://artifactory/repo/com/google/guava/guava/17.0/guava-17.0.pom
resolver: found md file for com.google.guava#guava;17.0
=> http://artifactory/repo/com/google/guava/guava/17.0/guava-17.0.pom (17.0)
downloading http://artifactory/repo/com/google/guava/guava/17.0/guava-17.0.pom ...
resolver: downloading http://artifactory/repo/com/google/guava/guava/17.0/guava-17.0.pom
[SUCCESSFUL ] com.google.guava#guava;17.0!guava.pom(pom.original) (58ms)
tried http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0.pom
resolver: found md file for com.google.guava#guava-parent;17.0
=> http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0.pom (17.0)
downloading http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0.pom ...
resolver: downloading http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0.pom
[SUCCESSFUL ] com.google.guava#guava-parent;17.0!guava-parent.pom(pom.original) (20ms)
resolver: revision in cache: org.sonatype.oss#oss-parent;7
tried http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0.jar
tried http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0.jar
tried http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0-sources.jar
CLIENT ERROR: Could not find resource url=http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0-sources.jar
tried http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0-src.jar
CLIENT ERROR: Could not find resource url=http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0-src.jar
tried http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0-javadoc.jar
CLIENT ERROR: Could not find resource url=http://artifactory/repo/com/google/guava/guava-parent/17.0/guava-parent-17.0-javadoc.jar
tried http://artifactory/repo/com/google/guava/guava/17.0/guava-17.0.jar
tried http://artifactory/repo/com/google/guava/guava/17.0/guava-17.0-sources.jar
tried http://artifactory/repo/com/google/guava/guava/17.0/guava-17.0-javadoc.jar
found com.google.guava#guava;17.0 in resolver
resolved ivy file produced in cache
:: resolution report :: resolve 2593ms :: artifacts dl 0ms
:: modules in use:
com.google.guava#guava;17.0 from resolver in [default]
---------------------------------------------------------------------
| | modules || artifacts |
| conf | number| search|dwnlded|evicted|| number|dwnlded|
---------------------------------------------------------------------
| default | 1 | 1 | 1 | 0 || 0 | 0 |
---------------------------------------------------------------------
report for com.google.guava#guava-envelope;17.0 default produced in .ivy2/cantabile/com.google.guava-guava-envelope-default.xml
resolve done (2593ms resolve - 0ms download)
You can see that Ivy wasted a few seconds while trying nonexistent -sources.jar, -src.jar, -javadoc.jar URLs for parent POMs.
Is there an option to disable this behavior when resolving a parent POM? Ideally I don't want to make HTTP requests to any .jars during resolution. Currently I need a programmatic solution but if anyone knows a command line/XML option it will be a great help.
PS: I think this is also the case when using sbt to resolve library dependencies; it takes very long while resolving oss-parent, commons-parent etc.
You need to specify a configuration mapping that excludes both optional dependencies and implicit dependencies like source and javadoc files.
In an ivy file you'd declare the dependency as follows:
<dependency org="myorg" name="mymodule" rev="1.0" conf="default"/>
Another option is to declare this dependency mapping as the default for your project.
<dependencies defaultconfmapping="default">
<dependency ..
<dependency ..
See the following SO questions on how to exclude sources and how ivy translates Maven repositories:
Ignore sources jar in Ivy retrieve
How are maven scopes mapped to ivy configurations by ivy
In conclusion Maven modules by default only have a single arefact. More can be stored (like sources and Javadocs) but there is no module metadata listing them. This is why Ivy performs a HTTP request to see if the artefacts exist or not. Changing the configuration mapping settings should help guide ivy to do the right thing :-)
PS
I think this can be done by called the "addDependencyConfiguration" method to the DefaultDependencyDescriptor object.

Categories

Resources