oracle acl что это
Мой блог
вторник, 16 июля 2013 г.
Настройка ACL
В Oracle11g для любого пакета, выполняющего внешние сетевые вызовы (UTL_SMTP, UTL_MAIL) необходимо создать список ACL, включить в него пользователя или роль и предоставить списку привилегию сетевого уровня.
Посмотреть, есть ли какие-либо ACL в базе можно так:
Создаем список ACL, включаем в него пользователя и предоставляем списку привилегию сетевого уровня:
begin
dbms_network_acl_admin.create_acl(
acl => ‘mail-server.xml‘
,description => ‘Permission to make connections to mail server’
,principal => ‘SCOTT‘
,is_grant => TRUE
,privilege => ‘connect‘
);
dbms_network_acl_admin.assign_acl(
acl => ‘mail-server.xml’
,host => ‘my-SMTP-servername’
,lower_port => 25
,upper_port => NULL /* открывается только порт 25*/
);
end;
begin
— Создание списка ACL
dbms_network_acl_admin.create_acl(
acl => ‘oracle-permissions.xml’
,description => ‘Network permissions for www.oracle.com’
,principal => ‘WEBROLE’
,is_grant => TRUE
,privilege => ‘connect’
,start_date => SYSTIMESTAMP
,end_date => NULL
);
— Назначение привилегий
dbms_network_acl_admin.create_acl(
acl => ‘oracle-permissions.xml’
,description => ‘Network permissions for www.oracle.com’
,principal => ‘WEDROLE’
,is_grant => TRUE
,privilege => ‘connect’
,start_date => SYSTIMESTAMP
,end_date => NULL
);
— Определение допустимых адресов
dbms_network_acl_admin.assign_acl(
acl => ‘oracle-permissions.xml’
,host => ‘www.oracle.com’
,lower_port =>80
,upper_port => 80
);
end;
Можно использовать пакет:
create or replace package «pkg_DBA_IR»
AUTHID CURRENT_USER
is
procedure change_assign_acl;
end «pkg_DBA_IR»;
create or replace package body «pkg_DBA_IR» is
—
— Константы:
—
— Имена баз данных:
C_DB_NAME_PROD constant varchar2(30) := ‘TEST’;
C_DB_NAME_UAT constant varchar2(30) := ‘TESTUAT’;
C_DB_NAME_DEV constant varchar2(30) := ‘TESTDEV’;
— Имена хостов:
C_HOST_NAME_PROD constant varchar2(30) := ‘esbprod.sun.com’;
C_HOST_NAME_UAT constant varchar2(30) := ‘esbuat.sun.com’;
C_HOST_NAME_DEV constant varchar2(30) := ‘esbdev.sun.com’;
— Имена параметров:
C_ACL_NAME constant varchar2(30) :=’networkacl.xml’;
— Смена параметров ACL:
procedure change_assign_acl
is
begin
if upper(SYS_CONTEXT (‘USERENV’, ‘DB_NAME’)) = C_DB_NAME_PROD then
raise_application_error(-20001, ‘Run Only in Test Environment’);
elsif upper(SYS_CONTEXT (‘USERENV’, ‘DB_NAME’)) = C_DB_NAME_UAT then
begin
dbms_network_acl_admin.drop_acl(
acl => C_ACL_NAME);
dbms_output.put_line(‘ACL dropped…..’);
exception
when others then
dbms_output.put_line(‘Error dropping ACL: ‘||C_ACL_NAME);
dbms_output.put_line(sqlerrm);
end;
begin
dbms_network_acl_admin.create_acl(
acl => C_ACL_NAME,
description => ‘Permissions to access WebServices’,
principal => ‘TS’,
is_grant => TRUE,
privilege => ‘connect’);
dbms_output.put_line(‘ACL created…..’);
exception
when others then
dbms_output.put_line(‘Error creating ACL: ‘||C_ACL_NAME);
dbms_output.put_line(sqlerrm);
end;
begin
dbms_network_acl_admin.assign_acl(
acl => C_ACL_NAME,
host => C_HOST_NAME_UAT,
lower_port => NULL,
upper_port => NULL);
dbms_output.put_line(‘ACL assigned…..’);
exception
when others then
dbms_output.put_line(‘Error assigning ACL: ‘||C_ACL_NAME);
dbms_output.put_line(sqlerrm);
end;
elsif upper(SYS_CONTEXT (‘USERENV’, ‘DB_NAME’)) = C_DB_NAME_DEV then
begin
dbms_network_acl_admin.drop_acl(
acl => C_ACL_NAME);
dbms_output.put_line(‘ACL dropped…..’);
exception
when others then
dbms_output.put_line(‘Error dropping ACL: ‘||C_ACL_NAME);
dbms_output.put_line(sqlerrm);
end;
begin
dbms_network_acl_admin.create_acl(
acl => C_ACL_NAME,
description => ‘Permissions to access WebServices’,
principal => ‘TS’,
is_grant => TRUE,
privilege => ‘connect’);
dbms_output.put_line(‘ACL created…..’);
exception
when others then
dbms_output.put_line(‘Error creating ACL: ‘||C_ACL_NAME);
dbms_output.put_line(sqlerrm);
end;
begin
dbms_network_acl_admin.assign_acl(
acl => C_ACL_NAME,
host => C_HOST_NAME_DEV,
lower_port => NULL,
upper_port => NULL);
dbms_output.put_line(‘ACL assigned…..’);
exception
when others then
dbms_output.put_line(‘Error assigning ACL: ‘||C_ACL_NAME);
dbms_output.put_line(sqlerrm);
end;
exception
when others then
null;
end change_assign_acl;
grant execute on dbms_network_acl_admin TO ts;
begin
TS.»pkg_DBA_IR».change_assign_acl;
end;
/
Веб-сервисы в Oracle
Веб-сервисы широко применяются для интеграции между компонентами одной системы или между различными системами. Популярность веб-сервисов как способа интеграции обусловлена их универсальностью, а также простотой реализации и отладки. Универсальность связана с передачей данных с помощью интернета и протокола HTTP. Веб-сервисы дают возможность относительно легко построить интеграции между компонентами, написанными на разных языках, запускаемыми на разных операционных системах и платформах. Простота реализации веб-сервисов достигается за счет встроенных во многие IDE средств и компонентов, позволяющих быстро разработать как сам веб-сервис (provider side), так и необходимый код для вызова сервиса на стороне клиента (client side). Отладку сервисов упрощает использование понятных человеку форматов обмена данными — XML и JSON. Кроме того, существует множество утилит для отладки и тестирования сервисов, в том числе нагрузочного.
В этой статье рассмотрим несколько способов создания веб-сервисов непосредственно из СУБД Oracle, то есть без использования сторонних средств.
Предыстория
Дано: информационная бизнес-система крупной торговой сети (порядка тысячи розничных магазинов), состоящая из множества компонентов и подсистем. Внутри каждого магазина находится главный сервер — БД Oracle с основной бизнес-логикой. Кассовые узлы управляются отдельным ПО со своей локальной БД. Это ПО периодически забирает данные с главного сервера (через WS SOAP) и отдает обратно результаты продажи (файловый обмен).
Прогресс не стоял на месте, и в магазинах появилось новое оборудование. Данные из этого оборудования периодически должны попадать на главный сервер магазина (период — каждые несколько минут), интеграция обязательно должна проходить через веб-сервис, сообщение должно иметь определенный формат, аутентификация не нужна. Мы посмотрели контракты обмена данными и выяснили, что используемая технология веб-сервисов не позволит построить интеграцию с таким оборудованием. И начались поиски решения…
В итоге было рассмотрено несколько вариантов реализации нужного веб-сервиса, вплоть до написания своего отдельного компонента, который открыл бы для БД Oracle окно в мир HTTP: с одной стороны предоставлял бы веб-сервис, с другой — взаимодействовал бы с БД через JDBC. Сложность в том, что новый компонент, во-первых, нужно было бы установить на тысячу магазинов, и, во-вторых, появилось бы еще одно звено, которое нужно было бы сопровождать. Поэтому приоритетным все же был вариант реализации веб-сервиса встроенными средствами Oracle.
В результате поисков мы обнаружили четыре способа, которые рассмотрим в данной статье:
Два других способа — Java Servlet и PL/SQL Servlet — мы рассматривали наряду с ORDS при поиске альтернативы Native Oracle WS, но в проекте применять не стали. Поэтому эти подходы детально рассматривать не будем и ограничимся короткой справкой.
В статье будут представлены некоторые практические примеры реализации веб-сервисов с инструкциями, которые помогут создать работающий сервис.
Native Oracle XML DB Web Services
Возможности
Позволяет организовать доступ к БД Oracle через HTTP, используя WS SOAP (версия 1.1):
Настройка
Для работы Native Oracle WS понадобится:
Настройка Oracle XML DB HTTP server
HTTP-сервер уже должен работать по умолчанию, но в некоторых случаях может потребоваться дополнительная конфигурация listener — добавление в DESCRIPTION_LIST следующего блока:
После этого нужно перезапустить listener.
Настройка доступа через HTTP
Создание сервлета для веб-сервиса
Для работы веб-сервиса требуется регистрация сервлета в конфигурации БД.
Настройка Access List
Для доступа к Oracle через HTTP нужно добавить правила в конфигурации СУБД. Делается это с помощью встроенных утилит СУБД.
Для настройки ACL понадобятся:
Сразу нужно отметить, что настройка ACL требуется при использовании не только Native Oracle WS, но и всех других рассмотренных в данной статье способов создания веб-сервисов.
Пример веб-сервиса с использованием пакетной процедуры
Простейший веб-сервис создан и готов к работе.
Для доступа к сервису нужно использовать URL следующего формата:
[server] — доменное имя или IP-адрес сервера БД Oracle
[port] — порт для доступа через HTTP, указанный в разделе «Настройка доступа через HTTP»
[servlet_name] — имя сервлета, указанное в разделе «Создание сервлета для веб-сервиса»
[DB_SCHEMA] — имя схемы БД (в верхнем регистре)
[WS_OBJ] — имя сервиса (в верхнем регистре), которое равно имени объекта БД, в нашем случае – имени пакета
Обратите внимание, что в URL регистр важен!
Если перейти по этой ссылке в браузере, получим автоматически созданный на основе нашего пакета WSDL:
Для проверки сервиса создаем новый SOAP-проект в SOAP UI. В качестве URL указываем адрес из примера выше.
При открытии Request 1 видим, что шаблон запроса уже сформирован автоматически по указанному WSDL.
Сразу же добавляем Basic-авторизацию для запроса — логин и пароль такие же, как при подключении в БД.
Пример запроса и ответа. Обратите внимание, что в автоматически сформированный запрос вручную добавлена строка
. Дело в том, что в Oracle 12c есть баг: OUT-переменные не добавляются в WSDL для Native Oracle WS).
Результат вызова видим в таблице лога.
Выводы
Технологию Native Oracle XML DB Web Services можно использовать как промышленное решение при условии, что на этот веб-сервис нет большой нагрузки (один запрос в несколько секунд). Этот вариант подойдет, когда у потребителей нет жестких требований к веб-сервису (его атрибутам, структурам данных, логике обработки) и нет строгого заранее определенного контракта. Если же нужно создать веб-сервис по заранее определенному WSDL (как в нашем случае с новым оборудованием), то технология Native Oracle WS окажется непригодна.
Oracle REST Data Service
Начиная с версии 11.1 в Oracle появилась полноценная поддержка RESTful в виде отдельного модуля, называемого Oracle REST Data Service (ORDS).
ORDS — это Java-приложение, которое позволяет создавать RESTful API для базы данных Oracle, используя SQL и PL/SQL. Является альтернативой использованию Oracle HTTP Server и mod_plsql. По сути ORDS — это HTTP-интерфейс между внешним миром и БД Oracle. Этот интерфейс позволяет замкнуть входящие HTTP-запросы на какой-либо объект базы данных — таблицу или PL/SQL-процедуру.
Все, что требуется сделать, — это установить, настроить и запустить ORDS для требуемой БД. Дальнейший процесс создания REST-сервисов сводится к написанию кода на PL/SQL (или даже кликанью мышкой в IDE, если код писать лень).
Для установки ORDS не требуется никаких дополнительных лицензий.
Возможности
В первом случае имеем дело с ресурсами в том смысле, как они понимаются в архитектурном стиле RESTful. Каждый ресурс определяется уникальным URI, а операции с ресурсами (CRUD — создание, чтение, изменение, удаление) определяются операциями из HTTP-запроса: PUT, POST, GET, DELETE. Например, если ресурс — это запись в таблице сотрудников, то эта запись будет доступна по URI вида:
Здесь в URI указывается имя схемы БД, имя таблицы и ID записи в таблице. Таким образом, этот HTTP-запрос на самом деле выполняет операцию выбора (SELECT) из указанной таблицы. С остальными операциями (добавление, изменение, удаление) принцип общения такой же: в URI указывается путь к ресурсу, а в теле запроса — дополнительные параметры, например значения полей для вставки записи в таблицу.
Во втором случае вместо обращения к ресурсу напрямую используется вызов процедуры, которая может делать все то же самое, что и в первом случае (CRUD), а также исполнять любую другую логику, реализующую нужный бизнес-процесс. Вызов процедуры из пакета может быть сделан с помощью HTTP-запроса такого формата:
Параметры для процедуры передаются в теле запроса в виде JSON-структур формата <"param" : "value">. Такой же подход используется и при применении Native Oracle WS, рассмотренном выше, но в случае REST-сервисов нет ограничений, накладываемых протоколом SOAP.
Настройка
ORDS можно запустить в двух режимах: через сервер приложений или в автономном (standalone) режиме.
В данной статье рассматривается только вариант запуска в standalone-режиме.
Для работы ORDS нужно:
Настройка параметров
В дистрибутиве ORDS имеется файл с параметрами, который по умолчанию выглядит так:
Описание параметров можно найти в документации
Параметры для standalone-режима:
Параметр | Описание |
db.hostname | Имя или IP-адрес сервера БД Oracle |
db.port | Порт БД (например, 1521) |
db.servicename | Servicename базы данных |
db.username | Имя пользователя PL/SQL-шлюза. По умолчанию = APEX_PUBLIC_USER, но в примере не планируется использовать APEX, поэтому можно не заполнять этот параметр |
db.password | Пароль пользователя (тоже не заполняем) |
migrate.apex.rest | Переход RESTful сервисов APEX на ORDS. Ставим false, если не используется APEX |
rest.services.apex.add | Конфигурировать ORDS для использования в APEX |
rest.services.ords.add | Установить схему БД для ORDS (ORDS_PUBLIC_USER и ORDS_METADATA). Значение должно быть true |
schema.tablespace.default | Табличное пространство по умолчанию для схемы ORDS_METADATA |
schema.tablespace.temp | Временное табличное пространство для схемы ORDS_METADATA |
standalone.http.port | Порт, на котором будет работать ORDS. Этот порт будет использоваться в URI для доступа к WS |
user.tablespace.default | Табличное пространство по умолчанию для схемы ORDS_PUBLIC_USER |
user.tablespace.temp | Временное табличное пространство для схемы ORDS_PUBLIC_USER |
В итоге содержимое файла должно получиться примерно таким:
Настройка необходимых параметров завершена, можно приступать к установке.
Установка
Выполняем в ОС команду:
В диалоге установки нужно сделать следующее:
Enter the location to store configuration data: conf
Enter the database password for ORDS_PUBLIC_USER:
Confirm password:
ёхэ 03, 2019 2:47:49 PM oracle.dbtools.rt.config.setup.SchemaSetup getInstallOrUpgrade
WARNING: Failed to connect to user ORDS_PUBLIC_USER jdbc:oracle:thin:@//***YOUR_HOST_NAME.DOMAIN***:1521/***YOUR_SERVICE_NAME.DOMAIN***
Enter 1 if you want to use PL/SQL Gateway or 2 to skip this step.
If using Oracle Application Express or migrating from mod_plsql then you must enter 1 [1]:2
ёхэ 03, 2019 2:48:32 PM
INFO: reloaded pools: []
Enter 1 if you wish to start in standalone mode or 2 to exit [1]:
Enter 1 if using HTTP or 2 if using HTTPS [1]:
2019-09-03 14:48:49.754:INFO::main: Logging initialized @4276887ms to org.eclipse.jetty.util.log.StdErrLog
ёхэ 03, 2019 2:48:49 PM
INFO: HTTP and HTTP/2 cleartext listening on port: 8082
ёхэ 03, 2019 2:48:50 PM
INFO: Disabling document root because the specified folder does not exist: D:\ords-19.2.0.199.1647\conf\ords\standalone\doc_root
Exception in thread «main» java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at oracle.dbtools.jarcl.Entrypoint.invoke(Entrypoint.java:66)
at oracle.dbtools.jarcl.Entrypoint.main(Entrypoint.java:89)
Caused by: java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Unknown Source)
at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source)
at java.lang.AbstractStringBuilder.append(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at java.util.AbstractMap.toString(Unknown Source)
at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at oracle.dbtools.jarcl.zip.ZipIndex.toString(ZipIndex.java:166)
at java.lang.String.valueOf(Unknown Source)
at java.lang.StringBuilder.append(Unknown Source)
at oracle.dbtools.jarcl.JarClassLoader.toString(JarClassLoader.java:51)
at org.eclipse.jetty.server.ClassLoaderDump.dump(ClassLoaderDump.java:67)
at org.eclipse.jetty.util.component.Dumpable.dumpObjects(Dumpable.java:225)
at org.eclipse.jetty.util.component.ContainerLifeCycle.dumpObjects(ContainerLifeCycle.java:746)
at org.eclipse.jetty.server.handler.ContextHandler.dump(ContextHandler.java:259)
at org.eclipse.jetty.util.component.Dumpable.dumpObjects(Dumpable.java:162)
at org.eclipse.jetty.util.component.ContainerLifeCycle.dumpObjects(ContainerLifeCycle.java:746)
at org.eclipse.jetty.util.component.ContainerLifeCycle.dump(ContainerLifeCycle.java:701)
at org.eclipse.jetty.util.component.Dumpable.dump(Dumpable.java:62)
at org.eclipse.jetty.util.component.ContainerLifeCycle.dump(ContainerLifeCycle.java:684)
at oracle.dbtools.standalone.StandaloneConfiguration.start(StandaloneConfiguration.java:241)
at oracle.dbtools.standalone.Standalone.execute(Standalone.java:508)
at oracle.dbtools.cmdline.DefaultCommand.execute(DefaultCommand.java:137)
at oracle.dbtools.cmdline.Commands.execute(Commands.java:207)
at oracle.dbtools.cmdline.Commands.main(Commands.java:163)
at oracle.dbtools.cmdline.Commands.main(Commands.java:368)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at oracle.dbtools.jarcl.Entrypoint.invoke(Entrypoint.java:66)
В результате будет создан каталог с конфигурацией ORDS, а в БД появятся служебные схемы для ORDS.
Запуск
Запуск в автономном режиме выполняется командой:
ёхэ 03, 2019 3:52:48 PM
WARNING: *** jdbc.MaxLimit in configuration |apex|pu| is using a value of 10, this setting may not be sized adequately for a production environment ***
ёхэ 03, 2019 3:52:48 PM
WARNING: *** jdbc.InitialLimit in configuration |apex|pu| is using a value of 3, this setting may not be sized adequately for a production environment ***
ёхэ 03, 2019 3:52:50 PM
INFO: Oracle REST Data Services initialized
Oracle REST Data Services version : 19.2.0.r1991647
Oracle REST Data Services server info: jetty/9.4.z-SNAPSHOT
2019-09-03 15:52:50.484:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@d56d67
2019-09-03 15:52:50.658:INFO:oejs.AbstractConnector:main: Started ServerConnector@12325ad
0.0:8082>
2019-09-03 15:52:50.659:INFO:oejs.Server:main: Started @6914ms
— порт, указанный в конфигурации ORDS.
При желании можно оформить скрипт для автоматического запуска ORDS при старте ОС.
Настройка доступа
И последний шаг — настройка ACL. Действия аналогичны тем, что и при использовании Native Oracle WS.
Выполнять этот шаг нужно после того, как будет создана схема БД, поэтому в примерах ниже будет отдельно указано, когда нужно выполнить данную настройку. Пока можно считать, что все предварительные действия выполнены, и приступать к примерам.
Пример 1: Обработчик для POST-запроса
В качестве примера рассмотрим вариант реализации RPC-style interaction, то есть сделаем метод веб-сервиса, обработчиком которого будет пакетная процедура.
Собственно, именно в таком варианте работа с ORDS была реализована в нашем проекте для торговой сети, и результат оправдал свои ожидания. Получился быстрый и универсальный способ создания новых методов веб-сервисов для разных бизнес-процессов — от работы с оборудованием до API для сайтов.
Как уже упоминалось выше, поддержка ORDS включена также в SQL Developer (IDE для баз данных, разрабатываемая Oracle). В SQL Developer создание веб-сервисов доступно прямо из пунктов меню или контекстного меню.
В этой статье примеры сделаны с помощью SQL Developer (версия 18), но также прилагается PL/SQL-код, который выполняется в БД в результате действий в IDE.
Версия БД, на которой делались эксперименты:
Создание тестового пользователя для WS
Для примеров нам снова понадобится новая схема — создаем ее:
Настройка схемы БД
После того, как схема создана, необходимо сделать ее доступной через ORDS.
Листинг:
Создание модуля и шаблона
Далее нужно создать модуль и шаблон для ресурса.
Модуль — это структурная единица, которая позволяет сгруппировать несколько логически связанных шаблонов ресурсов.
Шаблон — конкретный веб-сервис, обслуживающий определенный набор методов для ресурса.
Resource module: An organizational unit that is used to group related resource templates.
Resource template: An individual RESTful service that is able to service requests for some set of URIs (Universal Resource Identifiers). The set of URIs is defined by the URI Pattern of the Resource Template.
Например, для интернет-магазина модуль можно назвать shop — в этом модуле будут объединены все API магазина. Шаблонами могут быть конкретные ресурсы, например, заказ (шаблон order ), каталог товаров (шаблон item ), оплата (шаблон payment ) и т. д.
Для создания модуля и шаблона нужно выполнить такие шаги:
В последнем диалоге видим все введенные параметры модуля и шаблона. На вкладке SQL можно увидеть PL/SQL-код, который будет выполнен в БД при нажатии «Готово»:
Создание обработчика HTTP-запроса
Теперь нам нужно создать обработчик HTTP-запроса для нашего сервиса.
Сначала нам понадобится создать объекты БД, которые будут содержать логику обработки запроса.
Нам потребуются таблица для логгирования и пакет, в котором будет код обработчика.
Для этого выполняем следующие шаги:
Листинг кода обработчика POST-запроса:
При необходимости можно получить PL/SQL-код для создания обработчика. Для этого в контекстном меню ORDS-модуля нужно выбрать REST Definition и далее указать, куда выдать скрипт создания модуля, например в буфер обмена:
Замечание: если выполнить процедуру создания модуля ORDS.DEFINE_MODULE еще раз, то автоматически будут удалены все шаблоны этого модуля, при этом никакого предупреждения об этом не будет!
Пример вызова
На этом наш веб-сервис готов. Осталось проверить его работу.
Для проверки выполняем запрос:
Результат выполнения метода — запись с телом запроса и ответа в таблице логов:
Как видим, отправленный HTTP-запрос успешно был обработан процедурой из пакета.
Параметры из запроса
Выше мы уже увидели результат работы простейшего веб-сервиса. Теперь немного усложним задачу, добавив дополнительные параметры в запрос.
Есть два способа передачи параметров:
Через URL. Параметры задаются в URL в стандартном виде:
Через HEADER. Параметры задаются в заголовке запроса в виде p1: val1
В ORDS в обработчике запроса параметры определяются в виде bind-переменных.
Добавим в предыдущий пример два параметра: prm1 — параметр в URI, prm2 — параметр в заголовке запроса.
Внутри процедуры просто сделаем запись в лог значений новых параметров.
Обработчик POST-запроса запроса с новыми параметрами:
В обработчике на вкладке Parameters объявляем переменные:
В этой форме первое поле (Name) содержит имя параметра, которое ожидается в запросе, второе поле (Bind Parameter) — имя bind-переменной, которое будет указано в обработчике этого запроса.
Выполним запрос с новыми параметрами:
Результат — параметры из запроса сохранились в логе:
CGI-переменные
Пример 2: Доступ к таблице через ORDS
В этом примере рассмотрим организацию доступа к объекту БД (к таблице) через ORDS.
Как и в предыдущем примере, делаем доступ без авторизации. О том, как делать защищенный доступ к ресурсам, можно посмотреть в документации.
Создание тестовой таблицы
Для примера создадим таблицу «Заказы».
Скрипт создания таблицы:
Открытие доступа к таблице через ORDS
Листинг включения таблицы:
Создание или изменение записи
Доступ к таблице открыт — проверяем, как можно создавать и редактировать записи в таблице через ORDS.
В документации ORDS в описании метода PUT указан такой шаблон:
То есть поле KeyValues (ключ записи) должно быть заполнено даже для новой создаваемой записи. В самом запросе должны быть перечислены все поля таблицы (но ключевое поле можно не добавлять).
Смотрим содержимое таблицы — появилась наша новая запись:
Для изменения записи вызываем тот же метод PUT. Изменим примечание в нашем заказе:
В ответе получим тот же JSON с параметрами измененной записи. В таблице видим, что примечание обновилось:
Получение записей из таблицы
Есть три режима запроса данных из таблицы:
Для получения всех записей можно выполнить запрос без указания каких-либо параметров:
Как заставить Oracle добавлять кодировку в заголовок Content-Type — вопрос открытый.
Удаление записи
Запрос в исходном виде:
Выводы
ORDS — достаточно гибкий и универсальный механизм для работы с веб-сервисами, позволяющий реализовать полноценный REST. В плане производительности сильно превосходит Native Oracle WS с его тяжелым внутренним парсингом XML. Для реализации высоконагруженной системы этот подход не подойдет: в этом случае нужен другой стек технологий — отдельный сервер приложений, проксирование запросов, использование кластерных БД и так далее. Однако для реализации систем с относительно небольшим количеством HTTP-запросов (до 10–20 в секунду) ORDS — оптимальный подход как в производительности, так и в гибкости. ORDS уступает Native Oracle WS только в плане генерации спецификации веб-сервиса: последний выдает уже полностью готовую спецификацию (WSDL), которую «как есть» можно отдавать потребителям сервиса. В ORDS также есть возможность генерации описания, но для рассмотренного в этой статье подхода с полностью универсальным сервисом (когда есть общая процедура обработки для всех сервисов) автоматическая генерация спецификации становится невозможной. Oracle сгенерирует только спецификацию верхнего уровня, а детали (модели данных) придется описывать вручную.
Альтернативные подходы
Java Servlet
Данный подход к реализации веб-сервисов вполне универсальный и к тому же не требует установки никаких дополнительных компонентов. У нас не получилось его применить только из-за жестких требований к сервису: нужен был веб-сервис, не требующий аутентификации. При реализации данного подхода аутентификация обязательна, и это требование не получилось обойти.
Более подробно про этот способ можно узнать в документации Oracle.
Database Access Descriptor (PL/SQL Servlet)
Этот вариант полностью аналогичен предыдущему, только обработчиком запроса выступает хранимая процедура PL/SQL.
Пример URL — указывается имя пакета, имя процедуры, параметры (GET-запрос):
В случае POST-запроса имена параметров нужно прописывать прямо в теле запроса через знак «=», что довольно неудобно, так как тип содержимого запроса (ContentType) в этом случае может быть только текстовым. Передать xml- или json-структуру можно только в таком виде:
Такой вариант веб-сервиса применим только в случаях, когда имеем дело с совсем простыми запросами — вызовами процедуры с простыми типами данных. Передать какую-либо сложную многоуровневую структуру в этом варианте не получится.
Этот подход подробно описан на сайте ORACLE-BASE.
Заключение
Создание веб-сервиса в Oracle — задача довольно простая, не требующая написания какого-то сверхсложного кода. При этом разработчики Oracle получают в свой арсенал довольно мощный механизм, позволяющий интегрировать разнородные системы или части систем через HTTP.
В данной статье мы рассмотрели четыре подхода к созданию веб-сервисов.
Native Oracle WS — устаревшая технология, которая тем не менее имеет свои плюсы: автоматически генерируемый WSDL, автоматический парсинг XML, отсутствие необходимости установки дополнительного ПО. Главный недостаток — небольшая производительность и ограничение поддерживаемых типов данных.
ORDS — на мой взгляд, предпочтительный способ создания веб-сервисов. Достаточно гибкий и универсальный. Из неудобств этого способа можно выделить только то, что в стандартную поставку Oracle он не входит, то есть требует отдельной установки.
Java Servlet — вполне универсальный способ, не требующий установки дополнительного ПО. Однако все нужно делать полностью вручную, поскольку нет возможности автогенерации сервисов.
PL/SQL Servlet — наименее удачный подход. Из плюсов можно выделить то, что в этом варианте мы получаем возможность вызова хранимых процедур через HTTP без необходимости установки дополнительного ПО, а также без написания дополнительного кода на других языках: весь код пишется только на PL/SQL.
Всем спасибо за внимание! Надеюсь материал статьи окажется полезным тем, кто так или иначе связан с продуктами Oracle и озадачен проблемами внутрисистемных и межсистемных интеграций.