Tuesday, October 11, 2011

Applying View Criteria in Child VO at runtime in VO hierarachy


While developing VO hierarchy for generic applications recently i faced issue while trying to filter a Child VO at runtime.

1. View Link option:
First option that came to mind is to add the additional where clause in View Link, This works fine But makes the VO tree specific to your need and it doesn't remain generic.

2. Fetching Parent VO property  in childVO and setting VC in executeQueryForCollection :
ApplicationModule am= this.getApplicationModule();
ViewObject vo = am2.findViewObject("ParentView1");
prop = (String)vo.getProperty("Parent_prop");

if(propVo_prop.equals("Y"))
this.setApplyViewCriteriaName("VC");

super.executeQueryForCollection(object, object2, i);

This is not recommended ADF coding.

3. The correct way to do this in Parent VO , fetch Child VO from View Link and set the VC:

Method in parent VO/executeQueryForCollection

Row r = getCurrentRow();
if (r != null) {
RowSet rs = (RowSet)r.getAttribute("ChildView");
if (rs != null) {
ViewObject accessorVO = rs.getViewObject();
accessorVO.ensureVariableManager();
accessorVO.getVariableManager().setVariableValue( "Param", value);

ViewCriteriaManager vcm = accessorVO.getViewCriteriaManager();
ViewCriteria vc = vcm.getViewCriteria("QueryByParam");
accessorVO.applyViewCriteria(vc); }
executeQuery();

For details : http://www.oracle.com/technetwork/developer-tools/adf/learnmore/feb2011-otn-harvest-328207.pdf

This works !!

Monday, July 11, 2011

Installing Oracle Enterprise repository 11g


SOA governance has a wide spectrum , OER,OSR , OWSM are the key tools for effective SOA governance. OER provides Visibility into all SOA assets and their relationships to eliminate redundancy, promote reuse, and manage impact of change OER gives a broad view of the various service artifacts and developent in an organization. Unlike OSR , OER can be deployed with latest version of WLS like 10.3.4. Here are the steps to install and make it work.

Download OER from OTN , 11.1.1.5.0

1. Seup Database

Create table space
OER_DATA
OER_LOB
OER_INDEX

Create user OER IDENTIFIED BY OER_PWD

-----------------------------------------------------------------
-- create Table space
drop user OER_SOA1;
drop tablespace OER_SOA1_DATA INCLUDING CONTENTS AND DATAFILES;
drop tablespace OER_SOA1_LOB INCLUDING CONTENTS AND DATAFILES;
drop tablespace OER_SOA1_INDEX INCLUDING CONTENTS AND DATAFILES;

CREATE TABLESPACE OER_DATA
    DATAFILE 'D:/oraclexe/oradata/oer_data.dbf' SIZE 300M
 AUTOEXTEND ON NEXT 10240K MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL AUTOALLOCATE
    LOGGING
    ONLINE
    SEGMENT SPACE MANAGEMENT AUTO;
   
CREATE TABLESPACE OER_LOB
    DATAFILE 'D:/oraclexe/oradata/oer_lob.dbf' SIZE 300M
 AUTOEXTEND ON NEXT 10240K MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL AUTOALLOCATE
    LOGGING
    ONLINE
    SEGMENT SPACE MANAGEMENT AUTO;

CREATE TABLESPACE OER_INDEX
    DATAFILE 'D:/oraclexe/oradata/oer_index.dbf' SIZE 300M
 AUTOEXTEND ON NEXT 5120K MAXSIZE UNLIMITED
    EXTENT MANAGEMENT LOCAL AUTOALLOCATE
    LOGGING
    ONLINE
    SEGMENT SPACE MANAGEMENT AUTO;

---------------------------------------------------------------------
-- create user

CREATE USER OER IDENTIFIED BY OER_PWD DEFAULT TABLESPACE OER_DATA TEMPORARY TABLESPACE TEMP;

GRANT CREATE MATERIALIZED VIEW TO OER;
GRANT CREATE SEQUENCE TO OER;
GRANT CREATE SESSION TO OER;
GRANT CREATE SYNONYM TO OER;
GRANT CREATE TABLE TO OER;
GRANT CREATE TRIGGER TO OER;
GRANT CREATE VIEW TO OER;
GRANT UNLIMITED TABLESPACE TO OER;

2. before running the installer
set path=D:\Oracle\Middleware\home_osb_11g14\jdk160_21\bin;%PATH%

3. cd D:\Softwares\SOA-SW-Latest\OER\ofm_oer_generic_11.1.1.5.0_disk1_1of1
java -jar OER111150_generic.jar

4. specify home as : D:\Oracle\Middleware\home_osb_11g14
This the middleware home where you have WLS 10.3.4 or 10.3.x installed.
OER : D:\Oracle\Middleware\home_osb_11g14\repository111

5. Give server : localhost [This is imp as the server startup will use this server to connect, this can be other server if installed there]
port : 7102 [I used this as i have OSR running on the same port ie 7101]
Reposirory app name : oer

6. configure database :
Provide the table space and user created.
Details : XE DB details
User : OER /OER_PWD
driver file location : need ojdbc6.jar
can find this is soa software , like inside ofm_rcu_win_11.1.1.4.0_disk1_1of1\rcuHome\jdbc\lib

8.After the installation ,  Extend the exixting domain with OER

9. If need to create new domain : oerosbsoa_domain
update WL_LLR_ADMINSERVER
also the table : WL_LLR_OSB_SERVER1 to avoid


Caused By: java.sql.SQLException: JDBC LLR, table verify failed for table 'WL_LLR_OSB_SERVER1', row 'JDBC LLR Domain//Server' record had unexpected value
'soaosb_domain//osb_server1' expected 'soa_osb_oer_domain//osb_server1'*** ONLY the original domain and server that creates an LLR table may access it ***

11. login  to http://localhost:7102/oer/
default : admin/admin

12. istall the OER adapter in Jdev using help-> check for updates
Only after this you will see the option for creating OER connection and setting up the App level settings
- create connection
url : http://localhost:7102/oer
user : admin/welcome1

13. Install the Harvester to Jdev , locate the zip from the  repository111 folder
11.1.1.5.0-OER-Harvester
C:\Oracle\FMW\home11gR1\repository111\core\tools\solutions

14. Import the Harvester-Solution-Pack to OER
11.1.1.5.0-OER-Harvester-Solution-Pack

After this you should be able to harvest the SOA project to OER and start using OER.


Cheers !!

Wednesday, May 11, 2011

Split Join in OSB


Split Join :
This is one of an interesting feature in OSB , however if you know how FlowN works in Bpel this will appears to be same.
Use Case:
Orders -> Multiple Items
Services :
1. Get each Item Status (Instock/outStock)
2. Get Order Status.

Now split join splits the input request to multiple threads and executes parallely.
Like in this case for an Order with 10 items , 10 threads will get spawned.

Resources:
XSD : Order/Item Element
WSDL : for ItemStatus Service and Order Status service
Bpel : Implement the getItemStatus service for inividual item

OSB :
1. create a project for split join
2. Import XSD and both WSDl
   While importing wsdl it may create xsd as well , update the source with imported xsd from xsd folder and then delete the
   created one.
3. Create a Buss Service based on Item WSDL (get url from EM), this will be invoked as part of split join
   http://localhost:8001/soa-infra/services/default/SplitJoinRrcs/getitemstatusbpel_client_ep?WSDL
   
4. Create split join based on getOrderStatus Service , select operation.

- It will create Receive and Reply activity and request and response variables as well
- initialize the response variable by adding an assign action , Put this Assign action right after Receive
   <ord:Order xmlns:ord="http://pchanel/Orders">
   </ord:Order>
- add a ForEach Flow Control to iterate each item in Order
  parallel = yes
  counter var = loop
  start counter = 1
  final counter = count($request.payload/Items)
 
- Add invoke service for the check Item status for each Item inside for each

Before invoke and inside scope
---------------------------------------------
- create input/output scope variable for the service invoke
- Add another var "Param" to pass the value to the Service
- Add assign action inside the for each , initialize input variable for service

  <ord:Item xmlns:ord="http://pchanel/Orders">
  </ord:Item>
 
- Add copy operation to copy items to Param
 from exp : $request.payload/Items[$loop]
 to exp : $Param.payload

- Add replace to replace the service input with Param
Replace "." in input.payload with Exp : $Param.payload
Replace entire node
---------------------------------------------

- After the service invoke add Insert
Exp : $output.payload
LOcation : as first chil of
Xpath : .
Variable : response.payload
5. Right click split join.flow -> OSB -> Generate BS

Thats it split join is done !!

This is how it will look like in eclipse:



Transactions - One way Bpel


The first thing that comes to mind while testing the transaction management using 1 way Bpel is its Asynchronous and Transaction will not span across process.

However there are good amount of properties that actually impacts this , here are the properties from Dev guide that will actually makes lot of difference :
http://docs.oracle.com/cd/E21764_01/integration.1111/e10224/soa_transactions.htm#CHDHEAIC

- onewayDeliveryPolicy=async.persist
- onewayDeliveryPolicy=sync and transaction=requiresNew
- onewayDeliveryPolicy=sync and transaction=required

These properties doesn't actually behaves as it seems from there name :
transaction=requiresNew , This works in combination with onewayDeliveryPolicy=sync if we want the callee BPEL to execute in a different Transaction and all the BPEL involved will work in there atomic boundaries.

We also got confused with other Partner link properties :
idempotent = false
startnonblockinginvoke = true

These will force the Callee bpel to start a new transaction but will force the caller to dehyderate and commit the transaction before calling the second process.


Bottom Line : Use these properties with caution and as per your requirement.

Installing Oracle service registry


Oracle service registry is one of the usefull tool for SOA governance, here are the steps to install it.

1.   Use Weblogic 10.1.2, as the OSR version is 11.1.1.2, using the same version will not cause any   issue.
·         If we don’t use this then while opening the registry web , linking error and other error will come, the suggestion is to use Patch 9499508, however that again didn’t solved the error for me
-          Error 500--Internal Server Error org.idoox.wasp.WaspInternalException: java.lang.RuntimeException: Updates to config files not supported
-          registry: Error initializing servlet
-          Error 500--Internal Server Error
java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "com.idoox.wsdl.DefinitionImpl.getMessage(Ljavax/xml/namespace/QName;)Ljavax

2. Install WLS  10.1.2 and then use the same home for OSR installation.

3.  Use create schema option during installation, if you already have a Database setup normally if you are using the same database as for SOA

4.       If get error during re-install use option of connect to  existing schema
5.       The registry home should be inside wls home like
D:\Oracle\Mdw_Reg\home_11gR1
D:\Oracle\Mdw_Reg\home_11gR1\registry111
If this is not set the registry option will not show up while creating domain

6. After installing OSR , create/extend the existing domain.

7. In Jdeveloper create UDDI connection , give inquiry url as :

http://localhost:7101/registry/uddi/inquiry
default port for OSR os 7101

To login :
http://localhost:7101/registry/uddi/web
user/pwd : admin/welcome1

8. To publish the service from Jdev , open the Application server navigation.
Create Business entity: my_uddi_business



- publish wsdl to buss entity , use admin account

- use the service end point from UDDI to create Bpel



If get following error:

java.lang.Exception: oracle.sysman.emSDK.webservices.wsdlapi.SoapTestException: oracle.fabric.common.FabricInvocationException: Could not lookup the service endpoint

from UDDI either due to a UDDI connection error or the provided



Remove user/pwd from EM enquiry url.



Best practice is to install OSR in a separate server than SOA , you wont get any issue. if you need SOA + OSR to coexist than need to apply the patch and modify the domainENV file.

A great post about how to use OSR in your composite application is here :
http://biemond.blogspot.com/2009/12/using-oracle-service-registry-in-soa.html


This works !!

Java Callout with Collection in OSB


Java callout in OSB normally works well with primitives , however at times you may need to call java callout for custom objects/collections.
The guide says "You can also use Java callouts to create Java objects to store in the pipeline and to pass Java objects as parameters to other Java callouts. "

What does that mean: To pass a Collection to a java callout , call another java callout that returns the collection and pass this to the main java callout. Like :

- I have list of Strings
- And the java method1 takes ArrayList as input

What i did :
1. Created another java callout for method2 to convert strings to Arraylist
2. passed this Arraylist to method1

This approach looks tedious but strangely thats the way out .

Happy coding !!

The Strange Flow activity in Bpel


As per the dev guide and docs , Flow activity is supposed to execute the sequences inside in multiple threads , however it doesnt actually behave that way normally.
Does Setting non Blocking invoke for partner links really helps ?

Here is a very good article about it and the summary by Luccas Jellema:
-----------------------------------------------------------------------------------------------------------------------------
Flow in BPEL (or at least Oracle BPEL PM) allows for parallel branches of activities. When executed, the branches in the Flow get their turn to execute the next step. Steps are not truly executed at the same time – which may be a blessing in disguise in situations where activities in various branches access the same variables. Even synchronous calls with nonBlockingInvoke set to true (however, I may have set that property in an incorrect way or TP4 of BPEL may not yet provide proper support for that property) block other activities from being processed. Only asynchronous activities such as Receive (wait for response to invoke of an Asynchronous Service) will allow other activities in other branches to be executed. I had expected this also to apply to Wait – but that turned out not be the case in TP4.

-----------------------------------------------------------------------------------------------------------------------------
It looks a peformance hit at first sight and a blessing in disguise at second .

Custom SDO method with View Criteria using IN clause


IN Clause in Custom method:

1. Create type:
CREATE OR REPLACE TYPE  "IDTABTYPE"  as table of varchar2(4000);

2. Create a bind variable that will hold all the input ID's
dept_names_var -> oracle.jbo.Array
ColumnType="IDTABTYPE"
ElemType="java.lang.String"
Like :

  <Variable
    Name="dept_names_var"
    Kind="where"
    Type="oracle.jbo.domain.Array"
    ElemType="java.lang.String"
    ColumnType="IDTABTYPE"/>

3. Create VC using this variable: DepartmentNameVC
DepartmentName = Bind Var -> dept_names_var
Like :
 ( ( ( UPPER(DepartmentsEO.DEPARTMENT_NAME) = UPPER(:dept_names_var)  )  OR  ( :dept_names_var IS NULL ) ) )


4. Generate VORowImpl and VOImpl

5. In VOImpl create methods for creating IN Clause , one for fetch from DataBase and one for cache
 
  Like :
  whereCluase =this.getEntityDef(0).getAliasName() + ".DEPARTMENT_NAME IN (SELECT * FROM TABLE(CAST(:dept_names_var AS IDTABTYPE)))";  


   
6. In VOImpl

 Override:
 - protected void bindParametersForCollection [Can avoid overriding this]
 - public String getCriteriaItemClause

 Inside getCriteraItemClause fetch the IN clause created in methods created in step 5

6. Generate AMImpl class

 Create custom method that will be exposed in SDO for fetching departments based on list of department names.

   //custom Method
     public List<DepartmentsVORowImpl> findDeptsByNames(List<String> listOfNames) {
   
         List<DepartmentsVORowImpl> dept_list = new ArrayList<DepartmentsVORowImpl> ();
         DepartmentsVOImpl vo = (DepartmentsVOImpl)this.getDepartmentsVO1();
         vo.setApplyViewCriteriaName("DepartmentNameVC");
         vo.setNamedWhereClauseParam("dept_names_var", listOfNames.toArray());
         vo.executeQuery();
         while (vo.hasNext()) {
           DepartmentsVORowImpl r = (DepartmentsVORowImpl)vo.next();
          dept_list.add(r);
         }
           return dept_list;
     }
7. create service interface for AM

 - select the custom method, select the DepartmentVO from LOV

Define Bind variable as optional (uncheck required while creating Bind var), else you will get this error while executing any other operation on same VO
JBO-27122: SQL error during statement preparation.

Thats all !! it works

Setting MDS for Shared artifacts


With lots of artifacts (xsd,wsdl,dvm,rules..) in an organization , its very important to have a proper repository to strore them . Oracle MDS is a light weight repository with inherit support for SOA . Below are the steps needed to have it set up . MDS facilitates reusability and also makes the code independent of services deployed on any server being down. The other major benefit of MDS is to have dvm,rules persisted to memory once the changes are done to these artifacts from soa composer.

Steps :
1. create seed folder inside the Integration folder
D:\Oracle\Middleware\11114\jdev1114\jdeveloper\integration\seed
Inside seed-> apps
Here create project specific folders like :
LocalMDS -> xsd/dvm etc

This can be some other folder , like in source control like ADE/SCS :
WSH_MDS -> apps -> My_proj -> [xsd,dvm,rules,wsdl]

2. Copy the xsd, dvm inside the folders
Like in :
apps -> My_proj ->xsd
apps -> My_proj ->wsdl

3. Inside Jdev create connection for file based MDS
My_MDS  ->    MDS Root folder : C:\WSH_MDS\ This has to be one level above the apps folder

4. Use the artifacts wsdl,xsd,dvm from the MDS inside the SOA projects , dont copy the artifacts to project.

The usage should look like : oramds:/apps/My_proj/xsd/shipment_advice.xsd

5. The adf-config.xml will get updated as:
<namespace metadata-store-usage="mstore-usage_1" path="/apps"/>
and
       <metadata-store-usage id="mstore-usage_1">
       <metadata-store class-name="oracle.mds.persistence.stores.file.FileMetadataStore">
       <property value="C:/WSH_MDS/" name="metadata-path"/>
       <property value="apps" name="partition-name"/>
       </metadata-store>
      </metadata-store-usage>      
6. Deploy both MDS to server , use ANT scripts to deploy the MDS to server MDS.

7. Deploy composite to server.

Modification to referenced artifacts can be done directly inside MDS.

VO based on RefCursor returned from a stored procedure


ADF view objects can be heavily customized and works well most of the times. There may be sitautions when we need to create VO based on ref cusor returned by a stored procedure/function. Althogh there is no shortcut for this but definitely an extension to existing VO.

Steps:
- Create Proc/Function that returns ref cursor
   Function get_empdata(p_emp_id number,p_cursor OUT ref_cursor);
- Create a VO , select rows populated programmatically
- Dont create any attrs
- Once done with wizard and VOImpl is generated
Create the attrs in VO that you want (these are transient var)
    Like:
    Emp_id Number
    FirstName,LastName as string

- create a bind variable , this is used to pass the param for proc/function call dept_id Number

override the following methods in VOImpl
  -create
  -executeQueryForCollection
  -hasNextForCollection
  -createRowFromResultSet
  -getQueryHitCount
  -releaseUserDataForCollection
 
  write your custom method for calling the stored proc/function, like i created something like :
protected Object callStoredFunction(int sqlReturnType, String stmt,
        Object[] bindVars) {
        CallableStatement st = null;
        try {
          st = getDBTransaction().createCallableStatement("begin ? := " + stmt +
              "; end;", 0);
          st.registerOutParameter(1, sqlReturnType);
          if (bindVars != null) {
            for (int z = 0; z < bindVars.length; z++) {
              st.setObject(z + 2, bindVars[z]);
            }
          }
          st.executeUpdate();
          return st.getObject(1);
        }
        catch (SQLException e) {
          throw new JboException(e);
        }
      }

This VO is just like any other Read only VO and can have links to other view objects as well.

This works !!

Monday, April 11, 2011

Polymorphic VO


Polymorphic VO is one of the interesting feature for ADF business components , you can define parent-child hierarchy in Entity objects and can use single VO on base EO to retrieve diff childs .

Steps :
1. Create Base EO like Persons EO
-Keep attrs relevent to Person and remove others
-Select the discriminator check box for person_type and give default as 'PERS'

2. Create SubTypes
- Create EmployeeEO and extends it from Persons EO
- add additional columns from Table [Salary]
- override discriminator  column give default as 'Employee'

- Create CustomerEO and extends it from Persons EO
- add additional columns from Table [Credit Limit]
- override discriminator  column give default as 'Cust'

3. Polymorphic VO

- Create VO based on base EO
- After selecting the base EO , select subtypes and select the other two EO's


Now the hierarchy is complete and you have Polymorphic VO that can represent diff EO types.

You will see following code in VO :
  <AttrArray Name="EntityImports">
    <Item Value="project1.EO.CustomerEO"/>
    <Item Value="project1.EO.EmployeeEO"/>
  </AttrArray>

This shows the types of entities it can refer to.

Rest Support from OSB


Couple of times we need to call Rest based services like HTTP Post from OSB/SOA layer, as of now there is no well defined adapter for this. Most of the times we end up using POJO for this.The HTTP adapter provided in SOA is quite basic and doesnt generally fits the requirement like when calling services with complex input data like multi-mime etc.
Here is steps that can be followed , however its completely driven by the requirement and need to be customized accordingly.
Use case :
- HTTP Post service that has to be called
- Input is multi mime and handshake is through the boundary defined
- No ssl or any other security need.

Steps:
1. Create a Business service in OSB
Service Type : Messaging Service
Request/Response Message Type   : Text
Protocol  : html
Endpoint URI  : http://mysupplier/serviceendpoint/
HTTP Request Method  : POST

Test this with your multimime input from test console,
pass the input in body and Content-Type: multipart/form-data; boundary=scm-shipping-oracle;utf-8

2. Create proxy based on the business service .
Service Type : Messaging Service
Request/Response Message Type   : Text
Protocol  : html

Test this with your multimime input from test console ,
pass the input in body and Content-Type: Content-Type: multipart/form-data; boundary=scm-shipping-oracle;utf-8

- You can add alert here to display the body and attachment data

3. Create another proxy to call the proxy created in previous step, I added this to put customization logic and to not

disturb the proxy->Buss service route created in previous step.

In message flow :
- Set Transport Headers for outbound request
Content-Type: Content-Type: multipart/form-data; boundary=scm-shipping-oracle;utf-8

- Add Java callout to read the attachment data , the java callout must return org.apache.xmlbeans.XmlObject
- add replace for attachment with the java callout output [replace entire node]
- While responding can add another java callout to write the attachment , can use xs:string($attach_resp) to cast attachment to string.

This all is done.

4. Now to call this from bpel can add a proxy based on wsdl that calls the proxy created in 3rd step.

This works !!

State Caching , coherence


For SOA Domain if HA is needed , set the following properties in the weblogic server startup argument.

-Dtangosol.coherence.wka1=apphost1vhn1 -Dtangosol.coherence.wka1.port=<port1>
-Dtangosol.coherence.wka2=apphost2vhn1  -Dtangosol.coherence.wka2.port=<port1>
-Dtangosol.coherence.localhost=apphost1vhn1 -Dtangosol.coherence.localport=<port1>

Fusion Applications the New Age ERP


http://www.oracle.com/us/products/applications/fusion/index.html

Looks great to me , and yeah proud to be part of its Development .