June 30, 2008

An attempt on 8 Queens Problem

I was trying out a different approach to 8-Queen's problem. I visualized each cell [that has a coordinate from (0,0) to (7,7) as a single number 10x + y. So you would have sort of an octal number set from 0 to 77. Each column would be 0-7, 10-17, 20-27 etc and so on till 70-77.
Each row would be 0-70, 1 to 71 etc, in increments of 10.

7 17 27 37 47 57 67 77
6 16 26 36 46 56 66 76
5 15 25 35 45 55 65 75
4 14 24 34 44 54 64 74
3 13 23 33 43 53 63 73
2 12 22 32 42 52 62 72
1 11 21 31 41 51 61 71
0 10 20 30 40 50 60 70

The solution was a recursive function that takes in a current column index [ranging from 0 to 7], and computing the matching lists of size 8, after applying an exclusion rule.

The exclusion rule is interesting.
For an item with value, lets say 43, the exclusion rule would test the row-wise, columnwise and diagonal collisions through a simple modulo-checking logic. The code is given below. Note that the code has not been subjected to any review, including self-review, though it generates the required 92 distinct permutations as the 8Q solution demands.

package equeen;

import java.io.FileWriter;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class EightQueens {

public boolean computeMatches(int rowIndex, List matchedList) throws Exception{
if(matchedList.size() == 8) {
printToFile(matchedList);
}
boolean matched = false;
for(int i = 10*rowIndex ; i <= 10*rowIndex + 7 ; i++) {
int cellValue = i;
boolean isExcluded = computeExclusionRule(cellValue, matchedList);
if(!isExcluded) {
matched = true;
matchedList.add(cellValue);
if(computeMatches(rowIndex+1,matchedList)) matched = !matched;
}
}

if(!matched && matchedList.size() > 0) {
matchedList.remove(matchedList.size() - 1);
return true;

}
else return false;
}

private boolean computeExclusionRule(int value, List matchedList) {
for(int i = 0 ; i < matchedList.size() ; i++) {
int prevNumber = Integer.parseInt("" + matchedList.get(i));
int diff = (value - prevNumber);
if((diff % 9 == 0 && (prevNumber % 10 > value % 10)) ||
(diff % 10 == 0) ||
(diff % 11 == 0 && (prevNumber % 10 < value % 10))) {
return true;
}
}
return false;
}

public static void main(String[] args) throws Exception {
EightQueens q = new EightQueens();
List emptyList = new ArrayList();
int ZEROTHCOLUMN_INDEX = 0;
long t = System.currentTimeMillis();
q.computeMatches(ZEROTHCOLUMN_INDEX,emptyList);
System.err.println("Number of ms for execution - " + (System.currentTimeMillis() - t));
}

private static FileWriter fw = null;
private static void printToFile(List matchedList) throws Exception {
if(fw == null) {
fw = new FileWriter("d:\\temp\\results.log");
}
String str = "";
for(int i = 0 ; i < matchedList.size() ; i++) {
int itemValue = Integer.parseInt("" + matchedList.get(i));
str += getCoords(itemValue) + " ";

}
fw.write(str + "\r\n");
fw.flush();
}
private static String getCoords(int cellValue) {
int x = cellValue/10;
int y = cellValue % 10;
return "(" + x + "," + y + ")";
}

}

May 16, 2008

Invoking an EJB Session Bean from a BPEL Process

EJB session beans can be invoked from a BPEL process through WSIF. Oracle BPEL PM ships with a WSIF provider for invoking EJBs.

For demonstrating this, lets create a new EJB session bean. The session bean shall have one single business method namely "greetUser" that takes in a string argument userName, and returns a string value "Hello &lt;USERNAME>".

Step 1: Creating the HelloWorld Session Bean.


  1. Create a new BPEL empty process project.
  2. Open up the New Gallery and choose to create a new EJB session bean.



  3. Choose the option for creating EJB 2.1 session bean. Give the Bean the name"HelloWorld", accept the remaining defaults and finish the wizard.
  4. Double click on the EJB in the Applications Navigator to bring up the EJB Module Editor". Specify the new business method in the "Methods" tab. Type in the parameter name and type manually in the text editor



  5. CLick ok to accept the changes. Click on the "orion-ejb-jar.xml" in the Applications Navigator. Here you need to provide the JNDI locaiton of the session bean. For this, add a "location" attribute on the &lt;SESSION-DEPLOYMENT>to provide the JNDI "ejb/session/HelloWorld".




    1. &lt;?xml version = '1.0' encoding = 'windows-1252'?>  
    2. &lt;orion-ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    3.   xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-ejb-jar-10_0.xsd"  
    4.     schema-major-version="10" schema-minor-version="0">  
    5.     &lt;enterprise-beans>  
    6.         &lt;session-deployment name="HelloWorld" location="ejb/session/HelloWorld"/>  
    7.     &lt;/enterprise-beans>  
    8. &lt;/orion-ejb-jar>

  6. Your bean is now ready for deployment. Build the project and deploy to an OC4J container.

Step 2: Build the BPEL Process




  1. Create a new BPEL Process project.
  2. Create a new WSDL document in the project directory and name it HelloWorldEJB.wsdl.
  3. Add the bindings section that allow the process to invoke the EJB through WSIF. The salient portion of the bindings section is the jndiProviderURL. For an Application Server install, use the opmn ormi jndi provider URL. For standalone installations,use plain ormi provider URLs. The ejbName in the provider URL is the ejbName value in the ejb-jar.xml that was created as a part of the EJB session bean creation.






      1. &lt;?xml version="1.0" ?>  
      2. &lt;definitions targetNamespace="http://samples.otn.com/"  
      3.              xmlns:tns="http://samples.otn.com/"  
      4.              xmlns:xsd="http://www.w3.org/2001/XMLSchema"  
      5.              xmlns:format="http://schemas.xmlsoap.org/wsdl/formatbinding/"  
      6.              xmlns:ejb="http://schemas.xmlsoap.org/wsdl/ejb/"  
      7.              xmlns:plnk="http://schemas.xmlsoap.org/ws/2003/05/partner-link/"  
      8.              xmlns="http://schemas.xmlsoap.org/wsdl/">  
      9.   &lt;!-- message declns -->  
      10.   &lt;message name="HelloWorldRequestMessage">  
      11.     &lt;part name="userName" type="xsd:string"/>  
      12.   &lt;/message>  
      13.   &lt;message name="HelloWorldResponseMessage">  
      14.     &lt;part name="message" type="xsd:string"/>  
      15.   &lt;/message>  
      16.   &lt;!-- port type declns -->  
      17.   &lt;portType name="HelloWorldPT">  
      18.     &lt;operation name="greetUser">  
      19.       &lt;input name="HelloWorldRequest" message="tns:HelloWorldRequestMessage"/>  
      20.       &lt;output name="HelloWorldResponse"  
      21.               message="tns:HelloWorldResponseMessage"/>  
      22.     &lt;/operation>  
      23.   &lt;/portType>  
      24.   &lt;!-- binding declns -->  
      25.   &lt;binding name="EJBBinding" type="tns:HelloWorldPT">  
      26.     &lt;ejb:binding/>  
      27.     &lt;format:typeMapping encoding="Java" style="Java">  
      28.       &lt;format:typeMap typeName="xsd:string" formatType="java.lang.String"/>  
      29.     &lt;/format:typeMapping>  
      30.     &lt;operation name="greetUser">  
      31.       &lt;ejb:operation methodName="greetUser" parameterOrder="userName"  
      32.                      interface="remote" returnPart="message"/>  
      33.       &lt;input name="HelloWorldRequest"/>  
      34.       &lt;output name="HelloWorldResponse"/>  
      35.     &lt;/operation>  
      36.   &lt;/binding>  
      37.   
      38.   &lt;!-- service decln -->  
      39.   &lt;service name="HelloWorldService">  
      40.     &lt;port name="EJBPort" binding="tns:EJBBinding">  
      41.       &lt;!-- Put vendor-specific deployment information here -->  
      42.       &lt;ejb:address className="helloworldbean.HelloWorldHome"  
      43.            jndiName="ejb/session/HelloWorld"  
      44.            initialContextFactory="com.evermind.server.rmi.RMIInitialContextFactory"  
      45.    jndiProviderURL="opmn:ormi://serverHost:opmnRequestPort:oc4jInstanceName/ejbName"/>  
      46.     &lt;/port>  
      47.   &lt;/service>  
      48.   
      49.   &lt;plnk:partnerLinkType name="HelloWorldService">  
      50.     &lt;plnk:role name="HelloWorldServiceProvider">  
      51.       &lt;plnk:portType name="tns:HelloWorldPT"/>  
      52.     &lt;/plnk:role>  
      53.   &lt;/plnk:partnerLinkType>  
      54. &lt;/definitions>  
      55.       

    1. Create a partnerlink for the WSDL that you just created and an invoke activity that can be used to invoke the plnk.
    2. Provide the username/password for connecting to the OC4J Instance that hosts the EJB within the bpel.xml deployment descriptor. This is typically the oc4jadmin user.




      1.   
      2. &lt;?xml version = '1.0' encoding = 'UTF-8'?>  
      3. &lt;BPELSuitcase>  
      4.    &lt;BPELProcess id="HelloWorldBPELClient" src="HelloWorldBPELClient.bpel">  
      5.       &lt;partnerLinkBindings>  
      6.          &lt;partnerLinkBinding name="client">  
      7.             &lt;property name="wsdlLocation">HelloWorldBPELClient.wsdl&lt;/property>  
      8.          &lt;/partnerLinkBinding>  
      9.          &lt;partnerLinkBinding name="HelloWorld_plt">  
      10.             &lt;property name="wsdlLocation">HelloWorldEJB.wsdl&lt;/property>  
      11.             &lt;property name="java.naming.security.principal">oc4jadmin&lt;/property>  
      12.             &lt;property name="java.naming.security.credentials">welcome1&lt;/property>  
      13.          &lt;/partnerLinkBinding>  
      14.       &lt;/partnerLinkBindings>  
      15.    &lt;/BPELProcess>
      16. &lt;/BPELSuitcase>

    3. Copy the EJB compiled classes from the EJB project created earlier into the $ORACLE_HOME/bpel/system/classes directory and restart the BPEL runtime. These classes are required for BPEL to get a hold on the home interface of the EJB to create an invoke the business method.
    4. Deploy the BPEL Process and see the results for yourself

    The demo EJB and BPEL Client project can be downloaded from this link.

May 7, 2008

Interesting XSLT Recipe - Computing line totals

You might have run into a requirement where you need to compute the total value of all items in a purchase order. Consider the PO XML shown below.





  1.   
  2. &lt;?xml version="1.0" encoding="UTF-8" ?>  
  3. &lt;po xmlns="http://www.example.org">  
  4.    &lt;Items>  
  5.       &lt;item>  
  6.          &lt;price>1&lt;/price>  
  7.          &lt;qty>2&lt;/qty>  
  8.       &lt;/item>  
  9.       &lt;item>  
  10.          &lt;price>3&lt;/price>  
  11.          &lt;qty>4&lt;/qty>  
  12.       &lt;/item>  
  13.       &lt;item>  
  14.          &lt;price>5&lt;/price>  
  15.          &lt;qty>6&lt;/qty>  
  16.       &lt;/item>  
  17.    &lt;/Items>  
  18. &lt;/po>  
You might want to compute the total value of all items in the purchase Order. For computing this, you would need to multiply the price and qty for each item, and add them up. In XSLT 1.0, I guess the way to do this would be to recursively invoke a template that computes the sum total. In XSLT 2.0, this can be done in a very elegant single expression.




  1.   
  2.   &lt;xsl:variable name="itemVar" select="/tns:po/tns:Items/tns:item"/>                
  3.   &lt;xsl:template match="/">  
  4.     &lt;tns:poSummary>  
  5.       &lt;tns:totalValue>&lt;xsl:value-of select="sum(for $i in $itemVar return ($i/tns:price * $i/tns:qty))"/>&lt;/tns:totalValue>  
  6.     &lt;/tns:poSummary>  
  7.   &lt;/xsl:template>  
  8. &lt;/xsl:stylesheet>  

April 22, 2008

Viewing Audits for Stale instances

Wondering what to do if you wished to view the audit trail for stale instances?


Well, you could make use of the View Raw XML feature in the BPEL Console.


 


 

Reusing code snippets in JDeveloper

Here is one simple but useful thing that I've been too lazy to make use of, and had overlooked.


JDeveloper's component palette has a page named "Code Snippets". You could actually add frequently re-used code snippets and save them into the "code snippets" section.



Once you click on "Add component", you can give the snippet a name, for e.g. "Assign WS-Addressing Headers" and copy the snippet from your source code  to the given text area.


You can now re-use the code snippet by dragging and dropping the component from the code snippet palette onto the source view of any file that you open in JDeveloper.


Similarly, you can also add your own Pages to the Component palette, to capture Snippets for diferent cateogies of code [for instnace, BPEL,XML, XSD, XSLT etc].



Now you can specify the Page Name and specify the type  - "snippet", "java" etc.


 


 



 


Now you can add new code snippets to the new Palette Page that you created.


 

April 21, 2008

Obtaining the Execution Times of BPEL Processes over a period of time

Here is a simple BPEL Query that will get you the statistics of execution times of all BPEL Process instances over a period of time. The stats include the number of invocations, minimum, maximum and average time of execution.






  1. SELECT process_id,count(*) as num_invocations,   
  2.   max(((EXTRACT(HOUR FROM MODIFY_DATE) - extract(hour from creation_date)) *3600 +   
  3.       (EXTRACT(MINUTE FROM MODIFY_DATE) - extract(MINUTE from creation_date)) *60 +   
  4.       (EXTRACT(SECOND FROM MODIFY_DATE) - extract(SECOND from creation_date))) *1000)   
  5.   as Max_Time ,   
  6.   
  7.   min(((EXTRACT(HOUR FROM MODIFY_DATE) - extract(hour from creation_date)) *3600 +   
  8.      (EXTRACT(MINUTE FROM MODIFY_DATE) - extract(MINUTE from creation_date)) *60 +   
  9.      (EXTRACT(SECOND FROM MODIFY_DATE) - extract(SECOND from creation_date))) *1000)   
  10.   as Min_Time ,   
  11.   
  12.   avg(((EXTRACT(HOUR FROM MODIFY_DATE) - extract(hour from creation_date)) *3600 +   
  13.      (EXTRACT(MINUTE FROM MODIFY_DATE) - extract(MINUTE from creation_date)) *60 +   
  14.      (EXTRACT(SECOND FROM MODIFY_DATE) - extract(SECOND from creation_date))) *1000)   
  15.   as Avg_Time   
  16.   
  17.   FROM CUBE_INSTANCE   
  18.     WHERE  
  19.       state &lt;> 9   
  20.         and  
  21.       creation_date > '09-APR-08 09.00.00.000000000 AM'  
  22.         and  
  23.       creation_date &lt; '09-APR-08 01.00.00.000000000 PM'  
  24.   
  25.       group by process_id order by process_id asc  

In this query, you need to replace the sample date and time values with the values that you wish to use and report. Here is another query that gives the execution times of all BPEL instances over the given time period.






  1.   
  2. select bpel_process_name as process_id,   
  3.        instance_key as cikey,   
  4.        trunc(creation_date),   
  5.        eval_time as exec_time   
  6. from bpel_process_instances   
  7. where state &lt;> 9 and  
  8.       creation_date > '11-APR-08 09.00.00.000000000 AM' and  
  9.       creation_date &lt; '11-APR-08 05.00.00.420000000 PM'  
  10. order by process_id asc, exec_time desc  
  11.     

In this query, you need to replace the sample date and time values with the values that you wish to use and report. Note that the above query shall give you the execution times for a particular day. Take a look at the comments on this blog entry to see a modified example that uses the "day" as well to obtain stats that span across multiple days.

April 15, 2008

Dynamically updating bpel.xml properties within your BPEL Process

There are different properties that you could actually update in your process descriptor. They are a) The Configuration properties b) The preference properties c) The partnerlink properties. These properties are illustrated below.






  1. &lt;BPELSuitcase>  
  2.   &lt;BPELProcess id="UpdatePropertyProcess" src="UpdatePropertyProcess.bpel">  
  3.     &lt;partnerLinkBindings>  
  4.       &lt;partnerLinkBinding name="client">  
  5.         &lt;property name="wsdlLocation">  
  6.           UpdatePropertyProcess.wsdl   
  7.         &lt;/property>  
  8.         &lt;property name="partnerlinkProperty1">  
  9.           valueOfPartnerlinkProperty 1   
  10.         &lt;/property>  
  11.       &lt;/partnerLinkBinding>  
  12.     &lt;/partnerLinkBindings>  
  13.      &lt;preferences>  
  14.        &lt;property name="preferenceProperty1" encryption="plaintext">  
  15.          valueOfPreferenceProperty1   
  16.        &lt;/property>  
  17.      &lt;/preferences>  
  18.      &lt;configurations>  
  19.       &lt;property name="configProperty1" encryption="plaintext">  
  20.         valueOfConfigProperty1   
  21.       &lt;/property>  
  22.       &lt;/configurations>  
  23.    &lt;/BPELProcess>  
  24. &lt;/BPELSuitcase>  

To update these properties dynamically within the BPEL Process, you can use a Java embedding within the process, as shown below.






  1.   
  2. try {   
  3.   getLocator().lookupProcess ("UpdatePropertyProcess").   
  4.                  getDescriptor ().   
  5.                   getConfigurations().   
  6.                     setPropertyValue ("configProperty1",   
  7.                      "newValueOfConfigPropertyValue1");   
  8.   getLocator().lookupProcess ("UpdatePropertyProcess").   
  9.                   getDescriptor ().   
  10.                    getPreferences().   
  11.                     setPropertyValue ("preferenceProperty1",   
  12.                       "newValueOfPreferenceProperty1" );   
  13.   getLocator().lookupProcess ("UpdatePropertyProcess").   
  14.                   getDescriptor ().   
  15.                    getPartnerLinkBindings().   
  16.                      getPartnerLinkBinding ("client").   
  17.                        setPropertyValue ("partnerlinkProperty1",   
  18.                        "newValueOfPartnerlinkProperty 1");   
  19.  }   
  20.  catch(Throwable ex) {   
  21.  }   
  22.    

Click here to download the Sample BPEL Process project.

April 14, 2008

Recursively replacing a string in all files in a directory [Linux]

My colleague provided me an extremely useful script that will replace a source string with a target string in all files in the current directory and its subdirectories.

find . -type f | xargs perl -pi~ -e 's/oldtext/newtext/g;'

Replace "oldtext" with the source string, and "newtext" with the target string.


During the replacement, all original files are backed up with a  "~" suffix.

March 18, 2008

Reading only headers in an File/FTP Adapter and skipping the payload

At times, you might have a requirement where you only need to read the file headers[file name and directory] and ignore the payload while using an inbound file/ftp adapter.


For this purpose, you need to add UseHeaders="true" on the &lt;jca:operation> in the adapter wsdl.


This ensures that the payload is skipped while reading the file.


Then you can follow the usual steps to read the headers [through the inputHeaderVariable on the receive activity to retrieve the headers.


 

March 6, 2008

Stripping namespaces using XSLT

A common question often asked is "I have a namespace qualified XML document -
I need to remove all xmlns attributes from the same".



Here is an XSLT that you can use to strip all namespaces from your document.






  1. &lt;xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  
  2. exclude-result-prefixes="xsl">  
  3.   
  4.  &lt;xsl:template match="*">  
  5.     &lt;xsl:element name="{local-name()}">  
  6.       &lt;xsl:apply-templates select="@* | node()"/>  
  7.     &lt;/xsl:element>  
  8.   &lt;/xsl:template>  
  9.   &lt;xsl:template match="@* | text()">  
  10.     &lt;xsl:copy/>  
  11.   &lt;/xsl:template>  
  12. &lt;/xsl:stylesheet>