I am trying to deploy a new spring MVC app, I've done it a dozen times, but now I run on a really weird error, can't even figure out what's happening:
My javaee-api is conflicting with the servlet-api. In the console it writes:
INFO: validateJarFile(E:\development\workspace\conference\src\main\webapp\WEB- INF\lib\javaee-api-6.0.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2.
Offending class: javax/servlet/Servlet.class
Well, yes, it is a warning, but this jar is not loaded and I need it. Also, I have no servlet-api jars in my application libs, etc.
Also, the console throws such an exception:
SEVERE: Error configuring application listener of class com.sun.faces.config.ConfigureListener
java.lang.ClassNotFoundException: com.sun.faces.config.ConfigureListener
I mean, this jar is refered to the JSF and all of that stuff. I'm not using it at all, where should it try to get such a class? O_o
I am running the app on tomcat 7
Any ideas what is going on?
The problem with jar file is that Tomcat's classloader validates all clases, that it loads to JVM. In your case it faced a class from servlets API - javax.servlet.Servlet. You application code must not contain such classes inside WEB-INF/lib. These classes are shipped with servlet container itself. If you use maven, just change the scope of javax.servlet:servlet-api to provided.
After you fix this, try to reload the whole app, because it may occur that classloader just blocked javaee-api-6.0.jar entirely, not allowing any other classes be loaded from it.
You can remove the javaee-api-6.0.jar file from your webapps' WEB-INF/lib directory, by setting the scope provided in its dependency.
The Spec refers that the Servlet Container (Here, Tomcat) will supply the implementation classes of the Java EE spec. Having application specific implementations is a stability and security problem that is disallowed by the spec/Tomcat.
Thanks!
Related
I am in the process of migrating a legacy application from weblogic to Tomcat 6.
The application needs to access ejbs; to achieve that, I added wlclient.jar to the classpath.
When the methods in the legacy jars responsible for communicating with the ejbs are called, I get the following exception :
javax.naming.NamingException: Unhandled exception in lookup
[Root exception is org.omg.CORBA.MARSHAL: vmcid: SUN minor code: 211 completed: Maybe]
which cause is :
Caused by: java.lang.IllegalArgumentException: interface com.xxx.xxx.InterfaceName is not visible from class loader
at java.lang.reflect.Proxy.getProxyClass(Proxy.java:353)
at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:581)
at weblogic.iiop.ProxyDesc.readResolve(ProxyDesc.java:45)
That Interface seems to be used to define the method called from the client to return some informations from the server where the ejbs are deployed.
When running with verbose:class, I find that the Interface is actually loaded from the local jar. The corresponding interface on the server is loaded too :
[Loaded com.xx.xx.InterfaceName_t3s99q_InterfaceNameIntf from http://192.168.x.xx:port/path/classes/]
Even though I do not have any idea how that works internally, I assumed the lookup had gone well since it finds the correct class on the server.
When putting breakpoints in Proxy.getProxyClass, I found the used classloader when the exception occurs was a Launcher$AppClassLoader; the URL's it used to lookup were those in my local classpath (a.k.a. src/main/java and such) and not the webapp's path (a.k.a. WEB-INF/lib and such).
So my question is : is it possible that the wrong ClassLoader gets used for that specific lookup (local one instead of Tomcat's webapp level one)?
Can I specify a specific ClassLoader?
Am I looking in the completely wrong direction to resolve that issue ?
Well I lost 1.5 days on this, so I'll post an answer hoping it will eventually be useful to someone.
The problem was that I included wlclient.jar in eclipse classpath, and since the oracle implementation uses super.getClass().getClassLoader() , it would return the ClassLoader used to load the Class in which the call is made a.k.a. the local ClassLoader and not the one from the Webapp, so it did not have visiblity of the webapp dependencies.
I updated my project to include the jar in WEB-INF/lib so it would be loaded by the webapp and thus super.getClass().getClassLoader() would return the right ClassLoader.
An other possibility would have been to modify that line to use Thread.currentThread.getContextClassLoader instead.
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
I've written some code to create and run webservice client using CXF. I used JaxWsClientFactoryBean (not sure it's the best solution) to create client from .wsdl file.
The goal here was to do this programmatically avoiding Spring etc. Just pure code with Java and CXF.
JaxWsClientFactoryBean cfb = new JaxWsClientFactoryBean();
cfb.setAddress(getServiceProperty(intClass, PROPERTY_KEY_URL_SUFFIX));
cfb.setServiceClass(intClass);
cfb.setOutInterceptors(getOutInterceptors(intClass));
cfb.setServiceName(SERVICE_NAME);
cfb.setWsdlURL("classpath:wsdl/" + intClass.getSimpleName() + ".wsdl");
cfb.setEndpointName(ENDPOINT_NAME);
Client client = cfb.create();
ClientProxy cp = new ClientProxy(client);
I intService = (I)
Proxy.newProxyInstance(intClass.getClassLoader(), new Class[] { intClass }, cp);
I'm really not sure if this is done correctly, but it works when I run this code locally and when I deploy it on Tomcat.
Unfortunatelly I need to run this code on Weblogic and this results in strange exception:
Caused by: javax.wsdl.WSDLException: WSDLException: faultCode=PARSER_ERROR: org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was
made to insert a node where it is not permitted.
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:235)
at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:186)
at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:92)
... 26 more
Caused by: org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at com.sun.org.apache.xerces.internal.dom.ParentNode.internalInsertBefore(ParentNode.java:356)
at com.sun.org.apache.xerces.internal.dom.ParentNode.insertBefore(ParentNode.java:284)
at com.sun.org.apache.xerces.internal.dom.CoreDocumentImpl.insertBefore(CoreDocumentImpl.java:399)
at com.sun.org.apache.xerces.internal.dom.NodeImpl.appendChild(NodeImpl.java:235)
at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:1019)
at org.apache.cxf.staxutils.StaxUtils.readDocElements(StaxUtils.java:939)
at org.apache.cxf.staxutils.StaxUtils.read(StaxUtils.java:866)
at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:226)
... 28 more
This happens during application deployment. It looks like there is something wrong with .wsdl file, but wait... It was working on Tomcat!
I think that there could be some difference in com.sun.org.apache.xerces.* classes implementation within Weblogic with its JRockit VM and standard JVM, but I have no idea how to solve it.
I spent many hours trying differend ways of client creation. Most of them worked locally and in Tomcat, but none on WebLogic.
Any hints what to try next? I'm kinda tired of this topic :D
I agree with your suspicion that the problem is related to the used version of Xerces. The stacktrace shows that the Sun implementation of Xerces which is derivative of the Apache Xerces is used in your case.
Please check the Apache CFX Application Server Configuration Guide instructions related to WebLogic.
WebLogic ClassLoading
In WebLogic Server, any .jar file present in the system classpath is loaded by the WebLogic Server system classloader. All applications running within a server instance are loaded in application classloaders which are children of the system classloader. In this implementation of the system classloader, applications cannot use different versions of third-party jars which are already present in the system classloader. Every child classloader asks the parent (the system classloader) for a particular class and cannot load classes which are seen by the parent.
For example, if a class called com.foo.Baz exists in both $CLASSPATH as well as the application EAR, then the class from the $CLASSPATH is loaded and not the one from the EAR. Since weblogic.jar is in the $CLASSPATH, applications can not override any WebLogic Server classes.
In order to use an alternate version of Xerces you have to create a FilteringClassLoader.
Usage of FilteringClassLoader
The FilteringClassLoader provides a mechanism for you to configure deployment descriptors to explicitly specify that certain packages should always be loaded from the application, rather than being loaded by the system classloader. This allows you to use alternate versions of applications such as Xerces and Ant.
The FilteringClassLoader sits between the application classloader and the system. It is a child of the system classloader and the parent of the application classloader. The FilteringClassLoader intercepts the loadClass(String className) method and compares the className with a list of packages specified in weblogic-application.xml file.
In conclusion, check the steps included in the Apache CFX Application Server Configuration Guide and take care to explicitly specify that the org.apache.xerces.* package is loaded from the application, rather than being loaded from the system classloader.
For example the weblogic-application.xml file in the META-INF should look like:
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-application xmlns="http://www.bea.com/ns/weblogic/90">
<application-param>
<param-name>webapp.encoding.default</param-name>
<param-value>UTF-8</param-value>
</application-param>
<prefer-application-packages>
<package-name>javax.jws.*</package-name>
<package-name>org.apache.xerces.*</package-name>
</prefer-application-packages>
</weblogic-application>
I hope this helps.
I am trying to run a JSF 2.0 webapp using Apache MyFaces 2.1.7 on a Tomcat 6 webserver. The App uses Tomahawk 1.1.11 and expression language 2.2 (el-impl-2.2.jar). For that purpose I've put the myfaces-api and myfaces-impl into Tomcats lib folder and exchanged Tomcats el-api.jar for the 2.2 variant.
When I call the first page of the app I always get the error:
java.lang.IllegalStateException: No Factories configured for this Application. This
happens if the faces-initialization does not work at all - make sure that you properly
include all configuration settings necessary for a basic faces application and that all
the necessary libs are included. Also check the logging output of your web application
and your container for any exceptions!
If you did that and find nothing, the mistake might be due to the fact that you use
some special web-containers which do not support registering context-listeners via TLD
files and a context listener is not setup in your web.xml.
A typical config looks like this;
<listener>
<listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
</listener>
javax.faces.FactoryFinder._getFactory(FactoryFinder.java:286)
javax.faces.FactoryFinder.getFactory(FactoryFinder.java:206)
javax.faces.webapp.FacesServlet.init(FacesServlet.java:116)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
java.lang.Thread.run(Thread.java:679)
I definitely have the xml snippet mentioned in my web.xml. I tried to debug into the code and found that registeredFactoryNames on line 267 of javax.faces.FactoryFinder is empty which causes the error. I however do not understand why this is the case. What should be in there and how do I get it there?
The funny thing is that the webapp runs perfectly using embedded jetty 8. So it must be some dependency issue.
Hope someone with more insight into all of this can help me here.
Ok
I found the problem. The error results from having the myfaces-api.jar twice on your classpath. So for me the problem was I placed the myfaces-api.jar in the tomcat lib folder and in the WEB-INF/lib folder of the webapp.
While using an embedded tomcat with maven I had the myfaces-api.jar in the dependencies of the whole application and in the dependencies of the tomcat6-maven-plugin with scope compile both. I changed the scope from compile to provided in the global dependencies section and it worked.
I think it could be solved just adding an empty faces-config.xml file under /WEB-INF/ folder, to indicate the application uses JSF and MyFaces continue the initialization step. See the class org.apache.myfaces.ee6.MyFacesContainerInitializer for details.
My servlet application includes a number of library .jars, some of which contain embedded log4j.xml or log4j.properties files. I'd like to ensure that log4j finds my log4j.xml first! I've tried searching for some specification of the priorities of the various classpath elements in a servlet (e.g. does WEB-INF/classes always precede WEB-INF/lib?), or some way to configure or tweak the servlet's classloader so that a given resource directory appears early in the classpath. So far, I've drawn a blank. Any suggestions on ensuring that a servlet .war file loads the correct log4j.xml via the classloader?
Tomcat 8.5
Ditto Tomcat 8.0.
See documentation: Class Loader HOW-TO.
Tomcat 8.0
The answer is simple, taken from the Tomcat documentation page, Class Loader HOW-TO. In particular notice the use of the /WEB-INF/ directory/folder.
Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
Bootstrap classes of your JVM
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
System class loader classes (described above)
Common class loader classes (described above)
If the web application class loader is configured with <Loader delegate="true"/> then the order becomes:
Bootstrap classes of your JVM
System class loader classes (described above)
Common class loader classes (described above)
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
Tomcat 6
Excerpted from Tomcat 6 page, Class Loader HOW-TO.
Therefore, from the perspective of a web application, class or resource loading looks in the following repositories, in this order:
Bootstrap classes of your JVM
System class loader classes (described above)
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
$CATALINA_HOME/lib
$CATALINA_HOME/lib/*.jar
As far as I understand the resource selection from the classpath is non-deterministic (from the point of view of the app developer). Even if the same file is loaded consistently the behaviour could change:
1. When you upgrade the version of your current container.
2. If you switch containers.
The simplest solution will be to remove embedded log4j config files from library jars. It is almost never a good idea to embed log4j config's as it leads to the problem you are seeing here...
Are they third party jars or jars you developed?
We the Spring Log4jConfigListener in our web.xml file.
You can specify as a context parameter the location of the log4j config file, i.e. you could set it as /WEB-INF/log4j.xml
Would this be an option for you? If you're not using Spring I know that you can set the Log4j location programatically which might also work.
In my experience, WEB-INF/classes typically takes precedence over jars in WEB-INF/lib, however, that also depends on the servlet container you use (I could never figure out the behavior of JRun, for instance). It would help immensely if you could tell me which container you're using.
Also, are you certain that the offending log4j configuration is in a jar in WEB-INF/lib? Typically, when I've run into classpath problems in a servlet container situation, it's because of libraries that reside outside of the web app.
The servlet specs recommend that web app classloaders load their own classes before delegating to the container's classloader (SRV.9.7.2), but since this is counter to the Java spec, not all vendors do this by default (in fact Tomcat is the only container I've used that does this by default). With that said, it's always possible to configure your container's web app classloading behavior. If you tell me which container you're using, I may be able to help you (specifically, I have done this successfully before on WebLogic, WebSphere, Glassfish and JRun)).
If you're unable to control the classpath, since Tomcat is setting it for you, are you at least able to set a system property for log4j.configuration? I believe that location pointed to by that property can be set outside of the classpath.
If not, another approach, although an ugly one, would be to explicitly run one of the configurators yourself in your application code.
You need to have log4j.properties in your CLASSPATH. The best place is under WEB-INF/classes.
You also have to make sure that you use your version of log4j.jar. So, put it in WEB-INF/lib, just to make sure you are not using one from tomcat folders, since it may cause strange classloading issues.