[jboss-user] [JBoss Web Services CXF] - Continuing problem with XTS WS-T tests in AS trunk/CXF 2.2.9

Andrew Dinn do-not-reply at jboss.com
Fri Jun 18 06:58:33 EDT 2010


Andrew Dinn [http://community.jboss.org/people/adinn] created the discussion

"Continuing problem with XTS WS-T tests in AS trunk/CXF 2.2.9"

To view the discussion, visit: http://community.jboss.org/message/548690#548690

--------------------------------------------------------------
The XTS tests are still seeing some failures on the latest AS trunk with cxf stack 3.3.1.SP1. I think they all appear to stem from a single issue which relates to dispatch of soap faults. It's  not actually CXF's  fault handling which is the problem. The XTS code uses its own JaxWS based service to dispatch faults -- I know that sounds weird but I'll explain that in a minute. Anyway, the problem is not actually to do with the dispatch, routing or receipt of the soap faults, it's to do with creating the relevant JaxWS service. This is a WSDL first service defined as follows:


> <?xml version="1.0" encoding="utf-8"?>
> <!--
>     a specification for a service which can be used to dispatch a SOAP 1.1 SoapFault
>     to an arbitrary client
> -->
> <definitions
>         xmlns:s="http://www.w3.org/2001/XMLSchema"
>         xmlns:tns="http://jbossts.jboss.org/xts/soapfault"
>         xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
>         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
>         xmlns:wsaw="http://www.w3.org/2006/02/addressing/wsdl"
>         targetNamespace="http://jbossts.jboss.org/xts/soapfault"
>     xmlns="http://schemas.xmlsoap.org/wsdl/">
>     <types>
>         <s:schema>
>             <s:import namespace="http://schemas.xmlsoap.org/soap/envelope/"
>                       schemaLocation="http://schemas.xmlsoap.org/soap/envelope"/>
>         </s:schema>
>     </types>
>     <message name="SoapFault">
>          <part name="fault" element="soapenv:Fault" />
>     </message>
>  
> 
>     <portType name="SoapFaultPortType">
>         <operation name="SoapFault">
>             <input name="SoapFault" message="tns:SoapFault" />
>         </operation>
>     </portType>
>  
> 
>     <binding name="SoapFault_SOAPBinding" type="tns:SoapFaultPortType">
>       <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
>       <operation name="SoapFault">
>         <input message="tns:Soapfault">
>           <soap:body use="literal"/>
>         </input>
>       </operation>
>     </binding>
>  
> 
>     <service name="SoapFaultService">
>       <port binding="tns:SoapFault_SOAPBinding" name="SoapFaultPortType">
>     <wsaw:UsingAddressing required="true"/>
>     <soap:address location="http://localhost:9000/interopat/SoapFaultService"/>
>       </port>
>     </service>
> 
> 
> </definitions>
> 

I generated code from  this WSDL using wsconsume (well, actually, I think I generated it using Glassfish's wsimport but essentially it is the same thing) as follows:

> @WebServiceClient(name = "SoapFaultService", targetNamespace = "http://jbossts.jboss.org/xts/soapfault", wsdlLocation = "wsdl/soapfault.wsdl")
> public class SoapFaultService extends Service
> {
>     private final static URL SOAPFAULTSERVICE_WSDL_LOCATION;
>     private final static Logger logger = Logger.getLogger(org.jboss.jbossts.xts.soapfault.SoapFaultService.class.getName());
>  
> 
>     static {
>         URL url = null;
>         try {
>             URL baseUrl;
>             baseUrl = org.jboss.jbossts.xts.soapfault.SoapFaultService.class.getResource(".");
>             url = new URL(baseUrl, "wsdl/soapfault.wsdl");
>         } catch (MalformedURLException e) {
>             logger.warning("Failed to create URL for the wsdl Location: 'wsdl/soapfault.wsdl', retrying as a local file");
>             logger.warning(e.getMessage());
>         }
>         SOAPFAULTSERVICE_WSDL_LOCATION = url;
>     }
>  
> 
>     public SoapFaultService(URL wsdlLocation, QName serviceName) {
>         super(wsdlLocation, serviceName);
>     }
>  
> 
>     public SoapFaultService() {
>         super(SOAPFAULTSERVICE_WSDL_LOCATION, new QName("http://jbossts.jboss.org/xts/soapfault", "SoapFaultService"));
>     }
>     /**
>      * 
>      * @return
>      *     returns SoapFaultPortType
>      */
>     @WebEndpoint(name = "SoapFaultPortType")
>     public SoapFaultPortType getSoapFaultPortType() {
>         return super.getPort(new QName("http://jbossts.jboss.org/xts/soapfault", "SoapFaultPortType"), SoapFaultPortType.class);
>     }
>     /**
>      * 
>      * @param features
>      *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
>      * @return
>      *     returns SoapFaultPortType
>      */
>     @WebEndpoint(name = "SoapFaultPortType")
>     public SoapFaultPortType getSoapFaultPortType(WebServiceFeature... features) {
>         return super.getPort(new QName("http://jbossts.jboss.org/xts/soapfault", "SoapFaultPortType"), SoapFaultPortType.class, features);
>     }
> }
> 
> @WebService(name = "SoapFaultPortType", targetNamespace = "http://jbossts.jboss.org/xts/soapfault")
> @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
> @XmlSeeAlso({
>     ObjectFactory.class
> })
> public interface SoapFaultPortType {
>     /**
>      * 
>      * @param fault
>      */
>     @WebMethod(operationName = "SoapFault")
>     @Oneway
>     public void soapFault(
>         @WebParam(name = "Fault", targetNamespace = "http://schemas.xmlsoap.org/soap/envelope/", partName = "fault")
>         Fault fault);
> } 

The problem is that when my tests try to create a SoapFaultPortType I get a parse error during processing of the WSDL. Unfortunately, the error is not reported as being in my WDSL. It ahppens wen processing the imported schema

>         <s:schema>
>             <s:import namespace=" http://schemas.xmlsoap.org/soap/envelope/ http://schemas.xmlsoap.org/soap/envelope/"
>                       schemaLocation=" http://schemas.xmlsoap.org/soap/envelope http://schemas.xmlsoap.org/soap/envelope"/>
>         </s:schema>

I stepped through the code and found that it successfully loads the schema located at  http://schemas.xmlsoap.org/soap/envelope http://schemas.xmlsoap.org/soap/envelope but then runs into problems processing the contents. Here is the error message:
> [Fatal Error] strict.dtd:81:5: The declaration for the entity "ContentType" must end with '>'.
> [Fatal Error] envelope:2:2: The markup in the document following the root element must be well-formed.
> javax.xml.ws.WebServiceException: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
>     at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:152)
>     at org.apache.cxf.jaxws.spi.ProviderImpl.createServiceDelegate(ProviderImpl.java:63)
>     at javax.xml.ws.Service.<init>(Service.java:57)
>     at org.jboss.jbossts.xts.soapfault.SoapFaultService.<init>(SoapFaultService.java:46)
>     at com.arjuna.webservices11.wsaddr.client.SoapFaultClient.getSoapFaultService(SoapFaultClient.java:98)
>     at com.arjuna.webservices11.wsaddr.client.SoapFaultClient.getSoapFaultPort(SoapFaultClient.java:130)
>     at com.arjuna.webservices11.wsaddr.client.SoapFaultClient.sendSoapFault(SoapFaultClient.java:86)
>     at com.arjuna.webservices11.wsat.client.CompletionInitiatorClient.sendSoapFault(CompletionInitiatorClient.java:123)
>     at com.arjuna.wst11.tests.junit.CompletionCoordinatorTestCase.testSendError(CompletionCoordinatorTestCase.java:180)
>     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
>     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
>     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
>     at java.lang.reflect.Method.invoke(Method.java:597)
>     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
>     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
>     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
>     at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
>     at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
>     at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:31)
>     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
>     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
>     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
>     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
>     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
>     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
>     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
>     at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
>     at org.junit.runners.Suite.runChild(Suite.java:128)
>     at org.junit.runners.Suite.runChild(Suite.java:24)
>     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
>     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
>     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
>     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
>     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
>     at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
>     at org.junit.runners.Suite.runChild(Suite.java:128)
>     at org.junit.runners.Suite.runChild(Suite.java:24)
>     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
>     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
>     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
>     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
>     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
>     at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
>     at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
>     at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
>     at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
>     at com.arjuna.qa.junit.TestRunnerServlet$RunnerThread.run(TestRunnerServlet.java:523)
> Caused by: org.apache.cxf.service.factory.ServiceConstructionException: Failed to create service.
>     at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:93)
>     at org.apache.cxf.jaxws.ServiceImpl.initializePorts(ServiceImpl.java:207)
>     at org.apache.cxf.jaxws.ServiceImpl.<init>(ServiceImpl.java:150)
>     ... 46 more
> Caused by: javax.wsdl.WSDLException: WSDLException (at /definitions/types/s:schema): faultCode=PARSER_ERROR: Problem parsing 'http://schemas.xmlsoap.org/soap/envelope'.: org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.
>     at com.ibm.wsdl.xml.WSDLReaderImpl.getDocument(Unknown Source)
>     at com.ibm.wsdl.xml.WSDLReaderImpl.parseSchema(Unknown Source)
>     at com.ibm.wsdl.xml.WSDLReaderImpl.parseSchema(Unknown Source)
>     at com.ibm.wsdl.xml.WSDLReaderImpl.parseTypes(Unknown Source)
>     at com.ibm.wsdl.xml.WSDLReaderImpl.parseDefinitions(Unknown Source)
>     at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
>     at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
>     at org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:230)
>     at org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:179)
>     at org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:91)
>     ... 48 more
> Caused by: org.xml.sax.SAXParseException: The markup in the document following the root element must be well-formed.
>     at org.apache.xerces.parsers.DOMParser.parse(Unknown Source)
>     at org.apache.xerces.jaxp.DocumentBuilderImpl.parse(Unknown Source)
>     ... 58 more
> 


As you can see the problem occurs under ServiceImple.<init> below SoapFaultService.<init> when trying to create the SoapFaultService class  generated by wsconsume. This is somewhat bizarre given where the schema comes from.

Ok, so you might want an explanationfor what this servcie is and why it needs to import the soap envelope schema. It's abit copnvoluted but here goes. XTS implements the WS-C and WS-T services defined by the WSTX standard. WS-C includes two generic services for creating and enlisting with transactions from various transaction transaction protocols. WS-T includes two families of transaction protocol specific services which allow transaction clients and transactional web services to progress towards completion completion. The service APIs are specified by WSDL and our rimplementation uses JaxWS to implement  that WSDL.

The WS-T services (WS-AT atomic transaction and WS-BA business activity), are only mandated only to employ a OneWay MEP. Tthe SOAP used to deliver these messages is required to be configured with various mandatory WSA headers, including MessageId, ReplyTo and FaultTo. The SOAP headers also need to include service specific transaction identifiers as header elements. This is achieved by by installing them as ReferenceParameters in the endpoints used by the transaction protocol services and transactional web services communicate ie. they are attached to

* the transaction protocol specific Coordinator service endpoints handed out to transactional web services by the WS-C registration service when they enlist in a transaction
*  the endpoint in the ReplyTo/FaultTo header included by web services when they negotiate with the registration service or with their Coordinator service

Yes, as you can see, the use of one way messaging means that the container for the transactional web service must also contain a WS-AT or WS-BA Initiator service. The Coordinator talks back to this Initiator service in order to be able to constuct a long-running dialogue with the transactional web service composed  of a series of 1-way messages such as e.g. +enlist+, +prepare+, +prepared+, +commit+, +commited+. In the case of WS-BA this dialogue can be initiated asynchronously from either end --  that's why OneWay MEP was chosen over RPC.

The service specification mandates that in cases where processing of a message runs into certain error conditions a SoapFault must be dispatched to the FaultTo addess configured in the WSA headers. Obviously, if a fault  occurs in +delivering+ the message the JaxWS layer will dispatch a fault to the sender. But that's not that the spec is talking about (or  at least not +all+ it is talking about). The spec is concerned with faults which occur after delivery when the delivered message is being processed. By this stage JaxWS has done its stuff and told the sender 'message delivered'. If the service endpoint bean were to throw a fault nothing would get dispatched back to  the sender. So, the threads which are handling a request to the Coordinator or Initiator services need to be able to dispatch a fault to the FaultTo address asynchronously -- from a standing start. This fault needs to
* be sent to the FaultTo address
* provide a WSA RelatesTo header whcih includes the originating MessageId
* include the ReferenceParameter header obtained with the FaultTo address.

Now the WS-AT/BA coordinator and initiator service enpoint implementation classes all implement a WebMethod which accepts a SoapFault with a specific SOAPAction or WSA Action. This web method is declared by interface SoapFaultPortType generated from the SoapFaultService WSDL and all these services implement the interface i.e.they are capable of acting as an endpoint for the SoapFaultPortType of the SoapFaultService. Now, in order to dispatch an asynchronous SoapFault to the sender the handler thread merely needs to create a fault and an instance of SoapFaultService then clone a proxy port from it and call method soapFault(). So this is what is happening when my current implementation blows up trying to read the soap envelope WSDL.

--------------------------------------------------------------

Reply to this message by going to Community
[http://community.jboss.org/message/548690#548690]

Start a new discussion in JBoss Web Services CXF at Community
[http://community.jboss.org/choose-container!input.jspa?contentType=1&containerType=14&container=2046]

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jboss-user/attachments/20100618/d6580c58/attachment-0001.html 


More information about the jboss-user mailing list