Tuesday, July 15, 2014

How to add SOAP header to a Salesforce call out

There are situations when we need to add a SOAP header to the call out being made. If your WSDL has a definition for a SOAP header then the Apex to WSDL tool will generate the header code for you.

But most of the times the WSDL does not have the header information and the receiving server needs specific SOAP header to validate the call. In such a case we can add a custom header to the call. Here are the steps to add a customer.  e.g. If we need to send the following in the header.

<ApplicationContext>
    <consumerSystem>UN</consumerSystem>
    <organisation>PW</organisation>
</ApplicationContext>

1. Add a data structure to the stub generated for your data to be sent. For the example the class to be added to the stub would look like .
public class PolicyManagement_V2_Schema{ // this is the parent class which has the stub definition
public class ApplicationContext {
        public String consumerSystem;
        public String organisation;
        private String[] consumerSystem_type_info = new String[]{'consumerSystem','<SOAP Namespace>',null,'0','1','false'};
        private String[] organisation_type_info = new String[]{'organisation','<SOAP Namespace>',null,'1','1','false'};
        private String[] apex_schema_type_info = new String[]{'<SOAP Namespace>','true','false'};
        private String[] field_order_type_info = new String[]{'consumerSystem','organisation'};
    }
}
2. Add the following code to the class which makes the call out. Declare the application context as a local class variable and use <variable>_hns = '<PrimaryNode>=<SOAP Namespace>'. Adding the _hns node tells salesforce to put the information of the class in the SOAP header.
public PolicyManagement_V2_Schema.ApplicationContext Header;
private String Header_hns = 'ApplicationContext=http://www.iag.co.nz/soa/apexiaa/v2';

3. Once you have done step 1 and 2, you are all set to send custom data in SOAP header call out. All you need to do now is to instantiate the header variable in the actual call out and set the values for the class variables which would be sent as part of SOAP header. 

Monday, June 16, 2014

Salesforce Hover Helptext on fields not in apex page block section

We come across various use cases where we can not have the apex input field as a child item directly under the apex page block section. Or we cannot use apex input field at all and hence need to use some other tag. If you want to show salesforce field helptext with an on-hover icon then here is a way which would allow you to addyour custom hover help text which looks and behaves exactly same to the standard hover help text.

Here is the code you need to add in your pageblocksectionitem. The label needs to be a child item of a span and we will pass the id of the span to the standard function which is available by standard salesforce.com javascript itlself.

  <apex:outputPanel >
       <span class="helpButton" id="ANZSICcodeforLiab-_help"> 
             <apex:outputLabel value="{!$ObjectType.Common_Details__c.fields.Primary_Rating_ANZSIC_Code__c.Label}" for="PrimaryRatingANZSIC"/>
             <img class="helpOrb" src="/s.gif" />
             <script>
                  sfdcPage.setHelp('ANZSICcodeforLiab', '{!JSENcode($ObjectType.Common_Details__c.fields.Primary_Rating_ANZSIC_Code__c.inlineHelpText)}');
             </script>
       </span>
</apex:outputPanel>

The Label tag is added under an output panel because pageblocksection item can only have 2 direct children.
The important points to note are

  • Id of span passed to the JavaScript function is the first part of the string. The second part i.e. "-_help" is not passed to the setHelp method. 
  • sfdcPage.setHelp is the method which adds the on hover functionality to the image. 
  • If you miss the style class "helpButton"  to the span then the on hover behavior will not work properly.  



Sunday, May 18, 2014

How to Collapse the Apex Page block Panel on page load

If you have a big page with a lot of fields and multiple sections on the form, then you might want to collapse some of the sections on the form on page load. Although salesforce does not provide any thing out of the box to have those sections as collapsed by default but we can write a quick javascript hack to do this. 

Salesforce has a function twistSection which gets fired on click of the image to collapse or expand the page block section. So all we need to do is to pass the image object to this function and it toggles the section. On page load the sections are always expanded hence just by calling this function on page load will ensure that the section is collapsed after the page load. 

Here is the code to collapse a section on page load. 

Suppose the panel code is as given below 

<apex:pageBlockSection collapsible="true" title="MD" id="MDsection">

Then first we need to get the panel element by id using the code 

var mdsec = document.getElementById('{!$Component.MDsection}');

You might have to use form name and page block name based on where you put the  java script code in the page.

After this on page load you need to write the following code

twistSection(mdsec.childNodes[0].childNodes[0]);

This will ensure that the page block section will be collapsed on the page load.

Tuesday, April 29, 2014

Understanding generated code from WSDL to Apex Tool

We all have generated Apex code from WSDL in Salesforce.com. But there are alot of limitations in the xml parser and code generator. Out of these the biggest is the XSD extensions. If your wsdl Schema has xsd extensions then the Apex generator simply ignores it. As a result the code generated is incapable of handling the  response payload or send the correct request.

This can be a big challenge if the request and response xmls are complex. The only way out of this is looking at the xmls and writing the apex code your self. This can be challenging if we really dont understand the generated code properly.

Here in my blog I am giving a shot at it and trying to explain various components of the generated code. So that we can write our own code if the need be.

For example if your response/request xml looks something like this

<RetrieveIndustriesResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="<schema>" xmlns="<ur schema>" xsi:schemaLocation="..../XSD/iagiaa_v2.xsd">
<industry>
<dynamicProperties>
<kind>&lt;B&gt;Classification Information&lt;/B&gt;</kind>
<conformanceType>text</conformanceType>
</dynamicProperties>
<dynamicProperties>
<kind>Primary Activities</kind>
<conformanceType>text</conformanceType>
<theValue>This class consists of units mainly </theValue>
</dynamicProperties>
<dynamicProperties>
<kind>Exclusions</kind>
<conformanceType>text</conformanceType>
<theValue>Units mainly engaged in</theValue>
</dynamicProperties>
<description>Other Takeaway Food Retailing (not part of Restaurant)</description>
<industryCode>4512C</industryCode>
</industry>
</RetrieveIndustriesResponse>

and if the DynamicProperties is an extension then in the generated apex code for the xsd this property will be ignored and you will have to write it on your own.

The final code will look something like this.


public class Industry {
        public list<IAGSOAPstub.dynamicProperty> dynamicProperties;
        public string description;
        public String industryCode;
        private String[] dynamicProperties_type_info = new String[]{'dynamicProperties','http://www.iag.co.nz/soa/iagiaa/v2',null,'0','-1','false'};
        private String[] description_type_info = new String[]{'description','http://www.iag.co.nz/soa/iagiaa/v2',null,'0','1','true'};
        private String[] industryCode_type_info = new String[]{'industryCode','http://www.iag.co.nz/soa/iagiaa/v2',null,'0','1','true'};
        private String[] apex_schema_type_info = new String[]{'http://www.iag.co.nz/soa/iagiaa/v2','true','false'};
        private String[] field_order_type_info = new String[]{'dynamicProperties','description','industryCode'};
    }
    public class dynamicProperty {
        public String kind;
        public String description;
        public String conformanceType;
        public String theValue;
        private String[] kind_type_info = new String[]{'kind',<Schema URL>',null,'0','1','false'};
        private String[] description_type_info = new String[]{'description','<Schema URL>',null,'0','1','false'};
        private String[] conformanceType_type_info = new String[]{'conformanceType','<Schema URL>',null,'0','1','false'};
        private String[] theValue_type_info = new String[]{'theValue','<Schema URL>',null,'0','1','false'};
        private String[] apex_schema_type_info = new String[]{'<Schema URL>','true','false'};
        private String[] field_order_type_info = new String[]{'kind','description','<Schema URL>','theValue'};
        
    }
   
    public class RetrieveIndustriesResponseType {
        public IAGSOAPstub.Industry[] industry;
        private String[] industry_type_info = new String[]{'industry','<Schema URL>',null,'1','-1','false'};
        private String[] apex_schema_type_info = new String[]{'<Schema URL>','true','false'};
        private String[] field_order_type_info = new String[]{'industry'};
    }




The public variables are nothing but the actual xml elements or nodes or attribute. For each node/attribute there will be one public variable. It can either be primitive datatype or object of some other class which represents another complex type in xsd. 
If the variable represents another XML element or a text node, then there needs to be a matching _type_info String[] e.g. bar_type_info. 
The elements of this array are: 1. XML element name 2. Schema 3. XML type 4. minOccurs 5. maxOccurs (set to '-1' for unbounded) 6. isNillable
If the variable represents an attribute, then there must be a matching _att_info String[] e.g. a_type_info. Thise simply contains the XML name of the attribute.
Note that if an class variable name is a reserved word, then _x is appended to it e.g. bar_x. This would affect the other variables names: bar_x_type_info. The Apex Developer's Guide explains their rules for names, but if you are manually creating it, I think you can give it whatever name you want--the arrays determine the XML element name...
The apex_schema_type_info array specifies information about the XML element represented by the class: 1. Schema 2. 'true' if elementFormDefault="qualified" 3. 'true' if attributeFormDefault="qualified"
field_order_type_info simply specifies the order of the child elements.