Spring boot application stuck when adding jnpclient maven dependency - java

I need to load a JNDI resource located in a JBoss server. For this, I am using a jnp-client library:
<dependency>
<groupId>jboss</groupId>
<artifactId>jnp-client</artifactId>
<version>4.2.2.GA</version>
</dependency>
The problem is that as soon as I include this dependency in my pom.xml, the Spring application gets stuck at the start time without any message. Not a single line of logs, like if it is trying to load something forever. The main is not even invoked. Removing this dependency the application runs but I get an expected:
ClassNotFoundException: org.jnp.interfaces.NamingContextFactory
Which is normal because I have removed the dependency that includes this class.
Any clue?
I have tried all version of jnp-client or jbossall-client that also includes this NamingContextFactory
EDIT:
It is the mix of these two dependencies that unfortunately are inherited from required dependencies:
<dependency>
<groupId>org.jboss.naming</groupId>
<artifactId>jnp-client</artifactId>
</dependency>
and spring-webmvc inside
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
If I run with
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</exclusion>
</exclusions>
</dependency>
It works fine.
Now, if I exclude the jnp-client I cannot access the JNDI resource, but if I remove the spring-security-web I cannot access the REST endopoints this service exposes.
EDIT2:
So I thought it could be two classes interfering with each other and I started the java process with -verbose. This is what I found.
org.springframework.boot.context.config.ConfigFileApplicationListener$Loader$$Lambda$165/0x00000001002d8440
source:
org.springframework.boot.context.config.ConfigFileApplicationListener$Loader
[389.020s][info][class,load]
org.springframework.boot.context.config.ConfigFileApplicationListener$Loader$$Lambda$166/0x00000001002d8840
source:
org.springframework.boot.context.config.ConfigFileApplicationListener$Loader
[558.011s][info][class,load]
org.springframework.boot.context.config.ConfigFileApplicationListener$Loader$$Lambda$167/0x00000001002d8c40
source:
org.springframework.boot.context.config.ConfigFileApplicationListener$Loader
[558.012s][info][class,load]
org.springframework.boot.context.config.ConfigFileApplicationListener$Loader$$Lambda$168/0x00000001002d9040
source:
org.springframework.boot.context.config.ConfigFileApplicationListener$Loader
From time to time the application prints, only in verbose, this ConfigFileApplicationListener$Loader
EDIT 3:
It seems that the problem is TimedSocketFactory inside the jnp-client. Somehow, just by having this class inside the jnp-client dependency, the Spring application is blocked and never starts. Removing this from the jnp-client allows the application to start. Of course, it fails later because the JNDI cannot connect to the server.

Related

Change the version of the embedded tomcat using spring starter

The requirement is to use spring boot version 2.2.6.RELEASE however the tomcat version should be 9.0.37.
I tried to do it by excluding the tomcat starter from the spring-boot-starter-web depdendency like so :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
And added the spring-boot-starter-tomcat separately which has the 9.0.37 tomcat version :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<version>2.3.2.RELEASE</version>
</dependency>
However even after doing so the version is not override and the following gets used :
Mar 11 2020 09:31:38 UTC
Apache Tomcat/9.0.33
9.0.33.0
Do we need to do anything else to override the tomcat version?
Is it possible to override it by excluding started?
Update:
The parent pom is a corporate parent pom and not the spring-boot-starter-parent. As per one of the answers we can simply override the tomcat.version property however my effective pom doesn't show it.
If you're not inheriting from spring-boot-starter-parent I can only guess that you import spring-boot-dependencies in your dependencies management somewhere.
The documentation covers what you need to do to override the tomcat version. Each tomcat artifact should be listed with the overridden version, before you imports spring-boot-dependencies. The list of artifacts can be found in spring-boot-dependencies.
Using a different version of the starter is wrong (you can't mix two Spring Boot versions in the same app) and will have no effect since dependency management is in control anyway. In other words, you'll get spring-boot-starter-web version 2.3.2.RELEASE indeed but all the artefacts that it brings will be managed by the dependency management (the tomcat version defined by version 2.2.6.RELEASE).
In that particular case of yours, upgrading to 2.2.9.RELEASE could also be an option as it provides dependency management for the tomcat version that you need.
Well, this has been already answered.
For you, as you are using maven, you need to override the properties set in parent Spring pom.
<properties>
......
<tomcat.version>your_version</tomcat.version>
......
<properties>
For gradle, it is simple as
ext['tomcat.version'] = '8.5.34'
in your main build.gradle
Source: How to change embedded tomcat's version in existing spring boot app?

Displaytag + Tomcat -> silent failure

I'm trying to rehabilitate project which is approx 10 years old.
It is a java webapp which used to run well in Tomcat 6. There is a small cluster of modules which were variously built with Ant and Maven, using Java 5 and Java 6.
I've now got them all building correctly with Maven, using Java 6, deploying to Tomcat 7, trying to aim for the same version of dependencies - just to get it running, before attempting upgrades.
Some of the JSP pages use DisplayTag 1.2. If my Maven build includes the displaytag dependencies then the webapp doesn't run. There's no errors in the logs. It just reports a 404 for everywhere. If I exclude displaytag from the Maven build, everything works fine, except the JSP pages needing DisplayTag.
If I try to run the webapp in Tomcat 6, I get exception to do with incompatibilities between commons-logging and slf4j.
If a webapp silently fails like this, with no errors or exceptions in the logs, what should I suspect or investigate?
UPDATE
Based on Kayaman's answer, here is what I did:
Any place in any pom.xml which had a dependency on commons-logging, add the following:
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
Where there is an explicit dependency on commons-logging, mark it as provided:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
When booting up the webapp now, this is what I saw in catalina.out:
org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/webapp]]
Caused by: java.lang.NoClassDefFoundError: Lorg/apache/commons/logging/Log;
... 10 more
Caused by: java.lang.ClassNotFoundException: org.apache.commons.logging.Log
... 24 more
Next I added to the top-level webapp pom.xml the SLF4J "re-router" for commons-logging:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.6.4</version>
</dependency>
Also made sure that the SLF4J was wired up with Log4j, at the correct version (Log4J was the existing logging framework for this webapp, 10 years ago):
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.4</version>
</dependency>
Now when booting the webapp, this allowed JSP errors and Exceptions to be seen in catalina.out, which I was able to debug successfully!
So including the displaytag dependency causes the jsp compilation to fail for all jsps, resulting effectively in the webapp not having any views, hence the 404s. At least a very plausible sequence of events.
According to this any JSP compilation exceptions can be seen in tomcat's localhost_log.xxx file. However, the same thread goes on to complain that there's no info or not enough info, which probably means your logging config is borked.
For that you probably need to set up your logging bridge.
Since you're using slf4j, but other components are using commons-logging, you're losing the log information from the other components. For that you include commons-logging, but as provided, so it won't be pulled in by other libraries.
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
<scope>provided</scope>
</dependency>
And then you include the jcl-over-slf4j (which is what provides commons-logging as we promised above).
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>2.0.0-alpha2-SNAPSHOT</version>
</dependency>
This should allow components using commons-logging to bridge their logs to your slf4j (and to the actual implementation, logback or whatever).
Here's a link to Jasper's other config things, should they be necessary.

Bouncycastle dependency conflicts

I have a web application created using spring boot. I have added jasper report, iText and bouncycastle maven dependency. Jasper and iText both contain bouncycastle libraries and now because of this the web application is not working correctly.
Error is: java.security.NoSuchProviderException: JCE cannot authenticate the provider BC. Note that I already added this code: Security.addProvider(new BouncyCastleProvider());
This perfectly works using spring boot embedded tomcat but not when exporting to a war file running on a wildfly server.
Here is how I declare the pom.
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.58</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>net.sf.jasperreports</groupId>
<artifactId>jasperreports</artifactId>
<version>6.4.0</version>
<exclusions>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk14</artifactId>
</exclusion>
<exclusion>
<groupId>org.bouncycastle</groupId>
<artifactId>bcmail-jdk14</artifactId>
</exclusion>
</exclusions>
</dependency>
Upon creating war file, this are the list of libraries included:
bcmail-jdk14-138
bcprov-jdk14-138
bcpkix-jdk15on is not being included even I specify it as provided
To quote directly from the Maven docs
provided
This is much like compile, but indicates you expect the JDK or a container to provide the dependency at runtime. For example, when building a web application for the Java Enterprise Edition, you would set the dependency on the Servlet API and related Java EE APIs to scope provided because the web container provides those classes. This scope is only available on the compilation and test classpath, and is not transitive.
To paraphrase, it uses the .jar marked as "provided" to compile (and test) your software, but when you package it up, it will not be included in the .war: you are expecting the runtime system to provide a (presumably different) version of those classes.
Try removing changing the scope of that dependency to "compile" to see if that resolves your problem.

Maven - Unable to resolve dependency conflict b/w google-vision beta & aws-sdk sub-components

I'm trying to use google-vision to fetch text from an image (uploaded to AWS S3) and store it in AWS Dynamo DB. I'm encountering dependency conflicts on jackson-core as both google-api and aws-java-sdk are using two different versions.
Dependency Hierarchy
google-api-client: 1.22.0 uses jackson-core: 2.1.3
google-cloud-vision: 0.22.0-beta uses jackson-core: 2.1.3
aws-java-sdk: 1.11.106 uses jackson-core: 2.6.6
I tried "exclusions" and added explicit dependency in pom.xml to use jackson-core: 2.6.6. Google-vision api works fine with that change. However, AmazonDynamoDBClientBuilder fails with below error:
Exception in thread "main" java.lang.IllegalAccessError: tried to access method com.amazonaws.AmazonWebServiceClient.<init>(Lcom/amazonaws/client/AwsSyncClientParams;)V from class com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder.build(AmazonDynamoDBClientBuilder.java:60)
at com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder.build(AmazonDynamoDBClientBuilder.java:26)
at com.amazonaws.client.builder.AwsSyncClientBuilder.build(AwsSyncClientBuilder.java:46)
at com.oneglint.ImageProcessing.AddItem.main(AddItem.java:133)
Following error is displayed when there was version conflict
Exception in thread "main" java.lang.NoSuchMethodError: com.fasterxml.jackson.core.JsonFactory.requiresPropertyOrdering()Z
at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:537)
at com.fasterxml.jackson.databind.ObjectMapper.<init>(ObjectMapper.java:448)
at com.amazonaws.partitions.PartitionsLoader.<clinit>(PartitionsLoader.java:51)
at com.amazonaws.regions.RegionMetadataFactory.create(RegionMetadataFactory.java:30)
at com.amazonaws.regions.RegionUtils.initialize(RegionUtils.java:64)
at com.amazonaws.regions.RegionUtils.getRegionMetadata(RegionUtils.java:52)
at com.amazonaws.regions.RegionUtils.getRegion(RegionUtils.java:105)
at com.amazonaws.client.builder.AwsClientBuilder.withRegion(AwsClientBuilder.java:239)
at com.oneglint.ImageProcessing.AddItem.main(AddItem.java:132)
What am I missing here? Thanks for the help..
BTW, I'm using example code from github to achieve this. Here are the links:
DynamoDB example: https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/java/example_code/dynamodb
Google Vision DetectText example: https://github.com/GoogleCloudPlatform/java-docs-samples/blob/master/vision/cloud-client/src/main/java/com/example/vision/Detect.java
Additional Details
Both the examples are working fine if executed as independent projects. The problem occurs ONLY when both PutItem (AWS) & Detect (google-vision) classes are brought together in a single project, with appropriate code changes.
You can only have one version of jackson-core in your project. The easiest way to fix a version is to use <dependencyManagement> to set a version.
Your main problem is that jackson-core: 2.6.6 is not compatible with AmazonDynamoDBClientBuilder. The usual strategy is to try all versions from 2.1.3 to 2.6.6 until one of them works. If not, you can try to find versions of your amazon and google jars that require the same Jackson-core-version. In any case, this stupid and boring try-and-error.
If you do not come to any working solution, you can try to shade classes with maven-shade-plugin (I have not tried this, probably difficult) or you need to change your project in a way that not both dependencies are required.
After a lot of trial and error approach, the issue is finally solved.
It appears that I added multiple versions of aws-java-sdk jars during the process and an opennlp jar was associated with the project for some other module.
I had removed conflicting versions of aws-java-sdk and unnecessary libraries. Also, removed the exclusions and retained only the dependency addition in <dependencymanagement> for jackson-core.
Dependencies in my final pom listed below:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-bom</artifactId>
<version>1.11.106</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.6.6</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-vision</artifactId>
<version>v1-rev358-1.22.0</version>
</dependency>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.22.0</version>
<exclusions>
<exclusion> <!-- exclude an old version of Guava -->
<groupId>com.google.guava</groupId>
<artifactId>guava-jdk5</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-vision</artifactId>
<version>0.22.0-beta</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-dynamodb</artifactId>
</dependency>
</dependencies>
Hope this helps others..

java.lang.NoClassDefFoundError: Could not initialize class org.apache.commons.logging.LogFactory

I am new to Google App Engine. I am getting this error :
java.lang.NoClassDefFoundError: Could not initialize class
org.apache.commons.logging.LogFactory at
org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:282) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) at
org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:548) at
org.mortbay.jetty.servlet.Context.startContext(Context.java:136) at ...
I have added slf4j dependencies and excluded commons-logging in spring-context dependency but still getting this error. The app works perfectly fine on my local machine but gives me this error when deployed to the App Engine.
Thanks to this blog , I was able to resolve this issue :
Commons-logging is a dependency of many frameworks, Spring included. On the local server, everything runs fine. In the cloud, Google App Engine infrastructure replaces the commons-logging-1.1.1.jar with a JAR of its own that has a different package structure. In effect, that means you get funny NoClassDefFoundError on org.apache.commons.logging.LogFactory even though you included the JAR as a dependency. The solution is to still include the classes, but to give the JAR another name.
Since I use Maven, I removed the commons-logging dependency from the WAR with the exclusion tag for Spring and MyFaces artifact. Then, I added a dependency on commons-logging:commons-logging-api:1.1:jar with the runtime scope. This jar won’t be replaced.
So you should exclude commons-logging from Spring :
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
Then add a dependency on commons-logging-1.1 with runtime scope:
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging-api</artifactId>
<version>1.1</version>
<scope>runtime</scope>
</dependency>
You are missing a required jar in your /war/WEB-INF/lib/ folder. It's not enough to have it in your classpath.
If you use Eclipse, you should see a warning in the Problems tab. Right click on it, Quick Fix, select " Copy ...". Or add this jar to the /lib folder manually.

Categories