Wednesday, July 11, 2012

AIA Error Handler Email Config Tricks


I had to chase down a problem with an AIA error handler failing to send email today. Boy, it has been a few months since I last touched it. Everything got blurry. I had to relearn quite a bit. Let me document the tricks before I forget again.

1.      First of all, .under {AIA instance home}/AIAMetaData/config (e.g. /app/oracle/product/fmw/AIACCB/aia_instances/AIACCB/AIAMetaData/config)
make sure the two XML files are configured correctly.
2.      Follow this link to update the AIA config: http://docs.oracle.com/cd/E17904_01/doc.1111/e17364/bldgintflows.htm#BACEGBEJ
(1)    Browse to the folder at $AIA_HOME/aia_instances/$INSTANCE_NAME/bin.
(2)    Source the file aiaenv.sh by executing the following command:
source aiaenv.sh
(3)    Browse to the folder at $AIA_HOME/aia_instances/$INSTANCE_NAME/config and open the deployment plan file, UpdateMetaDataDP.xml.
(4)    Update the file UpdateMetaDataDP.xml by inserting include tags for each resource group that you want to add to the MDS:

a.      To upload all the files under "AIAMetaData", add the following:
<include name ="**"/>
b.      To upload the files copied to "AIAComponents/ApplicationObjectLibrary/SEBL/schemas" folder, add the following:
<include name ="AIAComponents/ApplicationObjectLibrary/SEBL/schemas/**"/>
Note:
In the include tag, the folder path must be relative to the folder AIAMetaData.
(5)    Browse to AIA_HOME/Infrastructure/Install/config. Execute the script UpdateMetaData.xml by typing the command:
ant -f UpdateMetaData.xml
3.      (Trick 1) Due to an AIA bug, when you run (5) above, make sure {AIA home}/lib/aia.jar (/app/oracle/product/fmw/AIACCB/aia.jar) is available. HOWEVER, after you finish step (5), make sure you hide that aia.jar (rename to aia.jar.bak), then bounce your SOA server! It’s ironic that you have to hide aia.jar in order for AIA to work! BUT, remember next time when you need to run AIA update again, step (5) above, make sure you unhide your aia.jar in order for the update to work. Also, double check on step (4) carefully, I burned several hours in the past due to a careless file path problem in the XML file on step (4).

4.      (Trick 2) Say, you set up your error tables, for that “Role” column, you enter the user name (e.g. “foo”) that will receive the email notifications. According to AIA doc, you need to configure that user’s email under {your AIA URL}/sdpmessaging/userprefs-ui (if your AIA console is foo.com/AIA, then your link is foo.com/sdpmessaging/userprefs-ui). However, that didn’t quite work for me either.
What you really need do is to go to weblogic console, under security realm, users, set the email for that user  (say “foo”), click “attribute” tab, then find mail (2nd page), and enter email address over there. That is what worked for me! The only that appears to be working under "sdpmessaging/userprefs-ui " is if you set one user as the default channel (I used AIAIntegrationAdmin). 

5.      (Trick 3), one useful trick to debug your email problem is under “em” console.
Expand “User Messaging Service” (last link on the left panel)
Click on “usermessagingserver (WLS_SOA1)”
On the right panel, look on the top left corner, find the little drop-down menu (under “usermessaingserver” bold letters),
select “Message Status” from the drop-down menu
Hopefully, you’ll see a list of message action entries.
Click on the one you are interested (failed, succeeded)

I have had luck to find out the root cause of email issues from this page. In the case, when it shows failed, I can check the bottom to find out the detailed reason.
Today, I found one showed succeeded; however, we didn’t get any emails. So that prompted me to login to the putty console, and run the mail command, like “mail foo@bar.com”, directly, where “foo@bar.com“ is the address that the server claimed to have sent successfully. However, my putty console test shows the recipient never get the email. As it finally turned out that email “foo@bar.com” happens to be a distribution list and it was not set up properly on the server.





Thursday, June 7, 2012

The Mess of XLST 1.0 / 2.0, JDEV and OSB

I ran into some mess with XSLT 1.0 / 2.0, JDEV and OSB. Oh, boy, I just have to blog it.

Let me sum up the lesson I learned before I dive into the details:
  • If you crafted your XSLT in JDEV, you tested it, and  it worked fine in JDEV.  Then you port it to OSB, the same XSLT code may blow up!
I have to admit that I didn't just do a "normal" XSLT and ported it OSB. I did something "smart" with XSLT. At first, I was proud of what I did. Then I spent hours to realize there is such a thing as being "too smart".

In JDEV,  the default version of XSLT is "1.0". You can change it to "2.0", so you can take advantage of some of the 2.0 features. I did that in the past. It worked well.

Here is what I did this time:

<xsl:stylesheet version="2.0"
                xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
...
  <xsl:template match="/">

  <!-- this only works with 2.0 -->
    <xsl:variable name="v">
      <var name="v1">legal</var>
      <var name="v2">preferred</var>
    </xsl:variable>
     <ns2:employeeElem>
      <ns2:id>
        <xsl:value-of select="/wd:Report_Data/wd:Report_Entry/wd:Employee_ID"/>
      </ns2:id>

      <xsl:for-each select="$v/var">
        <xsl:choose>
          <xsl:when test=".='legal'">
            <ns2:name>
              <ns2:firstName>        
                <xsl:value-of select="/wd:Report_Data/wd:Report_Entry/wd:Legal_First_Name"/>
              </ns2:firstName>
            </ns2:name>
          </xsl:when>
         <xsl:when test=".='preferred'">
            <ns2:name>
              <ns2:firstName>
                <xsl:value-of select="/wd:Report_Data/wd:Report_Entry/wd:Preferred_First_Name"/>
              </ns2:firstName>
            </ns2:name>
          </xsl:when>

        </xsl:choose>
      </xsl:for-each>
    </ns2:employeeElem>
  </xsl:template>
</xsl:stylesheet>

I created an array variable, so I can control a for-each loop to run precisely twice. I call this "smart", because it is packed with two complicated tricks. We know that XSLT doesn't have index-incremented loop. If you change the size of this array, then you can actually emulate an index-incremented loop!

Another trick I am playing is to create the result with multiple <name> elements. If you don't use for-each, and hard code two <name> elements, then you can't edit your XSLT in design view anymore. It complains that you mapped the <name> multiple times. But if you use above for-each loop , you can still use design view!

Well, more traps here, if you manually change your XSLT version to 2.0, and you use design view to make any changes, whenever you save, it switches version back to 1.0. So you have to remember to manually change it to 2.0 again. 

Sounds messy enough?

Anyway, after I finished my 2.0 trick, and tested in JDEV, it worked beautifully. Then I ported it OSB, it blew up. It took me hours to find out that OSB doesn't like that "smart" 2,0 feature. 

Now I have to bite the bullet and manually edit the whoel XSLT script.


Friday, April 27, 2012

Tuesday, April 24, 2012

OSB Alerts Data File Location

So I won't forget it again, OSB alerts are stored in a binary file

./servers/WLS_OSB1/data/store/diagnostics/WLS_DIAGNOSTICS000000.DAT

when it grows big, the OSB console takes long time to show alerts. You need to purge this file periodically.

A Few BPEL Java Embedding Notes

1. Error: SCAC-50012
    check \SCA-INF\classes\scac.log file to find more details.

    Common issues:

    #1.1) check that you added the proper import at the top of .bpel file
     
     for example (right after <:process ...> element, and before partner links   
     <bpelx:exec import="java.util.*"/>
    <bpelx:exec import="java.lang.*"/>
    <bpelx:exec import="java.math.*"/>
    <bpelx:exec import="org.w3c.dom.Element"/>
    <bpelx:exec import="oracle.xml.parser.v2.*"/>   
    <bpelx:exec import="com.foo.bar.*"/>
    <bpelx:exec import="com.collaxa.cube.ws.wsif.providers.java.*"/>

     #1.2) check your syntax carefully. When in doubt, comment out as much as you can.

2. incorparte your own special classes and jars
    create your class jar file, place it under "SCA-INF/lib" folder

3. get/set your variables
    For simple string variables, it's straight forward. If you need to process the XML payloads, use forms like this:
 oracle.xml.parser.v2.XMLElement targetElem =
    (oracle.xml.parser.v2.XMLElement) getVariableData("myVarName", "payload",  "/ns3:foo/ns3:bar/ns3:car");  where "ns3" is defined precisely as it appears at the top of your .bpel file.

you can manipulate this element with functions, here are a few common functions: "getParentNode, getTextContent, cloneNode, setTextContent, insertBefore" etc.

4. if you need to debug, add some log entries using "addAuditTrailEntry".

Monday, April 9, 2012

OSB coherence cache localhost configuration

I have a standard localhost SOA 11.1.1.4 install. I have global result caching enabled (default) and i enabled result caching for my business service. However, the result is not cached.

I have checked coherence configure files under C:\Oracle\Middleware\user_projects\domains\soa_domain\config\osb\coherence, but I couldn't tell what's wrong.

I did some search and this link turned up: http://docs.oracle.com/cd/E17904_01/core.1111/e10106/ha_soa.htm

Here is the section (5.14.9) of the doc I followed to get mine to work:
  1. Log into Oracle WebLogic Server Administration Console. In the Change Center, click Lock & Edit.
  2. In the Domain Structure window, expand the Environment node.
  3. Click Servers. The Summary of Servers page appears.
  4. Click the name of the server (represented as a hyperlink) in the Name column of the table. The settings page for the selected server appears.
  5. Click the Server Start tab.
  6. Enter the following for WLS_OSB1 (on a single line, without a carriage returns):
    -DOSB.coherence.localhost=osbhost1vhn1 -DOSB.coherence.localport=7890 
    -DOSB.coherence.wka1= osbhost1vhn1 -DOSB.coherence.wka1.port=7890 
    -DOSB.coherence.wka2= osbhost2vhn1 -DOSB.coherence.wka1.port=7890
    
Except step 6 is not 100% clear, it should say to put the value into the "arguments" field. See screen shot.

I also adjusted the value for my specific case (by default, my OSB server is "osb_server1"):

-DOSB.coherence.localhost=localhost -DOSB.coherence.localport=7890 -DOSB.coherence.wka1= localhost -DOSB.coherence.wka1.port=7890 -DOSB.coherence.wka2= localhost -DOSB.coherence.wka1.port=7890

After that I restarted OSB server, and it worked.

BTW, you may need to adjust the port#. I think the number should match the config files under your_domain/config/osb/coherence/



Friday, March 23, 2012

OSB: Hooking up Rest Service with XML Payload in Query String


Using OSB to hook up Rest Service is fairly common. There are quite a few articles online talking about how to do it. However, I ran into some particular issues where trying to hook up a Rest Service in OSB. The problem is this service uses query string with XML payload.  I had to jump through many hoops to get it to work. This post shows how I did it.

Assume the example Rest Service URL is “http://myRestServer:7001/sbconsole “ , this service takes a query string variable "information", the payload looks like
<location><searchFlag>Address</searchFlag><streetNumber>200</streetNumber><streetName>Water St</streetName></location>

Test Rest Service Directly


When I use Firefox poster to test the Rest service, it works fine. I can see Firefox sends up:
“GET /sbconsole?information=%3Clocation%3E%3CsearchFlag%3EAddress%3C%2FsearchFlag%3E%3CstreetNumber%3E200%3C%2FstreetNumber%3E%3CstreetName%3EWater%20St%3C%2FstreetName%3E%3C%2Flocation%3E HTTP/1.1
Host: myrestserver:7001”

Please note that the actual query string is URL encoded. As you will see, this will cause a couple of issues with OSB.

Business Service


Proxy Service
If you pay close attention, you will see the only difference is that Firefox encodes “Water St” as “Water%20St”, whereas OSB encodes it as “Water+St”.

To the best of my knowledge, both are supposed to be “correct”. But our test Rest Service runs on IIS, it appears to me that IIS does not filter “+” inside the actual data element.

I couldn’t make OSB to encode space as “%20”. I suspect it goes to the Java API “URLEncoder”. According to the API (http://download.oracle.com/javase/6/docs/api/java/net/URLEncoder.html):
 The space character " " is converted into a plus sign "+".

So I had to ask the Rest Service developer to filter “+” inside the code. That solves this part of the problem.
As a side note: IIS does filter “+” sign between element tags, just not inside the actual element data. I also suspect there may be a way to tweak IIS to filter “+” sign inside the element data. But I don’t know how if it really can work that way.

In order to pass in the query string to Business service, I need to escape the special characters like below:
With proxy service, when I call the Business service, I need to pass in “query-string” in HTTP header. However, if I pass in the payload directly, the Proxy service will encode the query string first. When the business service gets the string, it becomes garbled up, and the call will fail.
In order to pass in th
<http:query-string>information=&lt;location&gt;&lt;searchFlag&gt;{$body/typ:AddressValidatorRequest/typ:location/typ:searchFlag/text()}&lt;/searchFlag&gt;&lt;streetNumber&gt;{$body/typ:AddressValidatorRequest/typ:location/typ:streetNumber/text()}&lt;/streetNumber&gt;&lt;streetName&gt;{$body/typ:AddressValidatorRequest/typ:location/typ:streetName/text()}&lt;/streetName&gt;&lt;/location&gt;</http:query-string>

Conclusion
If there is an option to choose what method to use for the Rest service, my recommendation is to use POST, instead of query string (GET), especially if the Rest Service is expecting an XML payload.
With POST method, data is passed to the server as-is, no URL encoding is involved.
Source code
I don't know how to add attachment, so i'll just post the snippet of the source here:
    <con:pipeline name="PipelinePairNode1_request" type="request" xmlns:con="http://www.bea.com/wli/sb/pipeline/config">
      <con:stage name="stage1">
        <con:context>
          <con1:varNsDecl prefix="typ" namespace="
http://www.lasvegasnevada.gov/GisAddressValidator/types" xmlns:con1="http://www.bea.com/wli/sb/stages/config"/>
        </con:context>
        <con:actions>
          <con:wsCallout xmlns:con="
http://www.bea.com/wli/sb/stages/transform/config">
            <con1:id xmlns:con1="
http://www.bea.com/wli/sb/stages/config">_ActionId-8515072324608930629--ca66017.12fdc6a1a2e.-7fe8</con1:id>
            <con:service ref="myRestTest/restGetBS" xsi:type="ref:BusinessServiceRef" xmlns:ref="
http://www.bea.com/wli/sb/reference"/>
            <con:request>
              <con:payload wrapped="false">$requestBodyContent</con:payload>
            </con:request>
            <con:response>
              <con:payload wrapped="false">responseBodyContent</con:payload>
            </con:response>
            <con:requestTransform>
              <con:transport-headers copy-all="false">
                <con1:id xmlns:con1="
http://www.bea.com/wli/sb/stages/config">_ActionId-8515072324608930629--ca66017.12fdc6a1a2e.-7fe7</con1:id>
                <con:header-set>outbound-request</con:header-set>
              </con:transport-headers>
              <con:insert varName="outbound">
                <con1:id xmlns:con1="
http://www.bea.com/wli/sb/stages/config">_ActionId-8515072324608930629--ca66017.12fdc6a1a2e.-7fe5</con1:id>
                <con:location>
                  <con:xpathText xmlns:con="
http://www.bea.com/wli/sb/stages/config">./ctx:transport/ctx:request</con:xpathText>
                </con:location>
                <con:where>first-child</con:where>
                <con:expr>
                  <con:xqueryText xmlns:con="
http://www.bea.com/wli/sb/stages/config"><![CDATA[<http:query-string>information=&lt;location&gt;&lt;searchFlag&gt;{$body/typ:AddressValidatorRequest/typ:location/typ:searchFlag/text()}&lt;/searchFlag&gt;&lt;streetNumber&gt;{$body/typ:AddressValidatorRequest/typ:location/typ:streetNumber/text()}&lt;/streetNumber&gt;&lt;streetName&gt;{$body/typ:AddressValidatorRequest/typ:location/typ:streetName/text()}&lt;/streetName&gt;&lt;/location&gt;</http:query-string>]]></con:xqueryText>
                </con:expr>
              </con:insert>
            </con:requestTransform>
            <con:responseTransform>
              <con:replace varName="body" contents-only="true">
                <con1:id xmlns:con1="
http://www.bea.com/wli/sb/stages/config">_ActionId-8515072324608930629--ca66017.12fdc6a1a2e.-7fe4</con1:id>
                <con:location>
                  <con:xpathText xmlns:con="
http://www.bea.com/wli/sb/stages/config">.</con:xpathText>
                </con:location>
                <con:expr>
                  <con:xqueryText xmlns:con="
http://www.bea.com/wli/sb/stages/config">$responseBodyContent</con:xqueryText>
                </con:expr>
              </con:replace>
            </con:responseTransform>
          </con:wsCallout>
        </con:actions>
      </con:stage>
    </con:pipeline>
Tcpdump
In case you wonder how I captured my tcp packet, here is my sample command
/usr/sbin/tcpdump src 10.128.8.108 or dst 10.128.8.108 -nnvvXSs 1514 -w dump.cap