Expose a SOAP endpoint based from an external WSDL

Hello All, 

Appreciate any advice on how to go about this. 

Trying to expose a SOAP endpoint that must comply with an external WSDL (from Salesforce).  I can't seem to make the structure definitions to match. Added wsdl and sample soap envelope resource in the attached oml.


Thank you.

Hello Cezar,

Are you trying to replace an existing application that other applications are already consuming?

The Web Service Expose feature in OutSystems was made to make your life easier, but it has its limitations.
Unfortunately, you can't expose web services through extensions, as this would be, probably, the solution.

You can always create a "translator" API in C# for example, that exposes the exact structure you need and reach the OutSystems API the way it is being generated (like a middle layer), but of course this is far from ideal. 

I'll ask around to see if anyone with more knowledge and experience in SOAP can see if there is a way of setting your exposed SOAP inside OutSystems with the same structure you need, but I am not too optimistic about that...

Cheers.

Hi Cezar,

As Eduardo said this is not really a scenario that is particularly supported in OutSystems.

At first glance, you might try to do it by Consuming the WSDL, then Expose a SOAP with the same method names and parameter names/types (just copy+paste the parameters from the consumed methods to the exposed methods)... then go to the eSpace properties and set the eSpace's NameSpace to match the one on the WSDL you are trying to emulate (see this post).

I personally have never done this, but it's certainly worth a try. 

Cheers,

Miguel

@Eduardo, Thank you, No I'm not trying to replace an existing app.  It's just how salesforce is configured to integrate with third-party apps in broadcasting events (create/modified record). Our Outsystems apps need to be able to receive the SOAP message and extract the record metadata.


@Miguel, Thank you, that is exactly what I've done so far :) It's just that I can't figure out how to make the complexTypes on the generated wsdl to match the original or at least accept the sample payload. Outsystems allow a single value for the "Web Services Namespace" in the Advanced property that shows on targetNamespace attribute. No idea how I could add the ones highlighted.

This is the error I get.



The worst-case scenario is that I will need to expose a REST endpoint to receive the SOAP envelop (XML) and parse it. 




Yeah, that's what I was afraid of... (multiple) namespaces.

SOAP is a real pain the the derriere because of namespaces... my next suggestion would indeed be what you said: try to have a REST method that just captures the whole body and then parses the message envelope inside it. Assuming that you can configure salesforce to indeed call the "fake" REST service URL you are going to define.

In the looong past (i.e. 15 years ago?) I did something like that. We didn't have REST then, but I created a "fake" web screen that sniffed and parsed the GET's body in the preparation and rendered a response as a download node (or was it on the screen?)... and it did eventually work. But the details are lost in the midst of time...

UPDATE:

The initial test result is promising. Sharing it here in case someone's looking for an alternative solution.

Here's what I've done. 

  1. Created a REST endpoint POST
    • used binary input parameter to receive the soap envelope from the body of the request  
    • used BinaryDataToText() to convert the soap envelope to text
    • passed the soap envelope text to extension (see step 2)
    • <do the necessary process with the returned JSON string> 
    • ..
    • Return soap response. 
  2.  Created an extension (Integration Studio)
    • Created an Action that accepts soap envelope (text) and returns a JSON string
    • In Integration Studio, imported wsdl as a "WEB Reference", NOT as a "SERVICE Reference"
    • edited the generated proxy class to decorate the root element in the soap body with:

    • [System.Xml.Serialization.XmlRoot(ElementName = "<element name>", Namespace = "http://namespace.com")]
    • Deserialized the content of the soap body as the generated proxy class

    • memStream = new MemoryStream(Encoding.UTF8.GetBytes(ssXmlPayload ?? ""));
      Message m = Message.CreateMessage(XmlReader.Create(memStream), int.MaxValue, MessageVersion.Soap11);
      XmlSerializer serializer = new XmlSerializer(typeof(notifications));
      body = m.GetReaderAtBodyContents();
      RootClass rc = (RootClass)serializer.Deserialize(body);
    • Serialized the object to JSON string

    •  JsonConvert.SerializeObject(rc)
    • Return the JSON string


This looks really good Cezar, thanks for sharing! 

Indeed :)

Thanks for sharing the solution you found, and to Miguel, to come and share his ideas to solve the problem :)