QName problem with BEA WebLogic Server (WLS) 8.1

One day I was looking for a fast and easy to use Java webservice implementation. I found XFire, the next gen java SOAP framework which is based on a low memory StAX model. There’s a FAQ on the XFire website about how to run XFire in a WebLogic environment. XFire requires a newer version of the javax.xml.namespace.QName than is included in weblogic.jar. Now, this cures the problem with the missing constructor. Depending on what exactly you do in your webservice other errors may occur. The most prominent exception being this one:

java.lang.LinkageError:
loader constraints violated when linking
javax/xml/namespace/QName

The problem occurs if there’s the combination of an older version of QName (being loaded from the application server at boot time) and a library which uses the 3-string constructor introduced in a later version of QName. This most likely is a class loading issue because the QName class in weblogic.jar is loaded earlier by the system classloader and can’t be “overridden” by the EAR/WAR classloader. But that’s just my best bet as I am not a classloader expert when it comes to WebLogic’s classloading mechanism.

This is neither an XFire-only problem nor is it a WebLogic-only problem! I read about XML libraries (eg. XMLBeans, Spring, Muse) having the same issues with QName if running in an application server environment (e.g. IBM Websphere).

Solution for WebLogic Server: put QName (qname.jar) ahead of
weblogic.jar in your classpath and do not load qname.jar from the lib
directory of your web application.

In my company’s production environment (2000 users) we use a patch directory for WebLogic patches (quite a few…) we receive from BEA. The patches are being put ahead of weblogic.jar in the classpath. But our WebLogic administrator denied my request to put qname.jar in it because its not an “official” patch from BEA. So I opened a case at BEA’s support website. I was instructed to deliver a test case which you find a bit lower on this page.

If you are in a similar situation and have access to the support area you can refer to my BEA case #691432 to obtain an official patch/recommendation for the QName issue. I haven’t yet tested if the problem still exists in WebLogic 9.x which uses Java 5. I’m planning to do this in the first quarter of 2008.

QnameServlet.java

package qname;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URL;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.namespace.QName;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceFactory;

public class QnameServlet extends HttpServlet {

/**
* The doGet method of the servlet. <br>
*
* This method is called when a form has its tag value method equals to get.
*
* @param aRequest the request send by the client to the server
* @param aResponse the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest aRequest, HttpServletResponse
aResponse) throws ServletException, IOException {
aResponse.setContentType("text/html");
PrintWriter _out = aResponse.getWriter();
_out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01
Transitional//EN\">");
_out.println("<HTML>");
_out.println("  <HEAD><TITLE>QnameServlet</TITLE></HEAD>");
_out.println("  <BODY>");

/**
* Some XML-specific libraries use the 3-parameter QName constructor
introduced some time ago. BEA WebLogic 8.1
* SP6 uses an old version of QName in weblogic.jar.
*
* If you don't add the current version of the QName-class to your
classpath, this is what happens:
* java.lang.NoSuchMethodError:
javax.xml.namespace.QName.<init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
* at ch.suva.qnameservlet.QnameServlet.doGet(QnameServlet.java:39) at
* javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at
* javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at
* weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1072)
at
* weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:465)
at
* weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:348)
at
* weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:6981)
at
* weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at
* weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at
* weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3892)
at
* weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2766)
at
* weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224) at
* weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183)
*
* So, the qname.jar with the current version of QName is added to
the lib directory of the web application and
* weblogic is instructed (prefer-web-inf-classes in weblogic.xml)
to prefer the libs from the .WAR. Testing
* with the new prefixed QName constructor from the qname.jar in the
lib of this .WAR fails with:
* java.lang.LinkageError: loader constraints violated when linking
javax/xml/namespace/QName class unless you
* put qname.jar AHEAD OF weblogic.jar in the classpath! Complete
stacktrace: java.lang.LinkageError: loader
* constraints violated when linking javax/xml/namespace/QName class at
* ch.suva.qnameservlet.QnameServlet.doGet(QnameServlet.java:83) at
* javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at
* javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at
* weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1072)
at
* weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:465)
at
* weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:348)
at
* weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:6981)
at
* weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at
* weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at
* weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3892)
at
* weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2766)
at
* weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224) at
* weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183)
*
* Now, because the given URL is invalid, the service can't be
created. This is the proper exception when
* qname.jar is placed ahead of weblogic.jar in the classpath and
qname is NOT being loaded from the .WAR
* Stacktrace=javax.xml.rpc.JAXRPCException: failed to create service at
* weblogic.webservice.core.rpc.ServiceImpl.getWebService(ServiceImpl.java:123)
at
* weblogic.webservice.core.rpc.ServiceFactoryImpl.createService(ServiceFactoryImpl.java:42)
at
* ch.suva.qnameservlet.QnameServlet.doGet(QnameServlet.java:44) at
* javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at
* javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at
* weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1072)
at
* weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:465)
at
* weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:348)
at
* weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:6981)
at
* weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at
* weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
at
* weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3892)
at
* weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2766)
at
* weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224) at
* weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183)
*
* The problem is most likely a classloading issue.
*/
QName _qname = new QName("namespaceURI", "localPart", "prefix");
_out.println("QName=" + _qname.toString() + "<p>");
try {
URL url = new
URL("http://localhost:7001/non_existing_url_but_that_doesnt_matter");
ServiceFactory _factory = ServiceFactory.newInstance();
Service _service = _factory.createService(url, _qname);
}
catch (Throwable th) {
_out.println("Stacktrace=");
th.printStackTrace(_out);
_out.println("<br>");
}

_out.println("</BODY>");
_out.println("</HTML>");
_out.flush();
_out.close();
}

}

web.xml

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>

<servlet>
<servlet-name>XFireServlet</servlet-name>
<display-name>XFire Servlet</display-name>
<servlet-class>
org.codehaus.xfire.transport.http.XFireConfigurableServlet
</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>XFireServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>

<security-constraint>
<web-resource-collection>
<web-resource-name>Success</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
</security-constraint>

<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>

</web-app>

weblogic.xml

<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web
Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">

<weblogic-web-app>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>
===== weblogic.xml =====
<code xml>
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web
Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">

<weblogic-web-app>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>

5 thoughts on “QName problem with BEA WebLogic Server (WLS) 8.1

  1. Hi, did you get any problem after this changes? I’m using Struts with Axis2 1.4.1 and Weblogic 8.1 (I need to use Java1.4)

    And after some changes in the weblogic.xml file (http://axis.apache.org/axis/java/install.html Step 2).

    I have the following error when loading the page:

    Error 500–Internal Server Error

    java.lang.NullPointerException
    at org.apache.struts.util.RequestUtils.pageURL(RequestUtils.java:1441)
    at org.apache.struts.util.RequestUtils.computeURL(RequestUtils.java:456)
    at org.apache.struts.util.RequestUtils.computeURL(RequestUtils.java:365)
    at org.apache.struts.taglib.html.RewriteTag.doStartTag(RewriteTag.java:99)
    at jsp_servlet.__errorhandler._jspService(__errorhandler.java:183)
    at weblogic.servlet.jsp.JspBase.service(JspBase.java:33)
    at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1077)
    at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:465)
    at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:348)
    at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:330)
    at weblogic.servlet.jsp.PageContextImpl.forward(PageContextImpl.java:150)
    at weblogic.servlet.jsp.PageContextImpl.handlePageException(PageContextImpl.java:309)
    at jsp_servlet.__index._jspService(__index.java:151)
    at weblogic.servlet.jsp.JspBase.service(JspBase.java:33)
    at weblogic.servlet.internal.ServletStubImpl$ServletInvocationAction.run(ServletStubImpl.java:1077)
    at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:465)
    at weblogic.servlet.internal.ServletStubImpl.invokeServlet(ServletStubImpl.java:348)
    at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:7047)
    at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
    at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121)
    at weblogic.servlet.internal.WebAppServletContext.invokeServlet(WebAppServletContext.java:3902)
    at weblogic.servlet.internal.ServletRequestImpl.execute(ServletRequestImpl.java:2773)
    at weblogic.kernel.ExecuteThread.execute(ExecuteThread.java:224)
    at weblogic.kernel.ExecuteThread.run(ExecuteThread.java:183)

    Do you have any idea about?

    Danke schön,
    Cladio

  2. Mithlesh Panchal

    The old version of QName class is not supporting constructer with 3 param of type String. you have to use “xml-apis-1.4.01.jar” or latest version of jar file. java Java version also. if you are using Java 1.4 then you have to use only “xml-apis-1.4.01.jar” file

  3. Hi,
    I have got the same issue.I need the solution for this issue.But I don’t know how to register a case with bea.
    Please help me to get it.
    Thanks in advance.

  4. Christian, this number is an internal case id. You have to open a case and refer to that number. Eventually this will lead to the same patch that we got which was essentially just a qname.jar with a more or less official blessing.

  5. Hello, I am confronted with the same problem, but it is involving Axis2 and Weblogic 8.1. And I am also faced with a refusal to put the qname.jar in the server classpath by the “Operation Support” of my company. Could send me the reference of your case to BEA because I could not find the reference #691432 in the eSupport of http://www.bea.com.

    In my case I cannot use the inversion of classloader to override the server classloader. My composant is in an ear and not in a War.

    Thanks a lot.

Comments are closed.