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.
Related
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.
I am learning spring web mvc project from online resources, i came across this logger slf4j, and i want to use it in my application.
I don't have any idea on how to add this. what i am thinking is i should remove commons-logging.jar from lib folder, and add another jar file to lib folder, but then i don't know which jar file i should add as there are many jar files present in slf4j.zip that i have downloaded from its official site.
I have searched and read few posts/articles about integrating slf4j but they all were related to maven, and i don't have maven, i simply started working with adding spring framework jars to dynamic web project.
Please tell me how and what files i should add in lib folder for logging purpose. or how to configure the slf4j logger.
thanx folks!!
The official source of information on logging in Spring is the Spring Reference.
If you want to use SLF4J, this document suggests using the following Maven dependencies:
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.0.6.RELEASE</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
</dependency>
</dependencies>
In other words, you need four .jar files, and you need to make sure that the Commons Logging library is NOT on your classpath.
If you do not use Maven, you can download these .jars from the Maven Central Repository manually. Enter groupId, artifactId and version on that page, press Search, and download the .jar file (not sources.jar!). Here are direct links to these .jar files: jcl-over-slf4j, slf4j-api, slf4j-log4j12, log4j.
You will also need to create and put on your classpath the configuration file for log4j (log4j.xml or log4j.properties).
I think that by not using Maven you make your life harder, not easier. It's better to spend some time learning it, than spend a lot of time trying to avoid learning it.
I would actually argue against using pure SLF4J to begin with, because its own creators have already created a successor.
Reasons to use it instead of SLF4J are given on http://logback.qos.ch/reasonsToSwitch.html
And the "First baby steps" in the manual are at http://logback.qos.ch/manual/introduction.html
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.
I have prepared some util classes.
I planned to make them as jar and distribute it to required projects.
My util classes uses some already existing custom code provided in the form of jar file.
My code is dependent on "MainUtil.jar" whi internally dependends on Java Servlet, Commons IO, Commons Codec and so on.....
My POM dependency looks as below.
<dependency>
<groupId>com.solutions</groupId>
<artifactId>sol-core</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-ws-security</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-ws-policy</artifactId>
<version>${cxf.version}</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk16</artifactId>
<version>1.46</version>
</dependency>
When I package my jar it looks fine.
But when my jar is used in a project where these my util classes are used , I could see a wierd issue.
The commonc-codec jar files are not included in the project package when packaged.
Also code which requies this common-codec is failing.
When I explicitly include the commons-codec dependency, everything works perectly.
My confusion is, why should I explicitly add the codec dependency when I should be resolved by Maven based on the POM of the custom jar files.
And why the issue is happening only with the commons-codec but not with other dependency.
Your code depends on all the other jars. When you create jar for your project the jar file does not contain all the dependent jar classes.
Where ever you are using your jar you have to use other dependent jars. You have not mentioned whether you are using maven there also. If yes then if you have defined dependency then all the dependent jars will be in the classpath.
Issue with you dependency resolving is,
the existing dependency in your project might have some dependency management on this jar. That is the reason, old jar is taking precedence over your custom jar dependency.
Thry adding exclusion in your already existing jar for this common-codec jar.
like
<dependency>
<... Your existing dependency ..>
<exclusions>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
</dependency>
Use this command and check how your dependency is being resolved.
mvn dependency:resolve
Then everything should be fine.
Will adding a MANIFEST.MF file with Class-Path attribute to META-INF directory inside EAR influence the order of loading of JARs located in APP-INF/lib under WebLogic 8.1?
I don't believe you can control the APP-INF/lib order via ClassPath attribute of MANIFEST.MF.
I've done this a couple different ways, depending on the client.
Add the patch jar to the system classpath for WLS. If you examine domain/bin/setDomainEnv.sh (or .cmd) there should pre, post, patch classpath environment variables. You could try to add your patch jar to the classpath here. This makes it available for all apps, which might not be what your client wants.
Patch somejar.jar & name it somejar-patched.jar. Replace the jar in APP-INF/lib with the "-patched" version.
I thought the class loader read JARs as they're required by your application.
I have two questions for you:
Why are you still using WebLogic 8.1? It's off support now, and the current version is 10.x. You're two versions behind. Is this a legacy app that hasn't migrated yet? You'll get a big boost by upgrading, because you'll be using JDK 5 or 6 with the -server option. I'd recommend it.
Why should you care about the order of loading? It should be immaterial to your app how the container loads and manages the beans.
UPDATE:
That sounds different, almost as if you were having conflicts with server JARs. There's that prefer-web-inf-classes setting for that situation. Is that what you mean?
I agree with duffymo
You shouldn't have to worry about the order of class loading, if this is due to conflicting classes you can always exclude the conflicting classes from Jars using Maven or a similar tool.
For instance this is a very simple example of adding jersey-spring4 jar but I'm excluding its dependencies so I can use a different version of the spring framework library.
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring4</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-web</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-aop</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-context</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
<exclusion>
<artifactId>spring-beans</artifactId>
<groupId>org.springframework</groupId>
</exclusion>
</exclusions>
</dependency>