Showing posts with label SOA. Show all posts
Showing posts with label SOA. Show all posts

Sunday, March 22, 2015

Converting SAP IDoc XML date and time to structured XML Schema xsd:dateTime data type

In a recent project, we worked with the Oracle Application Adapter for SAP R/3 in order to retrieve data from and publish data to the customers SAP system. Did you ever have a look at an XML-based intermediate document (IDoc) from SAP? Well, good news is that you get structured data. Each IDoc type comes with a schema definition as XML Schema Definition (XSD) which can be retrieved from the SAP system using Oracle Application Explorer. Bad news is that absolutly everything is stored as xsd:string. No matter the content of the element, if it's some numeric values, text, date or time values ... the values are stored as string. SAP doesn't make use of the more appropriate default datatypes or the XML Schema Definition.
However, other sources do. So if you want to use for example the header data of an XML IDoc DC40 fragment to call a web service, you need to transform the string based date value CREDAT and the string based time value CRETIM to the more appropriate xsd:dateTime.

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            targetNamespace="urn:sap-com:document:sap:idoc"
            xmlns="urn:sap-com:document:sap:idoc"
            elementFormDefault="qualified">
   <xsd:element name="IDOCTYPEOFYOURCHOICE">
      <xsd:complexType>
         <xsd:sequence>
            <xsd:element name="IDOC" maxOccurs="unbounded" minOccurs="0">
               <xsd:complexType>
                  <xsd:sequence>
                     <xsd:element name="EDI_DC40">
                        <xsd:complexType>
                           <xsd:sequence>
                              ...
                              <xsd:element name="CREDAT" minOccurs="0">
                                 <xsd:simpleType>
                                    <xsd:restriction base="xsd:string">
                                       <xsd:maxLength value="8"/>
                                    </xsd:restriction>
                                 </xsd:simpleType>
                              </xsd:element>
                              <xsd:element name="CRETIM" minOccurs="0">
                                 <xsd:simpleType>
                                    <xsd:restriction base="xsd:string">
                                       <xsd:maxLength value="6"/>
                                    </xsd:restriction>
                                 </xsd:simpleType>
                              </xsd:element>
                              ...
                           </xsd:sequence>
                           ...
                        </xsd:complexType>
                     </xsd:element>
                     ...
                  </xsd:sequence>
                  ...
               </xsd:complexType>
            </xsd:element>
         </xsd:sequence>
         ...
      </xsd:complexType>
   </xsd:element>
</xsd:schema>


You can achieve this by assigning string data in the correct pattern to an xsd:dateTime element. This is possible since xsd:dateTime is accepting string inputs. However, the pattern of xsd:dateTime has to be respected. For our example, it is enough to target the pattern "yyyy-mm-ddThh:mm:ss" without the optional milliseconds and time zone parameters. Check out detailed information in XML Schema Definition Part 2 Datatypes.

The little POC for this is based on a synchronous BPEL process waiting for input data similar to XML IDoc data. An XSL Transformation is used to transform the string-based input data to xsd:dateTime data. Additionally, the XSL engine will add a generated xsd:dateTime value of the runtime environment. The following figure shows the BPEL process.

BPEL process GenerateTime
The service component architecture diagram is as simple as that, showing the exposed service endpoint and the BPEL process.

SCA composite overview of the POC
The input data to the request contains two elements date and time. Both of them are simple types based on xsd:string and restricted in length of 8 respectively 6 characters to represent a date of patter "yyyymmdd" and time of pattern "hhmmss".

XML Schema definition of the POC
The response data on the other hand contains two xsd:dateTime elements. One of them will be the target of the XSL transformation while the other one will hold engine generated data.

The following screenshot is taken from the XSLT editor in JDeveloper with SOA extension.

XSL Transformation is XSLT editor
We are using substrings to extract the year, month and day fragments from the input string date. The same way, we are extracting the hour, minute and second fragments from the input time value. Afterwards, we are concatinating all fragments including the required separators to the desired pattern of the xsd:dateTime based value ns1:customDateTime. Please find below the source code.

  <xsl:template match="/">
    <ns1:response>
      <ns1:customDateTime>
        <xsl:value-of select="concat(

          substring(/ns1:request/ns1:date,1.0,4.0),'-',
          substring(/ns1:request/ns1:date,5.0,2.0),'-',
          substring(/ns1:request/ns1:date,7.0,2.0),'T',
          substring(/ns1:request/ns1:time,1.0,2.0),':',
          substring(/ns1:request/ns1:time,3.0,2.0),':',
          substring(/ns1:request/ns1:time,5.0,2.0))"/>
      </ns1:customDateTime>
      <ns1:generatedDateTime>
        <xsl:value-of select="xp20:current-dateTime()"/>
      </ns1:generatedDateTime>
    </ns1:response>
  </xsl:template>



Now let's test the process (and XSL transformation) from Enterprise Manager, providing some sample data ...

Input data for testing
... and we are successfully receiving the transformed data as response:

Output data of the test
Notice that our transformed xsd:dateTime value only comes with the precision of the provided input data while the generated timestamp comes with the complete, detailed xsd:dateTime pattern including the optional parameters of milliseconds and time zone.

Here you can download the complete POC.

Tuesday, September 9, 2014

Testing your REST service in JDeveloper - How to access the sample data form

Oracle SOA Suite 12c does not only come around with support for RESTful Web services, but also provides extensive capabilities to test Web services directly from JDeveloper.

When trying to test a RESTful Web service endoint based on the Web Application Description Language (WADL) file, it is a bit less obvious what to do.

  1. Get the WADL from Enterprise Manager. Your WADL will look similar to https://localhost:7102/soa-infra/resources/default/ValidatePayment!1.0/validatePaymentRESTService/application.wadl where ValidatePayment is the SCA application name, 1.0 is the version of the SCA application and validatePaymentRESTService is operation name.
    Get WADL for RESTful Web service from Enterprise Manager
  2.  In JDeveloper, select Tools > HTTP Analyzer
  3. Create a new REST request in the HTTP Analyzer
    Create New REST Request in HTTP Analyzer
  4. Paste WADL to the URL input field and confirm by tabbing out of the line. You will end up with the WADL URI and the  Operations available on the WADL ... which is actually only to retrieve the WADL content.
    Request to retrieve WADL
  5. This is actually not what we want. What we expect to get a a form where we can enter test values for all (or at least some) of the parameters of the REST operation. What you actually need to do to get the WADL analyzed and a form created is to edit the WADL. Remove the last part of the WADL, in my case application.wadl.
    Manipulate WADL URI
  6. Confirm and you will end up with the expected form.
    Form to test endpoint of a RESTful Web service
  7. Including parameters and parameter values will add those to the URL of the HTTP request.
    Example of HTTP request parameterization
  8. Enjoy testing from JDeveloper!