Different versions in transitive dependencies in Gradle - 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)

Related

Pivotal Gemfire: Cannot create GemfireCache; NoSuchMethodError Jgroups

My system currently uses a gemfire cache and uses the io.pivotal.gemfire dependencies. Two of the dependencies, geode-core and geode-management both use org.jgroups (jgroups) as a runtime dependency. Currently I am using version 9.10.13 of the io.pivotal.gemfire dependencies (geode-core, geode-wan, geode-management etc. (see code snippet below)) and version 3.6.14.Final of jgroups.
Due to a vulnerability in the current version of jgroups, I want to upgrade to a newer version (any in version 4 would be sufficient but the newer the better (versions)). The problem I am having is that when I attempt to upgrade to a newer version (3.6.17 or newer), I get the following error when attempting to start-up the cache server:
java.lang.NoSuchMethodError: org.jgroups.View.<init>(Lorg/jgroups/ViewId;Ljava/util/List;)V
at org.apache.geode.distributed.internal.membership.gms.messenger.JGroupsMessenger.installView(JGroupsMessenger.java:459) ~[geode-membership-9.10.13.jar:?]
When I actually go to investigate the issue, it looks as though it is referencing a line where the View class constructor was changed to take in a "Collection" instead of a "List", which seemed like a strange error since a List is a Collection.
I have tried using different combinations of jgroups and gemfire going up to 4/5 and 9.10.17 respectively without success. If anyone has any recommendations on how to move past (solve) this jgroups vulnerability while using a gemfire cache it would be much appreciated. Also, is there a table that lists gemifre versions vs. supported versions of jgroups?
Was able to get in contact with VMware Tanzu. All 9.* versions of gemfire require jgroups 3.6.14.Final. The new version of gemfire (10.*) which is currently in beta, is supposed to remove all dependencies on jgroups.

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.

Websphere Java version

Can a Java 6 application work on Webpshere 8.5 if the nodes are built using Java 7? I have an EAR which was developed using Java6 and deployed on Websphere 8.5 using EA but the Webservice always gives 404.
Thanks.
It appears that that no support is provided for Java SE 6 in that version of WebSphere.
From the online documentation for WebSphere 8.5.5 (not sure if this is the version you are using tho')
Notice: Java SE 6 is being removed from service. Java SE 8 is the
recommended Java SDK because it provides the latest features and
security updates. You can continue to use Java SE 6, but no service
can be provided after the end of the support date, which might expose
your environment to security risks.
In fact, it appears that not even Java SE 7 is supported in this version of WebSphere either
There is a confusion here about the meaning of "version" and how it applies to JavaEE applications:
There is the version of the JVM which is selected to run the server.
There is the JavaEE specification level used to encode XML documents (web.xml, application.xml, ejb-jar.xml, etc) which are within an application.
There is the JavaEE specification level which is supported by the server.
There is the java compiler level which is set for classes packaged within an application.
There is, technically speaking, no specific version associated with an application. That an application is at Java 7 can mean "the classes of the application were compiled to java7", or, "the XML descriptors are set to the versions available to JavaEE7", or, "the function of the application requires a container which supports JavaEE7".
A key detail is that when running with WebSphere, its the server which decides to which JavaEE specification the application is run, not any feature of the application.
I'm guessing that in the original question, "Java 6 application" means the application was compiled to java6 and that the application features are limited to those available in java6. That should work on all of WebSphere v7.0, v8.0, v8.5, and v9.0 (at all service levels).
There are some complications to consider when using a distributed topology (having a DMGr node and more than one application server nodes). A frequent complication is that one or more of the application server nodes is at a lower version than the DMgr node. This is a supported scenario (with some limits on how big of a version difference is supported). The scenario is typical when a topology (a collection of federated nodes) is being migrated gradually from a particular WebSphere version to a higher version, and during the migration a mixture of node versions is available. When this is the case, the DMgr tracks the version of the application server nodes and constrains processing of the application to ensure the deployment is valid to all of the application server nodes to which the application is deployed.
Since the JavaEE level is set by the application server version, and since, generally, higher versions of the application server implement higher JavaEE levels, applications can function differently when migrated between application server versions. Whether this is the case for this question cannot be known without looking in more detail at the exact failure which is occurring.

Spring boot project publish to production environment choose war(standalone tomcat) or jar(embedded tomcat)?

Latest project I used Spring boot, and prepare to deploy to production environment, I want to know which way to run application have better performance or have the same performance?
generate a war package and put it in a stand-alone tomcat
generate a jar package and use embedded tomcat
In addition, when publish to production environment if should to remove devtools dependency.
This is a broad question. The answer is it depends on your requirements.
Personally, I prefer standalone applications with Spring Boot today. One app, one JVM. It gives you more flexibility and reliability in regard to deployments and runtime behaviour. Spring Boot 1.3.0.RELEASE comes with init scripts which allows you to run your Spring Boot application as a daemon on a Linux server. For instance, you can integrate rpm-maven-plugin into your build pipeline in order to package and publish your application as a RPM for deployment or you can dockerize your application easily.
With a classic deployment into a servlet container like Tomcat you will be facing various memory leaks after redeployment for example with logging frameworks, badly managed thread local objects, JDBC drivers and a lot more.
Either you spend time to fix all of those memory leaks inside your application and frameworks you use or just restart servlet container after a deployment. Running your application as a standalone version, you don't care about those memory leaks because you are forced to restart in order to bring you new version up.
In the past, several webapps ran inside one servlet container. This could lead to performance degradation for all webapps because every webapp has its own memory, cpu and GC characteristics which may interfere with each other. Further more, resources like thread pools were shared among all webapps.
In fact, a standalone application is not save from performance degradation due to high load on the server but it does not interfere with others in respect to memory utilization or GC. Keep in mind that performance or GC tuning is much more simpler if you can focus on the characteristics of just one application. It gets complicated as soon as you'll need to find common denominator for several webapps in one servlet container.
In the end, your decision may depend on your work environment. If you are building an application in a corporation where software is running and maintained by operations, it is more likely that you are forced to build a war. If you have the freedom to choose your deployment target, then I recommend a standalone application.
In order to remove devtools from a production build
you can use set the excludeDevtools build property to completely
remove the JAR. The property is supported with both the Maven and
Gradle plugins.
See Spring Boot documentation.

Glassfish tuning

We have here an application developed using Java EE 5 stack (using JSF, RichFaces, EJB, JPA, Hibernate, JAAS) that runs inside Glassfish 3.1! The thing is we are in need to run it as an installable deploy (actually many deploys =]).
My question is: What can we do to have the smallest footprint for the system?
I've already studied about:
uninstalling thing through upgrade tool (e.g. the admin parts),
run the application using embedded glassfish (but using the already existent domain),
configuring domain.xml to erase features (but at a trial and error way),
found some work on how to configure glassfish for production environment.
But as the system will be used by one user at a time, I would like to listen from you about options in this environment.

Resources