spring-boot, tomcat and java modules - java

I have migrated my OSS project (https://m-m-m.github.io) entirely to JPMS (modules). However, integrating with spring-boot now gives me really hard times.
First of all I stumbled over various issues with slf4j module support:
https://github.com/spring-projects/spring-boot/issues/12649
https://jira.qos.ch/browse/LOGBACK-1491?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel
But now I am entirely stuck with errors like:
[ERROR] error: the unnamed module reads package javax.servlet from both org.apache.tomcat.embed.core and java.servlet
Inside my modules, I am forced to require the code I am using and cannot access code from classpath/unnamed modules. Hence, I was forced to use modularized versions of servlet-api and slf4j.
However, spring-boot uses tomcat-embed and that contains servlet-api but is not using the official JPMS module from JakartaEE. I even tried to update to tomcat 10.0.0-M4 but this is not supported by spring-boot yet:
NoSuchMethodError: 'void org.apache.catalina.Context.addServletContainerInitializer(javax.servlet.ServletContainerInitializer, java.util.Set)'
Is there any magic trick left to get things like this solved? Or is the JPMS a closed shop and as the Java ecosystem is not moving fast enough for years (java9 was released 2017) I am more or less forced to reinvent the wheel and replace all such stuff with modularized code?

Related

MergedAnnotations Search Strategy failing after adding a dependency for com.graphql-java-kickstart

I was trying to include graphql integration test cases in an already existing maven project using java springframework v.4.1.0, for which I added library com.graphql-java-kickstart » graphql-spring-boot-starter-test v.6.0.0.
But after adding this, I got the following error for an existing and working test case:
java.lang.NoClassDefFoundError: org/springframework/core/annotation/MergedAnnotations$SearchStrategy
Could someone please help resolving this conflict. Is there some version of this library that is compatible with MergedAnnotations library of springframework. Or is there some other similar library available for implementing java graphql test cases. Also it will be very difficult to upgrade the springframework version because its a huge project and has a lot of dependencies.
I tried upgrading a few versions of com.graphql-java-kickstart » graphql-spring-boot-starter-test but nothing really worked as some or the other part of the project was getting affected.Also tried upgrading springframework version but could not do so because of the libraries and dependencies included.

What is the difference between jaxb-impl and jaxb-runtime?

Clearly the com.sun.xml.bind:jaxb-impl artifact is labelled "Old JAXB Runtime module" in the maven repository (see link below), and yet both of these artifacts are still getting new releases:
https://mvnrepository.com/artifact/org.glassfish.jaxb/jaxb-runtime
https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl
This answer Which artifacts should I use for JAXB RI in my Maven project?
does not clarify the difference.
The accepted answer to both the above question and this one How to resolve java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException conclude that for Java 9+ you should use: org.glassfish.jaxb:jaxb-runtime
But I have code using com.sun.xml.bind:jaxb-impl and it appears to be working fine. So what do I lose or gain by moving to jaxb-runtime?
Even the latest (3.0.2 at the time I write this) version is available for the "OLD" jaxb-impl module. If Oracle isn't doing this anymore, who makes the com.sun.xml.bind:jaxb-impl artifact? What is it for? Why doesn't it share the Maven group coordinates with jaxb-runtime?
Is there any central location that clearly documents what the current state of affairs is with JAXB?
There is just so much confusion with JAXB now.
P.S. I need to remain compatible with Java 8 for the time being - so I can't go to 3.x yet, and 2.4.x appears to be an abandoned attempt at fixing the modularity that they foolishly broke when it was split out of the JDK.
The only difference between jaxb-impl and jaxb-runtime is packaging: jaxb-impl bundles istack/txw2 inside the jar, whereas jaxb-runtime provides them via separate dependencies.
Version Compatibility and the JakartaEE Migration
I've been trying to make sense of this for the last day, and it's incredibly confusing. Particularly when you're trying to avoid the java.xml.bind to jakarta.xml.bind migration. There's out of date information everywhere and some broken releases in the jaxb-impl 2.3.x release line.
Best I can tell, GlassFish was providing the JAXB reference implementation. It's since moved to EE4J, but releases continue from that project against both sets of coordinates. Appears that com.sun.xml.bind:jaxb-ri is where the latest full bundles are released:
https://github.com/eclipse-ee4j/jaxb-ri/
Having figured out that piece of history, the real mess is that none of the artifacts reflect the javax.xml.bind to jakarta.xml.bind move in their artifact coordinates, only in the versions. This means if you're in ecosystem where you need both to exist, you're going to have a bad time.
For instance, the 2.3.3 release changed from depending on javax.xml.bind:jaxb-api to jakarta.xml.bind:jakarta.xml.bind-api because at 2.x, the jakarta artifacts provide the javax.xml.bind packages. At version 3.0.0 it provides jakarta.xml.bind.
The implementations are the same at 3.0.0 which means while the earlier versions could happily exist at runtime, you have no way of resolving them both in build tools and conflict resolution is going to break legacy uses of javax.xml.bind APIs.
Allow javax.xml.bind and jakarta.xml.bind to coexist
For projects that need both APIs to coexist without migrating the legacy code:
For javax.xml.bind use com.sun.xml.bind:jaxb-impl:2.3.6. Ignore the 3.0.0 and later releases. Add an explicit dependency on javax.xml.bind:jaxb-api:2.3.1 so that you have a package providing the javax.xml.bind API
For jakarta.xml.bind use the latest org.glassfish.jaxb:jaxb-runtime. Ignore the releases earlier than 3.0.0
Runtime compatibility with jakarta.xml.bind
Use the tomcat-jakartaee-migration tool to rewrite classes for deployment.
For Gradle projects, you can use the gradle-jakartaee-migration-plugin, and get the benefit of capabilities and transforms at development time too.
Migrate to jakarta.xml.bind
You can use either of the coordinates for the runtime based on your preferences for packaging:
com.sun.xml.bind:jaxb-impl:4.0.0
org.glassfish.jaxb:jaxb-runtime:4.0.0
Both depend on jakarta.xml.bind:jakarta.xml.bind-api with the jakarta.xml.bind package namespace.

Run two versions of elasticsearch in java application using maven

I have a legacy monolith application, which uses elasticsearch 1.X and now we need to run elasticsearch 7.X in the same application, so that same application index and query data in both version of elasticsearch.
In my project, there are multiple modules and they all have their own POM and parent POM, and my new module which uses elasticsearch 7.X depends on some module which uses 1.X.
Although I have excluded 1.X specific dependency in module which uses 7.X, Still it gives me below Error:
[76B7CCD2] java.lang.NoSuchFieldError: LATEST at
org.elasticsearch.Version.(Version.java:49) at
org.elasticsearch.common.io.stream.StreamInput.(StreamInput.java:114)
After doing a lot of research and using this and this link, As explained I excluded the elastic 1.x dependency but still looks like as my other sub-module still has ES 1.X and which is required as well, hence overall classpath of my application has both versions of org.elasticsearch.Version java class from the same package org.elasticsearch, which I feel is the root cause.
Now, How can I include the same class from the same package from two different versions of a same library.
You can't. You can only have one class with a given full qualified name (package + name).
You can try to shade one of the packages (i.e. rename it) with the Maven shade plugin (never tried that, actually), which might work.
Usually, you need to change code and fiddle around until you find a version of elasticsearch that works with all dependencies.

Should I use Java modularity into my existing Maven multi module web project when migrating to Java9+?

I have an existing Multi modules maven project (in Java 8), one of thoses modules is a webapp which produce a war file deployed into Tomcat 9.
I planned to migrate to Java 11. I am wondering if there is a benefit of adding java modularity to my project (i.e. creating a module-info.java for each maven modules) ?
Is there any benefit of adding Java Modularity when producing a war file (maven will already add all its dependencies in WEB-INF/lib) ?
At final, I suppose Tomcat is not using Java modularity when deploying the war ? So, I can't see any benefit of using Java modularity in a web environment, maybe I am missing something ?
I guess it depends on whether or not you are experiencing problems that modulization was intended to fix. I work in a Spring microservices team. We did not start using modules when we migrated to Java 10 from 8. Mainly because we were not encountering the problems that modules was intended to fix... like conflicting library dependencies, or large packages. So no need for the extra complexity.

ERROR [org.springframework.web.servlet.DispatcherServlet]

My code is built in maven and using jBoss 6 and java 7
The code is working fine on local machine but when i try running war on server i an getting error
ERROR [org.springframework.web.servlet.DispatcherServlet]
I tried using aop jar but still no success
Can some one explain me the error and how to solve it
It is failing during the creation of your #Beans. In particular, it is failing because NoClassDefFoundError: org/springframework/core/convert/converter/ConvertingComparator which means it can't find the Class definition for "ConvertingComparator". The earliest documentation I can find on the ConvertingComparator is Spring
3.2.0. Bear in mind, you are using Spring 3.1.0.RELEASE. I tried running a basic Spring project using your POM and ran into similar issues using the spring version you provided. I also ran into conflicts with Spring 3.2.0. I recommend using Spring 4.3.5.RELEASE in your POM. I had no issues running my basic example after setting the properties you have to:
<properties>
<org.springframework.version>4.3.5.RELEASE</org.springframework.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
That being said, you may have other issues in your code as well. It is difficult to provide a holistic solution without more information.
EDIT:
So here are all your spring dependencies:
spring-beans
spring-web
spring-webmvc
spring-tx
spring-jdbc
So first lets talk about redundancy. spring-webmvc actually contains spring-web and spring-beans. You can therefore remove those dependencies from your POM as they are redundant. spring-jdbc contains spring-tx, rendering that inclusion also redundant. You can remove all of those from your POM right now for clean up.
In your comment, you mentioned a new error being thrown in regards to package org.springframework.mail not being found. This package is found in spring-context-support. Spring context support is actually found in the spring-webmvc as well as an optional dependency. (so you would have to include it manually)
According to this thread, that package was moved into context-support separately. My guess is that you are trying to specifically use some of the objects available in the .mail package and because you were not including it, it wasn't being found. With more information as to your project, the more we can dive into why 3.2 did not work and 4.1 does work. Specifics aside, what this all means is that the 3.2 dependencies you were calling did not expose the required packages, but the 4.1 dependencies do.
Have you stopped the process, I mean that particular bean could be in-use ?

Categories

Resources