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.