2

Is there a commonly agreed upon best practice approach for how to generate XML in Apex that will adhere to the WSDL/XSD of an outbound service? I've so far only encountered code that does a manual piece-by-piece assembly of the XML using an XMLStreamWriter. This seems unnecessarily error-prone and high effort.

2
  • 1
    Your not really generating the XML, but if the WSDL is compatible then using Wsdl2Apex and the corresponding WebServiceCallout.invoke is what Apex directly supports. – Daniel Ballinger Nov 17 '16 at 18:34
  • 2
    Consider voting for direct XML Serialization support in Apex. Convert Object to XML (Serialize) – Daniel Ballinger Nov 17 '16 at 18:39
2

If you don't actually need to see the raw XML output along the way, then WSDL2Apex generated code is by far the best way to go. If you actually want to be able to look at the raw XML somewhere along the way, Daniel Ballinger upthread has mentioned (in other threads) his company FuseIT's own variant of WSDL2Apex. It autogenerates code that uses Dom.XmlNode objects to assemble the XML request. The resulting code is much longer than SFDC's WSDL2Apex but at least you don't write it yourself.

You can then create a utility class with a method that accepts a List<Account> and returns an instance (or list of instances) of a class defined by the auto-generated WSDL2Apex code. The utility class contains all your business logic that maps SObject fields to request element fields. So now when you have your list of Accounts and want to make the callout you invoke the utility class to produce the input element for a callout, then invoke your generated callout class using that element as the input. Any changes in mapping can be done by editing the utility class.

This is the approach I am (so far) successfully using in a client org. I have a bunch of utility methods that do all the translating of an SObject to the request element and then the response back to another SObject. This includes little utility methods that help translate Apex data types to what the web service expects (e.g. a date conversion method that outputs what SAP expects). This particular web service only takes one record at a time so I have a Batchable class in which the execute() method loops through to do the callouts, and then I call it with a maximum scope 10 at once to be on the safe side.

2

Not sure about commonly agreed upon approach but here's how I'd proceed. With this vf page:

<apex:page StandardController="Account" recordSetVar="Accounts" contentType="text/xml" showHeader="false" sidebar="false" cache="false">
<?xml version="1.0" encoding="UTF-8" ?>
<response>
<apex:repeat value="{!Accounts}" var="eachAccount" >
    <Account id="{!eachAccount.id}" name="{!eachAccount.name}">&
    <apex:repeat value="{!eachAccount.contacts}" var="eachContact">
        <Contact id="{!eachContact.id}" name="{!eachContact.name}" email="{!eachContact.email}"/>
    </apex:repeat>
    </Account>
</apex:repeat>
</response>
</apex:page>

Then:

Public static void PageToXml(){
  PageReference apage = Page.AccountToContactsXML;
  apage.setRedirect = true;
  System.debug(apage.getContent().toString());
}

Cons: Not scalable as you'd hit an exception if you have more than 1000 records.

Ref: http://it.toolbox.com/blogs/anything-worth-doing/a-better-way-to-generate-xml-on-salesforce-using-visualforce-55433

1
  • Shouldn't you set some more properties on your <apex:page> tag? At least I would think you want applyHtmlTag="false". – Adrian Larson Nov 17 '16 at 18:35
2

I went down the path of using Dom.Document and Dom.XmlNode to generate and parse the XML in Apex.

Why? I'm glad you asked :)

It gave me a consistent object based approach for both generating and parsing XML that matched the WSDL. The same approach also mirrored the internal workings of WebServiceCallout.invoke. So in many cases I could use the same Apex classes with either approach.

General approach:

  1. A service class exposes the web service methods. When called, it generates a Dom.Document and creates the outer SOAP enevelope Dom.XmlNode with the Header and Body elements.
  2. It then creates further XML nodes for the method element.
  3. The method element XmlNode is populated by another class the represents each WSDL element.
  4. The element classes recursively call other element classes to populate the XML.

Each Apex class can stay focused on generating and parsing the corresponding WSDL element. I could also test those elements in isolation.

The downside is that the Apex code can get really verbose. As Charles T mentioned, we made an alternative version of Wsdl2Apex that can generate a baseline for you to work from.

If you just want to see the XML Request and Response being sent to the SOAP web service then you can use the Debug log to capture the CALLOUT_REQUEST and CALLOUT_RESPONSE elements.

See also:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.