Monday, October 13, 2008

Valediction

Dear Co-workers and Managers,

I'm fighting the jarring dissonance of myriad thoughts as I set myself up to write this final memo. As absurd as it may seem, I can't help feeling vehemently nostalgic at having to bid adieu to my first company, and also, concomitantly, I can't help feeling ecstatically rhapsodic in eager anticipation of a wonderful journey I am waiting to embark on.

From being inducted into the organization two years back to the present day, I've come a long way. It's been a momentous undertaking for me - one that has seen the crests of exhilaration and troughs of despair; fortunately, the crests have by far outnumbered the troughs. From the carefree indulging in the youthful exuberance during my training days in Mumbai, to learning to cope with the vicious pressure of meeting deadlines, life has indeed come a full circle. And before I depart from here, it only befits that I give credit where it is due.

Foremost, special thanks are due to some of the most wonderful and fascinating people whose ingression into my life helped me see life in a new perspective. Deserving special mention amongst these are Abhishek, Amit, Amrita, Anil, Anitha, Bishnu, Chirag, Lalit, Mudita, Nancy, Neeraj, Piyush, Vanshika and Writu. If I had to thank each of you individually, I'd have to write till eternity. So, let me cut the long story short saying that I could always count on you, which kind of makes me think that I must have done something genuinely angelic to deserve guys like you. I wouldn't be the person I'm today without you. Your presence lends meaning to my life. Thanks. I'll miss you.

My thanks are long due to Mr. Manojkumar Khandelwal. Of late you've been looking despondent, which I would probably attribute to the anguish of watching your stocks plummet in the wake of the recent meltdown in the stock market (deliberate pun intended). I hope your stocks resurge with an even greater force than with what they went down. Apologize if I took liberties with you, but it's only you with who I could take liberties with. Despite me being several years junior, you always treated me like a friend. Your presence will be terribly missed. Have a wonderful life ahead.

Also, I wish to extend my heart-felt sense of gratitude to my managers and co-workers for showing faith in my abilities and providing me a platform to showcase my skills. Special thanks to Mr. Raghunandhan Kadirvelu, my on-site project manager. The fact that the project was a plain sailing right through could be majorly attributed to your perspicacious competence. I'll regret not meeting you in person. It was an honor to work under you nonetheless. Thanks.

And, last but not the least, thank you, Mr. Srinivasan Ranganathan for giving me the opportunity to make that presentation to Flowserve (if you can still remember). I'll never forget you walking up to my seat (after the presentation was over), shaking my hand, and then uttering, "Great job, Chief. I'm impressed" - undeniably, a magnanimous gesture from you and a remarkably proud moment for me. I still savor that moment and always will. You never fail to dazzle me with your sophistication and pristine demeanor. Thanks.

Finally, I wish the company a successful undertaking and a long lasting success.

Once again, thank you very much. Good bye.

Sincerely,
Sankash Thakuria.

Friday, September 26, 2008

Creating customized partnerlink bindings for deployment in different environments

The problem
Every BPEL process has a bpel.xml(deployment descriptor) file that provides information about the partners the BPEL interacts with. It does so by providing a partnerLinkBinding tag for every web service that the process invokes. Essentially, this tag gives the absoulute location of the WSDL file that is referred to by that partnerlink. A typical binding looks like this

<partnerLinkBinding name="SayHi">
<property name="wsdlLocation">
http://nebulasky.blogspot.com:7777/orabpel/develop/SayHiService/1.0</property></partnerLinkBinding>

Notice that the WSDL URL contains tokens like host, port, domain and revision of your web service. Since these values will differ in different environments(development, test, and production), your partnerLinkBindings too will change for different enviroments. A typical solution would be to have different bpel.xml files for different environments. This is the easy way but cumbersome and error-prone.

The solution
Fortunately, there is another way and which is much more simple. A customize ant task is provided that enables you to specify the property value for development and production environments in a single build file location. The customize task captures the changes between different versions of bpel.xml using the build file. This task can be used as a subtask of bpelc or as a standalone ant task. This is the subject matter of this post.

Customize Ant Task
Follow these steps to achieve the customization.

1. Create a custom build.xml under the bpel directory of your project folder. Here you will specify WSDL URL contains tokens like host, port, domain and revision of your web service. Here is how the new build.xml will look like.

<?xml version="1.0" encoding="iso-8859-1"?>
<project name="bpel.deploy" default="compile" basedir=".">
<target name="compile">
<bpelc input="${basedir}/bpel.xml" out="${process.dir}/output" rev="${rev}" home="${bpel.home}">
<customize>
<partnerLinkBinding name="SayHiService">
<property name="wsdlLocation">
">http://${host_name}:${port_number/orabpel/${domain_name/SayHiService/${rev}/SayHiService?wsdl</property>
</partnerLinkBinding>
</customize>
</bpelc>
</target>
</project>

2. Specify values for the host name, port, domain name, and process revision properties in the SOA_Oracle_Home\bpel\utilities\ant-orapbel-properties file. Here is an extract from the

file.host_name=nebulasky.blogspot.com
port_number=7777

domain_name=develop
rev=1.0
# --------------------------------------------------
# END OF FILE

Now, this is the only file you need to edit to take care of BPEL process migrations among various environents.

3. Go to the main bpel.xml file located under the project folder and specify a new target to override the one that is already there in this file. Here the target name of compile is changed to compileTest.

<target name="process-deploy" depends="validateTask, compileTest, deployProcess, deployTaskForm, deployDecisionServices" />

Now you need to create a new target by the same name(compileTest) in the same file. Within this you will provide the location to the custom build.xml file you created a few steps before. This way you shall override the target that already exists in the old build.xml file.

<target name="process-deploy" depends="validateTask, compileTest, deployProcess, deployTaskForm, deployDecisionServices" />
<target name="validateTask">
<validateTask dir="${process.dir}/bpel" />
</target>
<target name="compileTest">
<ant dir="${process.dir}/bpel"/>
</target>
<target name="compile">

4. Save the project. If you are using Jdeveloper in some other machine than the one where the application server is running, you need to transfer the project to the machine running the server. once this is done deploy the project using Ant. Fire up the developer prompt and navigate to the project directory and issue the following command

ant process-deploy

5. Go to the Oracle BPEL Console and ensure that the process was deployed successfully.

Friday, September 5, 2008

Calling concurrent programs from BPEL

When you are integrating some system with Oracle Apps, and especially if it involves an inbound data movement into Oracle, you will often find a situation where your BPEL process needs to call a concurrent program in Apps. Although, the the Oracle Apps Adapter supports this functionality, you'd rather write your own procedure. The reason is when you call the Apps adapter, it merely calls the concurrent program and exits. Usually, you don't want that to happen, but rather wait till the concurrent program has finished execution. Assume that somewhere later in your BPEL process you want to access some of the base tables (populated by the concurrent program), but since the BPEL goes ahead with its execution you end up looking into those tables when the concurrent program is still running and data has not been populated properly yet. Ofcourse, you can add a wait activity, but then you will have to set the wait time manually because there isn't a way to know when the program will have finished. In this post I am going to show you how to handle such situations.


For calling concurrent programs through PL/SQL Oracle provides a procedure submit_request. This procedure can be found under the fnd_request package. For calling a concurrent program you can directly call this procedure, however the 'wait' problem would persist. So, we are going to create a wrapper around this procedure and call this wrapper instead. This procedure takes in excess of 100 parameters, but the good thing is you need not worry about all of them. Pass a few mandatory ones and you are through. Here are the parameters it takes as input


  • application: Short name of application under which the program is registered
  • program: concurrent program name for which the request has to be submitted
  • description(Optional): Will be displayed along with user concurrent program name
  • start_time(Optional): Time at which the request has to start running
  • sub_request(Optional): Set to TRUE if the request is submitted from another running request and has to be treated as a sub request default is FALSE
  • argument1..100(Optional): Arguments for the concurrent request
Here is the code

PROCEDURE submit_journal_import(
p_source IN VARCHAR2,
p_post_errors_to_suspense IN VARCHAR2 DEFAULT 'N',
p_start_date IN VARCHAR2,
p_end_date IN VARCHAR2,
p_create_summary_journals IN VARCHAR2 DEFAULT 'N',
p_import_desc_flexfields IN VARCHAR2 DEFAULT 'N',
p_run_id IN NUMBER,
x_req_id OUT NUMBER
)
AS
v_run_id INTEGER;
v_req_id INTEGER;
v_phase_code CHAR := 'R';
BEGIN

/*Set appropriate values for user_id, responsibility_id and application_id. These must exist in the apps.fnd_user and apps.fnd_responsbility_tl*/
apps.fnd_global.apps_initialize(0, 20420, 1);
x_req_id := apps.fnd_request.submit_request('SQLGL', 'GLLEZL', 'Journal Import - ' || _source, NULL, FALSE, to_char(p_run_id),
'2001', p_post_errors_to_suspense,
p_start_date, p_end_date, p_create_summary_journals,
p_import_desc_flexfields
);

DBMS_OUTPUT.PUT_LINE('after');
COMMIT;

DBMS_OUTPUT.PUT_LINE('The request id is' || to_char(x_req_id));
/*
Wait for the concurrent program to finish
*/
WHILE(v_phase_code <> 'C')
LOOP
SELECT phase_code
INTO v_phase_code
FROM apps.fnd_concurrent_requests
WHERE request_id = x_req_id;
END LOOP;

END submit_journal_import;

Observe that we have passed the appropriate values into the submit_request procedure. For more information on these refer the Oracle Applications documentation. But, before you can call this procedure you need to set up the Apps environment. This is done by calling the apps.fnd_global.apps_initialize procedure. This again takes three parameters

  • user_id
  • responsibility_id
  • responsibility_application_id
These values can be found in apps.fnd_user and apps.fnd_responsbility_tl tables.

Also, notice that we have used a while loop that keeps looping over till the program has finished executing. Only when the program has completed, the procedure is exited.

Thursday, September 4, 2008

Google Chrome: Redefining browsing experience

Google inched a step closer towards its tacit goal of reigning supreme in a new era of computing dominated by the web, when it hurled its brand new web browser (Chrome) at an expectant world this Tuesday. The new browser had been under wraps for quite sometime now until a weblog spilled the beans by releasing a comic book that brings to fore Google’s idea behind creating a new browser from scratch. Legions of elegant and hitherto unheard of features are on offer – at least the comic book claims so. Not everybody is amused though, and the first name to feature in that list is – you guessed it – Microsoft, who else?

Google asserts that the internet has been through a never-seen-before evolutionary change and it only befits that the browsers follow suit. With Chrome it attempts to redefine user experience by leveraging the new capabilities of the web. Slowly and steadily, the web has become an overarching influence in people’s lives, embracing the flora and fauna of the computing ecosystem. At a time such as this, we need better alternatives for exploiting the gargantuan benefits the web offers, and Chrome is Google’s attempt to providing an answer.

So what does Chrome have that others, notably Internet Explorer and Firefox don’t. It’s too early to come up with a viable answer to that question given that Chrome is still in its nascent stage. However, it does promise some very exciting features, some of which might lead Microsoft’s top bracket to loose some sleep.

First Impressions
Chrome is available for download from www.google.com/chrome. Well, the installation is a breeze and before you know it, Chrome has imported all your bookmarks, passwords and browsing history from the browser you have been using. Presto! You are ready to experience the web in a way like never before.


The first thing you notice (or rather not notice) is the minimalist design of the browser, with no status bar and hardly-there buttons. Google has deliberately kept things simple on the surface to enhance user experience, but you can rest assured of some marvelous tech wizardry that silently drives the Chrome. Like Firefox 3.0 or Internet Explorer 7.0(version 8.0 is available for download, but who cares), Chrome has tabs but there is a noticeable difference – the address bar (Omnibar if you prefer Google’s terminology) is below the tabs. And the Omnibar is not just an address bar – it doubles up as a search box as well and you have the normal autosuggest feature thrown in that makes browsing a walk in the park.

Chrome presents you with a rather unusual home page – one that contains your recent bookmarks and most visited pages. Another great feature, I would think.

Rev it up
It feels much faster than its peers. For one thing Google uses V8 JavaScript Engine which, if rumors are to be believed, is nippier than others in the category. Also, Chrome uses multiprocessing to push the gas pedal – each new tab that you fire results in a new Chrome.exe being created in your machine unlike IE7 where you have only one process to take care of all the open tabs.

What crash?
Open a tab and you are starting from scratch. So while you are browsing, Chrome is creating and destroying processes all the time. Thus, even if a tab gets screwed up because of a memory leak and crashes, the others remain intact oblivious of the leak because each has its own block of memory. Cool stuff.

Open source
Google has developed it on top of Webkit which is an open source rendering engine and incidentally the same that powers Apple’s Safari. At the moment, add-ons aren’t supported, but that is only for now. Eventually, like in Firefox you should be able to wire up add-ons to Chrome.
Developer’s playground
Chrome has very elegant features that will have developer swooning over it. For one, there is a JavaScript console that facilitates debugging scripts like no other browser can. For another, you can see the HTML source of a page. Big deal, you say. The deal is Chrome shows you the line numbers too. I can see bloggers like me going hallelujah already.


Touch-me-not
Chrome offers you an ‘Incognito’ window that allows private browsing. Anything done from here is never logged on your computer and you have full access to your bookmarks and browsing history like you would have in any other window.
Annoyances
Not everything was smooth sailing though. I intended to write this blog on Chrome, but, unfortunately, it would not let me sign in to my blogger account. That apart, everything was a brezze.

Parting Thoughts
Of course, Chrome is not perfect, but then, what is? In an age where technology seems to change faster than you can blink, it is too early to predict what the future holds for Chrome. But going by the recent stats, and with none other than Google pushing the envelope, Chrome surely seems to be heading in the right direction.

Tuesday, September 2, 2008

Movie Review: Rock On

Rock on is an episode drawn out of the lives of four friends who share a common passion – music. But, in essence the movie isn’t as much about music as it is about seeing life in a new perspective, and about letting go of the inhibitions and following one’s heart.

Aditya(Farhan Akhtar), Joe(Arjun Rampal), Rob(Luke Kenny) and KD(Purab Kohli) are four buddies who form a music band called Magik. Fame seems within spitting distance when the foursome wins a music contest and is signed by a TV channel to do an album. But destiny plays spoilt sport and an altercation ensues between Aditya and Joe on the sets of the channel, and they lose their golden chance to glory.



Ten years have passed since, and the entire four have left (or rather have tried to leave) the past well behind them and got on with life. Aditya has long given up his music, and is professionally successful as an investment banker but leads a lonesome and monotonous life despite having a caring wife, Sakshi (Prachi Desai). KD has moved into his father’s diamond business and hates it more than anything. Rob works with Anu Malik (who plays a cameo), and creates jingles for advertisements. Joe is hard pressed for money and it is left to his wife, Debbie (Shahana Goswami), to make ends meet.

One day Sakshi finds an old box in the attic and upon opening it she finds some photographs of Aditya and his friends. Having realized that something is terribly amiss in her marital life with Aditya and that he has drawn himself into a cocoon, she decides to arrange for a reunion of the four, with the intent of lifting Aditya's spirits. Destiny connives, from then on a new journey ensues where the four must put behind their ego clashes and differences, and finish what they had left unfinished long ago.

I wouldn’t say that the movie has a brand new story to tell. In fact, far from it, the story has a feeling of déjà vu attached to it and clichés abound, but it has been presented in such a beautiful manner that you simply fall in love with it. The best thing is it manages to remove the divide between celluloid and reality. It is almost like seeing yourself on the screen; the connection is instant and at an emotional level, and this is precisely where it manages to win hearts.

Abhishek Kapoor, the director, has executed the script to near perfection and deserves kudos for it. The characters are well etched out and are easily identifiable with. Farhan Akthar – take a bow. He is impeccable and his acting is near perfect, sufficient to give even the seasoned actors jitters. Prachi, in her first movie, impresses, especially with her expressive demeanor, and so does Suhana Goswami as an estranged wife. Arjun Rampal comes of age and delivers his best performance till date.



Shankar, Ehsaan and Loy deserve a big round of applause for creating some breathtaking melodies. The lyrics are amateurish, but fit the bill completely for that is how the situation demands it. Kudos again to the producers for having the guts to use Farhan Akhtar’s vocals, and he doesn’t disappoint either.

To sum it up, Rock On is a great movie that should go down well with everyone, especially the young. As already stated, the movie is about celebrating life and making the most of it and it does succeed to drive home that message. For that alone the entire team of Rock On, take a bow!

Monday, September 1, 2008

Calling executables/batch files/scripts from BPEL

No direct way..
While working with a client, I was confronted with this problem - calling an executable from BPEL. The client was using PGP(Pretty Good Privacy) to encrypt/decrypt/sign files and my task was to write a BPEL prcoess that would perform these functions by calling the PGP program. Unfortunately, BPEL does not have an out of box functionality to address this. Thus I had to write a JAVA snippet that would do the task for me. The subject matter of this post is how to write the code. Though the code is specific to calling the PGP, it could be used for calling any executable with few changes. The essentials are the same.

Calling the code
There are three ways to incorporate the JAVA code into the BPEL.


  1. Wrap the code in a web service
  2. Use JAVA embedding and call the code directly
  3. Use WSIF to call the codeYou can use any of these.

In my case the client wanted it as a web service, so that it could be resued as and when needed.


The JAVA code
My code has just one public class EncryptDecrypt and the following methods


  • public String pgpEncryptFile (String pgpEncryptCommand): This method takes the command for encrypting a file and returns 'Success' if the encryption was successful or 'Error' otherwise
  • public String pgpDecryptFile (String pgpDecryptCommand): This mehtod takes the command for decrypting a file and returns 'Success' if the decryption was successful or 'Error' otherwise
  • private void getCommandOutput(): This method fetches the output produced subsequent to the execution of the command
  • private void writeCommandOutputToLog(): This method is responsible for writing the command output to a log file. Everytime the command is run the log file is updated

Declare and initialize the variables
//location of the executable
private static final String pathToPGPExecutable = "C:\\Program Files\\Network Associates\\PGPcmdln\\PGP.exe";
private static final String pgpInstallationDirectory = "C:\\Program Files\\Network Associates\\PGPcmdln";
//name for the log file to be created

private static final String logFileName = "CommandOutput.log";
private String executionStatus = null;
private String commandOutput = null;
private String logContent = "";
private BufferedReader stdInput = null;
private BufferedReader stdError = null;
private Process processInstance = null;


Method implementations
Below are the implementations of the menthods with explanations


pgpEncryptFile
Every Java application has a single instance of class Runtime that allows the application to interface with the environment in which the application is running. We can obtain the current runtime by using the static getRuntime method of this class. Then we will call the exec method to create a new process and execute the command in the process thus created. This is done as

processInstance = Runtime.getRuntime().exec(pgpEncryptCommand);
The pgpDecrypt is exactly same as this one. The only difference is in the command.Here is the implementation of this method

public String pgpEncryptFile(String pgpEncryptCommand ) {
try {
System.out.println(pgpEncryptCommand);
//create a process and execute the command
processInstance = Runtime.getRuntime().exec(pgpEncryptCommand);
//wait for the process to complete
processInstance.waitFor();
getCommandOutput();
System.out.print("LOG Content : " + logContent);
System.out.println("LOG finished");
}
catch (IOException e) {
executionStatus = "Error";
e.printStackTrace();
}
catch (InterruptedException e) {
executionStatus = "Error";
e.printStackTrace(); }
executionStatus = "Success";
return executionStatus;
}

getCommandOutput
The next step is to get is to get our hands on the ouput of the command. For this, we will create two streams - one connected to the normal output of the process and the other connected to error stream of the process(to make provision for in the case of an error). Then we will route the contents of the stream into a local variable logContent. The implementation of this method is as follows.

private void getCommandOutput() throws IOException {
String newline = System.getProperty("line.separator");
stdInput = new BufferedReader(new InputStreamReader(processInstance.getInputStream)));
while ((commandOutput = stdInput.readLine()) != null) {
logContent = logContent + commandOutput + newline;
stdError =new BufferedReader(new InputStreamReader(processInstance.getErrorStream)));
while ((commandOutput = stdError.readLine()) != null) {
logContent = logContent + commandOutput + newline;
}
}
}

writeCommandOutputToLog
This method will write the output of the command to a log file. First, a new directory will be created under the directory where PGP is installed, and then a log file will be created under the new directory thus created. This file will contain the output of the command

private void writeCommandOutputToLog() throws IOException {
File createDir = new File(pgpInstallationDirectory, "Log");
createDir.mkdir();
String logPathLocation = pgpInstallationDirectory + "\\Log";
PrintWriter fileWrite = new PrintWriter(new BufferedWriter(new FileWriter(new File (logPathLocation, logFileName))));
fileWrite.println(logContent);
fileWrite.flush();
fileWrite.close();
}



Finally

Readers may please note that this is a more specific example, but the concept is the same. Calling any other executable would need appropriate changes in the code provided here.




Wednesday, August 27, 2008

SOA and WOA

The debate sorrounding SOA(Service Oriented Architechture) and WOA(Web Oriented Architecture) is getting fiercer by the day and the blogosphere is abuzz with pundits claiming that WOA is the *in* thing citing plethora of reasons like simplicity, cost-effectiveness, decreased time to market, better manageability and so on. So, where does that lead SOA to - on the way to extinction? I don't think so.

To set the record straight, there seems to be a lot of misconceptions about both SOA and WOA - may think of them as a technology or an offshoot thereof. This is fundamentally wrong. They are, in fact, different architectural styles, or simply put two different way of doing things. And like similar styles in the same ecosystem, each has its own advantages and shorcomings. To simply put one ahead of the other, which is what is happening, is fundamentaly flawed.

Recently, while perusing an article in InformationWeek I came across some interesting stats about SOA. Let me share them with you.

"IT pros have expressed skepticism about SOA's promised return on investment. A 2007 InformationWeek Web survey of 278 IT pros found that 32% of those using SOA said those projects fell short of expectations. Of those, 58% said their SOA projects introduced more complexity into their IT environments, and 30% said they cost more than expected. Out of all respondents using SOAs, just 10% said the results exceeded expectations."

These are what the figures say, but what is indeed the fact? Well, the fact is that for a relatively new concept as SOA to stake claim to its usefulness in the market, it needs to spend a fair share of time in the market. If you look back 10-15 years from now, you will realize that its precursors like DCOM, CORBA had received the same lukewarm response. I do not put blame on organizations when they claim that the cost of implementing SOA far outweighs its usefullness, but such a statement can only be true for a small organization with relatively smaller number of offerings in their portfolio and when there aren't any pressing complexities. In such cases, it might make sense to go with an alternative to SOA, perhaps WOA.

Interestingly, Gartner Research defines WOA as "a subset of SOA". If you're using WOA, you are in anyway using SOA but not vice-versa. This again brings to fore the fact the debate between the two is on flawed grounds. In fact, for enterprises it is more of a choice between the two - or still better a mix of both, depending on their tech landscape. When it comes to service-enable a company's offerings, SOA (or WOA for that matter) should not be the default choice. A comprehensive study of what needs to be achieved is of utmost importance and this must the done first. Only after considerable thought has gone into this a choice should me made. For start ups and small companies that do not need complex integrations among disparate systems, WOA should be the approach, inasmuch as it is less complex and inexpensive to implement. Investing big money to set up SOA when such a set up serves no real advantage is totally uncalled for. For large oraganizations where huge integration setups are needed, WOA will be unsuaitable. It makes more sense to invest upfront on SOA and then reap the fruits in the long run.

So, it is not as much about SOA vs WOA as it is about the choice between the two. The approach should depend on what is desired and exactly what should be used to reach that goal. Ideally, a design should start with WOA and then add up SOA as and when the need so arises. In conclusion, the two are not diametric as they have been falsely portrayed to be, but are complementary.

Tuesday, August 26, 2008

REST Web Services demystified

The cacophony
Recenlty, a lot of dissonance has sorrounded the debate betwee REST(Representational State Transfer) styled web services and SOAP. In fact, proponents of REST group have even gone to the extent of procaliming that it is quickly gaining ground and will one day become the de facto standard of creating web services, forcing SOAP into oblivion in the process. The internet is abuzz with claims that SOA (based on SOAP) is a thing of the past and WOA (Web Oriented Architecture based on REST) is the future. Not wanting to be left behind, the exponets of the SOAP, on the other hand, want to leave no stone unturned to prove the others wrong. Whatever the noises may sound like it makes sense to look into REST. So, here is the REST story

What are REST styled web services?
As already stated, REST stands for Representational State Transfer. REST basically means that each unique URL is a representation of some object. You can get the contents of that object using an HTTP GET. Other operations such as POST, PUT can be used to modify the object. In essence, REST it is the repsentation of the current state of a resource on the web.

The debate between REST and SOAP
While SOAP services are built on top of host of specifications laid down by OASIS, REST declares that the already existing WEB 2.0 standards are sufficient to build robust web services. Also, a major faction of REST supporters believe that using HTTP to piggyback payloads like SOAP does, is against the rationale of HTTP and an abuse to the protocol. It also brings in intricate complexities especially on the security front. One worth mentioning is piggybacking allows SOAP messages to get past firewalls and thereby places an additional constraint of detecting piggybacked payloads and scanning them prior to letting them in within the enterprise, which is not what firewalls are innately intended for. This is the main reason why both factions have always been at loggerheads with each other. More on this later.

Benefits of REST
Irrescpective of what the critics say there are some advantages that REST offers over SOAP. We shall now look at a few of them.

Simpler Interface
The REST methodology uses the URI(the way you send requests from your browser to a web site) for its implementation. Thus any request/response is a simple HTTP request/response. This keeps things simple, for nearly all applications on the web support HTTP. Thus, any application that supports HTTP can fundamentally produce and consume REST services. Contrast this with SOAP services, which have to adhere to specifications that go beyond HTTP thereby making it more complicated. Request/response are sent/received in SOAP envelopes which are XML that sit on HTTP for trnasport. So, there is the extra work involved in creating the SOAP request and parsing the response.

Light weight
From the above point it follows, that SOAP needs an additional XML wrapper above and over HTTP. This is unlike REST which is simple HTTP resquest/response. This can result in significant bandwith savings, especially for enterprises whose porfolio has umpteen applications interaction with each other at a massive level.

Security
Since firewalls are intended to restrict traffic by looking at the HTTP command in the request, it becomes inherently easy to apply security policies for REST services. For instance, if a GET operation was used, it can be considered safe since it can't, by definition, modify or alter data. It is here that SOAP can take liberties with the HTTP protocol. SOAP generally use POST and unless one has a good long look at the SOAP envelope, security apprehensions can't be put to rest. Since looking into SOAP messages is not a feature provided by fire walls, one needs to do extra work to enforce security at this level

REST service support in Oracle
In Oracle AS 10.1.3, you can use the command line Web Services Assembler (WSA) in conjunction with ANT or use JDeveloper (10.1.3) wizards to create and test REST services. The rest of the post describes how to create REST services with JDeveloper.

Creating REST services with JDeveloper
For the purpose of demonstration I shall use a simple class that concatenates one string with another and then publish it as a REST web service. Here is my class:

package com.nebulasky.blogspot;
public class HelloWorld {

public HelloWorld() { }
public String sayHi(String s){
return "Hello "+ s; }
}

Once this you have created the class, go back to the application navigator. Right click the context menu of the source java file and click 'Create J2EE web service'. In the second step of the wizard select the checkbox for REST Support (as seen in figure below) in the Java Web Service Wizard.



You can now click 'Finish' to complete creating the serb service. Deploy the service.

Testing the REST Service
You can test the process from the Enterprise Manager console by clicking on the 'Invoke REST POST' or 'Invoke REST GET'



Or you can even create the HTTP request and pass parameters using a query string. In my case it is
http://172.28.0.54:7777/BlogDemo-RESTHelloService-context-root/SayHiServiceSoap12HttpPort/sayHi?s=sankash

You should see something as this

Monday, August 25, 2008

Handling Exceptions: Creating and using fault policies

Back then...and now
Prior to patch 10.1.3.3, we had to write fault handling code for each and every BPEL process we created. This was done at design time, and more often than not there was a great deal of overlap in the fault handling code for different processes. In essence, we merely ended up writing the same code over and over again. Reusability was thus non-existant as far as fault handling was concerned.

With the 10.1.3.3 patch things have turned over a new leaf. Now, you have the option of creating fault policies(fault handling) that can be applied to an entire domain. Besides, you can bind these policies to a BPEL process at different levels - partnerlink,port type, process and domain. The framework will use the binding in order of the following priority :
  • bpel.xml
  • policy defined on the server
The reader must note that a fault policy defined on the server will always takes precedence over one that is defined in the BPEL process(catch/catchall blocks), if at all one exists.

Designing a fault policy
A fault policy file defines fault conditions and their corresponding faultrecovery actions. Each fault condition specifies a particular fault or group of faults, which it attempts to handle, and the corresponding action for it. A set of actions is identified by an ID in the fault policy file. Please bear in mind that you can have only one fault-policy for a domain and it must be under SOA_ORACLE_HOME\bpel\domains\domain_name\config\fault-policies. You need to create the fault-policies directory under config as it does not exist by default.

The fault-policy file essentially consists of two sections - condition and action. The condition section is based on a faultName. Each condition has an optional test section and a mandatory action section. The test section tests the occurence of a particular fault and upon the test being true(when that fault has indeed occured ) an action is taken which again is defined in the same file. Several actions can be configured for a particular faultName.

For the purpose of demonstration I have created a fault-policy file which is as follows:
<?xml version="1.0" encoding="UTF-8"?><faultPolicy version="2.0.1" id="SankashPolicy" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.oracle.com/bpel/faultpolicy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
<Conditions>
<faultName xmlns:bpelx="http://schemas.oracle.com/bpel/extension" name="bpelx:remoteFault">
<condition>
<action ref="ora-retry"/>
</condition>
<condition>
<action ref="ora-terminate"/>
</condition>
</faultName>
</Conditions>
<Actions>
<Action id="ora-retry">
<retry>
<retryCount>2</retryCount>
<retryInterval>2</retryInterval>
<exponentialBackoff/>
</retry>
</Action>
<Action id="ora-terminate">
<abort/>
</Action>
</Actions>
</faultPolicy>

If you scroll down to the conditions section you will notice that I am testing for remotefault. If a remoteFault does occur, my remedial action is to retry the connection twice at an interval of 2 seconds. If that does not yeild any result, the final action is terminate the process altogether.

Associating a fault policy
Now that we are done with creating the fault policy, we will see how to bind the policy with a process. As already mentioned the binding can occur at partnerlink, port type, process and domain level. To associate a policy at the process level you need to create the bindings in the bpel.xml file. However, if you want it at the domain level you need to specify the bindings in the fault-bindings.xml under SOA_ORACLE_HOME\bpel\domains\domain_name\config directory. Whichever association you want, the bindings are defined as follows:

<faultPolicyBindings version="2.0.1" xmlns="http://schemas.oracle.com/bpel/faultpolicy" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
<process faultPolicy="SankashPolicy"/>
<partnerLink faultPolicy="SankashPolicy"/>
</faultPolicyBindings>

In order that the BPEL process manager picks up the policy you created just now, restart the server.

Use case
To ascertain that the policy is indeed active, create a synchronous BPEL process(wihtout any catch/catchall) that simply calls a java web service. Compile and deploy it. Verify that it executes successfully. Now log in to the enterprise manager console and undeploy the web service that the process was calling. Now, again initiate the process. Open the Activity Audit Trail for the instance. Observe that the process gets terminated. See screenshot below.



Remember nowhere in the process we had written code to terminate it upon the occurence of a remote fault. Evidently, the policy must have caused it to do so.

Friday, August 22, 2008

Handling database package migrations in BPEL

The catch
Recently while working on an integration project for a client, I was told that the custom database packages my BPEL process was referencing needed to be moved to a different database schema. Migration of the packages was promptly done. All that remained was tweaking the BPEL process so that it referenced the packages under the new schema. Since I had used server-side JNDI, my first impression was resetting the data source to the new schema would do the trick. As it turned out, that was not the only thing I needed to do, but a few more.

Recofigure the run-time connection
The first step is to reset the data source so that it points to the new schema. This is fairly easy. Since every data source is tied to a connection pool, it is in essence the connection pool that needs to be changed. To do that, first, log on to the enterprise manager and then modify the existing connection pool by resetting the jdbc url, user name and password. Save the changes. If you insist on creating a new connection pool altogether for better readability, by all means do so. But don't forget to tie it to the data source you are referring to from the JNDI name.

Reset the JCA operation
Go to your BPEL project and open the WSDL files for all the database adapters that were referring to the old schema. Scroll down to the jca:operation tag. You will find something like this:

<jca:operation
SchemaName="APPS"
PackageName="XXALV_BPEL_UTILITY_LIB_PKG" ProcedureName="SUBMIT_JOURNAL_IMPORT" InteractionSpec="oracle.tip.adapter.db.DBStoredProcedureInteractionSpec" > </jca:operation>

Notice that the SchemaName is set to the one you were referring to previously. Reset it to the new schema name. For instance, in my case the new schema is BOLINF. Thus, I will set it as:

...
SchemaName="BOLINF"
...

Leave everything else the same.

Compile and redeploy
You are done. Save the changes and deploy the process. It should now pick up the packages under the new schema.

Gotchas
Most of the time your procedures will call other procedures and functions that may not be under the same schema as your packages are. In such cases your schema will need privileges to perform operations on objects that are outside your schema. Be sure to ask the DBA to grant you the necessary permissions. Also, it is recommended that you qualify all the database objects you create with the schema name so that all references are made explicit.

Thursday, August 21, 2008

WSIF Revisited: Bottom up development using JDeveloper

Oversight....
In the previous post, I had elucidated how to call Java using WSIF. But, an oversight on my part caused the things to look a trifle more complicated than they actually were. Here is an attempt restore some sanity.


Create the Class
First, you need to create the Java class. Launch JDeveloper and create a new Java class. For ease of writing, I shall use the same class as that in the previous post. The class's task is to concatenate one string with another.



Here is the Java snippet:

package com.nebulasky.blogspot;
public class ConcatString {
public ConcatString() { }
public String getConcatenation(String input){
return "Hello " + input;
}
}

Generate the contract
A peek into the earlier post and you will realize that we had then created the contract manually, when in fact we could have done it with a JDeveloper wizard (the oversight I was blabbering about). Right click the Java source from the context menu of the project and click 'Create J2EE Web Service'



In the first step of the wizard check the WSIF Binding uncheck the SOAP 1.1 Binding (this is checked by default).



Once these are done, finish the wizard. Open the WSDL thus generated and have a look. Scroll down to the service tag and you should see something like this:

<service name="WSIFConcatService">
<port name="WSIFConcatServiceWSIFPort" binding="tns:WSIFConcatServiceWSIF">
<java:address className="com.nebulasky.blogspot.ConcatString"/>
</port>
</service>

Note java:address tag. It specifies a class name instead of a SOAP address which is how it would have been if you had chosen SOAP binding. Additionally, will also find some new tags like format:typeMap, format:typeMapping, java:binding and java:operation. For more information on these, visit my previous post.

Deploying the classes
Next, you load the com.nebulasky.blogspot.ConcatString class onto the application server. For this simply copy the class and put it &lt;BPEL_HOME>/system/classes directory. Restart the server.

Create the BPEL process
Create a synchronous BPEL process and create a new partnerlink. Import the WSDL from the local file system into the BPEL project directory. Assign the appropriate fields like operation, partnerR, myRole etc. Now drag an invoke activity and bind it with the service. Here is how the BPEL process will look like:




Deploy and test
Deploy the process and test it. Provided everything is in place, it should return the expected response.


Wednesday, August 20, 2008

WSIF: Calling native Java code from BPEL

What's the deal?
The alternatives to calling Java from BPEL aren't legion. Infact, there are only three.
  1. Using Java embedding to call the code directly
  2. Wrapping the code in a SOAP service
  3. Calling the code using Web Service Invocation Framework
Thus, it becomes all the more important to make a judicious choice amogst the three. The subject matter of this post is to acquaint the reader with calling native Java code using WSIF. But before moving on, it makes perfect sense to look at the pros and cons of all the three.

The pros and cons
Java Embedding: This is an out of box feature provided by BPEL to aid the developer to write and use Java snippets inside the BPEL environment. The greatest advantage is it lets the developer have full access to the entire BPEL environment. Consequently, direct manipulation of data inside the process is fairly easy. Add to it the ease of use, since you don't need to create auxiliary artifacts that you need with the other approaches, you are spared a lot of effort. On the flip side, it makes the BPEL code a little unreadable as you have mixed up Java with the BPEL tags. Use this to do seemingly simple tasks with short Java snippets.

SOAP Service: If you already have the Java code, wrapping it up as a SOAP service with JDeveloper is a peice of cake. Advantage is it lends a lot of reusability to the code and keeps your BPEL process clean. The disadvantage is that the reusability comes at a cost. You have to bear with the SOAP overhead, which can be tremendous especially if you are running a BPEL process that is swamped with SOAP calls. Use this when the service needs to be accessible from multiple machines and different BPEL processes or other applications.

WSIF: Without compromising much on readabiliy and resusability, WSIF provides a cleaner approach to use native code. By keeping the code separate from BPEL it makes sure that readability isn't sacrificed. Also, it calls the code directly, thereby eliminating the SOAP overhead altogether. Finally the code can easily be re-used by other BPEL processes by deploying the jar file containing the java classes and the WSDL document as part of a BPEL suitcase.

Prerequisites
Now that we have looked into the inherent positives and negatives of the three approaches, lets get ahead with the subject matter of this post - using WSIF to call java code. For the sake of demonstration, I shall use a Java class that takes a string as a parameter and concatenates it with another string. Here is code:

package com.nebulasky.blogspot;
public class ConcatString {

public ConcatString() { }
public String getConcatenation(String input)
{
return "Hello " + input;
}
}

Now, use JDeveloper and publish this as a J2EE service. Deploy and test it. Create a BPEL process and invoke this service. Fairly simple. Once these are done, we are all set to bring WSIF into the picture.

The WSIF file
To reiterate our purpose, we are going to tweak the BPEL to use WSIF to call the Java class instead of using SOAP. It makes sense to look at the WSDL file for the J2EE service. Of special interest is the binding section of the WSDL, since this tells our BPEL process how to call the service. I have omitted the rest of the file for simplicity, as they simply specify the data format for the messages. Here is an excerpt from the WSDL:

<binding name="ConcatenationSoapHttp" type="tns:Concatenation">
<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="getConcatenation">
<soap:operation soapAction="http://blogspot.nebulasky.com/getConcatenation"/>
<input> <soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/> </output> </operation>
</binding>

Notice that SOAP binding is being used (soap:binding, soap:operation , soap:body tags). All we need to do to persuade the BPEL to use WSIF is to change the binding information without changing the structure of the contract. As long as the contract is the same and references the same operations that the Java class exposes, and the messages in the contract are in conformance with the data types and parameters of the class, changing the binding will only change the way the BPEL communicates with the class, nothing else.

Definitions tag
Open the WSDL for the J2EE service in JDeveloper. Click on the source tab because you are going to edit it. Start by defining the two namespaces used by WSIF providers in the root element of the WSDL document, the tag. The format namespace is used to define the type mappings and the java namespace to define the operation mappings and the full name of the Java class:

<definitions name="Concatenation" targetNamespace="http://blogspot.nebulasky.com/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://blogspot.nebulasky.com/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:tns0="http://blogspot.nebulasky.com/types/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/" xmlns:java="http://schemas.xmlsoap.org/wsdl/java/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

Map Java types to XML Schema definitions
To generate Java to XML mapping we need to create XML facades. These façades are Oracle BPEL Process Manager's original Java-to-XML binding for WSIF. XML façades are a set of Java interfaces and classes through which you can access and modify XML data stored in BPEL variables in a relatively easy way using get/set methods. Here we need the mappings for the WSDL file for the J2EE service. For this, you need to use the schema compiler utility called schemac as:

C:\com\nebulasky\blogspot\>schemac Concatenation.wsdl

First, you indicate to the BPEL process that it is bound to native Java code and not to a SOAP service. This is how you do it:

<binding name="JavaBinding" type="tns:WSIFTestProcess">
<java:binding/>

Next, you specify that XSD types will be mapped onto Java types. For this use the format:typeMapping tag. Then you define what Java types shall be used for what xsd types by using the format:typeMap tag. Here is the snippet that does these two tasks for you:

<format:typeMapping encoding="Java" style="Java">
<format:typeMap typeName="xsd:string" formatType="String"/> </format:typeMapping>

Mapping Java methods to WSDL operations
The final step is now to map the Java method calls onto the WSDL operations. This is done using the java:operation tag to identify which Java method should be used to support a given operation:

<operation name="getConcatenation">
<java:operation methodName="getConcatenation"/>
<input/>
<output/>
</operation>
</binding>

Define the Service
We are through with most of it now. All that remains is defining the service. Here you will provide a Java address unlike a SOAP address which is how it was untill recently:

<service name="Concatenation"> <port name="JavaPort" binding="tns:JavaBinding">
<java:address className="com.nebulasky.blogspot.ConcatString"/>
</port>

Deploy the class
For it to work at runtime then the Process Manager must be able to find the Java classes referenced in the WSIF. When using WSIF the classpath for the invoked WSIF service is different to the classpath for the BPEL process. It is necessary to move the classes to the <BPEL_HOME>/system/classes directory. Here the classes are the the ones generated by the schemac command and the class responsible for the concatenation.

Test the process
If it is not already thus, ensure that the BPEL process takes the Concatenation.wsdl file from the current directory and not from the Web service itself. The bpel.xml file should look like this:

<partnerLinkBinding name="Concatenation"> <property name="wsdlLocation">Concatenation.wsdl</property>
</partnerLinkBinding>

Test the process. It should give you the expected result.

Tuesday, August 19, 2008

Security: Enabling SSL in OC4J

Securing the channel
Of the myriad ways to lend security to your enterprise, one that you certainly cannot afford to miss is securing the channel over which your partners communicate with you. An important step in this direction is configuring HTTPS on the OC4J. This is the subject matter of this post. Readers would do well to realize that this is not the final security enforcement point, but merely one among the plethora of policies that one must have in place.

Create a keystore
Your first step is to create a keystore (nothing but a repository of security certificates). Open command prompt and navigate to <JDEV_HOME>\jdk\bin directory. Now, use SUN's keytool to generate the keystore:

keytool -genkey -dname "CN=Sankash Thakuria, OU=Oracle, O=Fujitsu Consulting, L=Bangalore, S=Karnataka, C=IN" -keyalg RSA -sigalg Sha1WithRSA -keypass sankash -storepass sankash -keystore sankashkeystore.jks -alias nebulasky

Copy sankashkeystore.jks to <ORACLE_HOME>/j2ee/home/config.

Configure SSL in OC4J
The default behavior of the OC4J is to expose all resources (services) over HTTP, which is in turn is because of certain settings that are already in place in <ORACLE_HOME>/j2ee/home/config/default-web-site.xml file. We shall override this file to achieve SSL over HTTP. Create a copy of this file under the config directory and rename it as secure-web-site.xml. Open secure-web-site.xml in your favourite text editor and do the following:


  • Inside the <web-site> tag, change the port to 4443 and add the element secure="true".
  • Add <ssl-config> element and and point this to the newly created keystore.

Here is how the file will look like once these are done:

<web-site xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/web-site-10_0.xsd" port="4443" secure="true" protocol="ajp13" display-name="OC4J 10g (10.1.3) Default Web Site" schema-major-version="10" schema-minor-version="0" >

...

<ssl-config keystore="sankashkeystore.jks" keystore-password="sankash" />

...

<web-site>

Now, you need to make the OC4J aware of these changes. To do that, go ahead and open the server.xml file. Add the following to the file:

<web-site default="true" path="./default-web-site.xml" />

<web-site path="./secure-web-site.xml" />

In essence the secure-website.xml is the same as default-web-site.xml. Thus, all resources that were avaialble over HTTP will now become available over HTTPS. If you want some applications to be available only over HTTPS, you need to remove those applications from the default-web-site.xml. All applications are wrapped under the <web-app> tag.

Bounce OC4J and test

Restart the container and test. For instance, if the BPEL console was available over http://172.28.10.60:7777/BPELConsole it should now be also available over https://172.28.10.60:4443/BPELConsole provided the entry for the same exists in the secure-website.xml file.



Wednesday, August 6, 2008

Calling BPEL from PL/SQL

The UTL_HTTP package
Calling PL/SQL code from BPEL is a walk in the park. But what if you want to do the opposite? Is there a way? Well, fortunately, there is. Oracle 9i/10g comes intact with the UTL_HTTP package that can be used to access data on the Internet over the HTTP protocol. With a little tweaking you can leverage its functionality to call BPEL processes. And I shall show you exactly how to do it.

Declare variables
We declare the following PL/SQL variables

  • request_envelope VARCHAR2(30000): This is the SOAP request that will be sent to the BPEL process
  • response_envelope VARCHAR2(30000): The response message relayed back by the BPEL process after the request has been successfully served
  • http_request utl_http.req: The PL/SQL abstraction of the HTTP request sent to the web server
  • http_response utl_http.resp: The PL/SQL abstraction of the HTTP respone delegated to the caller
The SOAP message
Since SOAP is widely recognised as an industry standard to communicate with services avaialble over the internet, your first task is to create the message. For the sake of convinience, I shall assume that there is a synchronous BPEL process in place that accepts a string as input and concatenates the string with 'Hello' - a typical HelloWorld BPEL process. Initialize the request_envelope variable with the SOAP message as shown below

request_envelope :=
'<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header/>
<soap:Body xmlns:ns1="http://xmlns.oracle.com/HelloWorld">
<ns1:HelloWorldProcessRequest>
<ns1:input>Sankash</ns1:input>
</ns1:HelloWorldProcessRequest>
</soap:Body>
</soap:Envelope>';

BEGIN_REQUEST
BEGIN_REQUEST begins a new HTTP request. When the function returns, the UTL_HTTP package has established the network connection to the target Web server, and has sent the HTTP request line. This function takes three parameters which are

  • url : The end-point for the service you wish to invoke. This will typically be the URL of the BPEL process
  • method : POST or GET.

The "GET" method is suitable for non-parameterized URLs or for URLs with a manageable volume of parameter name-value pairs. The maximum length of the URL string is limited by the capacity of the PL/SQL VARCHAR2 variable used to pass it.

The "POST" method is suitable for parameterizing the request with an arbitrarily large volume of data, especially for example as might be the case when the request is expressed as an XML document.

  • http_version : the version of HTTP like 1.0 or 1.1 etc
In our case this function will look like

http_request :=
utl_http.begin_request(
url => 'http://172.28.0.54:7777/orabpel/default/HelloWorld/1.0', method => 'POST', http_version => 'HTTP/1.1');

Header information
The next step is to set the header information. For this we shall use SET_HEADER function. This function sets a HTTP request header. The request header is sent to the Web server as soon as it is set. The function takes three parameters which are

  • r : The http request object
  • name : The header name
  • value : The header value
In our case we need to set the values for Content-Type, Content-Length and SOAPAction to complete the header. This is done as follows

utl_http.set_header(
r => http_request,
name => 'Content-Type',
VALUE => 'text/xml');

utl_http.set_header(
r => http_request,
name => 'Content-Length',
VALUE => LENGTH(request_envelope));

utl_http.set_header(
r => http_request,
name => 'SOAPAction',
VALUE => 'process');

WRITE_TEXT
This function writes text data in the HTTP request body. As soon as some data is sent as the HTTP request body, the HTTP request headers section is completed. Text data is automatically converted from the database character set to the request body character set. This function takes two parameters

  • r : The http request object
  • data : The text data that forms the request. In our case this is the SOAP message

This is how we will call this function

utl_http.write_text(r => http_request, data => request_envelope);

GET_RESPONSE
This procedure reads the HTTP response. When this procedure returns, the status line and the HTTP response headers have been read and processed. The status code, reason phrase and the HTTP protocol version are stored in the response record. We shall call this in the following way

http_response := utl_http.get_response(r => http_request);

READ_TEXT
This reads the HTTP response body in text form and returns the output in the caller-supplied buffer. The end_of_body exception will be raised if the end of the HTTP response body is reached. Text data is automatically converted from the response body character set to the database character set. It takes two parameters

  • r : the HTTP response object
  • data : the text data of the response. In our case this is the SOAP response
We shall use this function in the following way

utl_http.read_line(r => http_response, data => response_envelope);

END_RESPONSE
This ends the HTTP response. This completes the HTTP request and response cycle. The function takes only one parameter which is the HTTP response object.
Use it like this

utl_http.end_response(http_response);

Handle Exceptions
To take care of any inadvertent exceptions that may arise we embed the following exception handling block in our code

EXCEPTION
WHEN utl_http.end_of_body
THEN utl_http.end_response(http_response);
WHEN utl_http.request_failed THEN
DBMS_OUTPUT.PUT_LINE('Request Failed: ' utl_http.get_detailed_sqlerrm);
WHEN utl_http.http_server_error THEN
DBMS_OUTPUT.PUT_LINE('Server Error: ' utl_http.get_detailed_sqlerrm);
WHEN utl_http.http_client_error THEN
DBMS_OUTPUT.PUT_LINE('Client Error: ' utl_http.get_detailed_sqlerrm);
WHEN others THEN
DBMS_OUTPUT.PUT_LINE(sqlerrm);

Gotchas
So far so good. But when you try to read the output you in your PL/SQL code you are almost certain to get this error, because in most of the cases the output from the BPEL process will be verbose.

ORA-20000: ORU-10028: line length overflow, limit of 255 chars per line

This is because DBMS_OUTPUT.PUT_LINE can write a maximum of 255 characters in one line as the error says. Thus you will have to break the output into multiple lines. To get round this problem I shall use the following piece of code. This restricts the number of characters per line to 255. Extra characters are passed onto the next line.

FOR i IN 1 .. MOD(LENGTH(response_envelope), 255)
LOOP
DBMS_OUTPUT.PUT_LINE(SUBSTR(response_envelope, j, 255));
j := j + 255;
END LOOP;

That is all. Check the BPEL console to ensure that the process was successfully initiated.