SOA Suite 11g doesn't provide an out of box way to call JSON based REST
services. In this blog we shall the alternative options to achieve the same.
HTTP binding in SOA
Suite 11g has ability to make calls to endpoints based on
HTTP verbs(GET, POST only) in request-response (or) one way modes as depicted
below.
However Oracle's Documentation states that -"An outbound HTTP binding reference supports only XML
as a response from an external HTTP endpoint. The response should contain the
correct XML part name according to outbound expectations."
In
other words Http binding supports only XML as output for either
GET/POST. For input it supports only url-encoded and xml. Though the
url-encoded input has to be expressed/defined in an xsd format as shown below.
Another
major hindrance is that - Majority of the REST services created in IT
world use JSON rather than XML as their messaging standard dues to its light
weight and simplicity ( the same reason to use REST as against SOAP). HTTP
adapter/binding has no support for calling REST endpoints which use JSON
as a message standard as against XML.
Does this leave us no
way to call REST services using JSON ? Well not really. We always have Java to
fall back on to do something that can't be done ( or provided) in SOA Suite.
The below Java code can be used to call REST service using JSON. The input of the methods is an xml format represented in a string ( to make it easier to interact with bpel). The following are the key points of this code
a. Takes input in XML string format.
b. Converts the XML
string to JSON object.
c. Creates a
HTTPClient and makes a call to post/get method using the REST URI providing the
required basic http authentication credentials.
d. Extra code to
bypass the SSL layer ( only to be used in dev mode). In production one should
import the right certificates to authenticate themselves.
RestService.java
package oracle.soa.rest;
import java.io.BufferedReader;
import
java.io.IOException;
import
java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import
org.apache.http.client.ClientProtocolException;
import
org.apache.http.client.methods.HttpPost;
import
org.apache.http.entity.StringEntity;
import
org.apache.http.impl.client.DefaultHttpClient;
import net.sf.json.JSON;
import
net.sf.json.xml.XMLSerializer;
import org.apache.http.auth.AuthScope;
import
org.apache.http.auth.Credentials;
import
org.apache.http.auth.UsernamePasswordCredentials;
import
org.apache.http.client.methods.HttpGet;
public class RestService
{
public
HttpResponse callPOSTService(String xmlStr,String url) throws
ClientProtocolException, IOException
{
// Convert
the input XML to the JSON String
XMLSerializer xmlSerializer = new
XMLSerializer();
JSON json = xmlSerializer.read(xmlStr);
System.out.println(json);
// Call POST of REST Service with JSON input
DefaultHttpClient client = new DefaultHttpClient();
client =
WebClientDevWrapper.wrapClient(client);
Credentials creds = new UsernamePasswordCredentials("username", "password");
client.getCredentialsProvider().setCredentials( new
AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), creds);
HttpPost post = new HttpPost(url);
StringEntity se = new StringEntity(
json.toString());
post.setEntity(se);
HttpResponse response =
client.execute(post);
return response;
}
public
HttpResponse callGETService(String url) throws ClientProtocolException,
IOException
{
// Call GET of
REST Service
DefaultHttpClient client = new DefaultHttpClient();
client =
WebClientDevWrapper.wrapClient(client);
Credentials creds = new UsernamePasswordCredentials("username", "password");
client.getCredentialsProvider().setCredentials( new
AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT), creds);
HttpGet get = new HttpGet(url);
HttpResponse
response = client.execute(get);
return response;
}
public static void main(String[] args) throws ClientProtocolException, IOException
{
RestService rs = new RestService();
/*
String inputString="<?xml version=\"1.0\"
encoding=\"UTF-8\"?>\n" +
"<root>\n" +
" <description>Product New
one</description>\n" +
" <sku>146-4100-901</sku>\n" +
"</root>";
// Create the product with SKU mentioned above.
HttpResponse response = rs.callPOSTService(inputString,"https://abc.com/api/v1/products");
// Get the URL to update the product - Eg:
"https://abc.com/api/v1/products/18"
Header header = response.getFirstHeader("Location");
String update_url=header.toString().substring(10);
System.out.println(update_url);*/
/* // Update the product
String updatedinputString="<?xml version=\"1.0\"
encoding=\"UTF-8\"?>\n" +
"<root>\n" +
" <description>Update Product New
one</description>\n" +
" <family>Items</family>\n" +
"</root>";
System.out.println(rs.callIPOSTService(updatedinputString,"https://abc.com/api/v1/products/22"));
*/
// Get Product
HttpResponse response =
rs.callGETService("https://abc.com/api/v1/products/22");
String xmlResponse = "";
BufferedReader rd = new BufferedReader (new
InputStreamReader(response.getEntity().getContent()));
String line = "";
while ((line = rd.readLine()) != null) {
xmlResponse+=line;
}
System.out.println(xmlResponse);
}
}
WebClientDevWrapper.java - Used to bypass the SSL
package oracle.soa.rest;
import java.io.IOException;
import java.security.cert.CertificateException;
import
java.security.cert.X509Certificate;
import
javax.net.ssl.SSLContext;
import
javax.net.ssl.SSLException;
import
javax.net.ssl.SSLSession;
import
javax.net.ssl.SSLSocket;
import
javax.net.ssl.TrustManager;
import
javax.net.ssl.X509TrustManager;
import
org.apache.http.conn.ClientConnectionManager;
import
org.apache.http.conn.scheme.Scheme;
import
org.apache.http.conn.scheme.SchemeRegistry;
import
org.apache.http.conn.ssl.SSLSocketFactory;
import
org.apache.http.conn.ssl.X509HostnameVerifier;
import
org.apache.http.impl.client.DefaultHttpClient;
/*
*/
public class
WebClientDevWrapper {
public static DefaultHttpClient wrapClient(DefaultHttpClient base) {
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs,
String
string) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] xcs,
String
string) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
X509HostnameVerifier verifier = new X509HostnameVerifier()
{
@Override
public void verify(String string,
SSLSocket ssls) throws IOException {
}
@Override
public void verify(String string,
X509Certificate xc) throws SSLException {
}
@Override
public void verify(String string, String[]
strings,
String[] strings1) throws SSLException {
}
@Override
public boolean verify(String string,
SSLSession ssls) {
return true;
}
};
ctx.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ssf.setHostnameVerifier(verifier);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", ssf, 443));
return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
}
The following are the libraries added to the class path:
I googled and found all of these in the net and added to
the class path.
The main() method
provides a way to
1. perform GET to
retrieve the records using the URL
2. perform POST to
create.
3. perform POST to
update.
The Java code can be
called via a BPEL/Mediator component using Java Embedding ( or more cleaner way
by using a Spring component). The code in main method could replace the most of
the code in the Java embedding. Most importantly we need to create an XML
schema containing the request/response in accordance to the JSON
request/response schema of the REST URI.
Eg : In JSON
{
"sku":"130-01-099",
"description":"Test"
}
equivalent XML for
the same
<?xml
version="1.0" encoding="UTF-8" ?>
<root>
<sku>130-01-099</sku>
<description>Test</description>
</root>
You could use the
following tool for this conversion
- http://www.utilities-online.info/xmltojson/#.U9_NevldWAg
You can create an XSD
based on the above XML and accordingly use it in the BPEL process to call the
Java embedding code/Spring Context component that calls REST service using JSON
messaging standard.
Conclusion:
While Oracle SOA
Suite 12c provides an out of box solution for interacting with REST services
with JSON data standard using HTTPAdapter, 11g still need to seek the help of
Java code to achieve the same. The way of creating a Java class that
takes XML as input ,converting it to an equivalent JSON and then calling
REST service using JSON ,provides us an interoperability between SOA suite
components those primarily still rely on XML messaging with REST services
relying on JSON.
This comment has been removed by a blog administrator.
ReplyDeleteI like entire script the RestService.java. Thank you.
ReplyDeleteI really appreciate information shared above. It’s of great help. If someone want to learn Online (Virtual) instructor lead live training in Oracle 11g Fusion Java Programming, kindly contact us http://www.maxmunus.com/contact
ReplyDeleteMaxMunus Offer World Class Virtual Instructor led training on Oracle 11g Fusion Java Programming. We have industry expert trainer. We provide Training Material and Software Support. MaxMunus has successfully conducted 100000+ trainings in India, USA, UK, Australlia, Switzerland, Qatar, Saudi Arabia, Bangladesh, Bahrain and UAE etc.
For Demo Contact us.
Nitesh Kumar
MaxMunus
E-mail: nitesh@maxmunus.com
Skype id: nitesh_maxmunus
Ph:(+91) 8553912023
http://www.maxmunus.com/
I would like to thank you for the efforts you have made in writing this article. I am hoping the same best work from you in the future as well. Your write up is a fine example of it.For more details about oracle fusion SCM training please check our website.
ReplyDeleteOracle Fusion Cloud SCM Online Training
This is very informative and interesting for those who are interested in blogging field.In this blog we can get useful information.
ReplyDeletehttp://www.erptree.com/course/oracle-fusion-procurement-online-training/
ReplyDeleteThanks for sharing Good Information
Oracle SOA Online Training Hyderabad
I read Your article, Your article is simply super. I really enjoy it. For more details please visit our link.
ReplyDeleteOracle Fusion SCM Training
Hi,
ReplyDeleteI would like to ask , that i am developing first time in SOA using Jdeveloper , and i created REST webservice but when i try running the application locally to check whether it has no errors . it prompts me the below message:
[01:55:34 PM] Deployment cancelled.
[01:55:34 PM] ---- Deployment incomplete ----.
[01:55:34 PM] Unable to package module
[01:55:34 PM] null
#### Cannot run application Application2 due to error deploying to IntegratedWebLogicServer.
[01:55:34 PM] Cancel requested
[Application Application2 stopped and undeployed from IntegratedWebLogicServer]
Can you let me know the cause of it.