backlogic quick-start tutorial · install oracle xe database upgrade oracle apex install backlogic...
TRANSCRIPT
BackLogic Quick-Start Tutorial
This quick-start tutorial includes step-by-step instructions on
Setting up BackLogic
Writing service procedures
Publishing service procedures, and
Testing service procedures
This tutorial includes further exercises on:
Querying data with PRDS_SQL
Saving data with PRDS_SQL
For the purpose of this tutorial, the planned setup is Oracle embedded PL/SQL gateway plus
Apache HTTP server on Windows. For the convenience of users, this tutorial also includes
instructions on installation of Oracle XE database and on installation of Apache HTTP server.
Setting Up BackLogic
For the purpose of this tutorial, setting up BackLogic includes the following steps:
Install Oracle XE database
Upgrade Oracle APEX
Install BackLogic framework
Configure embedded PL/SQL gateway, and
Install GnuWin32 (Windows version of “sed” utility command, used with Apache input
filter)
Install and Configure Apache HTTP Server
Test BackLogic setup
Install Oracle XE database
Download Oracle XE 11g R2
http://www.oracle.com/technetwork/database/database-technologies/express-
edition/downloads/index.html
Unzip the downloaded file, which creates a “~/Disk1” folder
Navigate to the “~/Disk1” folder from Windows Explorer
Run setup.exe
Copyright© BackLogic Systems LLC Page 1
Finish installation by following installer instruction (Database should be running at end
of installation)
Record the XML HTTP port you set during installation, for purpose of later Apache
reverse proxy configuration.
Upgrade APEX
Download APEX 4.2.5
http://www.oracle.com/technetwork/developer-
tools/apex/downloads/index.html?ssSourceSiteId=otnru
Unzip the downloaded file, which creates a “~/apex” folder
Navigate to the “~/apex” directory from Command Window
Connect to database as SYS
sqlplus /nolog
conn SYS as sysdba
Run installation script
@apxrtins.sql SYSAUX SYSAUX TEMP /i/
This step may take 30 min to complete.
Reconnect to database as SYS
sqlplus /nolog
conn SYS as sysdba
Run following scripts to install json parser
alter session set current_schema = APEX_040200;
@core/wwv_flow_json.sql
@core/wwv_flow_json.plb
grant execute on apex_040200.wwv_flow_json to public;
create public synonym apex_json for apex_040200.wwv_flow_json;
exit
Install BackLogic
Download BackLogic software
http://backlogic.net/download.html#
Navigate to the “~/prds” directory from Command Window
Unzip the downloaded file, which creates a “~/prds” folder
Connect to database as SYS
sqlplus /nolog
conn SYS as sysdba
Copyright© BackLogic Systems LLC Page 2
Run installation script
@install.sql
Note:
This script creates and installs BackLogic packages in a new user schema PRDS. The default
password for PRDS is prdsadmin.
Configure Embedded PL/SQL Gateway (EPG)
Connect to database as SYS
sqlplus /nolog
conn SYS as sysdba
Run following scripts to configure EPG
EXEC DBMS_EPG.CREATE_DAD('PRDS', '/prds/*')
EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('PRDS', 'path-alias', 'rest')
EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('PRDS','path-alias-
procedure','prds_rest.service')
EXEC DBMS_EPG.SET_DAD_ATTRIBUTE('PRDS', 'database-username', 'PRDS')
EXEC DBMS_EPG.AUTHORIZE_DAD('PRDS', 'PRDS')
exit
Install GnuWin32
Download GnuWin32
http://gnuwin32.sourceforge.net/packages/sed.htm
Note:
Get “Setup” not “zip” for complete package, for easy installation
Run downloaded file (sed-4.2.1-setup.exe) to start installation
Finish installation by following installer instruction
Install and Configure Apache HTTP Server
Install Apache Server
Download Apache HTTP Server 2.4
https://www.apachelounge.com/download/
Unzip downloaded file, which creates a “~/Apache24/” folder
Copyright© BackLogic Systems LLC Page 3
Note:
Get VC10 Win 64 or VC10 Win 32 to reduce chance of having to do for Visual C++ installation)
Configure Apache Server
Navigate to the “~/Apache24/” folder from Windows Explorer
Open and Edit the “httpd.conf” file
Update Apache directory in following lines:
ServerRoot "C:\Program Files\Apache24"
DocumentRoot "C:\Program Files\Apache24\htdocs"
<Directory "C:\Program Files\Apache24\htdocs">
Uncomment following modules:
LoadModule ext_filter_module modules/mod_ext_filter.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
Add following configurations at end of file:
#Reverse Proxy
ProxyRequests off
ProxyPass /prds/ http://localhost:8080/prds/rest
ProxyPassReverse /prds/ http://localhost:8080/prds/rest
#JSON Filter
ExtFilterDefine json mode=input intype=application/json cmd="C:\\Program\
Files\ (x86)\\GnuWin32\\bin\\sed.exe 1s/^/i=/"
<Location /prds/rest/>
SetInputFilter json
</Location>
Save change in “httpd.conf”
Note:
The above configurations assume:
The database HTTP port is 8080 (see ProxyPass and ProxyPassReverse)
Apache use default HTTP port 80 (see Listen)
Apache 2.4 is installed in “C:\Program Files\Apache24” (see ServerRoot, DocumentRoot
and <Directory>)
GnuWin32 is installed in “C:\Program Files (x86)\GunWin32” (see ExtFilterDefine)
Modify if not true.
Install BackLogic Testing Page to Apache server
Copyright© BackLogic Systems LLC Page 4
Navigate to the “~/Apache24/htdocs” folder form Windows Explorer
Create a new folder “prds” in the above folder
Copy the “testing.html” file from the BackLogic download folder “~/prds” to the new
folder “~/Apache24/htdocs/prds”
Start Apache Server
Navigate to the “~/Apache24/bin” directory from Command Window
Run “httpd.exe” to start Apache server
Test BackLogic Setup
For purpose of this tutorial, we will use the BackLogic Testing Page that comes with the
BackLogic download for all BackLogic testing:
Open a web browser and load the BackLogic Testing Page
http://localhost:80/prds/testing.html
On the BackLogic Testing Page
Enter URL:
http://localhost:80/prds/prds_rest/test
Enter JSON input:
{"hello":"World"}
Click “Submit” , you expect to see the following response:
{
"success": true,
"data": {
"hello": "World"
}
}
If you do see above response, congratulations! You have successfully completed the BackLogic
setup.
The setup process is expected to be fairly smooth. However, in case that you do encounter issues
that cannot be solved easily, please post your problem in BackLogic forum.
Writing Service Procedure
For purpose of this tutorial, we write a simple service procedure that takes a name from client
request and returns “Hi name!” as response.
Copyright© BackLogic Systems LLC Page 5
Package Specification
CREATE OR REPLACE PACKAGE greeting_service
AS
PROCEDURE HiMe(p_input IN PRDS_JSON, p_output OUT PRDS_JSON);
END;
/
Note that the service procedure must be placed in a PL/SQL package and must implement a
standard service interface that includes one PRDS_JSON input parameter and one PRDS_JSON
output parameter as shown.
Package Body
CREATE OR REPLACE PACKAGE BODY greeting_service
AS
PROCEDURE HiMe(p_input IN PRDS_JSON, p_output OUT PRDS_JSON)
AS
v_name VARCHAR2(100);
BEGIN
-- validate input
IF ( NOT p_input.exist('name') ) THEN
prds_exception.invalid_input('Name is missing!');
END IF;
-- get name
v_name := p_input.get('name');
-- validate name
IF ( length(v_name) > 10 ) THEN
prds_exception.invalid_transaction('Your name is too long!');
END IF;
-- construct output
p_output := prds_json.newObject();
p_output.put('hello', ('Hi ' || v_name || '!') );
END HiMe;
END;
/
Note that the HiMe procedure is purposely made more complicated than necessary to
additionally demo how input and business validation failures are supposed to be handled.
Package Compilation
For purpose of this tutorial, compile the above package in the PRDS schema.
Copyright© BackLogic Systems LLC Page 6
Publishing Service Procedure
Since the “greeting_Service” package is compiled directly in the PRDS schema, it is
automatically published and is ready to test. Otherwise, privilege to execute the package needs
to be granted to user PRDS.
Testing Service Procedure
Testing Tool
Open the BackLogic Testing Page in your web browser:
http://localhost:80/prds/testing.html
Testing URL
http://localhost:80/prds/rest/greeting_service/HiMe
Paste the above URL in the URL field of the Testing Page. Please notice how the service
package name (greeting_service) and procedure name (HiMe) are included in the URL.
Test Happy Path
Paste the following into the JSON input field of the Testing Page:
{"name":"John"}
Click “Submit” and you should get the following response:
{
"success": true,
"data": {
"hello": "Hi John!"
}
}
Test Exceptions:
Paste the following JSON:
{"name":"John Benjemin James"}
Click “Submit” and you should get:
{
"success": false,
"exception": {
"type": "InvalidTransaction",
Copyright© BackLogic Systems LLC Page 7
"message": "Your name is too long!",
"detail": null
}
}
Paste the following JSON:
{"hello":"John"}
Click “Submit” and you should get:
{
"success": false,
"exception": {
"type": "InvalidInput",
"message": "Name is missing!",
"detail": null
}
}
As the “name” property is not present in the input JSON.
Service Procedure Exercises
Overview
The exercises in this tutorial are based on the HR tables installed with Oracle database, including
locations
departments
employees
jobs, and
job_history
The relationships between these relations are basically:
a location has zero or many departments
a department has zero or many employees and zero or one manger, who is a glorified
employee
an employee has one current job and zero or many job history entries
a job history entry is associated with one job
The exercises included in this tutorial are:
Query department records by location
Query all locations along with departments
Saving employee records
Copyright© BackLogic Systems LLC Page 8
For these exercises, we will create a spate user schema, namely PRDSUSER, to host the service
procedures. To create this new user:
Connect to database as SYS from Command Window
sqlplus /nolog
conn sys as sysdba
Execute the following scripts
create user prdsuser identified by prdsuser;
grant connect, resource to prdsuser;
grant create public synonym to prdsuser;
grant all on hr.locations to prdsuser;
grant all on hr.departments to prdsuser;
grant all on hr.employees to prdsuser;
grant all on hr.jobs to prdsuser;
grant all on hr.job_history to prdsuser;
grant select on hr.employees_seq to prdsuser;
We are now ready for the exercises.
Exercise #1 Query Departments by Location
Requirements:
Purpose:
Write a service procedure to return the department records for a given location id.
This is a trivial exercise in the sense that it is a simple table dump, but it showcases how
convenient it is to hold the SQL statement and to bind an input parameter with REF CURSOR.
Input:
{locationId:1700}
Output:
[
{
"DEPARTMENT_ID": 160,
"DEPARTMENT_NAME": "Benefits",
"LOCATION_ID": 1700,
"MANAGER_ID": null
},
...
]
Copyright© BackLogic Systems LLC Page 9
Write Service Procedure
Specification:
Create package “tutorial_exercises” and procedure “depts_by_location” specification as in the
following:
CREATE OR REPLACE PACKAGE tutorial_exercises
AS
PROCEDURE depts_by_location (p_input IN prds_json, p_output OUT prds_json);
END;
/
Implementation:
Create the package and procedure body as in the following:
CREATE OR REPLACE PACKAGE BODY tutorial_exercises
AS
PROCEDURE depts_by_location (p_input IN prds_json, p_output OUT prds_json)
AS
cur sys_refcursor;
BEGIN
-- open cursor
OPEN cur FOR
SELECT * FROM hr.departments
WHERE location_id = p_input.getNumber('locationId');
-- crate output json from cursor
p_output := prds_sql.cursor_to_array(cur);
END depts_by_location;
END;
/
Publish Service Procedure
Connect to database as PRDSUSER
sqlplus prdsuser/prdsuser
Execute following:
grant execute on tutorial_exercises to prds;
Test Service Procedure
URL:
/prds/rest/prdsuser/tutorial_exercises/depts_by_location
JSON input:
Copyright© BackLogic Systems LLC Page 10
{locationId:1800}
Response:
{
"success": true,
"data": [
{
"DEPARTMENT_ID": 20,
"DEPARTMENT_NAME": "Marketing",
"LOCATION_ID": 1800,
"MANAGER_ID": 201
}
]
}
Exercise #2 Query All Locations Along with Departments
Requirements:
Purpose:
Write a service procedure to return all locations along with departments in each location,
manager and employees in each department, and job history for each employee.
This exercise not only illustrates how to write the SQL for a structured JSON, but also
showcases the power of the BackLogic object-relation transformation engine.
Input:
{}
Output:
[
{
"locId": 1700,
"city": "Seattle",
"state": "Washington",
"country": "US",
"departments": [
{
"deptId": 90,
"deptName": "Executive",
"employees": [
{
"email": "NKOCHHAR",
"empId": 101,
Copyright© BackLogic Systems LLC Page 11
"firstName": "Neena",
"lastName": "Kochhar",
"phone": "515.123.4568",
"title": "Administration Vice President"
"jobHistory": [
{
"endDate": "2005-03-15T00:00:00Z",
"startDate": "2001-10-28T00:00:00Z",
"title": "Accounting Manager"
},
...
]
},
...
],
"manager": {
"email": "SKING",
"empId": 100,
"firstName": "Steven",
"lastName": "King",
"phone": "515.123.4567",
"title": "President"
}
},
...
]
},
...
]
For this exercise, the output is a deep-nested structure. The requirement is to return a list of
locations; within each location is a list of departments; within each department are a manager
object and a list of employees; within each employee is a list of job history.
Write Service Procedure
Specification:
Add procedure “locations” to package “tutorial_exercises”:
CREATE OR REPLACE PACKAGE tutorial_exercises
AS
PROCEDURE depts_by_location (p_input IN prds_json, p_output OUT prds_json);
PROCEDURE locations (p_input IN prds_json, p_output OUT prds_json);
END;
/
Copyright© BackLogic Systems LLC Page 12
Implementation:
This procedure is not as straightforward as the previous one. We will do it by steps.
Firstly, add a skeleton for the “locations” procedure to the body of “tutorial_exercises” package:
...
PROCEDURE location (p_input IN prds_json, p_output OUT prds_json)
AS
cur sys_refcursor;
BEGIN
-- open cursor
OPEN cur FOR
-- select statement
-- crate output json from cursor
p_output := prds_sql.cursor_to_array(cur);
END location;
...
The select statement for the cursor is to be worked out in the subsequent steps.
Secondly, write the query to get all information needed to fulfill the output, and test it to make
sure it works:
select l.location_id,
l.country_id,
l.state_province,
l.city,
d.department_id,
d.department_name,
m.employee_id,
m.first_name,
m.last_name,
m.email,
m.phone_number,
mj.job_title,
e.employee_id,
e.first_name,
e.last_name,
e.email,
e.phone_number,
ej.job_title,
h.start_date,
h.end_date,
hj.job_title
from hr.locations l,
hr.departments d,
hr.employees m,
Copyright© BackLogic Systems LLC Page 13
hr.jobs mj,
hr.employees e,
hr.jobs ej,
hr.job_history h,
hr.jobs hj
where d.location_id(+) = l.location_id
and m.employee_id(+) = d.manager_id
and mj.job_id(+) = m.job_id
and e.department_id(+) = d.department_id
and ej.job_id(+) = e.job_id
and h.employee_id(+) = e.employee_id
and hj.job_id(+) = h.job_id
The out joins are used in the query, because not all locations have departments, not all
departments have manager and employees, and not all employees have job history.
Thirdly, add target JSON structure information to the query as column aliases:
select l.location_id As "locId",
l.country_id As "country",
l.state_province As "state",
l.city As "city",
d.department_id As "departments[.deptId",
d.department_name As "departments[.deptName",
m.employee_id As "departments[.manager.empId",
m.first_name As "departments[.manager.firstName",
m.last_name As "departments[.manager.lastName",
m.email As "departments[.manager.email",
m.phone_number As "departments[.manager.phone",
mj.job_title As "departments[.manager.title",
e.employee_id As "departments[.employees[.empId",
e.first_name As "departments[.employees[.firstName",
e.last_name As "departments[.employees[.lastname",
e.email As "departments[.employees[.email",
e.phone_number As "departments[.employees[.phone",
ej.job_title As "departments[.employees[.title",
h.start_date As "departments[.employees[.jobHistory[.startDate",
h.end_date As "departments[.employees[.jobHistory[.endDate",
hj.job_title As "departments[.employees[.jobHistory[.title"
from hr.locations l,
hr.departments d,
hr.employees m,
hr.jobs mj,
hr.employees e,
hr.jobs ej,
hr.job_history h,
hr.jobs hj
where d.location_id(+) = l.location_id
Copyright© BackLogic Systems LLC Page 14
and m.employee_id(+) = d.manager_id
and mj.job_id(+) = m.job_id
and e.department_id(+) = d.department_id
and ej.job_id(+) = e.job_id
and h.employee_id(+) = e.employee_id
and hj.job_id(+) = h.job_id
Notice how “departments[“ is used to indicate that “departments” is an array.
Fourthly, test the above query and we will find that the Oracle complains come columns are too
long (over 30 characters). To resolve this issue, we will an alias “emp” to substitute
“departments[.employees[” in the query:
select l.location_id As "locId",
l.country_id As "country",
l.state_province As "state",
l.city As "city",
d.department_id As "departments[.deptId",
d.department_name As "departments[.deptName",
m.employee_id As "departments[.manager.empId",
m.first_name As "departments[.manager.firstName",
m.last_name As "departments[.manager.lastName",
m.email As "departments[.manager.email",
m.phone_number As "departments[.manager.phone",
mj.job_title As "departments[.manager.title",
e.employee_id As "emp.empId",
e.first_name As "emp.firstName",
e.last_name As "emp.lastname",
e.email As "emp.email",
e.phone_number As "emp.phone",
ej.job_title As "emp.title",
h.start_date As "emp.jobHistory[.startDate",
h.end_date As "emp.jobHistory[.endDate",
hj.job_title As "emp.jobHistory[.title"
from hr.locations l,
hr.departments d,
hr.employees m,
hr.jobs mj,
hr.employees e,
hr.jobs ej,
hr.job_history h,
hr.jobs hj
where d.location_id(+) = l.location_id
and m.employee_id(+) = d.manager_id
and mj.job_id(+) = m.job_id
and e.department_id(+) = d.department_id
and ej.job_id(+) = e.job_id
and h.employee_id(+) = e.employee_id
Copyright© BackLogic Systems LLC Page 15
and hj.job_id(+) = h.job_id
Test it again and make sure it works now.
Lastly, paste the above query in the procedure:
...
PROCEDURE locations (p_input IN PRDS_JSON, p_output OUT PRDS_JSON)
AS
cur sys_refcursor;
alias_map prds_sql.map;
BEGIN
-- open cursor
OPEN cur FOR
select l.location_id As "locId",
l.country_id As "country",
l.state_province As "state",
l.city As "city",
d.department_id As "departments[.deptId",
d.department_name As "departments[.deptName",
m.employee_id As "departments[.manager.empId",
m.first_name As "departments[.manager.firstName",
m.last_name As "departments[.manager.lastName",
m.email As "departments[.manager.email",
m.phone_number As "departments[.manager.phone",
mj.job_title As "departments[.manager.title",
e.employee_id As "emp.empId",
e.first_name As "emp.firstName",
e.last_name As "emp.lastName",
e.email As "emp.email",
e.phone_number As "emp.phone",
ej.job_title As "emp.title",
h.start_date As "emp.jobHistory[.startDate",
h.end_date As "emp.jobHistory[.endDate",
hj.job_title As "emp.jobHistory[.title"
from hr.locations l,
hr.departments d,
hr.employees m,
hr.jobs mj,
hr.employees e,
hr.jobs ej,
hr.job_history h,
hr.jobs hj
where d.location_id(+) = l.location_id
and m.employee_id(+) = d.manager_id
and mj.job_id(+) = m.job_id
and e.department_id(+) = d.department_id
and ej.job_id(+) = e.job_id
Copyright© BackLogic Systems LLC Page 16
and h.employee_id(+) = e.employee_id
and hj.job_id(+) = h.job_id;
-- create output from cursor
alias_map('emp') := 'departments[.employees[';
p_output := PRDS_SQL.CURSOR_TO_ARRAY(cur, alias_map);
END locations;
...
However, because we have used an alias “emp” in the query, we need to create an alias map and
pass it to the “prds_sql.cursor_to_array” procedure along with the ref cursor.
Publish Service Procedure
Since the privilege to execute the “tutorial_excercises” has been granted to PRDS, the service
procedure “locations” is automatically published.
Test Service Procedure
URL:
/prds/rest/prdsuser/tutorial_exercises/locations
JSON input:
{}
Response:
{
"success": true,
"data": [
{
"city": "Bern",
"country": "CH",
"departments": [],
"locId": 3000,
"state": "BE"
},
{
"city": "Geneva",
"country": "CH",
"departments": [],
"locId": 2900,
"state": "Geneve"
},
...
... a lot more
Copyright© BackLogic Systems LLC Page 17
Exercise #3 Save Employee Records
Requirements:
Purpose:
Write a service procedure to save a list of new and modified employee records.
This exercise is to learn how to use the PRDS_SQL package to save a list of simple records.
Input:
[
{
"EMPLOYEE_ID":100,
"PHONE_NUMBER":"909-345-6789"
},
{
"EMPLOYEE_ID":null, "FIRST_NAME":"Bob",
"LAST_NAME":"Smith", "EMAIL": "[email protected]",
"HIRE_DATE":"2007-01-03T00:00:00Z", "JOB_ID": "AC_ACCOUNT"
}
]
Output:
{
"count": 2
}
Write Service Procedure
Specification:
Add procedure “save_employees” to package “tutorial_exercises”:
CREATE OR REPLACE PACKAGE tutorial_exercises
AS
PROCEDURE depts_by_location (p_input IN prds_json, p_output OUT prds_json);
PROCEDURE locations (p_input IN prds_json, p_output OUT prds_json);
PROCEDURE save_employees (p_input IN prds_json, p_output OUT prds_json);
END;
/
Implementation:
...
PROCEDURE save_employees (p_input IN PRDS_JSON, p_output OUT PRDS_JSON)
AS
Copyright© BackLogic Systems LLC Page 18
v_count integer;
BEGIN
-- save data
v_count := prds_sql.save_rec(
table_name => 'HR.EMPLOYEES',
data => p_input,
sequence_name => 'HR.EMPLOYEES_SEQ',
id_property => 'EMPLOYEE_ID'
);
--prepare output
p_output := prds_json.newObject();
p_output.put('count', v_count);
END save_employees;
...
The “save_employee” procedure is straightforward, including only one call to save records and
two lines to prepare the output.
Publish Service Procedure
The service procedure “save_employees” is automatically published.
Test Service Procedure
URL:
/prds/rest/prdsuser/tutorial_exercises/save_employees
JSON input:
[
{
"EMPLOYEE_ID":100,
"PHONE_NUMBER":"909-345-6789"
},
{
"EMPLOYEE_ID":null, "FIRST_NAME":"Bob",
"LAST_NAME":"Smith", "EMAIL": "[email protected]",
"HIRE_DATE":"2007-01-03T00:00:00Z", "JOB_ID": "AC_ACCOUNT"
}
]
Response:
{
"success": true,
"data": {
"count": 2
Copyright© BackLogic Systems LLC Page 19
}
}
Note that the field name of the input JSON exactly matches the column name of the table,
including the case.
Exercise #4 Save Employee Records With Job History
Requirements:
Purpose:
Write a service procedure to save a list of new and modified structured employee records.
This exercise is to learn how to use the PRDS_SQL package to save a list of structured records.
Input:
[
{
"EMPLOYEE_ID":101,
"PHONE_NUMBER":"909-345-6789",
"JOB_HISTORY": [
{ "EMPLOYEE_ID":101, "START_DATE":"2007-01-03T00:00:00Z", "END_DATE":"2009-
01-03T00:00:00Z"},
...
]
},
...
]
Output:
{
"success": true,
"data": {
"empCount": 2,
"histCount": 4
}
}
Write Service Procedure
Specification:
Add procedure “save_employees” to package “tutorial_exercises”:
CREATE OR REPLACE PACKAGE tutorial_exercises
Copyright© BackLogic Systems LLC Page 20
AS
PROCEDURE depts_by_location (p_input IN prds_json, p_output OUT prds_json);
PROCEDURE locations (p_input in prds_json, p_output out prds_json);
PROCEDURE save_employees (p_input in prds_json, p_output out prds_json);
PROCEDURE save_employees_with_history (p_input IN PRDS_JSON, p_output OUT
PRDS_JSON);
END;
/
Implementation:
...
PROCEDURE save_employees_with_history (p_input IN PRDS_JSON, p_output OUT PRDS_JSON)
AS
v_emp_count integer := 0;
v_hist_count integer := 0;
v_employee prds_json;
v_employee_id integer;
v_job_history prds_json;
BEGIN
--loop through the employee records in the input
FOR i IN 1 .. p_input.length()
LOOP
-- get the employee record
v_employee := p_input.getElement(i);
v_job_history := v_employee.getArray('JOB_HISTORY');
-- get and populate employee id for new record
IF ( v_employee.get('EMPLOYEE_ID') IS NULL ) THEN
-- get id
SELECT hr.employees_seq.nextval INTO v_employee_id FROM dual;
-- populate employee record
v_employee.put('EMPLOYEE_ID', v_employee_id);
-- populate job history
FOR i IN 1..v_job_history.length()
LOOP
v_job_history.put('['||i||'].EMPLOYEE_ID', v_employee_id);
END LOOP;
END IF;
-- save the employee record
v_emp_count := v_emp_count +
prds_sql.save_rec(
table_name => 'HR.EMPLOYEES',
data => v_employee
-- id_property => 'employee_id'
);
Copyright© BackLogic Systems LLC Page 21
-- save the job history records
v_hist_count := v_hist_count +
prds_sql.save_rec(
table_name => 'HR.JOB_HISTORY',
data => v_job_history,
id_property => 'EMPLOYEE_ID,START_DATE'
);
END LOOP;
--prepare output
p_output := prds_json.newObject();
p_output.put('empCount', v_emp_count);
p_output.put('histCount', v_hist_count);
END save_employees_with_history;
...
This procedure is more complex than “save_employee”. Records are inserted into two tables.
Note how the employee_id obtained from the sequence are added to the “employee” record and
the “job_history” records.
Publish Service Procedure
The service procedure “save_employees” is automatically published.
Test Service Procedure
URL:
/prds/rest/prdsuser/tutorial_exercises/save_employees_with_job_history
JSON input:
[
{
"EMPLOYEE_ID":101,
"PHONE_NUMBER":"909-345-6789",
"JOB_HISTORY": [
{ "EMPLOYEE_ID":101, "START_DATE":"2003-10-03T00:00:00Z",
"END_DATE":"2005-01-03T00:00:00Z", "JOB_ID": "ST_CLERK" },
{ "EMPLOYEE_ID":101, "START_DATE":"2005-10-28T00:00:00Z",
"END_DATE":"2007-01-03T00:00:00Z", "JOB_ID": "ST_CLERK" }
]
},
{
"EMPLOYEE_ID":null, "FIRST_NAME":"Bob",
"LAST_NAME":"Smith", "EMAIL": "[email protected]",
"HIRE_DATE":"2005-01-03T00:00:00Z", "JOB_ID": "AC_MGR",
Copyright© BackLogic Systems LLC Page 22
"JOB_HISTORY": [
{ "START_DATE":"2001-10-03T00:00:00Z", "END_DATE":"2003-01-
03T00:00:00Z", "JOB_ID": "ST_CLERK" },
{ "START_DATE":"2005-01-23T00:00:00Z", "END_DATE":"2007-01-
03T00:00:00Z", "JOB_ID": "ST_CLERK" }
]
}
]
Response:
{
"success": true,
"data": {
"empCount": 2,
"histCount": 4
}
}
Note that the field name of the input JSON exactly matches the column name of the table,
including the case.