Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:ords_rest_service

Oracle ORDS 3.0 REST API nativ verwenden

2017/03

Ziel: Ein JSON Record soll als Webservice zur Verfügung gestellt werden.

Das ganze kann zwar auch direkt in der APEX Oberfläche über APEX erfolgen, hier soll aber eine saubere Trennung der Umgebung durchgeführt werden, es wird auf die native ORDS Methoden gesetzt.

Ein ORDS wurde bereits für die Verwendung mit APEX konfiguriert und eingerichtet ⇒ Oracle ORDS 3.0 (Oracle REST Data Services) mit APEX 5.0

Ablauf:

  • URL Mapping auf den DB Connection Pool „apex_pu“ (DB User „ORDS_PUBLIC_USER“ !) für den REST Aufruf einrichten
  • Datenbank Schema für REST aktivieren
  • Lesenden Zugriff auf das Schema einrichten
  • PL/SQL Code für den JSON erstellen und aufrufen
  • CRUD Operationen über REST aktivieren

Mit „GET“ greifen wir später auf die folgenden URLS zu:

Base ORDS URL http://localhost:9090/ords/restsrv/
Schema (alias) http://localhost:9090/ords/restsrv/gpi/
Module http://localhost:9090/ords/restsrv/gpi/readEMP/
Template http://localhost:9090/ords/restsrv/gpi/readEMP/emp/

URL Mapping für den REST Aufruf einrichten

Um die APEX Funktionalität nicht zu beeinträchtigen und eine saubere Trennung zu den APEX DAD zu realisieren wird ein eigenes URL Mapping hinterlegt

Für den Connect zur DB wird dazu der Pool mit dem User „ORDS_PUBLIC_USER“ verwendet , d.h. wir verwenden den Pool „apex_pu“

C:\oracle\products\ords
 
java -jar ords.war map-url --type base-path /restsrv apex_pu
 
Mõr 22, 2017 10:00:01 AM
INFO: Creating new mapping from: [base-path,/restsrv ] to map to: [apex_pu,,]

Im „ords“ Konfigurationsverzeichnis wird die Datei „url-mapping.xml“ angelegt

D.h. über die Base ORDS URL http://localhost:9090/ords/restsrv/ wird nun später diesen REST Service zugegriffen.


Datenbank Schema für REST aktivieren - Schema Alias anlegen

In der Datenbank wird das DB Schema „GPI“ für die Daten des REST Service verwendet, das Schema muss natürlich bereits auch in der Datenbank existieren.

DB User aktiveren bzw. Schema Alias anlegen:

sqlplus gpi/gpi
 
 
BEGIN
  ORDS.enable_schema(
    p_enabled             => TRUE,
    p_schema              => 'GPI',
    p_url_mapping_type    => 'BASE_PATH',
    p_url_mapping_pattern => 'gpi',
    p_auto_rest_auth      => FALSE
  );
 
  COMMIT;
END;
/

Lesenden Zugriff auf das Schema einrichten

Modul/Handler/Template in einem Zug definieren

ÜBer die ORDS.DEFINE_SERVICE Procedure läßt sich der ganze REST Service in einem Zug definieren.

Dazu wird das REST Module und das Template angelegt:

BEGIN
  ORDS.define_service(
    p_module_name    => 'readEMP',
    p_base_path      => 'readEMP/',
    p_pattern        => 'emp/',
    p_method         => 'GET',
    p_source_type    => ORDS.source_type_query,
    p_source         => 'SELECT * FROM emp',
    p_items_per_page => 0);
 
  COMMIT;
END;
/

Überprüfen mit:

SET linesize 130 pagesize 300 
 
COLUMN source_type   format a15
COLUMN SOURCE        format a20
COLUMN uri_template  format a20
COLUMN name          format a20
COLUMN uri_prefix    format a20
COLUMN method        format a10
COLUMN id            format 9999999
 
ttitle LEFT  "ORDS Modules" skip 2
 
SELECT id
     , name
	 , uri_prefix
 FROM  user_ords_modules
ORDER BY name
/
 
ttitle LEFT  "ORDS Templates" skip 2  
SELECT id
     , module_id
	 , uri_template
FROM user_ords_templates
ORDER BY module_id
/
 
 
ttitle LEFT  "ORDS Handlers" skip 2  
SELECT id
     , template_id
	 , source_type
	 , method, SOURCE
FROM   user_ords_handlers
ORDER BY id
/
 
ttitle off

Nun kann die Tabelle mit http://localhost:9090/ords/restsrv/gpi/readEMP/emp/ komplett ausgelesen werden.


Modul/Handler/Template im Detail anlegen und konfigurieren

Modul anlegen:

BEGIN
 
  ORDS.define_module(
    p_module_name    => 'readDEPT',
    p_base_path      => 'readDEPT/',
    p_items_per_page => 0);
 
  commit;
END;
/    

Template anlegen um alles auszulesen

BEGIN
  ORDS.define_template(
   p_module_name    => 'readDEPT',
   p_pattern        => 'dept/');
 
  commit;
END;
/      

Template anlegen um nur ein Department auszulesen

BEGIN
  ORDS.define_template(
   p_module_name    => 'readDEPT',
   p_pattern        => 'dept/deptno/:deptno');
  commit;
END;
/      

Händler anlegen für das Template „dept/“

BEGIN
  ORDS.define_handler(
    p_module_name    => 'readDEPT',
    p_pattern        => 'dept/',
    p_method         => 'GET',
    p_source_type    => ORDS.source_type_query,
    p_source         => 'SELECT * FROM dept',
    p_items_per_page => 0);
  commit;
END;
/          

Aufruf mit http://localhost:9090/ords/restsrv/gpi/readDEPT/dept zeigt nun all Rekords aus der Tabelle

Händler anlegen für das Template „dept/deptno/:deptno/“

BEGIN
  ORDS.define_handler(
    p_module_name    => 'readDEPT',
    p_pattern        => 'dept/deptno/:deptno',
    p_method         => 'GET',
    p_source_type    => ORDS.source_type_query,
    p_source         => 'SELECT * FROM dept WHERE deptno = :deptno',
    p_items_per_page => 0);
  commit;
END;
/          

Aufruf mit http://localhost:9090/ords/restsrv/gpi/readDEPT/dept/deptno/20 ruft nur die Daten vom Departement 20 ab.


PL/SQL Routine aufrufen

Soll etwas komplexer abgefragt werden, bietet es sich an den Aufruf über eine PL/SQL Routine zu kapseln.

In diesem Beispiel wird der Übergabe Wert einfach wieder in Großbuchstaben zurückgeben

PL/SQL Beispiel:

CREATE OR REPLACE PROCEDURE getRestData(p_input_value varchar2)
IS
BEGIN
 htp.p(UPPER(p_input_value));
END;
/

REST Service:

BEGIN
 -- Module
  ORDS.define_module(
    p_module_name    => 'transVAL',
    p_base_path      => 'transVAL/',
    p_items_per_page => 0);
 
 -- Template
  ORDS.define_template(
   p_module_name    => 'transVAL',
   p_pattern        => 'trans/:value');
 
 -- Händler
 ORDS.define_handler(
    p_module_name    => 'transVAL',
    p_pattern        => 'trans/:value',
    p_method         => 'GET',
    p_source_type    => ORDS.source_type_plsql,
    p_source         => 'BEGIN getRestData(:value); END;',
    p_items_per_page => 0);
 
  COMMIT;
 
END;
/

Aufruf mit http://localhost:9090/ords/restsrv/gpi/transVAL/trans/dies_ist_klein_geschreiben

apex_json Package verwenden

Beispiel PL/SQL für das anlegen eines eigenen JSON Records, gebe das Datum, die Anzahl der Mitarbeiter und den Eingabewert zurück:

CREATE OR REPLACE PROCEDURE getRestData(p_input_value varchar2 DEFAULT NULL)
 AS
  l_cursor sys_refcursor;
BEGIN
 
  OPEN l_cursor FOR
     SELECT sysdate AS mydate
           , (SELECT COUNT(*) FROM emp) AS empcount 
           , UPPER(p_input_value) AS input_value FROM dual;
 
  apex_json.open_object;
  apex_json.write('emp_count', l_cursor);
  apex_json.close_object;
 
END;
/

CRUD - Daten mit REST Aufruf verarbeiten

REST AUFRUFAktion
POST Create or Update
PUT Update
DELETE Delete
GET Read

Neben dem Lesen soll auch Daten in die DB geschrieben werden.

Tabelle:

CREATE TABLE WAGO_LOG_MESSAGES( ID NUMBER(11), log_date DATE, message varchar2(2000));
 
CREATE SEQUENCE wago_log_messages_seq;

Wrapper um in die Tabelle zu schreiben mit POST und zu löschen mit DELETE REST Aufruf

CREATE OR REPLACE PROCEDURE logMessage(p_task varchar2, p_date varchar2 , p_message varchar2)
IS
BEGIN
  CASE p_task
    WHEN  'INSERT' THEN
          INSERT INTO wago_log_messages ( id, log_date,message) VALUES
          (wago_log_messages_seq.nextval,to_date(p_date,'dd.mm.yyyy-hh24:mi'), p_message);  
           htp.p('Insert ' ||SQL%ROWCOUNT||' Records');
    WHEN  'DELETE' THEN
           DELETE FROM wago_log_messages WHERE log_date=to_date(p_date,'dd.mm.yyyy-hh24:mi');
            htp.p('Delete ' ||SQL%ROWCOUNT||' Records');
    WHEN  'UPDATE' THEN  
            UPDATE wago_log_messages SET message=p_message WHERE log_date=to_date(p_date,'dd.mm.yyyy-hh24:mi');
            htp.p('Update ' ||SQL%ROWCOUNT||' Records');
    ELSE
          htp.p('Parameter p_task ::' ||p_task||' no action defined');
 
    END CASE      
    commit;
EXCEPTION
  WHEN OTHERS THEN
    HTP.print(SQLERRM);     
    ROLLBACK; 
END logMessage;
/ 

POST Handler für INSERT

Anlegen mit:

BEGIN
 -- Module
  ORDS.define_module(
    p_module_name    => 'logMESS',
    p_base_path      => 'logMESS/',
    p_items_per_page => 0);
 
 -- Template
  ORDS.define_template(
   p_module_name    => 'logMESS',
   p_pattern        => 'log/');
 
 -- Händler
 ORDS.define_handler(
    p_module_name    => 'logMESS',
    p_pattern        => 'log/',
    p_method         => 'POST',
    p_source_type    => ORDS.source_type_plsql,
    p_source         => 'BEGIN logMessage(p_task => ''INSERT'', p_date => :log_date , p_message => :message); END;',
    p_items_per_page => 0);
 
  COMMIT;
 
END;
/
URL:            http://localhost:9090/ords/restsrv/gpi/logMESS/log
Content-Type:  application/json
Daten:         { "log_date":"22.03.2017-12:22" , "message":"Sensor 2 - READ ERROR" }

PUT Handler für UPDATE

BEGIN
 -- Template
  ORDS.define_template(
   p_module_name    => 'logMESS',
   p_pattern        => 'log/update');
 -- Händler
 ORDS.define_handler(
    p_module_name    => 'logMESS',
    p_pattern        => 'log/update',
    p_method         => 'PUT',
    p_source_type    => ORDS.source_type_plsql,
    p_source         => 'BEGIN logMessage(p_task => ''UPDATE'', p_date => :log_date , p_message => :message); END;',
    p_items_per_page => 0);
 
  COMMIT;
 
END;
/
URL:            http://localhost:9090/ords/restsrv/gpi/logMESS/log/update
Content-Type:  application/json
Daten:         { "log_date":"22.03.2017-12:22" , "message":"Sensor 3 - READ SUCESS" }

DELETE Handler für Delete

BEGIN
 -- Template
  ORDS.define_template(
   p_module_name    => 'logMESS',
   p_pattern        => 'log/delete');
 
 -- Händler
 ORDS.define_handler(
    p_module_name    => 'logMESS',
    p_pattern        => 'log/delete',
    p_method         => 'DELETE',
    p_source_type    => ORDS.source_type_plsql,
    p_source         => 'BEGIN logMessage(p_task => ''DELETE'', p_date => :log_date , p_message => :message); END;',
    p_items_per_page => 0);
 
  COMMIT;
 
END;
/
URL:            http://localhost:9090/ords/restsrv/gpi/logMESS/log/delete
Content-Type:  application/json
Daten:         { "log_date":"22.03.2017-12:22" , "message":"" }

Quellen

Cookies helfen bei der Bereitstellung von Inhalten. Durch die Nutzung dieser Seiten erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Rechner gespeichert werden. Weitere Information
"Autor: Gunther Pipperr"
prog/ords_rest_service.txt · Zuletzt geändert: 2018/10/18 09:52 von Gunther Pippèrr