Friday 12 October 2012

How to pass event from ADF page to BPEL process using Java API

Step1:- We can write Java API to publish event in EDN based on JMS or EDN based on AQ. This java API code need to insert in ADF page on Click button action.  By default EDN would be AQ based. For changing it to JMS based need to change one property in SOA server and restart.
Note:- We need to decide if we want to use EDN-AQ or EDN-JMS. The AQ implementation is the default EDN implementation but this requires some datasources to the soa-infra database. This can be Ok in a small server network but it will create dependency to this SOA Suite Server in  WebLogic Server.”    

Step 2:- I will explain here EDN based on JMS.
      Step 2(i):- For using EDN based on JMS we have to do below changes in enterprise manager
1.     Open the enterprise manager application | SOA | soa-infra
2.     Open the Common Properties Menu item of the SOA-Infrastructure menu
3.     Click on More SOA-Infra Advanced Configuration Properties.This will open the System MBean Browser. In this we can change the EdnJmsMode and set this to true. Restart the SOA Server and take a look at the monitoring of the EDN Queue jms/fabric/EDNQueue which by default present on server


SOAJMSModule located at the JMSModules of WebLogic you can see that the module already contains an EDN Queue and an EDN ConnectionFactory.



By default jms/fabric/EDNConnectionFactory, jms/fabric/EDNQueue will be there on server. Create a JMS Connection Factory called xaEDNConnectionFactory with JNDI name jms/fabric/xaEDNConnectionFactory, enable XA and targeted this to your WebLogic server.

Step 2(ii):- Configure a Foreign JNDI Provider to Enable Administration Server Applications to Publish Events to the SOA Server

1.Log in to the Oracle WebLogic Server Administration Console.
2.In the Domain Structure section, expand Services > Data Sources.
You must remove the EDN-DB JNDI sources to use EDN-JMS data sources.
3.Select the following EDN-DB JNDI data sources, and click Remove.
◦jdbc/EDNDataSource
◦jdbc/EDNLocalTxDataSource
If the event publisher is in an application (for example, ADF) running in a different cluster or even in a different domain from the SOA server for EDN, you must configure a foreign JNDI provider with the local JNDI names for the cluster mapping to JNDI names targeted to the SOA Infrastructure. Local and remote JNDI names are the same in the links.
4.In the Domain Structure section, expand Services > Foreign JNDI Providers.
5.Click New.
6.In the Name field, enter a name for the foreign JNDI provider.
7.Select targets for the new JNDI provider, and click Finish.
8.In the Name field, click the new JNDI provider.
9.Specify provider settings (the initial context factory, provider URL, and so on), and click Save.
Initial Context Factory:- weblogic.jndi.WLInitialContextFactory.
Provider URL:-  t3://hostname:soa_server_port.
User:- Enter the Oracle WebLogic Server user name.
Password and Confirm Password:- Enter the password for the Oracle WebLogic Server user name.
10.Click the Links tab.
11.Click New to create a foreign JNDI link.
12.Enter a name, then specify the local and remote JNDI name of jms/fabric/EDNConnectionFactory.
13.Repeat Step 12, and specify a name and the local and remote JNDI name of jms/fabric/xaEDNConnectionFactory.Repeat Step 12, and specify a name and the local and remote JNDI name of jms/fabric/EDNQueue.
Once complete, three links are created.
14.Restart the targeted servers.
15.Confirm the new JNDI provider links in the JNDI tree view.

Step 2(iii):- ADF page will take two input parameter and will pass to xsd in API code and one create Event button .Java API code along with backing bean in ADF page:-
Need to add Libraries in View Controller to avoid any compilation error(i)SOA runtime (ii) Weblogic Remote Client (iii) JSF etc

package viewControler.backing;

import oracle.adf.view.rich.component.rich.RichDocument;
import oracle.adf.view.rich.component.rich.RichForm;
import oracle.adf.view.rich.component.rich.nav.RichCommandButton;

import java.util.Properties;


import javax.jms.Queue;
import javax.jms.QueueConnectionFactory;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import javax.transaction.UserTransaction;

import javax.xml.namespace.QName;

import oracle.adf.view.rich.component.rich.input.RichInputText;

import oracle.fabric.blocks.event.BusinessEventConnection;
import oracle.fabric.blocks.event.BusinessEventConnectionFactory;

import oracle.integration.platform.blocks.event.BusinessEventBuilder;
import oracle.integration.platform.blocks.event.jms.JmsRemoteBusinessEventConnectionFactory;

import oracle.soa.common.util.XMLUtil;


import org.w3c.dom.Element;
public class CallEventApI {
    public String cb1_action() {
        // Add event code here...
        // My SOA WebLogic variables
        // the business Event
//Enter name of business event
        String EmployeeEvent = "Event1";
//Enter target namespace of business event
        String NameSpace =
            "http://xmlns.oracle.com/SubscribedEventProject/EventDefinition1";
       
        String name = getIt1().getValue().toString();
        String id = getIt2().getValue().toString();
       //Enter the XSD payload
        String EmployeeEventBody =
            "<Employee xmlns=\"http://www.example.org\">" +
            "<Name>"+name+"</Name>" +
            "<Id>"+id+"</Id>" +
            "</Employee>";
       
        Element eventBody = null;
        try {
            eventBody =
                    XMLUtil.parseDocumentFromXMLString(
                        EmployeeEventBody.toString()).getDocumentElement();
        } catch (Exception e) {
            e.printStackTrace();
        }
       
        // EDN JMS environment
        String connFactName = "jms/fabric/EDNConnectionFactory";
        String xaConnFactName = "jms/fabric/xaEDNConnectionFactory";
        String queueName = "jms/fabric/EDNQueue";
       
        try {
            InitialContext context = new InitialContext();
            
                        // do a jndi lookup on the Server
                        UserTransaction userTransaction = (UserTransaction)context.lookup("javax.transaction.UserTransaction");
                        QueueConnectionFactory queueConnectionFactory = ((QueueConnectionFactory)context.lookup(connFactName));
                        QueueConnectionFactory xaQueueConnectionFactory = ((QueueConnectionFactory)context.lookup(xaConnFactName));
                        Queue jmsQueue = ((Queue)context.lookup(queueName));
            
       
            BusinessEventConnectionFactory factory =
                new JmsRemoteBusinessEventConnectionFactory(queueConnectionFactory,
                                                            xaQueueConnectionFactory,
                                                            jmsQueue,
                                                            userTransaction);
       
            BusinessEventConnection conn =
                factory.createBusinessEventConnection();
            
            // Create an event
            BusinessEventBuilder builder = BusinessEventBuilder.newInstance();
            builder.setEventName(new QName(NameSpace, EmployeeEvent));
            builder.setBody(eventBody);
            System.out.println("here called");
       
            // publish
            conn.publishEvent(builder.createEvent(), 4);
            conn.close();
       
        } catch (NamingException e) {
            e.printStackTrace();
        }
        return null;
    }
}

Step 3:- Deploy the ADF page as war file then open the page url and click the button.
Once event will be triggered from ADF page will put the message in jms/fabric/EDNQueue queue. Once message will reached to queue then it will automatically invoke Subscribed mediator as in Java API we are passing the Event name and namespace of EDL file and Input payload.

Hope this would be helpful.

Saturday 22 September 2012

How to call Shell Script in BPEL process using Java Embeed

Step 1:- Write Shell Script For addition of two number.
Step 2:- Create XSD which will contain two numbers.













<?xml version= '1.0' encoding= 'UTF-8' ?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xmlns.oracle.com/ns/Numeric"
     xmlns:num="http://xmlns.oracle.com/ns/Numeric" attributeFormDefault="qualified" elementFormDefault="qualified">
    <element name="Numeric" type="num:NumericType"/>
    <complexType name="NumericType">
        <sequence>
            <element name="Num1" type="int"/>
            <element name="Num2" type="int"/>
                    </sequence>
    </complexType>
</schema>

Step 3:-Write a Java code to call shell script along with passing variable to script. Below code is written to open the script created in cygwin.

package com.test;

import java.io.*;
public class MyTest1 {
       
          public String ShellScript(int i, int j) throws IOException
          {

               String Var=null;
          try{
                Process P;
                System.out.println(i);
                System.out.println(j);
              String strParam = "D:\\cygwin\\bin\\bash -c '/cygdrive/d/testShell/SumOfTwoNumber.sh "
                                                     + i +" + "+ j+" '";
                                     P = Runtime.getRuntime().exec(strParam);

                          System.out.println("here " + strParam);
             BufferedReader br = new BufferedReader(new InputStreamReader(P.getInputStream()));
            String line=null;
            
              while ( (line = br.readLine()) != null){
                        System.out.println("Output" + ">" + line);
                  Var=line;
                        }
                System.out.println(line);
                System.out.println("Output of Var:-"  +Var);
             
            int wait = P.waitFor();
            System.out.println("exit code: "+wait);
               
            }
            catch (InterruptedException ie)
            {
              System.out.println("exception caught");
            }
            catch (Throwable t)
                  {
                    t.printStackTrace();
                  }
               return Var;
              
           }
For Script available in Bash or Corn Shell then need to modify line.
 String strParam = "bin\bash -c \SumOfTwoNumber.sh + i +" + "+ j+" ";
 String strParam ="bin\ksh -c \SumOfTwoNumber.sh + i +" + "+ j+" ";


Step4:- Create BPEL process to contain java embeed.

Modify BPEL source code to containg following below class
<bpelx:exec import="YourFullyQualifiedClassName(example com.oracle.shellscript)"/>

Java Embeed will contain following below code
MyTest1 pocob = new MyTest1();               
try{         
addAuditTrailEntry("Started From This Place");        
String i = ((oracle.xml.parser.v2.XMLElement)getVariableData("inputVariable","payload","/ns1:Numeric/ns1:Num1")).getFirstChild().getNodeValue();   
int k = Integer.parseInt(i);        
addAuditTrailEntry("k Variable " +k);        
String j = ((oracle.xml.parser.v2.XMLElement)getVariableData("inputVariable","payload","/ns1:Numeric/ns1:Num2")).getFirstChild().getNodeValue();           
int n = Integer.parseInt(j);        
addAuditTrailEntry("n Variable " +n);        
addAuditTrailEntry("Before Variable");        
String greetings = pocob.ShellScript(k,n);       
addAuditTrailEntry("After Variable");        
addAuditTrailEntry("Value:- " +greetings);        
setVariableData("Var1",greetings);     //Var1 is a variable created in BPEL process to contain result     
addAuditTrailEntry("After Assignment");        
}        catch(Exception io){                                                                         
      addAuditTrailEntry("Exception occured:"+io.getMessage());                                                          
      javax.xml.namespace.QName qName=new javax.xml.namespace.QName("http://schemas.oracle.com/bpel/extension","remoteFault");                                                                               
      com.oracle.bpel.client.BPELFault bpelFault=new com.oracle.bpel.client.BPELFault(qName);               
      throw bpelFault;                                
    }       
finally{        
pocob=null;   
  
}

Add following libraries in classpath.

Assign Var1 Variable to BPEL output variable.


Enjoy the testing.

Tuesday 13 March 2012

How to resolve error "Failed to establish a connection to "localhost" at port 9001" while creating BAM connection using JDeveloper

While creating BAM connection from JDeveloper 11.1.1.x version If you faced any problem just like below :-
Testing HTTP connection ... success.
Testing Data Object browsing ... success.
Testing JNDI connection ... failed.
Failed to establish a connection to "localhost" at port 9001;
Please verify BAM Server Host & JNDI Port.

2 of 3 tests successful..

For Example if BAM server is installed on the port 7001, Whereas by default BAM server configuration files used to point to the port 9001. That's  why above stated error used to come due to wrong configuration port in connection detail:-

As in the above screen shot JNDI port also need to give the 7001 as BAM server is installed on 7001 and port number need to change as 7001 in the following BAM server Configuration files(BAMICommandConfig.xml, BAMCommonConfig.xml, BAMServerConfig.xml and BAMWebConfig.xml ) which are pointing to default port 9001.
               
Following steps need to follow :-
Step 1:-  Manually change the port number from 9001 to the new port number in the SOA_ORACLE_HOME\bam\config\BAMICommandConfig.xml (on Windows operating systems) file. The parameter that needs to be changed is shown below:

<ADCServerPort>9001</ADCServerPort> (Put here the configured port 7001)

Step2:- Oracle BAM single-instance web application configuration information is maintained in MW_HOME\user_projects\domains\domain_name\servers\BAM_server_name\tmp\_WL_user\oracle-bam_11.1.1\yhryfp\APP-INF\classes\config (on Windows operating systems) directory. Note:The folder name under oracle-bam_11.1.1 is randomly generated (in this case, it is yhryfp). When you are looking for this directory on your system, then the name can be any generated alphanumeric character
a. Changes in BAMCommonConfig.xml:

The <ApplicationURL> parameter should contain the new URL.

b. Changes in BAMServerConfig.xml:

 <ADCServerName>localhost</ADCServerName>

<ADCServerPort>9001</ADCServerPort>

c. Changes in BAMWebConfig.xml:

<ServerName>localhost</ServerName>

<ServerPort>9001</ServerPort>

After that restart the BAM manage server. It should work.

Monday 5 March 2012

How to Change DVM at Run Time


Oracle SOA Composer now offers support for editing domain value maps at runtime. Oracle SOA Composer is an EAR file, which is installed as part of Oracle SOA Suite installation. It enables to manage domain value maps at runtime.

1.   Access Oracle SOA Composer at the following location: 
http://hostname:port/soa/composer 

User must have the SOADesigner application role to access Oracle SOA Composer metadata. By default, all the users with Oracle Enterprise Manager Fusion Middleware Control administrator privileges have this role.


Saving Domain Value Maps at Runtime:- 
Every time a domain value map is opened in an edit session, a sandbox is created per domain value map, per user. After saving the changes, the changes are saved in current user sandbox.


Committing Changes at Runtime:-
Commit the changes for saving them permanently. Once changes will be commited, runtime picks up the changes and saves them in the MDS repository. In a session, If changes are saved  without committing them. In such a case, the domain value map remains in the saved state which can reopen the domain value map and commit the changes later.

Detecting Conflicts:-
Oracle SOA Composer detects conflicts that can occur among concurrent users. If we will open a domain value map that is being edited by another user, then one warning appear . However, if we still want to edit the domain value map, then click Yes and make the modifications.If the other user makes changes to the domain value map and commits the changes, one notification message will appear while trying to commit the changes.
If we click Yes and commit the changes, then the changes made by the other user are overwritten by our changes.

Sunday 5 February 2012

How To Work with Domain Value Map


In the below Example I will create one DVM file using four Column CityCode, CityName, CityLocation and Country. Where Country and CityLocation Column will act as qualifier. Mediator will lookup value from .dvm file and write result to local file system.

Step1:- Create .DVM FILE using  Right click on project -> Select SOA-> Transformation-> Domain Value Map . Give some name to domain value map file and give some name to the domain fields then click OK.
Now in .DVM file click on add button -> select the option add domain. In this example I am adding one more domain with name CityLocation with Qualifier as true and hierarchical order as 1 and another domain with name Country with Qualifier as true and hierarchical order as 2 to show the hierarchy weightage.



Step 2:- Now I am creating one Asynchronous Mediator in composite and exposing it as web Service and created one file Adapter which will be writing onto the local system. Wire the Mediator with write File adapter.


Step 3:- Now open the mediator and click on the transformation icon and select the Advance Function in XSLT Mapper file in Component Palette. Then select the DVM Funtion->lookupValue1M.
Drag this function onto the line connecting field from source to target. Open the function and select the following below values in respective field. In the sourceValue  column  click and press the ctrl+Shift to get the field from XSD. In my case I have taken XSD as Employee. The XSD can be anyone.
Whatever value will come from field EmployeeName will go to Source Column CityCode in .dvm file.
Target column is selected as CityName will show the value of output means full name of City and default value is selected as “Not Known”. If the passed value while testing will not be present in the CityCode column then the default value “Not Known” will come as output.
Qualifier columns will pick values from the EmployeeDetail and EmployeeSummary field passed while testing in Employee XSD.

Step 4:- After  Mapping deploy the function on Application server and test the function.

A qualifier order is used to find the best match during lookup at runtime. The order of a qualifier varies from highest to lowest depending on the role of the qualifier in defining a more exact match. In the CityLocation qualifier(1) have a higher order  than the Country qualifier(2), as a matching CityLocation indicates a more exact match.

Domain value maps support hierarchical lookup. If we specify a qualifier value during a lookup and no exact match is found, then the lookup mechanism tries to find a more generalized match by setting the higher order qualifiers to a "".

First Test case in the Usecase:-
Pass value BO in all four field. Now the result will come as Boston1 because it picks value where the CityLocation and Country Value Column has no value entered.

Second Test case in the Usecase:-
Pass value BO in all three field. Now the result will come as Boston1 because it picks value where the CityLocation is blank and Country is blank. It happens because CityLocation Column has hierarchy set 1 which is taking precedence over the Country Column. That’s why it did not pick value from the field where Country name is set as USA because in that case CityLocation is not set as BO.
Third Test case in the Usecase:-
Pass value BO in all two field. Now the result will come as Boston because it picks value where the CityLocation is EastUSA and Country is USA.

Hope this Example would help in understating DVM concept.

Domain Value Map Features:-
(i)                  Qualifier Support:- Qualifiers qualify mappings. A mapping may not be valid unless qualified with additional information. For example, a domain value map containing city code to city name mapping may have multiple mappings from KN to Kensington as Kensington is a city in Canada as well as USA. Hence this mapping requires a qualifier (USA or Canada) to qualify when the mapping becomes valid . You can also specify multiple qualifiers for a domain value map. Qualifiers are used only to qualify the mappings. Therefore, the qualifier values can not be looked up.
(ii)                Qualifier Order Support:- A qualifier order is used to find the best match during lookup at run time. Domain value maps support hierarchical lookup. If you specify a qualifier value during a lookup and no exact match is found, then the lookup mechanism tries to find a more generalized match by setting the higher order qualifiers to "". It proceeds until a match is found, or until a match is not found with all qualifiers set to "".
(iii)               One-to-Many Mapping Support:- You can map one value to a multiple values in a domain value map. For example, a domain value map for Payment Terms can contain mapping of payment terms to three values such as discount percentage, discount period, and total payment period.