Showing posts with label SOA. Show all posts
Showing posts with label SOA. Show all posts

Wednesday, April 24, 2013

Unix file permission when file adatper generates the output file

When use file adapter to write a file on Linux, what is the permission of the output file?

The common assumption is it is determined by the umask of the user who owns the “Weblogic” java process. If a user runs startWeblogic.sh from the command line, then that user is the owner of Weblogic processes (many places use “oracle” or “weblogic” as the user to start webogic processes).

For the discussion, let’s assume the owner of “weblogic” logic process is “webadmin”. We need to generate an output file with “664” permission. However, we keep getting 644.
We double checked “webadmin” user has 002 umask. We also tried to play with the umask settings in startWeblogic.sh script to no avail.

So it’s gloves off time, I added java embed to change the output file permission by calling “setWrtiable(true, false)”, and that, opened another can of worms.
To my surprise, I stumbled on another unexplainable file adapter behavior. After the file adapter finished writing the file (with 644 permission), if I use java embed to open the file, and do any operations on the file (even just read it), then it TRUNCATES the output file. I thought it has to do with the transaction, so I tried to call check_point() before I open the file in java. It made no difference.

In the end, I just skipped the file adapter, use java embedding to generate the output file, then set the permission. Here is the snippet:
        try {                   
                String content = (String)getVariableData("csvOutput");   // grab file content                       
                String fileName = (String)getVariableData("fileName"); 
                fileName = "/output/"+fileName;
                FileWriter fstream = new FileWriter(fileName);
                BufferedWriter out = new BufferedWriter(fstream);
                out.write(content+"\r\n");
                out.close();
                                               
                java.io.File f = new java.io.File(fileName);
                f.setWritable(true, false);  // set permissions
                f.setReadable(true, false);
        }      catch(Exception e)      {
                System.out.println("*****file exception:"+e.getMessage());
        }

 There is an Oracle Note - 1430075.1 that covers the same issue. Oracle recommendation is to use java embedding, then do
   System.exec(“chmod…”);
I didn’t try that. Not sure how it works. Hope it doesn’t truncate the output file.

Friday, January 4, 2013

Rolling soa_server.out log file

SOA server keeps many logs. They are mostly WLS logs, such as soa_sever1.log, osb_server1.log etc. All of these files can be configured to auto roll. Except soa_server1.out.

Strictly speaking, soa_server1.out is not really WLS "log" file. If you start SOA server from a command window, by default the standard output spits all the messages in the command Window. When you start SOA server via node manager, the standard output get redirected to soa_server1.out. Since standard output is not really a log file, you cannot configure WLS to roll this file. Over time, soa_server1.out can grow very big and cause problems. 

I'm sure many people have their solutions to deal with the issue. Here is a cheat I figured out that can achieve the effect of "rolling" soa_server1.out.

Write a simply script:

  cp soa_server.out soa_server.out_$(date +%b)_$(date +%d)_$(date +%Y)"
  echo > soa_server.out

the first command backs up the file, 2nd command truncates the file, but still keep the same file. SOA is happy to to dump data into the same "log" file. Use cron to schedule the script to run, that should be it.

One reminder, i used cp in the first step. Then truncate the file in 2nd step. I also attempted in the first step to rename soa_server1.out file, then "touch soa_server1.out" to create a new log file. It doesn't work that way. SOA server obviously has got its mind somewhere, it doesn't like you to rename the log file. Even if you create a new soa_server.out, it won't write to the new file.



Monday, December 10, 2012

Stuck: cannot undeploy SOA composite

You ever run into the problem that you cannot redeploy or even undeploy an SOA composite? It can be frustrating. The most common reason is that the composite references an URL doesn't exist anymore. I think it's almost "stupid" to require that a composite referenced URL to exist when you need to undeploy a composite, come on, i don't even want the composite anymore, why do i care if it references a non-existent URL.

Anyway, here is a sample scenario how you might get stuck, and how you can try to un-stuck yourself.


1. an previously deployed SOA composite references an URL, say on OSB, http://localhost:8011/blah, Now that URL doesn't exist on osb anymore.

2. When you try to redeploy the composite from jdev, it won't re-deploy, complains http://localhost:8011/ext/blah not exist

3. try un-deploy bpel from EM console, get the same error, so BPEL needs 8011/blah to exist even for straight un-deploy or retire

4. fix: go to osb to temporarily (remember to change it back after!!!) enable 8011/blah, then un-deploy BPEL from EM console

5. deploy BPEL from JDEV

6. if it still doesn't work, switch back the temporary change on OSB, and try to deploy to a new composite version, such as 2.0.

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.

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, September 27, 2012

Adding custom java classes to SOA

1. go to SOA ext folder, in my case: C:\Oracle\Middleware\Oracle_SOA1\soa\modules\oracle.soa.ext_11.1.1

2. you have two ways to do it:

2.1 explode your jars under "classes" sub folder here
2.2 copy the jar files in this folder, then in command prompt, run "ant" (this folder should have a default build.xml file), it basically does some magic and your jars will be included in SOA. As for the "magic", I believe it simply updates oracle.soa.ext.jar file and modified the "Manifiest" under "META-INF", set something like "Class-Path: yourCustomer.jar classes/"

Keep in mind, that push to shove, you may also have to add the same jar to  "$DOMAIN_DIR/lib", that you  just drop the file in.

I experienced problem before that merely putting jar in "racle_SOA1\soa\modules\oracle.soa.ext_11.1.1" works fine for SOA run time (with your BPEL referencing the class in the jar). However, if you don't copy the same file under "$DOMAIN_DIR/lib", you cannot re-deploy your BPEL composite that referencing the custom class. Because BPELCompiler, 2nd pass compilation (during the composite deployment),  seems to require the jar to be in "$DOMAIN_DIR/lib" folder. Go figure...

Wednesday, September 12, 2012

Extracting and Passing WSS Name Token Security Header in BPEL

How to extract and insert SOAP headers in BPEL 2.0 is documented in the Oracle doc here http://docs.oracle.com/cd/E12839_01/integration.1111/e10224/bp_manipdoc.htm#SOASE415 However, like all Oracle docs, it takes some hands on finessing to figure out the specifics.

Additionally, for WSS security tokens, I have to dance around the WSS security XSD files in order to get it to work. It may not be the best way, but it seems to work.

Let's look at how to extract SOAP headers in BPEL. As Oracle document indicates, it takes two steps. You need to be very precise with each step, otherwise, you won't see the headers inside BPEL.

Step I -  update the WSDL - the Oracle document provides an excellent sample with multiple headers, it just needs some more detailed descriptions. Let me copy the sample here:
<!-- custom header -->
   <message name="CustomHeaderMessage">
    <part name="header1" element="tns:header1"/>
    <part name="header2" element="tns:header2"/>
  </message>
  <binding name="HeaderServiceBinding" type="tns:HeaderService">
    <soap:binding style="document"
      transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="initiate">
      <soap:operation style="document" soapAction="initiate"/>
        <input>
          <soap:header message="tns:CustomHeaderMessage"
            part="header1" use="literal"/>
          <soap:header message="tns:CustomHeaderMessage"
            part="header2" use="literal"/>
          <soap:body use="literal"/>
        </input>
    </operation>
  </binding>

Step 1.1 - define the messages to enclose the header elements to be passed in SOAP header. 
Notice that in the <!-- custom header --> section, The CustomHeaderMessage has two parts.  In order to pass in multiple SOAP headers, each SOAP header needs to be included as a part in this message.

The part names are "part1" and "part2". Although not critical, in the real world, you should give them some more meaningful part names.

Although obvious, it is still worth noting that these elements need be defined somewhere or imported from somewhere. For example, in your schema "header1" may hypothetically defined as:

<element name="header1">
<complexType>
<sequence>
<element name="fristName" type="string"/>
<element name="lastName" type="string"/>
</sequence>
</complexType>
</element>
In the case of WSS security header, I have to import a few related XSD's - see details below.

Step 1.2 - update the operation in the binding section

The Oracle sample may not look like the typical BPEL WSDL, so here is the changes I made to my WSDL:

<wsdl:operation name="process">
<wsdl:input  message="client:fooBPELRequestMessage">
<soap:header message="client:securityHeaderMsg"  part="payload" use="literal"/>
<soap:header message="client:fooBPELResponseMessage"  part="payload" use="literal"/>
</wsdl:input>
<wsdl:output message="client:fooBPELResponseMessage"/>
</wsdl:operation>

Here I am passing two SOAP headers. Keep in mind, very importantly, in Step 1.1, these two headers need be declared in a single message as two parts.

Step II - Receive (extract) headers in BPEL

Step 2.1 - define a message-type variable using the CustomHeaderMessage

    <variable name="customHeaderVar" messageType="client:customHeaders"/>

Step 2.2 - update receive activity
  <receive name="receiveInput" 
partnerLink="foobpel_client" 
portType="client:fooBPEL" 
operation="process" variable="inputVariable" 
createInstance="yes" 
bpelx:headerVariable="customHeaderVar"/>
There you go, customHeaderVar will contain the SOAP header values if you pass them in. That's a big "if", because you do not pass the headers in your SOAP call, or do not pass them in correctly, you still won't receive the headers, although it causes no harm to the receive activity even if you don't pass the headers in yours SOAP call.

In my case, I am only interested in the WSS security header, so I first define a "security" variable:
   <variable name="SecurityVar" element="ns2:Security"/> 
where ns2 is xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
then I pick up the WSS header:
    <assign name="AssignCustomHeader">
      <copy>
        <from>$customHeaderVar.payload1</from>
        <to>$SecurityVar</to>
      </copy>
    </assign>

Step III - passing SOAP headers in BPEL invoke activity

Finally, I can pass in the WSS security header in the invoke:

     <invoke name="InvokeBar"
                partnerLink="fooCallsBar" portType="ns1:barBPEL"
                operation="process" inputVariable="Invoke_process_InputVariable"
                outputVariable="Invoke_process_OutputVariable"
                bpelx:invokeAsDetail="no" bpelx:inputHeaderVariable="SecurityVar"/>

The WSS Security XSD Conundrum 

I couldn't effectively importing WSS security XSD remotely, it takes forever for JDEV to drill down the WSS security element structure, so I ended up copying these 3 files locally:
"oasis-200401-wss-wssecurity-secext-1.0.xsd", 
"oasis-200401-wss-wssecurity-utility-1.0.xsd" 
"xmldsig-core-schema.xsd"
I had to comment out this line in the first file, so it won't bring my house down 
<!--xsd:import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/-->

Here is my entire WSDL:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="fooBPEL"
             targetNamespace="http://xmlns.oracle.com/cis/foo/fooBPEL"
             xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
             xmlns:client="http://xmlns.oracle.com/cis/foo/fooBPEL"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
             xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype">
<wsdl:types>
<schema xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://xmlns.oracle.com/cis/foo/fooBPEL" schemaLocation="xsd/fooBPEL.xsd" />
<import namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
                        schemaLocation="xsd/oasis-200401-wss-wssecurity-secext-1.0.xsd" />
</schema>
</wsdl:types>
<wsdl:message name="fooBPELRequestMessage">
<wsdl:part name="payload" element="client:process"/>
</wsdl:message>
<wsdl:message name="fooBPELResponseMessage">
<wsdl:part name="payload" element="client:processResponse"/>
</wsdl:message>
<wsdl:message name="securityHeaderMsg">
<wsdl:part name="payload" element="wsse:Security"/>
</wsdl:message>
<wsdl:message name="customHeaders">
<wsdl:part name="payload1" element="wsse:Security"/>
<wsdl:part name="payload2" element="client:processResponse"/>
</wsdl:message>
<wsdl:portType name="fooBPEL">
<wsdl:operation name="process">
<wsdl:input  message="client:fooBPELRequestMessage">
                                <soap:header message="client:securityHeaderMsg"  part="payload" use="literal"/>
                                <soap:header message="client:fooBPELResponseMessage"  part="payload" use="literal"/>
                        </wsdl:input>
<wsdl:output message="client:fooBPELResponseMessage"/>
</wsdl:operation>
</wsdl:portType>
<plnk:partnerLinkType name="fooBPEL">
<plnk:role name="fooBPELProvider" portType="client:fooBPEL"/>
</plnk:partnerLinkType>
</wsdl:definitions>

Here is the SOAP UI test payload:

soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:foob="http://xmlns.oracle.com/cis/foo/fooBPEL">
   <soapenv:Header>
    <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsse:UsernameToken>
         <wsse:Username>weblogic</wsse:Username>
         <wsse:Password>welcome1</wsse:Password>
      </wsse:UsernameToken>
   </wsse:Security>
   <processResponse xmlns="http://xmlns.oracle.com/cis/foo/fooBPEL">
      <result>this is my header</result>
   </processResponse>
   </soapenv:Header>
   <soapenv:Body>
      <foob:process>
         <foob:input>SOAPUI invokes foo</foob:input>
      </foob:process>
   </soapenv:Body>
</soapenv:Envelope>

Snippet of BPEL source:


         xmlns:ns2="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
  ...
  <variables>
    <variable name="inputVariable" messageType="client:fooBPELRequestMessage"/>
    <variable name="outputVariable" messageType="client:fooBPELResponseMessage"/>
    <variable name="Invoke_process_InputVariable"
              messageType="ns1:barBPELRequestMessage"/>
    <variable name="Invoke_process_OutputVariable"
              messageType="ns1:barBPELResponseMessage"/>
    <variable name="SecurityVar" element="ns2:Security"/>
  </variables>

  <sequence name="main">

    <!-- Receive input from requestor. (Note: This maps to operation defined in fooBPEL.wsdl) -->
    <receive name="receiveInput" partnerLink="foobpel_client" portType="client:fooBPEL" operation="process" variable="inputVariable"
    createInstance="yes" bpelx:headerVariable="customHeaderVar"/>
    <assign name="AssignCustomHeader">
      <copy>
        <from>$customHeaderVar.payload1</from>
        <to>$SecurityVar</to>
      </copy>
    </assign>
    <assign name="AssignBarInput">
      <copy>
        <from>"knock, knock, foo's calling"</from>
        <to>$Invoke_process_InputVariable.payload/ns1:input</to>
      </copy>
    </assign>

    <invoke name="InvokeBar"
            partnerLink="fooCallsBar" portType="ns1:barBPEL"
            operation="process" inputVariable="Invoke_process_InputVariable"
            outputVariable="Invoke_process_OutputVariable"
            bpelx:invokeAsDetail="no" bpelx:inputHeaderVariable="SecurityVar"/>






Wednesday, August 22, 2012

BPEL Wait, it's synch vs. asynch?

In BPEL process if you use "wait", the result may depend on if it's synch or asynch. I found it out the hard way. I suspect it's documented somewhere by Oracle. I just haven't found it.

Synch: if you use "wait" for 3 seconds in a synch BPEL, you'll get a time out exception. I don't know why it does that. If you wait for 1 or 2 seconds, it simply ignores the wait. That's because the server uses "MinBPELWait" as the threshhold, the default is 2 sec.

Asych: works without any problem.

If you are too deep into your "synch" BPEL process, and doesn't want to start allover, just go to your WSDL, take out the "output" in your operation. Then go to your BPEL, take out the last reply. That converts your synch into "one-way", essentially it's almost the same as "asynch", you just don't have the callback operation.

Additionally, you can go clean out the synch response message etc. Or you can add callback in the WSDL to make it asynch.


Saturday, October 15, 2011

Deployment Plan File not Taking Effect?

I suppose there can be many reasons that the deployment file plan does not work properly.

I ran into a perticular situtation where my deployment plan file won't take effect, so all my replacement strings have no effect. It baffled me for a long time. I accidentally figured out the reason today.

In my particular case, I have an AIA EBS process, which uses mediator to route services. So there is no XSD and no WSDL for the project. So the generated plan file has this section at the bottom:
   <wsdlAndSchema name="">
      <searchReplace>
         <search/>
         <replace/>
      </searchReplace>
   </wsdlAndSchema>
I think the empty "name" attribute renders the plan file invalid, therefore it won't take effect. I simply changed it to 
   <wsdlAndSchema name="NONE">
that did the trick for me. With that change, my plan file worked without problem.