Tomcat ClassCastException due to ClassLoaders - java

I am having some trouble implementing my own authentication filter in Tomcat. When I deploy the project I get the following log:
Caused by: java.lang.ClassCastException: class
com.somename.sec.sso.camunda.KeycloakSSOAuthenticationProvider cannot
be cast to class
org.camunda.bpm.engine.rest.security.auth.AuthenticationProvider
(com.somename.sec.sso.camunda.KeycloakSSOAuthenticationProvider is in
unnamed module of loader java.net.URLClassLoader #6fc6f14e;
org.camunda.bpm.engine.rest.security.auth.AuthenticationProvider is in
unnamed module of loader
org.apache.catalina.loader.ParallelWebappClassLoader #7a498efa)
Which is weird, since my KeycloakSSOAuthenticationProvider implements AuthenticationProvider. Apparently the casting fails due to the different Class Loaders. I suppose the casting fails in my web.xml file when I define the Authentication Filter:
<!-- Container Based Authentication filter -->
<filter>
<filter-name>Container Based Authentication Filter</filter-name>
<filter-class>org.camunda.bpm.webapp.impl.security.auth.ContainerBasedAuthenticationFilter</filter-class>
<init-param>
<param-name>authentication-provider</param-name>
<param-value>com.somename.sec.sso.camunda.KeycloakSSOAuthenticationProvider</param-value>
</init-param>
</filter>
Is there a way to force KeycloakSSOAuthenticationProvider to be loaded with the same class loader as AuthenticationProvider? Or how should I approach this problem?

I was having similar casting errors with Keycloak. The issue for me was that part of the set up for running keycloak on Tomcat (not embedded tomcat) you have to copy a number of keycloak library files into the tomcat_home/lib directory. You then also need those libs available to your java code, so they were included in the POM file as well.
The solution was to set the <scope>provided</scope> for the keycloak dependencies in the pom file. That way the code would compile, but there wouldn't be two versions of the class on the classpath while running.

Related

AbstractAnnotationConfigDispatcherServletInitializer with Jetty

I'm using Jetty 9.1.0.RC2 and Spring 4.
Have a AbstractAnnotationConfigDispatcherServletInitializer and trying to kick start the initialization with:
Server server = new Server();
WebAppContext webAppContext = new WebAppContext();
webAppContext.setContextPath("/");
webAppContext.setConfigurations(new Configuration[] { new AnnotationConfiguration() });
webAppContext.setParentLoaderPriority(true);
webAppContext.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*/target/classes/.*");
server.setHandler(webAppContext);
server.start();
server.join();
But failing to detect:
No Spring WebApplicationInitializer types detected on classpath
This is a common problem. Many more people are facing this issue. Sometimes it is causing error or sometimes it gives just as info. For info, there is no problem(just like warning). For error, there are many types of reason for occuring this error. I am trying to give you some sort of solutions.
Sometimes spring library and jdk version mismatch causes this error.
Classes are built in lower version of jdk and trying to run in upper
version may cause the error. Then we need to change using Eclipse
from Preferences\Java\Compiler We have to set "compiler compliance
level: 1.7" and "Generated .class files compatibility: 1.6", "Source
compatibility: 1.6".
Some of people get that log4j wasn't configured to capture error
output which was throwing configuration errors in the background.
If you are using maven, then WEB-INF directory must be inside your
webapp. Structure will be src/main/webapp/WEB-INF It also solves
this issue.
If "Project -> Build Automatically" is not selected. You can force
the "m2e-wtp folder and contents" generation by doing;
"(right-click
on your project) -> Maven -> Update Project..."
Note: make sure the
"Clean Projects" option is un-selected. Otherwise the contents of
target/classes will be deleted and you're back to square one.
Add WebROOT file directory to the default directory, then this
problem will be solved.
properties->MyEclipse->Deployment
Assembly->Add
Resource Link:
No Spring WebApplicationInitializer types detected on classpath
INFO: No Spring WebApplicationInitializer types detected on classpath
only one error: No Spring WebApplicationInitializer types detected on classpath
For tomcat,
if maven has tomcat7 plugin but the JRE environment was 1.6. Then
this problem occurs. Then you need to downgrade tomcat7 to tomcat6
or upgrade jdk and jre version to 1.7.
Sometimes it is need to stop your tomcat. Then clean the project,
clean the server and run again your project. Sometimes caches make this
issue. After following this way, it may solve.
For JBOSS,
#Sotirios Delimanolis given a very nice answer. That is given below:
In a typical servlet application, you would have a web.xml descriptor file to declare your serlvets, filters, listeners, context params, security configuration, etc. for your application. Since servlet 3.0 you can do most of that programmatically.
Servlet 3.0 offers the interface ServletContainerInitializer, which you can implement. Your servlet container will look for your implementation of that class in META-INF/services/javax.servlet.ServletContainerInitializer file, instantiate it, and call its onStartup() method.
Spring has built WebApplicationInitializer on top of that interface, as an adapter/helper.
You need either the web.xml descriptor or a class that implements WebApplicationInitializer to setup and run your application.
Resource Link:
Jboss No Spring WebApplicationInitializer types detected on classpath
A brief detail answer is given below with Jetty:
Spring WebApplicationInitializer - how it works and what may go wrong
Startup of servlet contexts without web.xml
Servlets of release 3 can be configured programatically, without any web.xml.
With Spring and its Java-configuration you create a configuration class that implements org.springframework.web.WebApplicationInitializer.
Spring will automatically find all classes that implement this interface and start the according servlet contexts. More excatly its not Spring that searches for those classes, its the servlet container (e.g. jetty or tomcat ).
The class org.springframework.web.SpringServletContainerInitializer is annotated with
#javax.servlet.annotation.HandlesTypes(WebApplicationInitializer.class)
and implements javax.servlet.ServletContainerInitializer
According to the Servlet 3 specification the container will call org.springframework.web.SpringServletContainerInitializer.onStartup(Set<Class<?>>, ServletContext) on every class in the classpath implementing that interface, suppling a set of classes as defined in HandlesTypes
Startup order, if there is more than one context
If there is more than one class that implements WebApplicationInitializer, the order in which they are started can be controlled with the annotation org.springframework.core.Ordered .
Things that may go wrong
Different Spring versions in the classpath
If you have different versions of WebApplicationInitializer in the classpath, the servlet container may scan for the classes implementing WebApplicationInitializer of version 'A' while your configuration classes implement WebApplicationInitializer of version 'B'. And than your configuration classes will not be found and the sercletontexts will not be started.
Unexpected WebApplicationInitializers in the classpath
Do not package any WebApplicationInitializers into jars or wars that you later may have in the classpath of other web applications. They may get found and started when you do not expect it. This happend to me when I packed WebApplicationInitializers with Maven into test-jars, which were reused by other tests.
To many classes in the classpath
The servlet container has to scan the classpath, and the more classes, the longer it takes.
At least Jetty has a build in timeout, so you may get an
javax.websocket.DeploymentException thrown by
org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer
The solution is to tell jetty which jars to scan. This will make the
startup much faster and avoids the timeout. In Maven you can do it
like this :
pom.xml
<plugin>
<groupId> org.eclipse.jetty</groupId >
<artifactId> jetty-maven-plugin</artifactId >
<configuration>
<webAppConfig>
<contextPath> /${project.artifactId}</contextPath >
<webInfIncludeJarPattern> busines-letter-*.</webInfIncludeJarPattern >
</webAppConfig>
Spring logging
When you have logging configured you should find one of the following entries in your log :
If Spring finds no WebApplicationInitializer at all, you will see in the log :
No Spring WebApplicationInitializer types detected on classpath
If Spring finds at least one WebApplicationInitializer you will see :
Spring WebApplicationInitializers detected on classpath: " + initializers

Struts2 <filter> and <filter-mapping> causing error

I have a web application using Eclipse, Struts2, and running on a Tomcat 7 Server.
I've been going off of the http://javabrains.koushik.org tutorials.
I have all the basic Struts pieces in place, but for some reason when I introduce this snippet of code into the web.xml.
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
<filter-mapping>
It throws the book at me.
SEVERE: Dispatcher initialization failed
Unable to load configuration. - bean -
Caused by: Unable to load bean: type: class:com.opensymphony.xwork2.ObjectFactory - bean -
Caused by: Bean type class com.opensymphony.xwork2.ObjectFactory with the name struts has already been loaded by bean -
SEVERE: Exception starting filter struts2
Unable to load configuration. - bean -
Caused by: Unable to load configuration. - bean -
Caused by: Unable to load bean: type: class:com.opensymphony.xwork2.ObjectFactory - bean -
Caused by: Bean type class com.opensymphony.xwork2.ObjectFactory with the name struts has already been loaded by bean - jar:file:/C:/Program%20Files%20(x86)/Apache%20Software%20Foundation/Tomcat%207.0/lib/struts2-core-2.3.16.jar!/struts-default.xml:40:72
- bean -
I know this isn't the complete text dump but I don't know how useful the rest of it would be. I need to understand why it's doing this so I can get it working.
You should not copy application specific jars to the server lib folder. Instead use WEB-INF/lib. Remove struts2-core-2.3.16.jar from the server lib. If you have another struts2-core-x.x.x.jar in WEB-INF/lib it prevents Tomcat to deploy your application because libraries from the Tomcat lib folder loading before any application is being deployed. It stops the deployment. Tomcat lib folder should contain only Tomcat installed jars needed to run the web container, there's no need to copy there other jars unless you know what are you doing.
Never mind. It turns out all I needed to do is to forget the build path and only put the jars into the WEB-INF/lib folder. Works like a charm :D

classloading woes with Jboss & RestEasy using a separately deployed jar containing the javax.ws.rs.Application

I have a simple setup with a war file containing only a web.xml that specifies the javax.ws.rs.Application class to use in the servlet.
The jar that contains the implementation for javax.ws.rs.Application is also completely trivial. Both the web.xml and the implementation are based off the examples in jboss documentation
However, I get different behavior when I deploy the war + jar combination in jboss AS 7.1.1 Final versus jboss 4.0.4. Upon accessing the rest api I get the following exception in the jboss logs (snippet only):
06:33:59,540 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/wrapper]] (MSC service thread 1-2) StandardWrapper.Throwable: java.lang.RuntimeException: java.lang.ClassNotFoundException: com.projectgoth.provider.restapi.RestApiProvider from [Module "deployment.wrapper.war:main" from Service Module Loader]
at org.jboss.resteasy.spi.ResteasyDeployment.createFromInjectorFactory(ResteasyDeployment.java:271) [resteasy-jaxrs-2.3.2.Final.jar:]
at org.jboss.resteasy.spi.ResteasyDeployment.createApplication(ResteasyDeployment.java:259) [resteasy-jaxrs-2.3.2.Final.jar:]
If however, I change the scope of the jar from provided to runtime in the war's pom.xml - the error does indeed go away from jboss as 7.1.1.
For reference, I've uploaded the code use for both the war and jar to bitbucket (where provider = implementation for the javax.ws.rs.Application, and wrapper is the war deployable)
I think this is normal. Per class loader policy, a child class can always see the parent class not the vice verse. When you put the jar scope as runtime, the JAR is loaded in the classpath up in the stream than the WAR application and hence it's visible to the WAR classes.

Extending spring based app

I have a spring-based Web Service. I now want to build a sort of plugin for it that extends it with beans. What I have now in web.xml is:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/*-configuration.xml</param-value>
</context-param>
My core app has main-configuration.xml which declares its beans. My plugin app has plugin-configuration.xml which declares additional beans. Now when I deploy, my build deploys plugin.jar into /WEB-INF/lib/ and copies plugin-configuration.xml into /WEB-INF/classes/ all under main.war.
This is all fine (although I think there could be a better solution), but when I develop the plugin, I don't want to have two projects in Eclipse with dependencies. I wish to have main.jar that I include as a library. However, web.xml from main.jar isn't automatically discovered. How can I do this? Bean injection? Bean discovery of some sort? Something else?
Note: I expect to have multiple different plugins in production, but development of each of them will be against pure main.jar
Thank you.
I think there is a simpler approach:
In your host application (the webapp) define something like the following contextConfigLocation parameter:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:/META-INF/foo/*-configuration.xml</param-value>
</context-param>
The crucial parts are classpath*:as it results in scanning the entire classpath for config files matching the following pattern. If you only use classpath: the lookup will stop at the first file found. It also won't traverse JARs if not starred correctly.
The second crucial part is having at least one non-wildcarded basepath for the lookup to work. This is due to Classloader traits that only reliably returns all resources if they contain a base path (see the Javadoc on PathMatchingResourcePatternResolver for details).
What you now have to do with your plugin projects is place your plugin-configuration.xml in /META-INF/foo/, package that as JAR and place it into your classpath (in case you build with Maven just add the dependency).
On application start Spring will now also pickup all config files from your plugins and build the ÀpplicationContext` from em.
You also might wanna checkout another post I did on application modularity with Spring: How do you make a multi-module spring configuration?
Instead of /WEB-INF/classes/*-configuration.xml, try classpath:*-configuration.xml
You can also list configuration files, each on a new line.
You will have to make sure that main.jar ends up in WEB-INF/lib, if you're not using maven you can do this in eclipse by marking you webapp as dependent on the project that creates the main.jar, via the project properties.

Two struts2 webapps fail to start together

I have problems getting two different struts2 webapps to start together in tomcat. But each of the webapps start correctly when placed independently inside webapps folder of tomcat.
I get the following in catalina.out logs-
SEVERE: Error filterStart
Aug 13, 2009 3:17:45 PM org.apache.catalina.core.StandardContext start
SEVERE: Context [/admin] startup failed due to previous errors
Environment- Java1.6, Tomcat6, Struts2.1.6, FC10
The webapps are "admin" and "user". Both of these webapps contain struts2 jars inside their WEB-INF/lib directory respectively.
web.xml contains the following in both the webapps-
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
A point to note that always the "admin" webapp fails to load with the above error. If I remove the "user" webapp from webapps folder, "admin" webapp comes up just fine.
I have also observed one more thing w.r.t struts2 filter in web.xml- If I remove the struts2 filter from web.xml in one of the webapps, BOTH the webapps start without any errors in the logs (but of course I won't be able to use struts in the webapp where the filter is removed).
I have also tried moving the struts2 jar to tomcat lib and removing them from individual webapps, but same problem exists..
Any ideas what is causing this problem?
Updates: This strangely works fine on Ubuntu OS. But the problem persists on FC10 and OpenSolaris.
I had a similar problem using Spring and using this listener class in web.xml:
org.springframework.web.util.Log4jConfigListener
See the documentation of the Spring Log4jWebConfigurer, which says you need unique "web app root" properties defined per web-app, so I had to have a section like this in each web.xml:
<!-- used by Log4jConfigListener -->
<context-param>
<param-name>webAppRootKey</param-name>
<param-value>myappname.root</param-value>
</context-param>
Are you using Spring ? If not hope this gives you some clues, I don't know much about Struts2 maybe it does something similar. Do let me know how it goes !
We had the same problem while launching two struts2 Maven apps on the same server. The xerces lib was the problem so we did add xalan in the pom.xml dependencies and everything worked fine:
<dependency>
<groupId>xalan</groupId>
<artifactId>xalan</artifactId>
<version>2.7.1</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
Thanks alzoid, extraneon and Peter.
I had overlooked an exception coming up on localhost..log file. I thought I had redirected all the struts log to a different log file but had overlooked mentioning the opensymphony package in the log4j properties file.
Coming to original problem- there was a class loader issue with xerces-impl jar and some other jar file belonging to struts2. So when I removed the xerces-impl jar from the WEB-INF/lib directories in both apps, it started worked fine!

Categories