Monday, November 26, 2012

more notes on java embedding

I noted in the past on BPEL java embedding http://yuanmengblog.blogspot.com/2012/04/few-bpel-java-embedding-notes.html

here are some additional notes:

1. importing syntax:

I'm using BPEL 2.0 this time. This is the importing syntax I'm using now, not sure if it's BPEL 2.0 thing. For sure it's different from my previous post:

add imports right above partner links and right below name spaces.


  <import location="oracle.xml.parser.v2.XMLElement" importType="http://schemas.oracle.com/bpel/extension/java"/>      
  <import location="java.io.File" importType="http://schemas.oracle.com/bpel/extension/java"/>      

2. Two ways to get and set variables:

2.1. getting and setting string variables:
   nothing fancy, you can do straight:
    String foo = (String) getVariableData("foo");
    setVariableData("foo", "bar");

2.2. If you need to get to an Xpath in an element, then you have to do something like

XMLElement srcElem = (XMLElement) getVariableData("inputVariable", "payload", "/client:foo/client:bar");      
String bar = srcElem.getTextContent();      

remember you need to add "import" like in step 1. 

3. Gotcha's

Although it's very tempting, don't do this:
   String srcElem = (String) getVariableData("inputVariable", "payload", "/client:foo/client:bar");   
it doesn't work that way.

If you don't want to deal with the hassles of "importing" and casting, here is a recommended way to go around it. 
Using above example:
 a) create a BPEL string variable, call it "bar"
 b) inside BPEL, assign ("inputVariable", "payload", "/client:foo/client:bar") to the "bar" variable
 c) inside your java embedding, you can use get/set freely on "bar", just like in step 2.1 above.

Wednesday, November 21, 2012

"Teach" JDEV where to look for MDS artifacts

A common task with JDEV is to tell it where to find the MDS connection. If JDEV fails to find MDS, then you may get errors like:

  • Error: Error in getting XML input stream: oramds:/apps/xsd/foo.xsd: oracle.mds.exception.MDSException: MDS-00054: The file to be loaded oramds:/apps/xsd/foo.xsd does not exist. 
There might be many reasons for this error. One possible reason could be that JDEV does not know where to look for MDS. JDev uses ad-config.xml to look for MDS connections.


Assume you use DB based MDS, here is how I give JDev a "jolt" and make it to learn:

1. make sure you have a DB connection points to your MDS schema, create one if needed (default schema name is "DEV-MDS")
2. make sure you have your MDS connection in the resource panel, create a new MDS connection if needed and point to your DB connection above

3. finally, create a dummy SOA project, called it "junk", "dummy" or anything, create it with a BPEL process, on the BPEL process screen do these steps:
  1) click on the search glass for input schema
  2) click on search schema in "Type Chooser" popup window
  3) click on search glass in "Import Schema File" popup window
  4) select "Resource Palette" in "SOA Resource Browser" popup window
  5) find your MDS connection, and drill down to where you stored your XSD
  
pick a XSD and any element, pretend you need to use it for your "junk" project input, save your project. That should do it. We just gave JDev a "jolt", it should know where to find your missing MDS artifacts now.

 Now go back and open your adf-config.xml again, you should see the file has picked up a new entry for your MDS connection.

Thursday, November 1, 2012

OSB, http basic authentication and OWSM policy

OWSM and OSB are bundled together after-fact. So OSB doesn't support some of the security policies that comes with OWSM.

However, it is misleading that OSB allows you to attach any OWSM policy to your proxy,but  that doesn't mean it will actually work. It took me a while to find out that the simplest of all: OWSM "wss_http_token_service_policy" does not work in OSB!

However, not all is lost. OSB actually supports http basic authentication out of box without OWSM. You just need to go to "HTTP Transport Configuration" tab in your proxy configuration page, check that "basic authentication" checkbox.

Then the caller needs to add a HTTP header like:
     Authorization: Basic d2VibG9naWM6d2VsY29tZTE=
where d2VibG9naWM6d2VsY29tZTE= is base64 encoded user:password, in this example, it's "weblogic:welcome1". You are not required to encode it, but it's the common practice.

You can base64 encode your stuff online from here: http://www.base64decode.org/

that's all.

Thursday, October 25, 2012

importing OSB projects into Eclipse

Sometimes our OSB Eclipse projects get corrupted, or sometimes you need to create new workspace from existing source code (from project source code control).

Here are steps I use:

I'll assume your entire OSB source is under a folder call "c:/osb".

0. back up your osb folder (if you used it for an existing workspace), e.g. rename it osb.bak
1. create new folder "c:/osb"
2. check out your source files under "c:/osb", e.g. ("my config proj", "my proj1", "my proj2")
    or copy your backed project files if you backed them in step 0
3. fire up eclipse, switch to OSB pespective, and create a new workspace under "c:/osb"
4. select "file", "import", "general", then "existing projects into workspace"
5. pick your "c:/osb" folder, check and uncheck the projects you want
6. import them
7. it may whine about your .svn, or .vss files, you can ignore them, or you can google it up, i believe there is way to mask off those warnings in Eclipse preference, i just don't remember how
8. if you happen to see one of the projects showing error saying it doesn't have an associated OSB configuration project, just drag that project in Eclipse "project explorer" panel, and drop it into your OSB configuration project.

hope that takes care of everything.

Friday, October 19, 2012

PGP and SOA

My environment:
      SOA 11.1.1.6
      Java 1.6.x
Goal:
      sftp adapter to grab a PGP encrypted file, then decrypt the file in the SOA composite then process the data. You will be supplied with a PGP private key file (binary key ring, or ascii key), and pass phrase to decode the file.

My solution:
     use java embedding to decrypt PGP file. In essence, it's a Java solution.

Java part:

Here is how to do it in Java:
1. go to Bounce Castle to download the latest jars


Download
 bcpg-jdk15on-147.jar 
bcprov-jdk15on-147.jar 

2. online resource to use the package to encrypt/decrypt:


3. I added a simple main() to the above PGPFileProcessor class:

public static void main(String args[]) throws Exception
{
   PGPFileProcessor pgp = new PGPFileProcessor();

   //pgp.setAsciiArmored(true); // if you want dump ascii file
   // hard code for my test
   pgp.setInputFileName("c:/pgp/java/sample_file.txt");
   pgp.setOutputFileName("c:/pgp/java/sample_file.txt.pgp");
   pgp.setPublicKeyFileName("c:/pgp/java/mypgp-pub.key"); //can be either binary or text key
   pgp.encrypt();

// decrypt the same file
   pgp.setInputFileName("c:/pgp/java/sample_file.txt.pgp");
   pgp.setOutputFileName("c:/pgp/java/sample_file-decrypted.txt");
   pgp.setSecretKeyFileName("c:/pgp/java/mypgp-pri.key"); // can be either binary or text key
   pgp.setPassphrase("mypassword");
   pgp.decrypt();
}

3. set your class path to include the jars in step 1, and compile java files from step 2

4. if you get java exceptions like:
PGPKeyRingTest: exception: java.security.InvalidKeyException: Illegal key size

You may need to download

Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files 6


save the jars to “C:\java\jdk1.6.0_31\jre\lib\security”. Backup local_policy.jar, and US_export_policy.jar first!


5. package the compiled classes into a jar, let's call it mypgp.jar

Add Java to the composite:

1. copy  bcpg-jdk15on-147.jar, bcprov-jdk15on-147.jar and mypgp.jar (you just generated) to two locations (you need to figure out your own soa environment)
C:\Oracle\Middleware\Oracle_SOA1\soa\modules\oracle.soa.ext_11.1.1
and
C:\Oracle\Middleware\user_projects\domains\soa_domain\lib


For the first copied location, there is build.xml in that directory already, you need to run "ant" command in that directory. If you don't want to run "ant" command, you can also unjar your files into the "classes:" sub directory.
After you finish that, you need to bounce the entire SOA suite (including weblogic server).

2. code embedded java:
            <![CDATA[System.out.println("**********new pgp");      
pgp.test.com.PGPFileProcessor pgp = new pgp.test.com.PGPFileProcessor();      
      
System.out.println("*end *********new pgp");      
     
XMLElement srcElem = (XMLElement) getVariableData("inputVariable", "payload", "/client:myReqeust/client:srcFile");    
String srcFile = srcElem.getTextContent();    
String tgtFile = srcFile.substring(0, srcFile.lastIndexOf(".pgp"));    
      
args[0] = ;      
args[1] = ;      
      
      
pgp.setInputFileName(new String("/soaIntegration/pgp/receive/") + srcFile);      
pgp.setOutputFileName(new String("/soaIntegration/pgp/process/") + tgtFile);      
pgp.setSecretKeyFileName("/soaIntegration/pgp/pri-key.key");      
pgp.setPassphrase("mypassword");      
      
try {      
pgp.decrypt();      
}      
catch(Exception e)      
{      
  System.out.println("###PGP decryption failed:"+e.getMessage());      
}]]>

Additional: generate your own key pairs for test or for fun

What if you want to generate your own key pairs for test?  Here is what I did:
download "bcpg-jdk15on-147.zip" with source, then find this file PGPKeyRingTest.java in package org.bouncycastle.openpgp.test.

I modify generatetest() like below:
    public void generateTest()         throws Exception
    {
System.out.println("********* intercepted ********");
        char[]              passPhrase = "hello".toCharArray();
        KeyPairGenerator    dsaKpg = KeyPairGenerator.getInstance("DSA", "BC");
        dsaKpg.initialize(512);
...
PGPPublicKeyRing        pubRing = keyRingGen.generatePublicKeyRing();
        PGPPublicKey            vKey = null;
        PGPPublicKey            sKey = null;

  byte[] b = null;
            ByteArrayOutputStream baos = null;
            ArmoredOutputStream aos = null;
            try {
                    baos = new ByteArrayOutputStream();
                    aos = new ArmoredOutputStream(baos);
                    // get public key
                    pubRing.encode(aos);
                    aos.flush();
                    baos.flush();
                    aos.close() ;
                    b = baos.toByteArray();
                    System.out.println(new String(b));

                    baos = new ByteArrayOutputStream();
                    aos = new ArmoredOutputStream(baos);
                    // get private key
                    keyRing.encode(aos);
                    aos.flush();
                    baos.flush();
                    aos.close() ;
                    b = baos.toByteArray();
                    System.out.println(new String(b));

            } catch (Exception e) {
                    System.out.println("Exception caught while exporting SecretKeyRing"+ e);
            } finally {
                    aos.close();
                    baos.close();
            }
of course, i modified performTest() only to run generatetest().

you need to add bctest-jdk15on-147.jar to the classpath to run the above class. 

If you get java exceptions compiling or running, check step 4 above in the Java section.

There you go, you'll get your own public and private keys to play with (remember your password is "hello" in the above code, you can change it if you like).

PGP Command Line

BTW, if you happen to have the PGP command line from old PGP Corporation (currently owned by Symatec), you can generate your own keys, and test encryption and decryption from the command line.

To generate key:
   pgp --gen-key "foo@bar.com" --key-type rsa --bits 2048 --passphrase car

export the key:
     pgp --export-key-pair foo

To test encryption/decryption:
  pgp -e test.txt --recipient foo (or pgp -e test.txt --recipient foo --armor)

  pgp --decrypt test.txt.pgp  --passphrase "car"--output foo.txt

if you wonder where pgp command line stores key ring files, they are under here on windows: C:\Documents and Settings\yourUserName\My Documents\PGP. I was using the binary key rings initially before I figured out the export commands.

That's all

I assumed anyone reading this post has the basic idea how PGP works. What I demonstrated is how to use Java to decrypt a PGP file, and add the java solution to SOA composite. 





Thursday, October 11, 2012

OSB alert and report activities

I normally use "alert" to trace my message flows. Occasionally, I use "report".

Here is my personal view of pros and cons.

with "alert", you can drill down to the detail in 2 clicks. Once on the main "home" or "pipeline alerts" tab on the main console, then click on the actual alert. However, the "alert" title can't show any variable values. If you have 20 calls coming in, you have an "alert" that shows "id", then the subject of all those alerts will all show "id". You have to drill down to see the detail.

With report, you can put a key value, and report main page will show the entry with the actual value of the "id" from your payload. The good thing is you can see multiple entries with different ID's. However, in order to see the detail, you have to drill it twice more. Click on the "id" entry, then click on the "details" to see more.

Here is an example of my report entry:

I have a payload body looks like:


<ins:CisPidsRtCollection xmlns:ins="http://xmlns.oracle.com/pcbpel/adapter/db/top/insertRTPids">
     <ins:CisPidsRt>
        <ins:pid>123</ins:pid>
    </ins:CisPidsRt>
</ins:CisPidsRtCollection>

in my report, I can add expression like $body, then above payload will show in the "detail" link. I can also add a key "pid". Look closely, "pid" is an actual element inside the payload, then in the value section, i put in path as "ins:CisPidsRtCollection/ins:CisPidsRt/ins:pid", and variable as "body", then the report entry will show "pid=123".

OSB "publish" activity

Long story short, here is how I made my "publish" to work.

Assign "body" with this


<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    <myBizPayload xmlns="blah">
        <blah>and</blah>
    <myBizPayload >
</soapenv:Body>

where <myBizPayload>...</myBizPayload> is the actual payload when you invoke your business service. You can find the biz service payload by popping up the OSB debug console on the Biz service, it will fill in a default payload for you.

Make sure you include soap <Body> as the wrapper, no more and no less. If you assign the wrong payload, OSB won't spit out a clue anywhere, it simply ignores your call and move on to the next activity!!!

Keep in mind that all variables inside "publish" block are local. You can make changes to any variable: body, inbound, outbound etc, they are all local copies. Any changes you make do not affect the variables outside "publish".

It's simple but very important to remember, you "publish" with the "body" variable. It beats why Oracle (or BEA doc for that matter) doesn't mention that anywhere. I had to figure out it trial and errors for hours: twice and a few years apart. Hence, this post. And I don't want to relearn this again.