Sunday 3 April 2011

HTTP Adapter in SOA 11g

At SOA 10g I faced a lot of difficulty while invoking a REST endpoint having POST or GET method as binding verb.You have to create your own custom wsdl and embed your message type and binding etc..
But SOA 11g comes with HTTP adapter , through this blog I’ll demonstrate invocation of Yahoo Geolocation REST service using HTTP adapter.
You can get the endpoint details in this location http://developer.yahoo.com/maps/rest/V1/geocode.html. If you paste http://local.yahooapis.com/MapsService/V1/geocode?appid=YD-9G7bey8_JXxQP6rxl.fBFGgCdNjoDMACQA--&street=701+First+Ave&city=Sunnyvale&state=CA in browser then you will get below result.
<?xml version="1.0"?>
<ResultSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:yahoo:maps" 
xsi:schemaLocation="urn:yahoo:maps http://local.yahooapis.com/MapsService/V1/GeocodeResponse.xsd">
<Result precision="address">
<Latitude>37.416397</Latitude>
<Longitude>-122.025055</Longitude>
<Address>701 1st Ave</Address>
<City>Sunnyvale</City>
<State>CA</State>
<Zip>94089-1019</Zip>
<Country>US</Country>
</Result></ResultSet>
<!-- ws01.ydn.ac4.yahoo.com compressed/chunked Sun Apr  3 00:08:24 PDT 2011 –>
But we need to achieve this using adapter.This service has got its input and 
output schema structure like below,

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  targetNamespace="urn:yahoo:maps"
  xmlns="urn:yahoo:maps"
  elementFormDefault="qualified">

    <xs:element name="ResultSet">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="Result" type="ResultType" minOccurs="0" maxOccurs="50" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:complexType name="ResultType">
        <xs:sequence>
            <xs:element name="Latitude" type="xs:decimal" />
            <xs:element name="Longitude" type="xs:decimal" />
            <xs:element name="Address" type="xs:string" />
            <xs:element name="City" type="xs:string" />
            <xs:element name="State" type="xs:string" />
            <xs:element name="Zip" type="xs:string" />
            <xs:element name="Country" type="xs:string" />
        </xs:sequence>
        <xs:attribute name="precision" type="xs:string" />
        <xs:attribute name="warning" type="xs:string" use="optional"/>
    </xs:complexType>
    <xs:element name="RequestSet">
        <xs:complexType>
            <xs:sequence>
                <xs:element name="appid" type="xs:string"/>
                <xs:element name="street" type="xs:string"/>
                <xs:element name="city" type="xs:string"/>
                <xs:element name="state" type="xs:string"/>
            </xs:sequence>
        </xs:complexType>
    </xs:element>
</xs:schema>
<!-- ws13.ydn.gq1.yahoo.com compressed Fri Oct 22 03:06:44 PDT 2010 –>

We’ll bind RequestSet to service input parameter and Result to service output.

Drag and drop an HTTP adapter in Reference lane ,

image

image

In HTTP Binding Configuration give the value as mentioned,

image

Bind input and output message type and click finish,

image

Then create a composite like below where adapter input parameter is same as process input and output parameter would be process output parameter,

image

Deploy the composite and test by passing proper value like below,

image

and in response you will get,

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <env:Header>
        <wsa:MessageID>urn:D6C31E005DDA11E0BFCB817CB1165FA2</wsa:MessageID>
        <wsa:ReplyTo>
            <wsa:Address>http://www.w3.org/2005/08/addressing/anonymous</wsa:Address>
        </wsa:ReplyTo>
    </env:Header>
    <env:Body>
        <ResultSet xmlns:ns0="urn:yahoo:maps" xmlns="urn:yahoo:maps">
            <ns0:Result precision="address">
                <ns0:Latitude>37.416397</ns0:Latitude>
                <ns0:Longitude>-122.025055</ns0:Longitude>
                <ns0:Address>701 1st Ave</ns0:Address>
                <ns0:City>Sunnyvale</ns0:City>
                <ns0:State>CA</ns0:State>
                <ns0:Zip>94089-1019</ns0:Zip>
                <ns0:Country>US</ns0:Country>
            </ns0:Result>
        </ResultSet>
    </env:Body>
</env:Envelope>


So Invoking REST endpoint from composite is just one click away !!!!!!!!

11 comments:

Din said...

Thanks for the Post!
I am trying to achieve the same thing and when i try testing my example, I face this error.

The selected operation process could not be invoked.

An exception occured while invoking the webservice operation. Please see logs for more details.

oracle.sysman.emSDK.webservices.wsdlapi.SoapTestException: faultName: {{http://schemas.xmlsoap.org/ws/2003/03/business-process/}selectionFailure}
messageType: {{http://schemas.oracle.com/bpel/extension}RuntimeFaultMessage}

Are these the only steps or should i change anything in the WSDL?

shrikworld said...

Hi, this might be some configuration issue or proxy related problem.Today I recheck my code and its working fine for me , share ur id I'll email the code.
Thanks..

Din said...

Thanks for the code. The issue was in the transformation. I used an assign activity to map the result of the HTTP adapter to the reply activity.
I had to use the if condition and restrict the attributes if they are null.

I have a question here. Is there anyway we could find a meaningful message from anywhere and really understand the issue? Is there any place where it will show it failed during transformation or something?

Anonymous said...

Hi Shri,
I am getting below expception while accessing the URL http://local.yahooapis.com/MapsService/V1/geocode?appid=YD-9G7bey8_JXxQP6rxl.fBFGgCdNjoDMACQA--&street=701+First+Ave&city=Sunnyvale&state=CA

Exception
------------

The following errors were detected:
backend fetch error 404


Is this URL still accessible? Do i need to do any configuration?

Sujit Nair said...

Hi Sir,

Need a Help on HTTP Adapter POST.

I have a requirement where i need to take an Image as Service Input in a Rest Service & Send that Image as Email Attachment.

To achieve this I used a HTTP Adapter with Type- Service , Operation- Request-Response & Verb- GET and payload type - url encoded and recieving the image as
an input in base64Binary element and sending that as attachment. Can test in browser by using the URL.

*GET*
url-encoded

This works fine if Image is small , but if Image is large GET does not work due to size limitation of GET , to avoid this in the HTTP Adapter i used Verb- POST

*POST*
url-encoded

But this does not work as the Service is not getting Invoked . Created a sample HTML Page which invoke this service with POST but not working . GET works perfectly fine but Issue with POST.

Please help in identifying the Issue with POST , do i need to do anythng additional in my SOA Service to support HTTP POST.

Abhinav Chand Mittal said...

HiShreekanta
I need to pass header information while doing an HTTP POST. Does your sample covers that as well?
I am not sure how to include the Header information as it is not part of configuration.
I am trying to accomplish following :
these headers have to be set as part of the post:
Content-type: text/xml
Accept: text/plain
Connection: Keep-Alive
Authorization: “Basic ” + BASE64Encoder.encode(username:password)
=>Basic encodedPortion

Please guide me if possible. You can email me at abhinav9mittal@gmail.com

Abhinav Chand Mittal said...

Hi Shrik,

I need to pass HTML Header while making a HTTP POST.
I have followed several blogs to achieve this but it's not working for me.
I need to pass (Content-type, Accept, Connection, Authorization).I can't use the oracle/wss_http_token_client_policyfor Authorization as i have to pass Authentication information against the
Authorization header which will following value :
for e.g.
'Basic Yw79u1jshbihchjasj=='
where, Yw79u1jshbihchjasj== represents Base64Encoded username:password
I have following configuration based on various blogs regarding Adding BPEL Headers

1) I have added following in composite.xml under reference

property name="oracle.webservices.http.headers">Authorization/property>

2) I have added following in MyBPEL.bpel under invoke

bpelx:toProperties>
bpelx:toProperty name="Authorization" variable="tempString1"/>
/bpelx:toProperties>


I am assigning the value to Autorization(string variable) using Assign activity.
But, it is not working for me. I am using SOA 11.1.1.5
In addition, do I need to add bpelx:inputHeaderVariable="Autorization" along with the Custom Header properties?

Please help as I am not able to figure out other ways to send this Header while making a HTTP POST call using HTTP Bindings adapter

Anonymous said...

Hi Shreekantha,

I have tried your sample of yahoo maps with a similar API of our company. Our API also takes multiple parameters as part of query string.

However when I test I am getting REPLACE_WITH_ACTUAL_URL error.

I checked in metalink and found a note saying that this is a known issue in SOA Suite 11g when we try to use complex type schema's as input to HTTP Binding adapter.

I am not sure how it has worked for you! Do we have to add any settings/properties in HTTP Adapter to make this work?

Thanks,
Surya.

JAVAMAN said...

Hi please can you share your BPEL code App ..?, because i have problem to use the HTTP Adapter to consume a REST like a Proxy since a BPEL WS. The problem is in the parse the response. The JCA generated does not has response element.

My email is: cesarricardo_guerra19@hotmail.com

Anonymous said...

Hi Surya,

You are right that HTTP binding adapter gives REPLACE_WITH_ACTUAL_URL error when you are working with xml containing complex elements. This issue exists in all versions of SOA till 11.1.1.6. But this issue is fixed in 11.1.1.7 version. Hence, it works for us.

Thanks,
PG

Anonymous said...

Hi Surya,

HTTP binding adapter doesnot support complex xml types and gives REPLACE_WITH_ACTUAL_URL error till 11.1.1.6 SOA version. This is a known issue. This issue has been fixed in SOA 11.1.1.7 version.

Thanks,
PG