Monday, March 2, 2015

Use Spring SimpleJdbcCall to invoke Oracle stored procedure with

Here I would like to show a simple example of using Spring SimpleJdbcCall to invoke one Oracle stored procedure with out parameters as the table of the PL/SQL object.  


Maven

The Oracle database is Oracle 11g and JDBC driver class used ojdbc6-11.2.0.4.jar.  The below is Maven dependency in the project file.
  <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-jdbc</artifactId>
     <version>${spring.version}</version>
  <dependency>
     <groupId>com.oracle</groupId>
     <artifactId>ojdbc6</artifactId>
     <version>11.2.0.4</version>
  </dependency>


Table Schema

The below is DDL for the table BATCH.
  CREATE TABLE "BATCH" 
   ( 
      "ID" NUMBER NOT NULL, 
      "BATCH_NAME" VARCHAR2(256), 
      "BATCH_STATUS" VARCHAR2(20), 
      "LAST_UPDATE_DATE" DATE, 
      "CREATION_DATE" DATE, 
      "LAST_UPDATED_BY" VARCHAR2(100), 
      "CREATED_BY" VARCHAR2(100),
      CONSTRAINT BATCH_PK PRIMARY KEY (ID)
   ) ;


Object Type

In the database one object type: BATCH_REC is defined.
CREATE or REPLACE
TYPE BATCH_REC as OBJECT (
        BATCH_ID NUMBER(10,0), 
        BATCH_NAME VARCHAR2(256), 
        BATCH_STATUS VARCHAR2(20), 
        CREATION_DATE DATE,
 
        INVOICES            INVOICE_TAB
);

CREATE OR REPLACE
TYPE BATCH_TAB IS TABLE OF BATCH_REC; 
/


Stored Procedure

The stored procedure RETRIEVE_BATCH_BY_BATCHSTATUS is shown as below.  This is used to retrieve a list of batches by using batchStatus.  batchStatus is defined as in parameter and batches of type BATCH_TAB as out parameter.
CREATE OR REPLACE PROCEDURE "RETRIEVE_BATCH_BY_BATCHSTATUS" 
  ( 
    batchStatus in BATCH.BATCH_STATUS%TYPE,
    batches out BATCH_TAB,
    p_error_flag out varchar2,
    p_error_code out varchar2,
    p_error_message out varchar2
    ) 
IS 

BEGIN

  batches := BATCH_TAB();
  
  select BATCH_REC(bat.ID,
                   bat.BATCH_NAME,
                   bat.BATCH_STATUS, 
                   bat.VENDOR_SITE_ID,
                   bat.CREATION_DATE,
                   bat.LAST_UPDATE_DATE,
                   bat.LAST_UPDATED_BY,
                   bat.CREATED_BY) 
     bulk collect into batches                
     from BATCH bat where bat.BATCH_STATUS=batchStatus;
  
     p_error_flag := 'N';
   
    EXCEPTION
      WHEN OTHERS THEN
         p_error_code := SQLCODE;
         p_error_message := concat( concat( SQLERRM, '  '), dbms_utility.format_error_backtrace() ); 
         p_error_flag := 'Y';
      
END; 


Spring Class

Here is the DAO class which will use Spring SimpleJdbcCall to invoke the stored procedure: RETRIEVE_BATCH_BY_BATCHSTATUS.  In order to return a list of batches from SimpleJdbcCall there are some points worth to be noticed:  

  1. When declaring out parameter batches, specify its type as Types.ARRAY and also specify its type name as "BATCH_TAB" which is collection type defined in the database.
  2. After the invocation the return value of batches will be casted into the object of oracle.sql.ARRAY, from which the array will be casted into array of Object.
  3. When looping each object in the arry cast each object into oracle.sql.STRUCT.   From the object of STRUCT a list of attributes are obtained.  The values of the attribute match the values of BATCH_REC. 

    
public class BatchDAO {
    private static String PROC_NAME="RETRIEVE_BATCH_BY_BATCHSTATUS";
    
    private static String PARA_BATCHSTUS="batchStatus";
    
    private static String PARA_BATCHES="batches";
    
    private static String PARA_ERROR_FLAG="p_error_flag";
    
    private static String PARA_ERROR_CODE="p_error_code";
    
    private static String PARA_ERROR_MESSAGE="p_error_message";
    
    private SimpleJdbcCall simpleJdbcCall;

    @Autowired
    public void setDataSource(DataSource dataSource) {
        // Set up datasource
        this.simpleJdbcCall = new SimpleJdbcCall(dataSource)
                                  .withProcedureName(PROC_NAME)
                                  .declareParameters(
                                        new SqlParameter(PARA_BATCHSTUS, Types.VARCHAR),
                                        new SqlOutParameter(PARA_BATCHES, Types.ARRAY, "BATCH_TAB"),
                                        new SqlOutParameter(PARA_ERROR_FLAG, Types.VARCHAR),
                                        new SqlOutParameter(PARA_ERROR_CODE, Types.VARCHAR),
                                        new SqlOutParameter(PARA_ERROR_MESSAGE, Types.VARCHAR));
                                        
    }


    public List<Batch> getBatch(String status) throws ScanningException  {
        
        
        SqlParameterSource in = new MapSqlParameterSource().addValue(PARA_BATCHSTUS, status);

        Map<String, Object> out = simpleJdbcCall.execute(status);
        
        List<Batch> batches = new ArrayList<Batch>();
        String errorFlag = (String)out.get(PARA_ERROR_FLAG);
        
        if ( errorFlag.equals("N")) {
            try {
                ARRAY oracleObjectArray = (ARRAY)out.get(PARA_BATCHES);
                Object[] objArr = (Object[])oracleObjectArray.getArray();
                logger.info("Length of retrieved batches from database = "+objArr.length); 
                for (int i=0; i<objArr.length; i++) {
                    STRUCT st = (STRUCT)objArr[i];
                    Object[] obj = st.getAttributes();

                    Batch batch = new Batch();
                    batch.setBatchName((String)obj[1]);
                    batch.setStatus((String)obj[2]);
                    batch.setCreationDate((Date)obj[3]);
                    
                    batches.add(batch);
                }
            } catch (SQLException ex) {
                throw new ScanningException("SQLException occurred.", ex);
            }
        } else {
            String errorCode = (String)out.get(PARA_ERROR_CODE);
            String errorMessage = (String)out.get(PARA_ERROR_MESSAGE);
            
            throw new ScanningException("Exception occurred in "+PROC_NAME);
        }
        
        return batches;
    }
}

Thursday, October 16, 2014

AXF Redirect error from EBS workflow

Recently I had one test regarding viewing the managed attachment from EBS workflow.  During the test there was one error shown as the below when clicking on Managed Attachment.   The issue happened from OAF page to redirect to UCM url.  After some investigation I found one thing which causes this issue.  In AXF schema of EBS database there is table called: OAF_AXF_PROPERTIES.  One property is AXF_SOAP_USER.  Its value is UCM admin user name.  Because the wrong user name is put here it leads to the error.  After the value is corrected the issue is solved. 


Wednesday, September 10, 2014

Responsibility in EBS

In EBS it uses responsibilities to control user access to menus, forms, applications, data, functions and queries in Oracle E-Business Suite.   One EBS user is assigned certain responsibilities so he can access the application or modules to perform the works.  Meanwhile the responsibility also restricts him from other applications which are not open to the user.

Responsibilities are created and assigned through another responsibility called “System Administrator”.

Responsibility is associated with application.     One application can have multiple responsibilities.   One responsibility defines the access level for associated application.

Oracle comes with many pre-defined responsibilities.   Custom responsibility can be created.

A responsibility can be assigned to many users and a user can be assigned many responsibilities.  A user with multiple responsibilities can switch responsibilities after login into EBS.

Behind the scene all these are stored in several database tables:
                                     FND_USER,  
                                     FND_APPLICATION,                       
                                     FND_RESPONSIBILITY,
                                     FND_RESPONSIBILITY_TL,
                                     FND_SECURITY_GROUPS,
                                     FND_USER_RESP_GROUPS

Here the prefix FND stands for foundation table, suffix TL means that this table is basically the same as the table without TL but with language support.


FND_USER table stores details about the application user information such as name, email, encrypted password and etc.

FND_USER
Name                                                                   Null     Type         
----------------------------- ------------------------------------------------ -------------
USER_ID                                                            NOT NULL NUMBER(15)   
USER_NAME                                                    NOT NULL VARCHAR2(100)
EMAIL_ADDRESS                                                                VARCHAR2(240)
ENCRYPTED_FOUNDATION_PASSWORD NOT NULL VARCHAR2(100)
ENCRYPTED_USER_PASSWORD                 NOT NULL VARCHAR2(100)
………………..

FND_APPLICATION table defines the information about all applications in EBS.

FND_APPLICATION
Name                                                 Null               Type        
----------------------                            --------           ------------
APPLICATION_ID                            NOT NULL  NUMBER      
APPLICATION_SHORT_NAME     NOT NULL VARCHAR2(50)
LAST_UPDATE_DATE                    NOT NULL DATE        
LAST_UPDATED_BY                      NOT NULL NUMBER(15)  
CREATION_DATE                           NOT NULL DATE        
CREATED_BY                                  NOT NULL NUMBER(15)  
LAST_UPDATE_LOGIN                 NUMBER(15)  
BASEPATH                                      VARCHAR2(20)
PRODUCT_CODE                          VARCHAR2(50)


Responsibility is stored in the following tables:
FND_RESPONSIBILITY
FND_RESPONSIBILITY_TL

FND_RESPONSIBILTY table defines the information about all responsibilities in EBS.   It has responsibility Key which is the short name for responsibility. It also has its associated application and data group which is related to table FND_SECURITY_GROUPS.

FND_RESPONSIBILITY
Name                                                 Null               Type        
----------------------                            --------           ------------
APPLICATION_ID                            NOT NULL NUMBER(15)  
RESPONSIBILITY_ID                       NOT NULL NUMBER(15) 
RESPONSIBILITY_KEY                    NOT NULL VARCHAR2(30)
DATA_GROUP_ID                          NOT NULL NUMBER(15)      
………………


FND_RESPONSIBILITY_TL is almost same as FND_RESPONSIBILITY.   But it has the name of responsibility, which can is any user understandable name in specified language.

FND_RESPONSIBILITY_TL
Name                                         Null               Type         
------------------- -------- -----------------------------------------------
APPLICATION_ID                     NOT NULL NUMBER       
RESPONSIBILITY_ID               NOT NULL  NUMBER       
LANGUAGE                              NOT NULL  VARCHAR2(4)  
RESPONSIBILITY_NAME       NOT NULL  VARCHAR2(100)
DESCRIPTION                                               VARCHAR2(240)
…………



FND_SECURITY_GROUP Stores information about security groups used to partition data.

FND_SECURITY_GROUPS
Name               Null     Type        
------------------ -------- ------------
SECURITY_GROUP_ID      NOT NULL NUMBER(15)  
SECURITY_GROUP_KEY   NOT NULL VARCHAR2(30)
…………….

SECURITY_GROUP_ID SECURITY_GROUP_KEY             CREATED_BY CREATION_DATE LAST_UPDATED_BY LAST_UPDATE_DATE LAST_UPDATE_LOGIN
----------------- ------------------------------ ---------- ------------- --------------- ---------------- -----------------
                0 STANDARD                                1 09/OCT/98                   2 22/OCT/01                        0


FND_USER_RESP_GROUPS will define the assigned responsibilities for the users.  It is here that user – responsibility association is defined.

FND_USER_RESP_GROUPS
Name                          Null     Type      
----------------------------- -------- ----------
USER_ID                                                  NOT NULL NUMBER(15)
RESPONSIBILITY_ID                                                  NUMBER    
RESPONSIBILITY_APPLICATION_ID  NOT NULL NUMBER    
SECURITY_GROUP_ID                         NOT NULL NUMBER(15)
START_DATE                                                              DATE      
END_DATE                                                                 DATE      
DESCRIPTION                                                            VARCHAR2()
CREATED_BY                                                             NUMBER    
CREATION_DATE                                                      DATE      
LAST_UPDATED_BY                                                 NUMBER    
LAST_UPDATE_DATE                                               DATE      
LAST_UPDATE_LOGIN                                            NUMBER 


After understanding the schema of the above tables we can have some PL/SQL codes which can be used to query and manipulate the responsibility in the background.



Find the application short name by Responsibility name
SELECT FA.APPLICATION_SHORT_NAME,
                 FR.RESPONSIBILITY_KEY,
                 FRG.SECURITY_GROUP_KEY,                     
                 FRT.DESCRIPTION

     FROM FND_RESPONSIBILITY FR,
                 FND_APPLICATION FA,
                 FND_SECURITY_GROUPS FRG,
                 FND_RESPONSIBILITY_TL FRT
    WHERE FR.APPLICATION_ID = FA.APPLICATION_ID
      AND    FR.DATA_GROUP_ID = FRG.SECURITY_GROUP_ID
      AND    FR.RESPONSIBILITY_ID = FRT.RESPONSIBILITY_ID
      AND    FRT.LANGUAGE = 'US'
      AND    FRT.RESPONSIBILITY_NAME = 'Payables Manager';


Check the user’s responsibilities
SELECT  fu.USER_NAME,
               frt.RESPONSIBILITY_NAME
  FROM FND_USER_RESP_GROUPS furg,
              FND_USER fu,
              FND_RESPONSIBILITY_TL frt
 WHERE furg.USER_ID = fu.USER_ID
   AND    furg.RESPONSIBILITY_ID = frt.RESPONSIBILITY_ID
   AND    fu.USER_NAME  = 'CHEM307'


Check the user’s responsibilities
set serveroutput on format wrapped;

DECLARE
   v_user_name                  VARCHAR2 (100) := 'CHEM307';
   v_responsibility_name  VARCHAR2 (100) := 'Payables Manager';
   v_application_name      VARCHAR2 (50);
   v_responsibility_key      VARCHAR2 (30);
   v_security_group           VARCHAR2 (30);
   v_description                  VARCHAR2 (240);

BEGIN
   ----   Get the responsibility key, application name, security group and etc. for given responsibility name
   SELECT fa.APPLICATION_SHORT_NAME,
                 fr.RESPONSIBILITY_KEY,
                 frg.SECURITY_GROUP_KEY,                     
                 frt.DESCRIPTION
      INTO  v_application_name,
                 v_responsibility_key,
                 v_security_group,
                 v_description
     FROM FND_RESPONSIBILITY fr,
                 FND_APPLICATION fa,
                 FND_SCURITY_GROUPS frg,
                 FND_RESPONSIBILITY_TL frt
    WHERE fr.APPLICATION_ID = fa.APPLICATION_ID
      AND    fr.DATA_GROUP_ID = frg.SECURITY_GROUP_ID
      AND    fr.RESPONSIBILITY_ID = frt.RESPONSIBILITY_ID
      AND    frt.LANGUAGE = 'US'
      AND    frt.RESPONSIBILITY_NAME = v_responsibility_name;
 
    ----   Invoke addresp in fnd_user_pkg to assign the responsibility to the user
    fnd_user_pkg.addresp (username=> v_user_name,
                                               resp_app=> v_application_name,
                                               resp_key=> v_responsibility_key,
                                              security_group => v_security_group,
                                              description=> v_description,
                                              start_date=> SYSDATE,
                                              end_date=> NULL);

   DBMS_OUTPUT.put_line (   'Responsiblity ' || v_responsibility_name || ' is assigned to the user ' || v_user_name);
                         
EXCEPTION
   WHEN OTHERS
   THEN
      DBMS_OUTPUT.put_line(   'Error occurred while assigning responsibility to the user. The error is '|| SQLERRM );
END; 

Tuesday, June 24, 2014

Change JDK used by JDeveloper

You can change JDK used by JDeveloper.
The JDK configuration for JDeveloper is defined in the jdev.conf which located in your Jdeveloper folder JDeveloper\jdeveloper\jdev\bin.

Open the file and find the item:  SetJavaHome.  Change its value to your new JDK folder.

In the below example I switch JDK from JDK 7 to JDK 6 by commenting out JDK 7 and adding a new item for JDK 6. 

#SetJavaHome C:\Java\jdk1.7.0_06
SetJavaHome C:\Program Files\Java\jdk1.6.0_45

After saving the changes restart JDeveloper and it will use the new JDK set in jdev,conf.

You can check JDK used in JDeveloper from JDeveloper.   From JDeveloper goes to Help->About.  Then select the tab Properties and will find java.home properties now is set to the JDK specified in jdev.conf.


Monday, June 9, 2014

Set the composite name using function ora:setCompositeInstanceTitle()

ora:setCompositeInstanceTitle() can be used to set the name of the composite instance.  It is very useful because you can set the name of the composite instance using the values with business meaning.  It would be convenient for the support people to search for a particular instance by the business value.

It is can be done in either BPEL component or Mediator component.

Within BPEL component what needs to be done is set one variable using ora:setCompositeInstanceTitle() which can be found from Advanced Functions.  


<variable name="CompositeTitle" type="xsd:string"/>
<assign name="SetInstanceName">
      <copy>
        <from expression="ora:setCompositeInstanceTitle(concat('Test   :', ora:getCompositeInstanceId()) )"/>
        <to variable="CompositeTitle"/>
      </copy>        
</assign>





Within Mediator component it is done by setting one property using ora:setCompositeInstanceTitle().   Clicking on Assign Values button in the below diagram will start to set the value to the property.



In Assign Value popup window To type is selected as property and the property value is select as: tracking.compositeInstanceId.

From type is selected as expression. In the expression Builder select ora:setCompositeInstanceTitle() which can be found from Mediator Expression Functions.



Now the property is assigned which will set the composite title in Mediator.


Sunday, May 25, 2014

Sending email with attachments in Oracle SOA 11g

Here I show one generic BPLE service which will send the email with attachment.  


Generic Email Service Interface


The service interface is defined by the below xsd file.  In the request message apart from email to, from, subject and body elements there is one array of attachment elements which are sent with the email.

<element name="NotificationRequest">
 <complexType>
  <sequence>
   <element name="From" type="string" minOccurs="0"/>
   <element name="To" type="string"/>
   <element name="CC" type="string" minOccurs="0"/>
   <element name="Subject" type="string"/>
   <element name="Body" type="string" minOccurs="0"/>
   <element name="Attachment" type="tns:AttachmentType" minOccurs="0" maxOccurs="unbounded"/>
  </sequence>
 </complexType>
</element>
<complexType name="AttachmentType">
 <sequence>
  <element name="MimeType" type="string"/>
  <element name="AttachmentContent" type="anyType"/>
  <element name="AttachmentName" type="string"/>
  <element name="ContentEncoding" type="string"/>
 </sequence>
</complexType> 



Oracle Notification Service


This service will use Notification service provided by Oracle SOA 11g. Notification service uses Oracle User Messaging Service to send email, SMS, IM and etc. notification to the recipients.   Notification service can be invoked from BPEL process.   From JDeveloper you can choose the different notification channels.  For sending email you need to choose Email as below.


After dragging and dropping Email into BPEL process, NotificationService.wsdl and NotificationService.xsd are added to the project.  These wsdl and xsd files define the interface to Oracle User Messaging Service.  For request message which sends email is defined as EmailPayloadType.  The key to send the email with attachments is to populate the appropriate values in EmailPayload.

EmailPayloadType defines the request message for invoking Oracle Notification service to send the email.  
<xsd:complexType name="ContentType">
 <xsd:sequence>
  <xsd:element name="MimeType" type="xsd:string" default="text/plain" minOccurs="0"/>
  <xsd:element name="ContentBody" type="xsd:anyType" nillable="true"/>
  <xsd:element name="ContentEncoding" type="xsd:string" nillable="true"/>
 </xsd:sequence>
</xsd:complexType>

ContentType defines the email content.  Note here that ContentBody is defined as anyType.  In order to include the attachments in email there are two things needed to be done:

  • MimeType should be set as: multipart/mixed.   
  • ContentBody will use MultiPartType.


<xsd:complexType name="MultiPartType">
 <xsd:sequence>
  <xsd:element name="BodyPart" type="BodyPartType" maxOccurs="unbounded"/>
 </xsd:sequence>
</xsd:complexType>

The MultiPartType is an array of BodyPartType.  First element in thus array is the email body itself and the subsequent elements are the attachments for the email.
<xsd:complexType name="BodyPartType">
 <xsd:sequence>
  <xsd:element name="MimeType" type="xsd:string" default="text/plain" minOccurs="0"/>
  <xsd:element name="ContentBody" type="xsd:anyType" nillable="true"/>
  <xsd:element name="BodyPartName" type="xsd:string"/>
  <xsd:element name="Disposition" type="dispositionEnum" default="inline" minOccurs="0"/>
  <xsd:element name="ContentId" type="xsd:string" minOccurs="0"/>
  <xsd:element name="ContentEncoding" type="contentEncodingEnum" nillable="true"/>
  <xsd:element name="AttachmentContentEnclosed" type="xsd:boolean" default="true" minOccurs="0"/>
 </xsd:sequence>
</xsd:complexType>

BodyPartType defines the email body and attachment for the email.   MimeType specifies the type of data in email.   If the email body is HTML email the MimeType of email body(first Body Part) would be: "text/html; charset=UTF-8".   Depending on the attachments with the email the MimeType in BodyParts for attachments can be set the values of proper Mime type.   
Some of such values are shown below:
image/tiff;            - tiff image file
image/jpeg;            - jpeg image file   
application/pdf;       - PDF file
application/xml;       - XML file  
application/msword;    - MS Word file

ContentBody in BodyPartType will be the actual data for email body and attachment.  For the attachment the ContentEncoding will be set as base64. BodyPartName will be set as the file name for the attachment.

The below is one example of EmailPayload message which are populated with the data.  The email will have one attachment of .tiff image file whose name is Testing.tif.
<EmailPayload xsi:type="def:EmailPayloadType">
 <FromAccountName>Default</FromAccountName>
 <To>Mark_ke_chen@yahoo.com</To>
 <ReplyToAddress/>
 <Subject>Tesyimg email with one attachement</Subject>
 <Content>
  <ns:MimeType>multipart/mixed</ns:MimeType>
  <ns:ContentBody>
   <ns:MultiPart>
    <ns:BodyPart>
     <ns:MimeType>text/html; charset=UTF-8</ns:MimeType>
     <ns:ContentBody>
      ......  Email body here
     </ns:ContentBody>
     <ns:BodyPartName/>
     <Disposition>inline</Disposition>
    </ns:BodyPart>
    <ns:BodyPart>
     <ns:MimeType>image/tiff;</ns:MimeType>
     <ns:ContentBody>
      .... Tiff image data
     </ns:ContentBody>
     <ns:BodyPartName>Testing.tif</ns:BodyPartName>
     <ns:ContentEncoding>base64</ns:ContentEncoding>
     <Disposition>attachment</Disposition>
    </ns:BodyPart>
   </ns:MultiPart>
  </ns:ContentBody>
 </Content>
 <Cc/>
 <Bcc/>
 <NotificationContext/>
</EmailPayload>

Here use xlst transformation to populate the Content element.
<copy>
 <from expression="ora:processXSLT('xsl/EmailContentBodyTransform.xsl', $NotificationRequest.payload)"/>

 <to variable="varNotificationReq"
  part="EmailPayload"
  query="/EmailPayload/ns1:Content"/>
</copy>

The below is the snippet of XSLT transformation.
<ns:Content>
 <ns:MimeType>multipart/mixed</ns:MimeType>
 <ns:ContentBody>
  <ns:MultiPart>
   <ns:BodyPart>
    <ns:MimeType >text/html; charset=UTF-8</ns:MimeType>
    <ns:ContentBody>
     <xsl:value-of select="/*[local-name()='NotificationRequest']/*[local-name()='Body']"/>
    </ns:ContentBody>
    <ns:BodyPartName/>
   </ns:BodyPart>
   <xsl:for-each select="/*[local-name()='NotificationRequest']/*[local-name()='Attachment']">
    <ns:BodyPart >
     <ns:MimeType>
      <xsl:value-of select="./*[local-name()='MimeType']"/>
     </ns:MimeType>
     <ns:ContentBody >
      <xsl:value-of select="./*[local-name()='AttachmentContent']"/>
     </ns:ContentBody>
     <ns:BodyPartName>
      <xsl:value-of select="./*[local-name()='AttachmentName']"/>
     </ns:BodyPartName>
     <ns:ContentEncoding>
      <xsl:value-of select="./*[local-name()='ContentEncoding']"/>
     </ns:ContentEncoding>
    </ns:BodyPart>
   </xsl:for-each>
  </ns:MultiPart>
 </ns:ContentBody>
</ns:Content>


Testing Email service with attachments


In order to test this generic email service I have another BPEL service which will populate email body and attachment and then invoke the generic email service.  The below shows the two assign activities used in the BPEL to set the email body and email attachment.

<assign name="AssignEmailBody">
  <copy>
 <from expression="ora:toCDATA(  ora:processXSLT('xsl/TransformHTMLEmailBody.xsl', $Request.request, bpws:getVariableData('Parameters')) )"/>
 <to variable="EmailNotificationRequest" part="payload"
  query="/ns4:NotificationRequest/ns4:Body"/>
  </copy>
</assign>

<assign name="AssignEmailAttachment">
  <copy>
 <from expression="ora:readFile( $ImageFileName) )"/>
 <to variable="EmailNotificationRequest" part="payload"
  query="/ns4:NotificationRequest/ns4:Attachment/ns4:AttachmentContent"/>
  </copy>
</assign>

One assign is used to set the email body. Since the email is HTML format the assign activity uses ora:toCDATA to wrap the html content.   
Another assign activity uses orad:readFile function to read the physical file which is going to attach in the email.

Tuesday, May 20, 2014

Setting and Getting Configuration Property and Preference Variable in Oracle SOA Suite 11g

Configuration property and preference variable can be set in composite.xml.  The advantage of using these is that the values can be set in the design time, deployment time and run time.

Define the Properties and Preference Variables


The configuration property and preference variable is defined in composite.xml
In the component of the example composite one configuration property: ConfigVar is defined.  Its value is set Value123 initially. One preference varaible PrefVar is also defined and its value is set to Value789 initially.



In the reference of the example composite one configuration property: OUT_FILE_PATH is defined.  This property is set when configuring the logical file path for File adpter.   This property value is also defined in .jca file.


Retrive the Values of  the Properties and Preference Variables

The component is the example composite is BPEL process where the configuration properties and preference variables can be retrived from winthin BPEL.  The retrival can be done by using BPEL XPath Extension Functions: ora:getPreference() and ora: 

View and Midify the Values in Enterprise Manager


These values of the configuration properties and preference variables can be viewed and modified in run time with Enterprise Manager.   



After login into EM navigate into the domain and right click on the domain to invoke System MBean Browser.  From System MBean Browser navigate to Application Defined MBeans/oracle.soa.config/Server: SOA_server1/SCAComposite.   Expand it and expand SCAComposite: ConfigPreferenceProject[1.0].  



To view or modify the values defined for BPEL: select SCAComposite.SCAComponent and then click on BPELProcess1.  Then click on properties in Attribute tab.  All the configuration properties and preference variables defined in the BPEL are shown now.  





In order to change the value of one variable or property just type in the new value and then click on Apply button.

To view or modify the property values defined for reference: select SCAComposite.SCARefernce.  All other steps are the same as the above.



Similarily if there is any configuration property defined in SCAComposite.SCAService select SCAComposite,SCAService in order to view or modify the property values. 




Test the Composite with the Modified Values 

When testing the SCA composite using EM testing utility, the response will show the values of configuration and preference variable in BPEL process as :Value123   Value789".(This BPEL process simply concatenate these two values as the response for the process.) 


Next modify the value of configuration property to 123Value and preference value to 789Value and apply these changes.  Then run the testing again.   This time the response will show as the new values:


Deploy the Composite with Environment Specific Values

With configuration properties and preference variables in the component, service and references in SCA composite different deployment plans can be generated for various environments.  In each deployment plan the values for these properties and variables are environment specific.