The requirement was pretty straightforward - I had a web service from a third party system (in this case OpenText) which I needed to consume. And since I had the URL of the WSDL, I could easily generate a consumer proxy class.
Piece of cake, or so I thought.
Soon came to know that there is an authentication token required to be passed through the web service. And I managed to generate another consumer proxy class using the authentication service that will return me the token.
Happy news that I got the token? Nope, now comes the challenge of passing it through the SOAP header for the first web service call. Haven’t done that before. I checked SDN forums and realized I wasn’t the first to do so. And some pretty good forums were present in which detailed code was present – in fact so detailed as to reconstruct the entire XML structure.
But I wasn’t sure of that. Do I really need to re-invent the wheel? OpenText has got a pretty good integration with SAP and there must be something that I could leverage. I wasn’t wrong. There are several standard authentication handler classes and its related helpers which could assist me. These methods help to modify the header protocol information with additional data. So this blog (if you haven’t already figured out) is for those looking to add some information to the SOAP header during a web service consumption based on an OpenText web service. Needless to say, the concept here is good enough to be used in any such scenario, and not just OpenText, provided you have the right parameter info.
Some of the data declarations and constants required:
CONSTANTS:
c_header_elem_name TYPE string VALUE 'OTAuthentication',
c_header_elem_prefix TYPE string VALUE 'ecs',
c_header_elem_uri TYPE string VALUE 'urn:api.ecm.opentext.com',
c_header_elem_attr_ecs TYPE string VALUE 'xmlns:ecs',
c_header_elem_attr_token TYPE string VALUE 'AuthenticationToken'.
DATA:
lref_protocol TYPE REF TO if_wsprotocol,
lref_proxy_basis TYPE REF TO if_proxy_basis,
lref_ws_header TYPE REF TO if_wsprotocol_ws_header,
lref_system_fault TYPE REF TO cx_ai_system_fault,
ixml TYPE REF TO if_ixml,
xml_document TYPE REF TO if_ixml_document,
xml_root TYPE REF TO if_ixml_element,
xml_element TYPE REF TO if_ixml_element,
xml_node TYPE REF TO if_ixml_node,
l_xstring TYPE xstring,
l_string TYPE string,
lh_dom TYPE REF TO if_ixml_document,
lh_ixml TYPE REF TO if_ixml,
lh_header_element TYPE REF TO if_ixml_element,
lh_element TYPE REF TO if_ixml_element,
- Call the service proxy to get the authentication token. (I’m not giving details here as it is irrelevant.) Let it be in a parameter call LV_TOKEN.
- Create an instance of the proxy class using the right logical port information.
CREATE OBJECT search_service
EXPORTING
logical_port_name = p_logical_port
EXCEPTIONS
others = 1.
3. Get the header protocol from the service:
lref_proxy_basis ?= search_service.
CHECK lref_proxy_basis IS BOUND.
lref_protocol = lref_proxy_basis->get_protocol( if_wsprotocol=>ws_header ).
lref_ws_header ?= lref_protocol.
4. Build the DOM for the soap header. This has been adapted from the standard.
CLASS cl_ixml DEFINITION LOAD.
lh_ixml = cl_ixml=>create( ).
lh_dom = lh_ixml->create_document( ).
lh_header_element = lh_dom->create_element_ns(
name = c_header_elem_name
prefix = c_header_elem_prefix
uri = c_header_elem_uri ).
lh_header_element->set_attribute_ns(
name = c_header_elem_attr_ecs
value = c_header_elem_uri ).
5. Add the element corresponding to the authentication token (we first create the element and then set the value we already have).
lh_element = lh_dom->create_element_ns(
name = c_header_elem_attr_token
prefix = c_header_elem_prefix
uri = c_header_elem_uri ).
lh_element->set_value( lv_token ).
lh_header_element->append_child( lh_element ).
lref_ws_header->set_request_header(
name = c_header_elem_name
namespace = c_header_elem_prefix
dom = lh_header_element ).
We are ready to consume the web service (in this case, the search service). The SOAP header now has got the authentication token added to it.
I hope this blog throws ideas to everyone to explore more of the standard. This will help a good deal to re-use the standard classes available and avoid re-building the whole xml document for the sake of a few new parameters that need to be added,