java.lang.NullPointerException in org.apache.cxf.attachment.LazyDataSource.getInputStream - nullpointerexception

I am using cxf 2.7.7 and using MTOM with https ... and it is working ok with cxf java client.
However when I send a message though SOAP UI client, and at the server side (in my endpoint implementation class) I try to access any of the methods of the Datahandler object (please see abridged code below) then I get java.lang.NullPointerException in org.apache.cxf.attachment.LazyDataSource. Please note that call to any .getXXX method gives exception (these calls translate to corresponding call to LazyDataSource.getXXX methods ... and looks like LazyDataSource is null)
This does NOT happen when I send requests through java client. Happens only when I use SOAPUI for request
#WebService(targetNamespace = "http://webservice.dcca.dell.com",
portName = "ObjectMTOMService", serviceName = "ObjectMTOMServiceService")
public class ObjectMTOMServiceImpl implements ObjectMTOMService {
#Resource
WebServiceContext wsContext;
public ObjectStoreResp uploadObject(ObjectStoreReq objectReqParam) {
DataHandler objHandler = objectReqParam.getObjData();
try {
if (objHandler != null)
{
String objName=objHandler.getName();
String contentType=objHandler.getContentType();
InputStream iStream= objHandler.getDataSource().getInputStream();
}
catch (Exception e) {
e.printStackTrace();
respParam.setRespCode(-1);
return (respParam);
}
}
The exception I see is as follows
java.lang.NullPointerException
at org.apache.cxf.attachment.LazyDataSource.getName(LazyDataSource.java:73)
at javax.activation.DataHandler.getName(DataHandler.java:191)
at com.dell.dcca.webservice.objectmtomservice.ObjectMTOMServiceImpl.uploadObject(ObjectMTOMServiceImpl.java:98)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
........ <<< removed lot of stack trace for brevity >>>
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1555)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
java.lang.NullPointerException
The message that SOAPUI sends is as follows << I have approximated this -- copying and pasting from SOAPUI log >>
POST https://160.110.73.35:8443/ObjectMTOMService/services/ObjectMTOMService HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: multipart/related; type="application/xop+xml"; start="<rootpart#soapui.org>"; start-info="text/xml"; boundary="----=_Part_13_756617.1389959552144"
SOAPAction: "http://InteropBaseAddress/interop/header"
MIME-Version: 1.0
Content-Length: 5432
Host: 160.110.73.35:8443
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
------=_Part_13_756617.1389959552144"
"Content-Type: application/octet-stream; name=InfantHealthcare.jpg"
Content-Transfer-Encoding: binary
Content-ID: <images.jpg>
Content-Disposition: attachment; name="images.jpg"; filename="InfantHealthcare.jpg
<< file contents ... >>
Any inputs welcome.
If anyone has tried MTOM with SOAPui client and Axis 2.7.X onwards combination, let me know
Thanks a ton for your help
Yogesh

This problem was because I was using incorrect setting in SOAPUI that was sending the Data as Null. I consider this as a CXF bug that it gives a Null Pointer exception. There should be a safer way of reporting that I have a null attachment. Anyways, the question is how did I fix it.
The below link, does give information but IMHO it is a bit ambiguous ( or may be I did not interpret it right :-( - had to read it many times over
http://www.soapui.org/SOAP-and-WSDL/adding-headers-and-attachments.html
My incorrect way of specifying the request SOAP message in SOAP UI was
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:typ="http://webservice.dcca.dell.com/types">
<soapenv:Header/>
<soapenv:Body>
<typ:objectStoreReq>
<typ:ObjData>cid:183942097334</typ:ObjData>
<typ:objMetadata>
<typ:objName>img</typ:objName>
<typ:organizationName>Dell</typ:organizationName>
</typ:objMetadata>
</typ:objectStoreReq>
</soapenv:Body>
</soapenv:Envelope>
The correct way is ( note that instead of filling a part id in "Objdata" element- using "cid: id" which sends it as base64 encoded we have to specify XOP Include element referring to the second Mime-Part using href.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:typ="http://webservice.dcca.dell.com/types">
<soapenv:Header/>
<soapenv:Body>
<typ:objectStoreReq>
<typ:ObjData>
<inc:Include
href="cid:myImage.jpg"
xmlns:inc="http://www.w3.org/2004/08/xop/include"
/>
</typ:ObjData>
<typ:objMetadata>
<typ:objName>img</typ:objName>
<typ:organizationName>Dell</typ:organizationName>
</typ:objMetadata>
</typ:objectStoreReq>
</soapenv:Body>
</soapenv:Envelope>
With this my SOAP-UI messages were very much palatable to my service :-)

Related

Httpwebrequest soap Request

Hi What is the best practice for sending Http Request using C#, passing a number of parameters to a SOAP end point. I also require to Add few headers in the request.
I have a SOAP API defined as
<soapenv:Envelope xmlns:soapenv="schemas.xmlsoap.org/soap/envelope/" ; xmlns:mac="iib.macinfra.in/mac">;
<soapenv:Header>
<mac:RequestHeader>
<mac:Id>GFyZxV0</mac:ApplicationId>
<mac:MessageId>pfoshdttc</mac:MessageId>
</mac:RequestHeader>
</soapenv:Header>
<soapenv:Body>
<mac:FindMailRequest>
<mac:QueryString>CM7JT</mac:QueryString>
</mac:FindMailRequest>
</soapenv:Body>
</soapenv:Envelope>
I would like to build a HttpRequest and pass the parameters using HttpWebRequest webreq = WebRequest.Create(webserviceUrl) as HttpWebRequest;

HTTP post request is getting intermittently called via C# client in mule 3.6

I am hosting webservice using mule 3.6.
I observed POST HTTP request is working fine with java client. But C# client this webservice is getting called intermittently i.e first call is ok, second time out , third call is ok , fourth time out and so on.
GET HTTP request is working fine with C# client
Below is the sample of mule-flow.xml
<http:listener-config name="Port1_WS_Listener" host="0.0.0.0" port="7001" doc:name="WS Listener">
<http:worker-threading-profile maxThreadsActive="20" maxThreadsIdle="10" threadTTL="10000" threadWaitTimeout="5000"/>
</http:listener-config>
<http:listener-config name="Port2_WS_Listener" host="0.0.0.0" port="7002" doc:name="WS Listener">
<http:worker-threading-profile maxThreadsActive="20" maxThreadsIdle="10" threadTTL="10000" threadWaitTimeout="5000"/>
</http:listener-config>
<flow name="WSFlow">
<composite-source>
<http:listener config-ref="Port1_WS_Listener" path="getAttributes1"
doc:name="Port1 " allowedMethods="POST"/>
<http:listener config-ref="Port2_WS_Listener" path="getAttributes2"
doc:name="Port2" allowedMethods="POST"/>
</composite-source>
<component doc:name="java : WSHandler">
<interceptor-stack ref="default" />
<spring-object bean="httpWSHandler" />
</component>
<catch-exception-strategy doc:name="Catch Exception Strategy">
<logger level="ERROR" message="#[exception]" doc:name="Logger" />
</catch-exception-strategy>
</flow>
C# client sample code
poststring value would be like param=[{'empId':'123', 'empName':'xyz'}]
WebRequest webRequest = (HttpWebRequest)WebRequest.Create(requestUrl);
webRequest.Method = "POST";
webRequest.Timeout = Timeout;
byte[] postBytes = Encoding.UTF8.GetBytes(postString);
webRequest.ContentType = "application/x-www-form-urlencoded";
StreamWriter writer = new StreamWriter(webRequest.GetRequestStream());
writer.WriteLine(postString);
writer.Close();
WebResponse wsResponse = webRequest.GetResponse();
Console.WriteLine("Response Successful");
Stream dataStream = wsResponse.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string response = reader.ReadToEnd();
dataStream.Close();
Console.WriteLine("Response Closed");
Curl output
Note: in below out parameter value has been replaced with dummy parameter hence content length value may differ
About to connect() to localhost port 7002
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 7002
> POST /getAttributes2 HTTP/1.1
> User-Agent: curl/7.15.5 (x86_64-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8
> Host: localhost:7002
> Accept: */*
> Content-Length: 417
> Content-Type: application/x-www-form-urlencoded
>
> param=[{'empId':'123', 'empName':'xyz'}]HTTP/1.1 200
< MULE_ENCODING: US-ASCII
< Content-Length: 719
< Date: Fri, 31 Jul 2015 09:19:20 GMT
Connection #0 to host localhost left intact
* Closing connection #0
[{"company":"xyz","department":"xyz"}]
I have figured out solution , seems we need to use http-proxy like below
HTTP Proxy
<pattern:http-proxy name="http-proxy-sample">
<http:inbound-endpoint address="http://0.0.0.0:10011/getEmployeeAttributesProxy" />
<http:outbound-endpoint address="http://0.0.0.0:10001/getEmployeeAttributes" />
</pattern:http-proxy>
I experienced the same problem with C# HTTP POST requests going through the APIKit to the new HTTP Listener to the same flow in rapid succession. I worked around it by switching back to the deprecated HTTP Inbound Endpoint, where it is not a problem.
<http:inbound-endpoint doc:name="HTTP" exchange-pattern="request-response" path="api/v1/" host="${http.cs-testing-tools.host}" port="${http.cs-testing-tools.port}" />
When monitoring the flows using Mule Management Console, the calls which timeout are never registered by Mule, so it appears that the HTTP listener never gets a payload to process.
Nov 18 2015 UPDATE - After some discussion with Mule support, this is caused by the interaction between C# and the library used by the new HTTP Listener. The behavior manifests as every other POST timing out.
You can work around this on the C# side as follows:
var httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ServicePoint.Expect100Continue = false;
You can add Settings to app.config or web.config in your C# project
<system.net>
<settings>
<servicePointManager expect100Continue="false"/>
</settings>
</system.net>

Consuming SOAP web service in SENCHA TOUCH?

I have found this post that worked for me but I recieved a HTML response instead of a XML one which is what I need for my app.
How to consume SOAP web service in SENCHA TOUCH?
This is my request to my server... I know I should be doing a POST action as this guy was told, but I still get a root node error.
Is this the proper way to consume a WebService, or there is another way to consume in Sencha using data models and stores? I have already saw an example using CFC but I am using IIS 7.5
POST /url/mobilews.asmx HTTP/1.1
Host: 10.0.1.182
Content-Type: text/xml; charset=utf-8
Content-Length: length
SOAPAction: "http://tempuri.org/HelloWorld"
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<HelloWorld xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope>
Ext.Ajax.request({
method: 'GET',
url: 'http://url/mobileservice/mobilews.asmx?op=HelloWorld',
params: { method: 'HelloWorld', format: 'json' },
success: function (response, request) {
alert('Working!');
alert(response.responseText);
},
failure: function (response, request) {
alert('Not working!');
}
});
Here goes the error message:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><soap:Code><soap:Value>soap:Receiver</soap:Value></soap:Code><soap:Reason><soap:Text xml:lang="en">System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.

WCF request with default empty tags

I'm trying to connect to a SOAP 1.1 webservice, using TLS.
The certificate has been set up right, and I am able to communicate with the webservice.
However, when I try to do this using a plain C# project, using proxyclasses generated by VS2010, the request seems to be incomplete, as in, the empty tags are not in the request. I then get a "This is an operation implementation generated fault" fault, viewable in Fiddler
If I then try to launch a request using SoapUI, I get a succesful response from the webservice.
I used Fiddler to compare both requests, and I noticed that the C# request was pretty plain, only sending elements that were filled in in my C# class.
But when I check the SoapUI request, this request included EVERY element defined in the WSDL/XSD's, even though they're empty.
I'm trying to understand how I can configure the C# client to include empty elements, to see if the webservice will accept my request, however I was unable to find such setting.
The C# request response:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode xmlns="">
SOAP-ENV:Server
</faultcode>
<faultstring xmlns="">
This is an operation implementation generated fault
</faultstring>
<faultactor xmlns=""/>
<detail xmlns="">
<ns:SOAPFault xmlns:ns0="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="urn:xxx:xxx:data:soapfault:1:standard" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<ns:ErrorCode>2.0</ns:ErrorCode>
<ns:ErrorText>XML schema validation error</ns:ErrorText>
<ns:ErrorDetails>
/{urn:xxx:xxx:service:contractcancellation:1:standard}ContractCancellationRequestEnvelope[1]/part1[1]/ContractCancellationRequestEnvelope[1]/BusinessDocumentHeader[1]/Destination[1]
</ns:ErrorDetails>
</ns:SOAPFault>
</detail>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
The C# request:
POST xx HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "urn:ContractCancellationRequestEnvelope"
Host: xx
Content-Length: 887
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ContractCancellationRequestEnvelope xmlns="urn:xxx:xxx:data:contractcancellationrequest:1:standard">
<Portaal_Content>
<Portaal_MeteringPoint>
<EANID>xxx</EANID>
<MPCommercialCharacteristics>
<ContractCancellationDate>
2013-11-15
</ContractCancellationDate>
</MPCommercialCharacteristics>
<Portaal_Mutation>
<Initiator>xxx</Initiator>
<Dossier>
<ID>TST0000001</ID>
</Dossier>
</Portaal_Mutation>
</Portaal_MeteringPoint>
</Portaal_Content>
</ContractCancellationRequestEnvelope>
</s:Body>
</s:Envelope>
The SoapUI request:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:xxx:xxx:data:contractcancellationrequest:1:standard">
<soapenv:Header/>
<soapenv:Body>
<urn:ContractCancellationRequestEnvelope>
<urn:BusinessDocumentHeader>
<!--Optional:-->
<urn:ContentHash>?</urn:ContentHash>
<!--Optional:-->
<urn:ConversationID>?</urn:ConversationID>
<!--Optional:-->
<urn:CorrelationID>?</urn:CorrelationID>
<urn:CreationTimestamp>?</urn:CreationTimestamp>
<!--Optional:-->
<urn:DocumentID>?</urn:DocumentID>
<!--Optional:-->
<urn:ExpiresAt>?</urn:ExpiresAt>
<urn:MessageID>?</urn:MessageID>
<!--Optional:-->
<urn:ProcessTypeID>?</urn:ProcessTypeID>
<!--Optional:-->
<urn:RepeatedRequest>?</urn:RepeatedRequest>
<!--Optional:-->
<urn:TestRequest>?</urn:TestRequest>
<urn:Destination>
<urn:Receiver>
<!--Optional:-->
<urn:Authority>?</urn:Authority>
<!--Optional:-->
<urn:ContactTypeIdentifier>?</urn:ContactTypeIdentifier>
<urn:ReceiverID>?</urn:ReceiverID>
</urn:Receiver>
<!--Optional:-->
<urn:Service>
<!--Optional:-->
<urn:ServiceMethod>?</urn:ServiceMethod>
<!--Optional:-->
<urn:ServiceName>?</urn:ServiceName>
</urn:Service>
</urn:Destination>
<!--Optional:-->
<urn:Manifest>
<urn:NumberofItems>?</urn:NumberofItems>
<!--1 or more repetitions:-->
<urn:ManifestItem>
<!--Optional:-->
<urn:Description>?</urn:Description>
<!--Optional:-->
<urn:LanguageCode>?</urn:LanguageCode>
<urn:MimeTypeQualifierCode>?</urn:MimeTypeQualifierCode>
<urn:UniformResourceIdentifier>?</urn:UniformResourceIdentifier>
</urn:ManifestItem>
</urn:Manifest>
<urn:Source>
<!--Optional:-->
<urn:Authority>?</urn:Authority>
<!--Optional:-->
<urn:ContactTypeIdentifier>?</urn:ContactTypeIdentifier>
<urn:SenderID>?</urn:SenderID>
</urn:Source>
</urn:BusinessDocumentHeader>
<urn:Portaal_Content>
<urn:Portaal_MeteringPoint>
<urn:EANID>?</urn:EANID>
<urn:MPCommercialCharacteristics>
<urn:ContractCancellationDate>?</urn:ContractCancellationDate>
</urn:MPCommercialCharacteristics>
<urn:Portaal_Mutation>
<!--Optional:-->
<urn:ExternalReference>?</urn:ExternalReference>
<urn:Initiator>?</urn:Initiator>
<!--Optional:-->
<urn:Dossier>
<urn:ID>?</urn:ID>
</urn:Dossier>
</urn:Portaal_Mutation>
</urn:Portaal_MeteringPoint>
</urn:Portaal_Content>
</urn:ContractCancellationRequestEnvelope>
</soapenv:Body>
</soapenv:Envelope>
As you can see, the SoapUI request is far more complete, even though the elements are empty.
C# code (important parts):
_binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
_binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
_endpoint = new EndpointAddress(endpointAddress + "xxx");
_proxy = new ContractCancellationPortTypeClient(_binding, _endpoint);
_proxy.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"xxx");
_proxy.ContractCancellation(new ContractCancellationRequestEnvelope()
{ Portaal_Content = new ContractCancellationRequestEnvelope_PC()
{ Portaal_MeteringPoint = new ContractCancellationRequestEnvelope_PC_PMP()
{ EANID = request.EanId,
MPCommercialCharacteristics = new ContractCancellationRequestEnvelope_PC_PMP_MPCC()
{ ContractCancellationDate = request.ContractCancellationDate },
Portaal_Mutation = new ContractCancellationRequestEnvelope_PC_PMP_PM()
{ Initiator = request.SupplierEanId,
Dossier = new ContractCancellationRequestEnvelope_PC_PMP_PM_Dossier()
{ ID = "TST0000001" }
}
}
});
In your code, you're generating the Portaal_Content portion of the ContractCancellationRequestEnvelope, but not the BusinessDocumentHeader portion.
If you look at the fault received (via C#) I'm betting that there's one or more required elements in the BusinessDocumentHeader section that are missing:
The error text is XML schema validation error, and the error detail is:
ContractCancellationRequestEnvelope[1]/part1[1]/ContractCancellationRequestEnvelope[1]/BusinessDocumentHeader[1]/Destination[1]
You need to ensure that all required elements are present in your SOAP message.
EDIT
Something like this should do the trick:
ContractCancellationRequestEnvelope reqMsg = new ContractCancellationRequestEnvelope();
reqMsg.BusinessDocumentHeader = new BusinessDocumentHeader()
{ CorrelationTimestamp = "?",
MessageID = "?" };
reqMsg.BusinessDocumentHeader.Destination = new Destination();
reqMsg.BusinessDocumentHeader.Receiver = new Receiver()
{ ReceiverID = "?" };
And so on. Basically, make sure that you create every element that is required.
By the way, you can do nested automatic initialization (as in the code you posted), I simply took a more explicit route in my example for readability.
The service's WSDL will tell you what is required or optional.
If you need more help either provide the URL for the service or post the WSDL.

BizTalk Orchestration: Respond with Untyped SOAP Fault

I have a BizTalk 2009 orchestration with a request-response port type that is published as a WCF Basic-HTTP web service. The port has one operation, and that operation has request and response messages with appropriate schemas. After receiving a request on this port, there are a few cases where a fault message should be returned to the client instead of the standard response message. I'm having difficulty getting the correct fault message back to the client. I'd like to be able to set both the faultcode and faultstring elements of the SOAP fault message. Here's what I've tried:
Adding a Fault Message of Type String:
I tried adding a fault message with a message type of string to the operation. Within the orchestration, I constructed a string message and sent it as the response. The fault that was delivered back to the client looked like:
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">a:InternalServiceFault</faultcode>
<faultstring xml:lang="en-US"><?xml version="1.0" encoding="utf-8"?>
<string>This is the error message.</string></faultstring>
<detail>
<ExceptionDetail xmlns="http://schemas.datacontract.org/2004/07/System.ServiceModel" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<HelpLink i:nil="true"/>
<InnerException i:nil="true"/>
<Message><?xml version="1.0" encoding="utf-8"?>
<string>This is the error message.</string></Message>
<StackTrace>at Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkAsyncResult.End() ...</StackTrace>
<Type>Microsoft.BizTalk.Adapter.Wcf.Runtime.BizTalkNackException</Type>
</ExceptionDetail>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
This almost works, except the faultstring element contains the xml serialized version of my string instead of the string itself. I also cannot set the faultcode element.
Adding a Fault Message of Type http://schemas.xmlsoap.org/soap/envelope/#Fault
I thought I might be able to convince BizTalk to return a fault message along the lines of what I'd expect if I constructed the Fault element and sent that. So I added a fault message with a type of http://schemas.xmlsoap.org/soap/envelope/#Fault, constructed the appropriate message and sent that as the response. The result was the same as above, except instead of a string, the faultstring element contained a CDATA section with the entire xml message I had constructed inside.
So I'm stuck now; I feel like this should be a simple task in BizTalk. The documentation on MSDN, How to Throw Fault Exceptions from Orchestrations Published as WCF Services, tells you nothing about "how" to throw fault exceptions, except that they can be thrown and that you need to set includeExceptionDetailInFaults in the configuration (which I've already done).
Does anyone have any suggestions on how this could be accomplished in BizTalk 2009?
I solved this exact problem by adding a custom WCF IDispatchMessageInspector where i read the reason text from the serialized message and then return a new System.ServiceModel.FaultException message using the deserialized reason text.
In the BizTalk orchestration i use System.String as the PortType fault message-type.
public class HandleUntypedSoapFault : IDispatchMessageInspector
{
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
if (reply.IsFault)
{
MessageBuffer buffer = reply.CreateBufferedCopy(int.MaxValue);
MessageFault messageFault = MessageFault.CreateFault(buffer.CreateMessage(), int.MaxValue);
if (!messageFault.HasDetail)
{
reply = buffer.CreateMessage();
return;
}
using (XmlReader reader = XmlReader.Create(new StringReader(messageFault.Reason.ToString())))
{
reader.MoveToContent();
string _faultText = reader.ReadElementContentAsString();
}
reply = Message.CreateMessage(
reply.Version,
new FaultException(
_faultText,
new FaultCode("client")).CreateMessageFault(),
null);
}
}
}
Now the SoapFault will look more like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="en-US">An untyped SoapFault from my BizTalk orchestration. This text was set in the orchestration.</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
Reminded of this long thread I participated in a while back:
http://social.msdn.microsoft.com/forums/en-US/biztalkr2adapters/thread/f69ec7af-a490-4229-81d4-3d1b41bf9c48/
They refer to an SDK sample that might help you, but it's a typed (not un-typed as you requested) fault exception.