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
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&...]