Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
stephen_xue
Active Participant

Introduction


In my previous blog poster, the way to post simple message structure message via OData adapter in batch mode has been elaborated.

However in that case, the message type is from a flat structure. In real world, the structure of the message to be post might be multi-layer. Whereas NWDS has a defect for generating xsd from a multi-layer structure OData service. In this blog poster, a way to deal with multi-layer complex structure OData service by using POST $batch mode has been introduced.

 

NWDS Issue


I am not sure SAP is aware of this issue. However it does exist. It looks like, when the message structure becomes complex, the OData adapter in NWDS has difficulty to generate XSD. This is the symptom:

Think about a complex message structure like below



We have implemented an OData service with the above message structure.



When we try to generate information by using OData adapter's Model Operation as below



there will be popup window indicating edmx file created only. whereas the xsd file has not been created.



 

The XSD file has not been generated. The one listed here was created in the last Blog Post.



 

Solution Implementation


It seems that the fact that the NWDS cannot generate XSD file prevents us from posting a complex structure message to backend by using OData adapter. Whereas there is a walk around via a generic xsd.

Here are the steps.

1. XSD file


Create a request xsd file by using the source code below
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="batchParts">
<xs:complexType>
<xs:sequence>
<xs:element name="batchChangeSet" nillable="false" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="batchChangeSetPart" nillable="false" minOccurs="1" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:any />
<xs:element name="method" type="xs:string" nillable="false" minOccurs="1" maxOccurs="1"/>
<xs:element name="uri" type="xs:string" nillable="true" minOccurs="0" maxOccurs="1"/>
<xs:element name="headers" nillable="true" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="header" nillable="true" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="headerName" type="xs:string" nillable="false" minOccurs="1" maxOccurs="unbounded"/>
<xs:element name="headerValue" type="xs:string" nillable="false" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>

for synchronous call, please create a generic response xsd file as below
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" targetNamespace="">
<wsdl:types>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xsd:element name="batchPartResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="batchChangeSetResponse" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="batchChangeSetPartResponse" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="statusCode" type="xsd:string" />
<xsd:element name="statusInfo" type="xsd:string" minOccurs="0" nillable="true" />
<xsd:element name="contentId" type="xsd:string" minOccurs="0" nillable="true" />
<xsd:element name="headers" minOccurs="0" maxOccurs="unbounded" nillable="true">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Accept-Language" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
<xsd:element name="DataServiceVersion" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
<xsd:element name="Accept" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
<xsd:element name="location" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
<xsd:element name="Content-Length" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
<xsd:element name="cache-control" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
<xsd:element name="dataserviceversion" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
<xsd:element name="pragma" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
<xsd:element name="Content-Type" type="xsd:string" minOccurs="0" maxOccurs="unbounded" nillable="true" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="body" nillable="true">
<xsd:complexType>
<xsd:sequence>
<xsd:any />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>
<wsdl:message name="batchPartResponse">
<wsdl:part name="batchPartResponse" element="batchPartResponse" />
</wsdl:message>
</wsdl:definitions>

 

2. Imported Archive


Create Request/Response imported archive by using the xsd files above;

3. Service Interface


Create inbound interface by using the imported archive created. For my showcase, i just create an outbound interface and an inbound interface with the same message structure.

The Operation Mapping uses direct mapping on both request and response direction.



 

4. OData Receiver Configuration


In the Parameters tab page, input the URL of OData service into the address field



 

In the Processing tab page, fill in the Entity Set name into the Operation field and check the flag for batch processing



 

In the Advanced tab page, add parameter ContentTypeEncoding to none.



There are only 6 supported content type in $Batch mode which are fix coded in the system. If you are interested in view them, please setup a break point in method /IWCOR/IF_DS_PROCESSOR~PROCESS of class /IWCOR/CL_DS_PROC_DISPATCHER
mv_header_accept = io_request->get_header_field( if_http_header_fields=>accept ).

The default content type generated by OData adapter is not supported by SAP Gateway service framework. by using this parameter, the message will be acceptable.

 

One more information. The OData adapter only supports XML message. It doesn't support JSON.

Unit Test


In POSTMAN, input the multi-layer request message as below



in my case, i used a REST sender to receive request message from POSTMAN and a direct mapping forwarding the request into OData Receiver adapter to backend.

This is the response message parsed by OData adapter is like this



If we want to check the raw request data that has been converted by OData adapter from the xml source and the raw response data that OData adapter converted for us into the xml response, please trace it via transaction code /IWFND/TRACES



 

from the trace log view, we can see that OData adapter made 4 times call for one consume and it handled the csrf token by itself.



double click on the first line which is the real request/response process.

This is the raw request message after being converted by OData Adapter from XML



 

This is the raw response message from Gateway Service before it has been converted by OData adapter into XML



 

Conclusion


By using the above generic request/response xsd, all kind of complex message structure can be handled by OData adapter. However the mapping program can only java or xslt. It doesn't support graphic mapping.
Labels in this area