Custom Interface Application Module Service to return Employee Information using Oracle E-Business Suite Integrated SOA Gateway

In this post, I will create a custom interface using Application Module Service as opposed to the Java Bean Service in my previous post here.

Using Application Module Service, we can take advantage of Oracle Application Framework (OAF) components like View Object (VO), Entity Object (EO) etc.

In this test case that I'm working on, I will be using just a view object and the application module.

Here are the details of the Employees View Object (EmployeesVO).

SQL Query
select person_id
     , effective_start_date
     , effective_end_date
     , employee_number
     , marital_status
     , date_of_birth
  from per_people_x
 where hr_person_type_usage_info.get_user_person_type(sysdate,person_id) like 'Employee%'
   and employee_number = nvl(:p_employee_number,employee_number)


Note that I added a bind variable p_employee_number. We'll use this to filter the results of the query later on.

Here are some more setting for the EmployeesVO. Check the "Generate Java File" and "Accessors" for the View Row Class: EmployeesVORowImpl as shown in the screen shot below. This will generate the necessary Java files which we will use to access the Row of the View Object.


Now we need to create the Application Module and attach the Employees View Object to it as shown in the screen shot below.


Next, we need to create a method getEmployees in the Application Module to fetch the rows. See the code below.

EmployeesAMImpl.java
package oracle.apps.per.sample.server;

import java.util.ArrayList;

import oracle.apps.fnd.framework.server.OAApplicationModuleImpl;

import oracle.apps.per.sample.beans.Employee;
import oracle.apps.per.sample.beans.EmployeeInfo;

import oracle.jbo.RowSetIterator;
// ---------------------------------------------------------------------
// ---    File generated by Oracle ADF Business Components Design Time.
// ---    Custom code may be added to this class.
// ---    Warning: Do not modify method signatures of generated methods.
// ---------------------------------------------------------------------

/**
 * A sample class to demonstrate how Application Module can use the ISG REST framework. This class provides
 * methods to return Employees
 * @rep:scope public
 * @rep:product PER
 * @rep:displayname Employees
 * @rep:category BUSINESS_ENTITY HR_USER_HOOK
 * @rep:category IREP_CLASS_SUBTYPE AM_SERVICES
 */
public class EmployeesAMImpl extends OAApplicationModuleImpl {
    /**This is the default constructor (do not remove)
     */
    public EmployeesAMImpl() {
    }

    public EmployeesVOImpl getEmployeesVO1() {
        return (EmployeesVOImpl)findViewObject("EmployeesVO1");
    }

    /**
     * 
     * This method returns Employee Info
     *
     * @param pEmployeeNumber Employee Number of the Employee
     * @return EmployeeInfo
     * @rep:paraminfo {@rep:innertype oracle.apps.per.sample.beans.EmployeeInfo}
     * @rep:scope public
     * @rep:displayname Get Employees
     * @rep:httpverb get
     */
    public EmployeeInfo getEmployees(String pEmployeeNumber) {
        EmployeeInfo info = new EmployeeInfo();
        ArrayList employees = new ArrayList();
        EmployeesVOImpl vo = getEmployeesVO1();
        
        if (pEmployeeNumber != null) {
            vo.setNamedWhereClauseParam("p_employee_number",pEmployeeNumber);
        }
        
        vo.executeQuery();

        RowSetIterator iter = vo.createRowSetIterator(null);
        iter.reset();

        while (iter.hasNext()) {
            EmployeesVORowImpl row = (EmployeesVORowImpl)iter.next();
            Employee emp = new Employee();
            emp.setPersonId(row.getPersonId().intValue());
            emp.setEffectiveStartdate(row.getEffectiveStartDate().dateValue());
            emp.setEffectiveEndDate(row.getEffectiveEndDate().dateValue());
            emp.setEmployeeNumber(row.getEmployeeNumber());
            emp.setMaritalStatus(row.getMaritalStatus());
            emp.setDateOfBirth(row.getDateOfBirth().dateValue());
            employees.add(emp);
        }
        
        info.setEmployees(employees);

        return info;
    }

}

Explanation

The following code is the java class with the required annotations for Oracle E-Business Suite Integrated SOA Gateway. You can refer here for more information on the required annotations.
/**
 * A sample class to demonstrate how Application Module can use the ISG REST framework. This class provides
 * methods to return Employees
 * @rep:scope public
 * @rep:product PER
 * @rep:displayname Employees
 * @rep:category BUSINESS_ENTITY HR_USER_HOOK
 * @rep:category IREP_CLASS_SUBTYPE AM_SERVICES
 */
public class EmployeesAMImpl extends OAApplicationModuleImpl {}

The following code is the method for getting the EmployeeInfo along with the required annotations. You can see here how we declared an EmployeeInfo, an ArrayList of Employee, how we used the View Object to get the data by iterating thru the rows, creating an Employee in each loop and adding it to the ArrayList. Then set the ArrayList to the EmployeeInfo and finally returning the EmployeeInfo. You will also see here the parameter pEmployeeNumber that was mentioned above. In here, I decided to make the parameter optional. If a value is passed then it returns the specific EmployeeInfo. Otherwise, returns all EmployeeInfo.
    /**
     * 
     * This method returns Employee Info
     *
     * @param pEmployeeNumber Employee Number of the Employee
     * @return EmployeeInfo
     * @rep:paraminfo {@rep:innertype oracle.apps.per.sample.beans.EmployeeInfo}
     * @rep:scope public
     * @rep:displayname Get Employees
     * @rep:httpverb get
     */
    public EmployeeInfo getEmployees(String pEmployeeNumber) {
        EmployeeInfo info = new EmployeeInfo();
        ArrayList employees = new ArrayList();
        EmployeesVOImpl vo = getEmployeesVO1();
        
        if (pEmployeeNumber != null || pEmployeeNumber.length() != 0) {
            vo.setNamedWhereClauseParam("p_employee_number",pEmployeeNumber);
        }
        
        vo.executeQuery();

        RowSetIterator iter = vo.createRowSetIterator(null);
        iter.reset();

        while (iter.hasNext()) {
            EmployeesVORowImpl row = (EmployeesVORowImpl)iter.next();
            Employee emp = new Employee();
            emp.setPersonId(row.getPersonId().intValue());
            emp.setEffectiveStartdate(row.getEffectiveStartDate().dateValue());
            emp.setEffectiveEndDate(row.getEffectiveEndDate().dateValue());
            emp.setEmployeeNumber(row.getEmployeeNumber());
            emp.setMaritalStatus(row.getMaritalStatus());
            emp.setDateOfBirth(row.getDateOfBirth().dateValue());
            employees.add(emp);
        }
        
        iter.closeRowSetIterator();
        info.setEmployees(employees);

        return info;
    }

Some pointers to remember when using this interface type.

Oracle Application Framework has a limited number of records allowed to fetch when querying data through a View Object. If you need to return more than the limit, I would suggestion to use an OraclePreparedStatement instead.

Oracle Integrated SOA Gateway doesn't seem to support Oracle Data Types ie. oracle.jbo.domain.Number, oracle.jbo.domain.Date and probably more. For some reason, I get an error "FND_SOA_SERVICE_EXECUTION_ERR" when invoking the service while using these types. I can invoke the service successfully if I use int and Date.

Oracle Integrated SOA Gateway also doesn't seem to support returning Arrays, ArrayList, List objects. I get the same error "FND_SOA_SERVICE_EXECUTION_ERR" if return these so I ended up creating an Employee class and an EmployeeInfo class with an ArrayList of Employee. Here are the codes below.

Employee.java
package oracle.apps.per.sample.beans;

import java.sql.Date;


public class Employee {

    private int personId;
    private Date effectiveStartdate;
    private Date effectiveEndDate;
    private String employeeNumber;
    private String maritalStatus;
    private Date dateOfBirth;
    
    public Employee() {
    }


    public void setPersonId(int personId) {
        this.personId = personId;
    }

    public Number getPersonId() {
        return personId;
    }

    public void setEffectiveStartdate(Date effectiveStartdate) {
        this.effectiveStartdate = effectiveStartdate;
    }

    public Date getEffectiveStartdate() {
        return effectiveStartdate;
    }

    public void setEffectiveEndDate(Date effectiveEndDate) {
        this.effectiveEndDate = effectiveEndDate;
    }

    public Date getEffectiveEndDate() {
        return effectiveEndDate;
    }

    public void setEmployeeNumber(String employeeNumber) {
        this.employeeNumber = employeeNumber;
    }

    public String getEmployeeNumber() {
        return employeeNumber;
    }

    public void setMaritalStatus(String maritalStatus) {
        this.maritalStatus = maritalStatus;
    }

    public String getMaritalStatus() {
        return maritalStatus;
    }

    public void setDateOfBirth(Date dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public Date getDateOfBirth() {
        return dateOfBirth;
    }
    
}
EmployeeInfo.java
package oracle.apps.per.sample.beans;

import java.util.List;

public class EmployeeInfo {

    private List employees;
    
    public EmployeeInfo() {
    }
    
    public void setEmployees(List employees) {
        this.employees = employees;
    }
    
    public List getEmployees() {
        return this.employees;
    }
}

Now we need to compile the java codes and then transfer the java files together with the class files to the appropriate folder in the server. Make sure that JAVA_HOME is set to $IAS_ORACLE_HOME/appsutil/jdk.


Then we generate the iLDT file with the following command:
$IAS_ORACLE_HOME/perl/bin/perl $FND_TOP/bin/irep_parser.pl -g -v -username=sysadmin per:patch/115/java:EmployeesAMImpl.java:12.1.21=$JAVA_TOP/oracle/apps/per/sample/server/EmployeesAMImpl.java

If successful, you should see something similar to the screen shot below.


Then we upload the iLDT to the Repository.

FNDLOAD apps/<apps_password> 0 Y UPLOAD $FND_TOP/patch/115/import/wfirep.lct EmployeesAMImpl_java.ildt

Now let’s check the service in the Repository.

Login to your Oracle E-Business Suite instance as SYSADMIN.



Switch to Integrated SOA Gateway responsibility.



Select Integration Repository



Click Search and then search for your service. In my case, I'll search for Employees.


Click the name of the service to see details of it.


Click the WADL link to get more information on how to invoke the service.


And now we invoke the REST web service. I will be using Postman for this. Since we made the parameter p_employee_number optional in the VO and handled the logic in the AM getEmployees method, we can choose to pass a value or not. To pass a value, we just need to add a query parameter pEmployeeNumber.


If we don't pass a value, then all records are returned.


And that's it. Enjoy!

Additional References

No comments:

Post a Comment