Including mpHealth feature breaks standalone application in Open Liberty - open-liberty

I'm currently playing with Open Liberty 18.0.0.4 and its Microprofile support. When I try to build a standalone runnable Jar which includes the mpHealth-1.0 feature, startup fails with
[ERROR ] CWWKF0033E: The singleton features com.ibm.websphere.appserver.javax.servlet-3.1 and com.ibm.websphere.appserver.javax.servlet-4.0 cannot be loaded at the same time. The configured features mpHealth-1.0 and jaxrs-2.1 include one or more features that cause the conflict. Your configuration is not supported; update server.xml to remove incompatible features.
[ERROR ] CWWKF0033E: The singleton features com.ibm.websphere.appserver.javax.annotation-1.2 and com.ibm.websphere.appserver.javax.annotation-1.3 cannot be loaded at the same time. The configured features mpHealth-1.0 and jaxrs-2.1 include one or more features that cause the conflict. Your configuration is not supported; update server.xml to remove incompatible features.
[ERROR ] CWWKF0033E: The singleton features com.ibm.websphere.appserver.javaeeCompatible-8.0 and com.ibm.websphere.appserver.javaeeCompatible-7.0 cannot be loaded at the same time. The configured features jsonb-1.0 and mpHealth-1.0 include one or more features that cause the conflict. Your configuration is not supported; update server.xml to remove incompatible features.
[ERROR ] CWWKF0033E: The singleton features com.ibm.websphere.appserver.javax.cdi-2.0 and com.ibm.websphere.appserver.javax.cdi-1.2 cannot be loaded at the same time. The configured features jsonb-1.0 and mpHealth-1.0 include one or more features that cause the conflict. Your configuration is not supported; update server.xml to remove incompatible features.
I'm using jaxrs-2.1 and jsonb-1.0 and everything works fine. As soon as I add the mpHealth-1.0 feature I get the above errors. Here's the relevant snippet of the server.xml:
<featureManager>
<feature>jaxrs-2.1</feature>
<feature>jsonb-1.0</feature>
<feature>mpHealth-1.0</feature>
</featureManager>
And this is what the started Jar says at then end (but no service will be available):
[AUDIT ] CWWKF0012I: The server installed the following features: [jsonb-1.0, servlet-4.0, jndi-1.0, mpHealth-1.0, json-1.0, cdi-1.2, jsonp-1.1, jaxrsClient-2.1, jaxrs-2.1].

This error occurs because not all OpenLiberty features are compatible with each other, and if you enable conflicting features you get an error indicating which features conflict. It should be resolvable by enabling additional features in your server.xml to help the runtime disambiguate which features should be enabled.
The two main reasons features conflict are:
Two versions of the same feature try to be enabled (e.g. foo-1.0 and foo-2.0)
A mix of Java EE 7 and Java EE 8 features are enabled (e.g. cdi-1.2 from EE 7 and jaxrs-2.1 from EE 8)
To break down the feature dependencies of what you have enabled, it looks something like this:
- jsonb-1.0 -> jsonp-1.1
- jaxrs-2.1 -> cdi-2.0
-> servlet-4.0
- mpHealth-1.0 -> cdi-1.2 (tolerates cdi-2.0)
The reason you are seeing these errors is because the OpenLiberty feature manager does not have sufficient evidence to know that it can failover to the mpHealth-1.0 -> cdi-2.0 dependency.
To fix this, you have two options:
Enable the cdi-2.0 feature in server.xml. This should help to disambiguate for the feature manager so it can failover to the mpHealth-1.0 -> cdi-2.0 dependency.
Instead of enabling individual features, enable the microProfile-2.0 convenience feature. Here you won't have to worry about feature conflicts, but it will load more features into the runtime (e.g. MP Metrics, MP Config, MP Fault Tolerance, etc), which will incur some additional startup time and memory footprint cost.

Related

Gradle version supportive for Logback v1.2.10

Before the log4j shell issue happened last month I was using 'org.springframework.boot:spring-boot-starter-logging:1.5.22.RELEASE' which has internal dependencies on
ch.qos.logback:logback-classic:1.1.11 and ch.qos.logback:logback-core:1.1.11 jars respectively.
After that log4j shell issue occurred I had upgraded both the jars to version ch.qos.logback:logback-classic:1.2.3 and ch.qos.logback:logback-core:1.2.3 with gradle v3.5 which works fine. Now when I am trying to upgrade jars to logback-classic:1.2.10 and logback-core:1.2.10, this stops me while running the application stating below error:
org.gradle.tooling.BuildException: Could not execute build using Gradle distribution 'https://services.gradle.org/distributions/gradle-3.5-all.zip'.
Do I need to move to higher version of Grails or Gradle 3.5 have any issue with upgrade. Please any hint or guidance is most welcome.
From https://logback.qos.ch/news.html
We note that the vulnerability mentioned in CVE-2021-42550 requires
write access to logback's configuration file as a prerequisite. Please
understand that log4Shell and CVE-2021-42550 are of different severity
levels. In response to CVE-2021-42550 (aka LOGBACK-1591) we have
decided to make the following steps. 1) Hardened logback's JNDI lookup
mechanism to only honor requests in the java: namespace. All other
types of requests are ignored. Many thanks to Michael Osipov for
suggesting this change and providing the relvant PR. 2) SMTPAppender
was hardened. 3) Temporarily removed DB support for security reasons.
4) Removed Groovy configuration support. As logging is so
pervasive and configuration with Groovy is probably too powerful, this
feature is unlikely to be reinstated for security reasons. We note
that the aforementioned vulnerability requires write access to
logback's configuration file as a prerequisite. Please understand that
log4Shell/CVE-2021-44228 and CVE-2021-42550 are of different severity
levels. A successul RCE attack with CVE-2021-42550 requires all of the
following conditions to be met: write access to logback.xml use of
versions < 1.2.9 reloading of poisoned configuration data, which
implies application restart or scan="true" set prior to attack As an
additional extra precaution, in addition to upgrading to logback
version 1.2.9, we also recommend users to set their logback
configuration files as read-only
For now no support for grails so v1.2.9 onwards logback is not supported for now.

LinkageError on WebSphere 9 for javax.transaction.* classes

I have a web application that used to run fine on many web servers (tomcat, jboss, weblogic and websphere). Now, however, it has an error when deploying on WebSphere 9.
The app contains the jar javax.transaction-api-1.2. Some of its classes, e.g., javax.transaction.xa.XAResource, are also included in Java SE, but not all of them. Some are specific to Java EE and are required by some 3rd-party libraries in my app. The app is always deploying with child-first (parent-last) classloader.
WebSphere 9 throws this error during startup when the app tries to load the Oracle JDBC driver:
java.lang.LinkageError: loading constraint violation: loader "com/ibm/ws/classloader/CompoundClassLoader#7157be44" previously initiated loading for a different type with name
"javax/transaction/xa/XAResource" defined by loader "com/ibm/oti/vm/BootstrapClassLoader#422c7b1b"
Note that we aren't actually using XA transactions in the app, we are using regular transactions.
On other servers, and previous versions of WebSphere, it was never a problem. The server didn't care that we load XAResource from inside the war, even if it was previously loaded somewhere in the server. Now WebSphere 9 is different, it says that the app classloader already loaded this class from the server, but I don't know why or when did this happen.
Any idea how to solve this?
Remove the transaction API from your application. JTA 1.2 is already included in the server and provides no value in your applications. It's always risky to bring Java EE/SE APIs in a parent-last class loader unless you are 100% certain that they are technically necessary, because they can lead to issues like this one.
I can't say how this worked in previous server versions (there have been some Java-level changes in enforcing linkage issues like this), but the solution is reasonably straightforward.
At the end we did two things to solve this problem.
1) We upgraded the jta jar to version 1.3 (link here). This jar solves the problem by avoiding duplicate classes - it contains only J2EE classes and omits the J2SE classes that are already included in the JVM.
2) We upgraded WebSphere server from 9.0.0.7 to 9.0.0.11.
At the time, I suspected just upgrading the jar should suffice, but our QA had some issues with it and they also upgraded the server. Due to lack of time, we didn't investigate it further and just decided to do both.

wasJmsClient-2.0 is not compatible to ejbLite-3.1

I Wanted to migrate my existing code from JMS1.1 to JMS 2.0. I am deploying application through WebSphere Liberty Profile 16.0 using Java 8. When I am enabling wasJmsClient-2.0 feature in server.xml, I am getting below error:
['wasJmsClient-2.0' --> 'com.ibm.websphere.appserver.internal.jms-2.0' --> 'com.ibm.websphere.appserver.javax.connector.internal-1.7'] and ['ejbLite-3.1' --> 'com.ibm.websphere.appserver.transaction-1.1' -->
'com.ibm.websphere.appserver.javax.connector.internal-1.6'] features are in conflict. Select a compatible set of features.
How do I know which features are compatible and which are not?
In general, most feature incompatibility issues in WebSphere Liberty come when mixing features from Java EE 6 technologies with features from Java EE 7. This is the case in your example - wasJmsClient-2.0 is a part of the EE 7 feature set while ejbLite-3.1 is part of the EE 6 feature set. You can resolve the feature incompatibility by changing feature ejbLite-3.1 to ejbLite-3.2.
If you want to determine the compatibility of multiple features, there are two ways that I know of (both are somewhat complex...):
1) Inspect the feature manifest files in the wlp/lib/features directory, and look for the Subsystem-Content header - and specifically entries that are of type "osgi.subsystem.feature". These are the feature's dependencies - some of them will declare that they can work with different versions of a particular feature. Others are more stringent.
2) Run "wlp/bin/featureManager featureList myFeatureList.xml". This will generate an XML file that will provide the same information as the feature manifests, but in an XML format that may be easier to read. It will show the dependencies like this:
<feature name="wasJmsClient-2.0">
<symbolicName>com.ibm.websphere.appserver.wasJmsClient-2.0</symbolicName>
<singleton>true</singleton>
<displayName>JMS 2.0 Client for Message Server</displayName>
<!-- ... -->
<include symbolicName="com.ibm.websphere.appserver.channelfw-1.0"></include>
<include symbolicName="com.ibm.websphere.appserver.transaction-1.2"></include>
<include symbolicName="com.ibm.websphere.appserver.internal.jms-2.0"></include>
</feature>
From there you could follow the dependency chain and see that wasJmsClient-2.0 depends on transaction-1.2, but that ejbLite-3.1 depends on transaction-1.1 - and neither feature would tolerate the other version.
JMS 2.0 and EJB 3.1 are at different Java EE spec levels. Try switching from ejbLite-3.1 to ejbLite-3.2 (and update any other features in your server configuration to all match the EE 7 spec level).

Different versions in transitive dependencies in Gradle

In my project I am forced to use these packages:
com.sparkjava:spark-core:2.3, which ends up using jetty-server:9.3.2.v20150730
org.apache.spark:spark-core_2.10:1.2.0, which ends up using jetty-server:8.1.14.v20131031
Note that com.sparkjava and org.apache.spark have nothing to do with each other. They are called both spark funnily.
The issue here is that both jetty versions are incompatible, so if I force jetty 8.X the system crashes, if I force jetty 9.X the system crashes again, I get java.lang.NoClassDefFoundError: org/eclipse/jetty/server/ServerConnector in one case and java.lang.NoClassDefFoundError: org/eclipse/jetty/server/bio/SocketConnector in the other.
What I am expected to do in such a situation ?
Note: I've tried to shadow jetty, but the dependency manager resolves just one (9.X by default, or 8.X if I force it) and then it shadows it, so it's really not helping.
It would be exceedingly difficult to resolve this situation.
Jetty 8.1 is about 4 major version behind Jetty 9.3, which represents many hundreds of releases of difference.
Note: Jetty versioning is [servlet_support].[major_ver].[minor_ver].
Jetty 8.x is Servlet 3.0, while Jetty 9.x is Servlet 3.1
The architecture of the connectors has evolved tremendously in that time frame, from being old school blocking Sockets in Jetty 8 to no blocking connectors at all in Jetty 9, with Jetty 9 needing to evolve the connectors to support features in TLS/1.2, and ALPN in order to properly support HTTP/2, and the internal I/O handling to support the new Servlet 3.1 Async I/O feature set.
Solution #1:
You won't be able to have both versions running in the same VM without some sort of classloader isolation, and careful configuration to ensure they don't claim the same resources (listening ports, temp files, etc)
Solution #2:
Upgrade (or downgrade) one or the other spark dependency till you hit a common jetty version. (Spark_2.11 / 2.0.0 seems to support Jetty 9.2.x)
Solution #3:
Apache Spark is open source, go submit a patch that upgrades its use of Jetty to 9.3 (this might be difficult as Apache Spark isn't ready to use Java 8 yet, which is a requirement for Jetty 9.3)

WebSphere7 classloading Issues

I am just wondering, if the below is possible with Websphere or not?
I have an Enterprise application using Websphere 7 and with PARENT_LAST classloading mode. I am now trying to use a third party feature namely, gemfire in the application. My application with gemfire runs perfectly in PARENT_FIRST classloading mode. But, I can see some linkage errors occuring because of PARENT_LAST setting. Temperarly, I could solve them by removing the classes that are conflicting from gemfire jar(By this, I am actually asking those removed classes to be loaded from web app server). But, I am not sure if this will create some bigger issues as my appliaction grow to its fullest.
My question is : Suppose we have abc.jar in both web app server and also in gemfire.jar, with PARENT_LAST loading mode.Is it possible to solve the above class conflicts by not removing any class files from jars, instead tell the classloading mechanism to use the class loaded from web app server at a particular case and use the same class loaded from gemfire jar(meaning load from application) at another case?
Thanks
Yes, it is possible. We are using a similar setup. You should be very careful though and only use the exact same jars (or at least the same classes) in all the places you need to have them.

Resources