Fixed SWS-79: Add faults into dynamically created WSDL

This commit is contained in:
Arjen Poutsma
2007-04-11 22:37:10 +00:00
parent 0a920628f7
commit b7629e47d1
5 changed files with 129 additions and 35 deletions

View File

@@ -33,6 +33,7 @@ import javax.wsdl.extensions.ExtensibilityElement;
import javax.wsdl.extensions.soap.SOAPAddress;
import javax.wsdl.extensions.soap.SOAPBinding;
import javax.wsdl.extensions.soap.SOAPBody;
import javax.wsdl.extensions.soap.SOAPFault;
import javax.wsdl.extensions.soap.SOAPOperation;
import javax.xml.namespace.QName;
@@ -180,9 +181,9 @@ public abstract class AbstractSoap11Wsdl4jDefinitionBuilder extends AbstractBind
*/
protected void populateBindingFault(BindingFault bindingFault, Fault fault) throws WSDLException {
super.populateBindingFault(bindingFault, fault);
SOAPBody soapBody = (SOAPBody) createSoapExtension(BindingOutput.class, "body");
populateSoapBody(soapBody);
bindingFault.addExtensibilityElement(soapBody);
SOAPFault soapFault = (SOAPFault) createSoapExtension(BindingFault.class, "fault");
populateSoapFault(bindingFault, soapFault);
bindingFault.addExtensibilityElement(soapFault);
}
/**
@@ -197,6 +198,20 @@ public abstract class AbstractSoap11Wsdl4jDefinitionBuilder extends AbstractBind
soapBody.setUse("literal");
}
/**
* Called after the <code>SOAPFault</code> has been created. Default implementation sets the use style to
* <code>"literal"</code>, and sets the name equal to the binding fault. Subclasses can override this behavior.
*
* @param bindingFault the WSDL4J <code>BindingFault</code>
* @param soapFault the WSDL4J <code>SOAPFault</code>
* @throws WSDLException in case of errors
* @see javax.wsdl.extensions.soap.SOAPBody#setUse(String)
*/
protected void populateSoapFault(BindingFault bindingFault, SOAPFault soapFault) throws WSDLException {
soapFault.setName(bindingFault.getName());
soapFault.setUse("literal");
}
/**
* Creates a <code>SOAPAddress</code>, and calls <code>populateSoapAddress()</code>.
*

View File

@@ -19,9 +19,11 @@ package org.springframework.ws.wsdl.wsdl11.builder;
import java.io.IOException;
import java.util.Iterator;
import javax.wsdl.Definition;
import javax.wsdl.Fault;
import javax.wsdl.Input;
import javax.wsdl.Message;
import javax.wsdl.Operation;
import javax.wsdl.OperationType;
import javax.wsdl.Output;
import javax.wsdl.Part;
import javax.wsdl.PortType;
@@ -71,6 +73,9 @@ public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jD
/** The default suffix used to detect response elements in the schema. */
public static final String DEFAULT_RESPONSE_SUFFIX = "Response";
/** The default suffix used to detect fault elements in the schema. */
public static final String DEFAULT_FAULT_SUFFIX = "Fault";
/** The default prefix used to register the schema namespace in the WSDL. */
public static final String DEFAULT_SCHEMA_PREFIX = "schema";
@@ -96,6 +101,8 @@ public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jD
private String responseSuffix = DEFAULT_RESPONSE_SUFFIX;
private String faultSuffix = DEFAULT_FAULT_SUFFIX;
/**
* Sets the suffix used to detect request elements in the schema.
*
@@ -114,6 +121,15 @@ public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jD
this.responseSuffix = responseSuffix;
}
/**
* Sets the suffix used to detect fault elements in the schema.
*
* @see #DEFAULT_FAULT_SUFFIX
*/
public void setFaultSuffix(String faultSuffix) {
this.faultSuffix = faultSuffix;
}
/** Sets the port type name used for this definition. Required. */
public void setPortTypeName(String portTypeName) {
this.portTypeName = portTypeName;
@@ -207,20 +223,22 @@ public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jD
}
/**
* Creates messages for each element found in the schema for which <code>isRequestMessage()</code> or
* <code>isResponseMessage()</code> is <code>true</code>.
* Creates messages for each element found in the schema for which <code>isRequestMessage()</code>,
* <code>isResponseMessage()</code>, or <code>isFaultMessage()</code> is <code>true</code>.
*
* @param definition the WSDL4J <code>Definition</code>
* @throws WSDLException in case of errors
* @see #isRequestMessage(javax.xml.namespace.QName)
* @see #isResponseMessage(javax.xml.namespace.QName)
* @see #isFaultMessage(javax.xml.namespace.QName)
*/
protected void buildMessages(Definition definition) throws WSDLException {
NodeList elements = schemaElement.getElementsByTagNameNS(SCHEMA_NAMESPACE_URI, "element");
for (int i = 0; i < elements.getLength(); i++) {
Element element = (Element) elements.item(i);
QName elementName = getSchemaElementName(element);
if (elementName != null && (isRequestMessage(elementName) || isResponseMessage(elementName))) {
if (elementName != null &&
(isRequestMessage(elementName) || isResponseMessage(elementName) || isFaultMessage(elementName))) {
Message message = definition.createMessage();
populateMessage(message, element);
Part part = definition.createPart();
@@ -256,6 +274,18 @@ public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jD
return name.getLocalPart().endsWith(responseSuffix);
}
/**
* Indicates whether the given name should be included as <code>Message</code> in the definition. Default
* implementation checks whether the local part ends with the fault suffix.
*
* @param name the name of the element elligable for being a message
* @return <code>true</code> if to be included as message; <code>false</code> otherwise
* @see #setFaultSuffix(String)
*/
protected boolean isFaultMessage(QName name) {
return name.getLocalPart().endsWith(faultSuffix);
}
/**
* Called after the <code>Message</code> has been created.
* <p/>
@@ -305,19 +335,22 @@ public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jD
portType.setQName(new QName(targetNamespace, portTypeName));
}
/** @noinspection UnnecessaryLocalVariable */
private void createOperations(Definition definition, PortType portType) throws WSDLException {
for (Iterator messageIterator = definition.getMessages().values().iterator(); messageIterator.hasNext();) {
Message message = (Message) messageIterator.next();
for (Iterator partIterator = message.getParts().values().iterator(); partIterator.hasNext();) {
Part part = (Part) partIterator.next();
if (isRequestMessage(part.getElementName())) {
Message responseMessage = definition.getMessage(getResponseMessageName(message.getQName()));
Message requestMessage = message;
Message responseMessage = definition.getMessage(getResponseMessageName(requestMessage.getQName()));
Message faultMessage = definition.getMessage(getFaultMessageName(requestMessage.getQName()));
Operation operation = definition.createOperation();
populateOperation(operation, message, responseMessage);
if (message != null) {
populateOperation(operation, requestMessage, responseMessage);
if (requestMessage != null) {
Input input = definition.createInput();
input.setMessage(message);
input.setName(message.getQName().getLocalPart());
input.setMessage(requestMessage);
input.setName(requestMessage.getQName().getLocalPart());
operation.setInput(input);
}
if (responseMessage != null) {
@@ -326,6 +359,21 @@ public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jD
output.setName(responseMessage.getQName().getLocalPart());
operation.setOutput(output);
}
if (faultMessage != null) {
Fault fault = definition.createFault();
fault.setMessage(faultMessage);
fault.setName(faultMessage.getQName().getLocalPart());
operation.addFault(fault);
}
if (requestMessage != null && responseMessage != null) {
operation.setStyle(OperationType.REQUEST_RESPONSE);
}
else if (requestMessage != null && responseMessage == null) {
operation.setStyle(OperationType.ONE_WAY);
}
else if (requestMessage == null && responseMessage != null) {
operation.setStyle(OperationType.NOTIFICATION);
}
operation.setUndefined(false);
portType.addOperation(operation);
}
@@ -352,6 +400,25 @@ public class XsdBasedSoap11Wsdl4jDefinitionBuilder extends AbstractSoap11Wsdl4jD
}
}
/**
* Given an request message name, return the corresponding fault message name.
* <p/>
* Default implementation removes the request suffix, and appends the fault suffix.
*
* @param requestMessageName the name of the request message
* @return the name of the corresponding response message, or null
*/
protected QName getFaultMessageName(QName requestMessageName) {
String localPart = requestMessageName.getLocalPart();
if (localPart.endsWith(requestSuffix)) {
String prefix = localPart.substring(0, localPart.length() - requestSuffix.length());
return new QName(requestMessageName.getNamespaceURI(), prefix + faultSuffix);
}
else {
return null;
}
}
/**
* Called after the <code>Operation</code> has been created.
* <p/>

View File

@@ -29,6 +29,14 @@
</complexType>
</element>
<element name="GetFlightsFault">
<complexType>
<sequence>
<element name="errorCode" type="string"/>
</sequence>
</complexType>
</element>
<element name="BookFlightRequest">
<complexType>
<all>
@@ -123,47 +131,39 @@
</schema>
</wsdl:types>
<wsdl:message name="GetFrequentFlyerMileageResponse">
<wsdl:part element="schema:GetFrequentFlyerMileageResponse" name="GetFrequentFlyerMileageResponse">
</wsdl:part>
<wsdl:part element="schema:GetFrequentFlyerMileageResponse" name="GetFrequentFlyerMileageResponse"/>
</wsdl:message>
<wsdl:message name="BookFlightResponse">
<wsdl:part element="schema:BookFlightResponse" name="BookFlightResponse">
</wsdl:part>
<wsdl:part element="schema:BookFlightResponse" name="BookFlightResponse"/>
</wsdl:message>
<wsdl:message name="GetFlightsRequest">
<wsdl:part element="schema:GetFlightsRequest" name="GetFlightsRequest">
</wsdl:part>
<wsdl:part element="schema:GetFlightsRequest" name="GetFlightsRequest"/>
</wsdl:message>
<wsdl:message name="GetFlightsFault">
<wsdl:part element="schema:GetFlightsFault" name="GetFlightsFault"/>
</wsdl:message>
<wsdl:message name="GetFrequentFlyerMileageRequest">
<wsdl:part element="schema:GetFrequentFlyerMileageRequest" name="GetFrequentFlyerMileageRequest">
</wsdl:part>
<wsdl:part element="schema:GetFrequentFlyerMileageRequest" name="GetFrequentFlyerMileageRequest"/>
</wsdl:message>
<wsdl:message name="GetFlightsResponse">
<wsdl:part element="schema:GetFlightsResponse" name="GetFlightsResponse">
</wsdl:part>
<wsdl:part element="schema:GetFlightsResponse" name="GetFlightsResponse"/>
</wsdl:message>
<wsdl:message name="BookFlightRequest">
<wsdl:part element="schema:BookFlightRequest" name="BookFlightRequest">
</wsdl:part>
<wsdl:part element="schema:BookFlightRequest" name="BookFlightRequest"/>
</wsdl:message>
<wsdl:portType name="Airline">
<wsdl:operation name="GetFlights">
<wsdl:input message="tns:GetFlightsRequest" name="GetFlightsRequest">
</wsdl:input>
<wsdl:output message="tns:GetFlightsResponse" name="GetFlightsResponse">
</wsdl:output>
<wsdl:input message="tns:GetFlightsRequest" name="GetFlightsRequest"/>
<wsdl:output message="tns:GetFlightsResponse" name="GetFlightsResponse"/>
<wsdl:fault message="tns:GetFlightsFault" name="GetFlightsFault"/>
</wsdl:operation>
<wsdl:operation name="GetFrequentFlyerMileage">
<wsdl:input message="tns:GetFrequentFlyerMileageRequest" name="GetFrequentFlyerMileageRequest">
</wsdl:input>
<wsdl:output message="tns:GetFrequentFlyerMileageResponse" name="GetFrequentFlyerMileageResponse">
</wsdl:output>
<wsdl:input message="tns:GetFrequentFlyerMileageRequest" name="GetFrequentFlyerMileageRequest"/>
<wsdl:output message="tns:GetFrequentFlyerMileageResponse" name="GetFrequentFlyerMileageResponse"/>
</wsdl:operation>
<wsdl:operation name="BookFlight">
<wsdl:input message="tns:BookFlightRequest" name="BookFlightRequest">
</wsdl:input>
<wsdl:output message="tns:BookFlightResponse" name="BookFlightResponse">
</wsdl:output>
<wsdl:input message="tns:BookFlightRequest" name="BookFlightRequest"/>
<wsdl:output message="tns:BookFlightResponse" name="BookFlightResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="AirlineBinding" type="tns:Airline">
@@ -176,6 +176,9 @@
<wsdl:output name="GetFlightsResponse">
<soap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="GetFlightsFault">
<soap:fault name="GetFlightsFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>
<wsdl:operation name="GetFrequentFlyerMileage">
<soap:operation soapAction=""/>

View File

@@ -23,6 +23,14 @@
</complexType>
</element>
<element name="GetFlightsFault">
<complexType>
<sequence>
<element name="errorCode" type="string"/>
</sequence>
</complexType>
</element>
<element name="BookFlightRequest">
<complexType>
<all>

View File

@@ -6,6 +6,7 @@
</properties>
<body>
<release version="1.0-RC1">
<action dev="poutsma" type="add" issue="SWS-79">Add faults into dynamically created WSDL</action>
<action dev="poutsma" type="add" issue="SWS-20">Added MethodEndpoint functionality, invoking methods for
incoming requests
</action>