workarea SOAP header cause the SOAPFaultException

By W.ZH Dec 2014

Issue:

When I was working on a project about the WS, my client jar always get this error:

Get Eligibility failed. Severity level is 5. Msg=SOAPFaultException – FaultCode [{http://schemas.xmlsoap.org/soap/envelope/}Server] FaultString [15
] FaultActor [null] Detail [<detail><bea_fault:stacktrace xmlns:bea_fault=”http://www.bea.com/servers/wls70/webservice/fault/1.0.0″>java.lang.ArrayIndexOutOfBoundsException: 15
at com.sun.beans.ObjectHandler.dequeueResult(ObjectHandler.java:139)
at java.beans.XMLDecoder.readObject(XMLDecoder.java:201)
at weblogic.wsee.workarea.WorkContextXmlInputAdapter.readUTF(WorkContextXmlInputAdapter.java:111)
at weblogic.workarea.spi.WorkContextEntryImpl.readEntry(WorkContextEntryImpl.java:92)
at weblogic.workarea.WorkContextLocalMap.receiveResponse(WorkContextLocalMap.java:226)
at weblogic.workarea.WorkContextMapImpl.receiveResponse(WorkContextMapImpl.java:182)
at weblogic.wsee.workarea.WorkAreaClientHandler.handleResponse(WorkAreaClientHandler.java:49)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.java:287)
at weblogic.wsee.handler.HandlerIterator.handleResponse(HandlerIterator.java:271)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.handleResponse(ClientDispatcher.java:213)
at weblogic.wsee.ws.dispatch.client.ClientDispatcher.dispatch(ClientDispatcher.java:150)
at weblogic.wsee.ws.WsStub.invoke(WsStub.java:87)
at weblogic.wsee.jaxrpc.StubImpl._invoke(StubImpl.java:341)

When I look at the SOAP XML. found this in the header:

<work:WorkContext xmlns:wsu=”http://schemas.xmlsoap.org/ws/2002/07/utility&#8221;

                      xmlns:work=”http://bea.com/2004/06/soap/workarea/”&gt;

     <java class=”java.beans.XMLDecoder”>

      <string>**************</string>

      <int>214</int>

      <string>weblogic.workarea.StringWorkContext</string>

      <string>1.4.1.18</string>

      <string>oracle.dms.context.internal.wls.WLSContextFamily</string>

      <int>335</int>

      <string>weblogic.workarea.SerializableWorkContext</string>

      <int>356</int>

      <array class=”byte” length=”356″>

       <void index=”0″>

       ……………………………………..

      <boolean>false</boolean>

      <string/>

     </java>

    </work:WorkContext>

 

Reason:

As my jar client is legacy code, so it in fact can not read this extra header properly, so it will get error.

Solution:

Use this flag at your setDomainEnv.sh to change java flag for this extra header:

-Dweblogic.wsee.workarea.skipWorkAreaHeader=true

after restart server. it will be fine

Advertisements

How to add data to SOAPHeader in the Web Service client code

By W.Zh   Mar 2014

Request

When you create a web service client proxy, after that, you want to insert some data in the SOAP header part, such as some security information, some user related or transaction information etc. how to do that in the WS java client code?

Solution

Use the
SOAPHandler to do this.

1. Create a SOAPandler  class to implement the handleMessage, inside this you can create your own SOAP elements structure and add to the SOAP header part. code is like this.


import com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl;

import java.util.Set;

import java.util.TreeSet;

import javax.xml.namespace.QName;

import javax.xml.soap.SOAPElement;

import javax.xml.soap.SOAPEnvelope;

import javax.xml.soap.SOAPFactory;

import javax.xml.soap.SOAPHeader;

import javax.xml.soap.SOAPMessage;

import javax.xml.ws.handler.MessageContext;

import javax.xml.ws.handler.soap.SOAPHandler;

import javax.xml.ws.handler.soap.SOAPMessageContext;

public class SOAPHeaderHandler implements SOAPHandler<SOAPMessageContext> {

  

    private static final String CLASS_NAME = “SOAPHeaderHandler”;

  

    public Set<QName> getHeaders() {

        return new TreeSet();

    }

    //<ns1:Security xmlns:ns0=”http://com.test.ws/”&gt;

    //       <ns1:userName>name here</ns0:userName>

    //     </ns1:Security>

    public boolean handleMessage(SOAPMessageContext context) {

        Boolean outboundProperty =

            (Boolean)context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

     

        if (outboundProperty != null && outboundProperty.booleanValue()) {

            SOAPMessage message = context.getMessage();

            try {

                SOAPEnvelope envelope =

                    context.getMessage().getSOAPPart().getEnvelope();

                SOAPHeader header = envelope.getHeader();

                SOAPFactory factory = SOAPFactory.newInstance();

                String prefix = “ns1”;

                String uri = “http://com.test.ws/&#8221;;

                SOAPElement securityElem =

                    factory.createElement(“Security”, prefix, uri);

                SOAPElement nameElem =

                    factory.createElement(“userName”, prefix, uri);

                String na = “Name here”;

                nameElem.addTextNode(na);

                securityElem.addChildElement(nameElem);

                // if no header, add one

                if (header == null) {

                    try {

                        header = envelope.addHeader();

                    } catch (SOAPExceptionImpl se) {

                      se.printStackTrace();

                    }

                }

                header.addChildElement(securityElem);

            } catch (Exception e) {

                e.printStackTrace();

            }

        } else {

            // inbound

        }

        return true;

    }

    public boolean handleFault(SOAPMessageContext context) {

       

        return true;

    }

    public void close(MessageContext context) {

        //

    }

}

2.  Then you can use the Jdev to create a Web server proxy client code. at the client code, after you get the server, you can setup the handler chains before you can the method in your WS.

YourWebservice yourWebservice=
new YourWebservice(new URL(yourWSDLAddress),
new QName(“http://………………&#8221;,
“YourWebservice”));

//add header for SOAP
yourWebservice.setHandlerResolver(new HandlerResolver() {
  public List<Handler> getHandlerChain(PortInfo portInfo) {
List<Handler> handlerList =
new ArrayList<Handler>();
handlerList.add(new SOAPHeaderHandler());
return handlerList;
}

});

3. Please note that
new YourWebservice(new URL(yourWSDLAddress), new QName(“http://………………&#8221;,”YourWebservice”));
is be used to define the dynamic WSDL URL.
 

 

SOAP JAX-RPC JAXB JAX-WS

Technical background  By ngoc.giang.nguyen and W.ZH

This section reviews some related technologies.

SOAP

SOAP is the protocol that specifies how a exchanged message between client and web service should be formed. Currently, there are 2 versions of SOAP being used: SOAP 1.1 and SOAP 1.2. The differences between SOAP 1.1 and SOAP 1.2 are usually irrelevant to end-users. For further information, please refer to this article.
When exposing a function, the web service always specifies which SOAP version the client should use to form the invocation message. It is done by supplying the appropriate namespace to the binding tag. E.g, for SOAP 1.2, the namespace should be http://schemas.xmlsoap.org/wsdl/soap12/; while for SOAP 1.1, the namespace should be http://schemas.xmlsoap.org/wsdl/soap/. The message sent by the client to a web service function must be of the same SOAP version with that function.
SOAP 1.2 is supported by most of the application servers such as OC4J and WebLogic?.

JAX-RPC

JAX-RPC is the protocol that specifies how to invoke a web service function. It can be seen as the bridge between WSDL, the guy who talks in business terms, and the application server, the guys who talks in technical terms. Using JAX-RPC tool, from a WSDL, we can generate a set of Java code understood by the application server.
JAX-RPC is good in communication, but it attempts to do extra thing, i.e. generating the mapping from WSDL data types to Java, and does it very badly. Not all types defined in WSDL are generated. The generation is done in a best-effort basis. When a type cannot be generated, a generic type (SOAPElement) is used instead. As a result, generated code is often unusable, or users have to do manual mapping on unsupported data types. In short, JAX-RPC mapping technology is an evolutionary dead-end, and soon people will move away from it.
JAX-RPC is the current web service standard and is fully supported by most applications servers such as OC4J and WebLogic?.

JAXB

JAXB is the XML mapping framework. The beauty of JAXB is that it bases on XML schema instead of predefined type as in JAX-RPC. Given an arbitrary XML schema, JAXB can generate corresponding Java code. At runtime, an XML string can be parsed again the schema to obtain Java object, and vice versa.
JAXB is a standalone technology and is not necessarily affiliated with web service.
There are 2 available versions of JAXB: JAXB 1.0 and JAXB 2.0. Oracle XDK 10g supports JAXB 1.0 only, while WebLogic? supports JAXB 2.0.

http://www.java.net/forum/topic/glassfish/metro-and-jaxb/customizing-jaxb-marshalled-xml-0
http://blogs.sun.com/enterprisetechtips/entry/customizing_jaxb
http://www.func.nl/community/knowledgebase/customize-namespace-prefix-when-marshalling-jaxb

==================== JAXB in Jdev 11g ==============================
http://technology.amis.nl/blog/3221/how-to-quickly-generate-an-xsd-xml-schema-definition-based-on-a-java-class-model-using-jdeveloper-11g
http://biemond.blogspot.com/2008/02/jaxb-20-in-jdeveloper-10g-and-11g.html
http://download.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.html

JAX-WS

JAX-WS is the marriage of JAX-RPC communication (which is the good part of JAX-RPC) and JAXB data binding. Therefore, it is much more superior than JAX-RPC and become standard in Jdeveloper 11g.
JAX-WS is only supported in Weblogic 10 and Oracle 11g onwards.