dev@jax-ws.java.net

Re: SOAPFault headers? (and SOAPFault in general)

From: Ryan Shoemaker - JavaSoft East <Ryan.Shoemaker_at_Sun.COM>
Date: Fri, 08 Dec 2006 10:54:18 -0500

Arun Gupta wrote:
>
> Ryan Shoemaker - JavaSoft East wrote:
>>
>> One final question: suppose that I want to dispatch a SOAPFault to an EPR
>
> What do you mean by dispatching a fault to an EPR ?

My wsdl is full of one-way operations that do not specify any faults. For
example:

     <wsdl:portType name="RegistrationCoordinatorPortType">
         <wsdl:operation name="RegisterOperation">
             <wsdl:input message="wscoor:Register"
                         wsa:Action="http://schemas.xmlsoap.org/ws/2004/10/wscoor/Register"/>
         </wsdl:operation>
     </wsdl:portType>

The implementation of this operation is required to send faults under certain
error conditions, but I can't throw SOAPFaultException since it's one-way.

Everyone else I've spoke with about this says that I need to use Dispatch to
send the fault. I'm currently trying something like this (but the code isn't
complete):

     MessageContext msgContext = wsContext.getMessageContext();
     HeaderList headers = (HeaderList) msgContext.get(JAXWSProperties.INBOUND_HEADER_LIST_PROPERTY);
     String msgID = headers.getMessageID(AddressingVersion.MEMBER, SOAPVersion.SOAP_11);
     EndpointReference replyTo = (headers.getReplyTo(AddressingVersion.MEMBER, SOAPVersion.SOAP_11)).toSpec();
     WSEndpointReference faultTo = (headers.getFaultTo(AddressingVersion.MEMBER, SOAPVersion.SOAP_11));

     if( error detected ) {
         WsaHelper.sendFault(
             faultTo != null ? faultTo.toSpec() : null,
             registrationRequesterEPR,
             WsaHelper.createFault(SOAPVersion.SOAP_11, TxFault.InvalidState, "Some Message"),
             null);
     }

Where WsaHelper.sendFault looks like:

     public static void sendFault(@Nullable EndpointReference faultTo,
                                  @NotNull EndpointReference replyTo,
                                  @NotNull SOAPFault fault,
                                  @NotNull QName serviceName) {

         EndpointReference to = faultTo != null ? faultTo : replyTo;

         Service s = Service.create(new QName("foo", "bar"));
         Dispatch<Source> d = s.createDispatch(to, Source.class, Service.Mode.MESSAGE,
                                              /* TODO: enable one-way feature??? */ null);
         d.invokeOneWay(new DOMSource(fault));
     }

WsaHelper.createFault just creates a SOAP 1.1 SOAPFault and fills in the
fields.

The above code isn't working. I'm passing bogus info into Service.create
since I don't have a service name. Apparently this was a 2.1 MR spec issue
that never got resolved. Beyond that, I'm now getting:

javax.xml.ws.WebServiceException: EPR does nt have WSDL Metadata which is needed for the current operation
         at com.sun.xml.ws.client.WSServiceDelegate.getPortNameFromEPR(WSServiceDelegate.java:478)
         at com.sun.xml.ws.client.WSServiceDelegate.addPortEpr(WSServiceDelegate.java:441)
         at com.sun.xml.ws.client.WSServiceDelegate.createDispatch(WSServiceDelegate.java:351)
         at javax.xml.ws.Service.createDispatch(Service.java:450)
         at com.sun.xml.ws.tx.common.WsaHelper.sendFault(WsaHelper.java:96)
         etc.

Which is kind of funny since the EPR I'm passing into createDispatch was
created by the JAX-WS runtime system.

The bottom line is that I need to be able to construct a new SOAPFault and
send it back to the faultTo or replyTo EPRs contained in the message I'm
currently processing. The fault has to contain wsa:Action and wsa:RelatesTo.

Any help would be greatly appreciated since I'm basically stuck and don't
really know what to try next. Pointers to source code examples would be
great.

Thanks,

--Ryan