Oracle DB, Oracle APEX, Linux etc.

понедельник, 29 марта 2010 г.

APEX: Popup Key LOV, onChange и Submit

Сегодня на повестке дня три небольших вопроса, которые возникают относительно Popup Key LOV в APEX. В ответах P1_POPUP_KEY будет использоваться в качестве элемента этого типа.

Внимание: ответы верны для APEX версии 3.2. В принципе, они должны быть правильными и для более ранних версий, но если что не так - задавайте вопросы в комментариях.

0. Как получить значение ключа выбранного значения?


Если попробовать использовать $v("P1_POPUP_KEY"), то мы получим отображаемое значение, а не ключ, ради которого и используется обычно Popup Key LOV. Но если взглянуть в исходный код страницы, то рядом с элементом P1_POPUP_KEY мы увидим ещё один скрытый - P1_POPUP_KEY_HIDDENVALUE, который и хранит ключ.

1. Можно ли использовать событие onChange у элемента Popup Key LOV?


Можно. :) Попробуйте добавить элементу следующий код в HTML Form Element Attributes и изменить его значение в приложении:
onChange="alert($v(this) + ';' + $v(this.id+'_HIDDENVALUE'))"

2. Можно ли сделать Popup LOV, выполняющий SUBMIT при изменении значения?


Зная ответ на предыдущий вопрос, легко понять, что можно. Вот небольшой JavaScript-код с объектом, автоматизирующим этот процесс:
/* Помните, этот код использует jQuery. */
submitPopupLov = {
addSubmitHandlerToPopupLov : function (pLovId, pSubmitRequest){
$("#" + pLovId).addClass("submit-popup-lov submit-popup-lov-processed");
$("#" + pLovId + "_HIDDENVALUE").change(function (){
doSubmit(!!pSubmitRequest ? pSubmitRequest : pLovId);
});
},
setPopupLovSubmit : function (pLovId){
$("#" + pLovId).addClass("submit-popup-lov submit-popup-lov-not-processed");
},
processSubmitablePopupLovs : function (){
$(".submit-popup-lov-not-processed").each(function(){
$(this).removeClass("submit-popup-lov-not-processed").addClass("submit-popup-lov-processed");
$("#"+this.id + "_HIDDENVALUE").change(function(){
doSubmit(this.id);
});
});
}
};


Я надеюсь, вопросов без ответов стало меньше. :)

Читать далее

воскресенье, 21 марта 2010 г.

APEX: Quick Picks (QP)

Прочитав довольно интересный пост о динамически создаваемых быстрых значениях (aka quick picks, далее QP) для элемента, я решил довести дело до более логически завершённого функционала. Вот спецификация пакета, который используется для создания QP:

CREATE OR REPLACE package apex_quick_picks_pkg as 
/* APEX_QUICK_PICKS_PKG
Автор: Александр "suPPLer" Поливаный
Дата релиза: 22.03.2010
Версия: 1.0
Назначение: функции для создания списка быстрых значений (aka quick picks, QP) элемента.

Распространяется под лицензией New BSD (http://cylib.iit.nau.edu.ua/Mirrors/ask.km.ru/unics/bsd.html) :

* Copyright (c) 2010, Александр "suPPLer" Поливаный
*
* Разрешается повторное распространение и использование как в виде исходного
* кода, так и в двоичной форме, с изменениями или без, при соблюдении
* следующих условий:
*
* * При повторном распространении исходного кода должно оставаться
* указанное выше уведомление об авторском праве, этот список условий и
* последующий отказ от гарантий.
* * При повторном распространении двоичного кода должна сохраняться
* указанная выше информация об авторском праве, этот список условий и
* последующий отказ от гарантий в документации и/или в других
* материалах, поставляемых при распространении.
* * Имена владельцев авторских прав не могут быть
* использованы в качестве поддержки или продвижения продуктов,
* основанных на этом ПО без предварительного письменного разрешения.
*
* ЭТА ПРОГРАММА ПРЕДОСТАВЛЕНА ВЛАДЕЛЬЦАМИ АВТОРСКИХ ПРАВ И/ИЛИ ДРУГИМИ
* СТОРОНАМИ "КАК ОНА ЕСТЬ" БЕЗ КАКОГО-ЛИБО ВИДА ГАРАНТИЙ, ВЫРАЖЕННЫХ ЯВНО
* ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ПОДРАЗУМЕВАЕМЫЕ
* ГАРАНТИИ КОММЕРЧЕСКОЙ ЦЕННОСТИ И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. НИ В
* КОЕМ СЛУЧАЕ, ЕСЛИ НЕ ТРЕБУЕТСЯ СООТВЕТСТВУЮЩИМ ЗАКОНОМ, ИЛИ НЕ УСТАНОВЛЕНО
* В УСТНОЙ ФОРМЕ, НИ ОДИН ВЛАДЕЛЕЦ АВТОРСКИХ ПРАВ И НИ ОДНО ДРУГОЕ ЛИЦО,
* КОТОРОЕ МОЖЕТ ИЗМЕНЯТЬ И/ИЛИ ПОВТОРНО РАСПРОСТРАНЯТЬ ПРОГРАММУ, КАК БЫЛО
* СКАЗАНО ВЫШЕ, НЕ НЕСЁТ ОТВЕТСТВЕННОСТИ, ВКЛЮЧАЯ ЛЮБЫЕ ОБЩИЕ, СЛУЧАЙНЫЕ,
* СПЕЦИАЛЬНЫЕ ИЛИ ПОСЛЕДОВАВШИЕ УБЫТКИ, ВСЛЕДСТВИЕ ИСПОЛЬЗОВАНИЯ ИЛИ
* НЕВОЗМОЖНОСТИ ИСПОЛЬЗОВАНИЯ ПРОГРАММЫ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ
* ПОТЕРЕЙ ДАННЫХ, ИЛИ ДАННЫМИ, СТАВШИМИ НЕПРАВИЛЬНЫМИ, ИЛИ ПОТЕРЯМИ
* ПРИНЕСЕННЫМИ ИЗ-ЗА ВАС ИЛИ ТРЕТЬИХ ЛИЦ, ИЛИ ОТКАЗОМ ПРОГРАММЫ РАБОТАТЬ
* СОВМЕСТНО С ДРУГИМИ ПРОГРАММАМИ), ДАЖЕ ЕСЛИ ТАКОЙ ВЛАДЕЛЕЦ ИЛИ ДРУГОЕ
* ЛИЦО БЫЛИ ИЗВЕЩЕНЫ О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ.

*/

--
-- Набор функций, которые формируют соответствующий HTML-код QP и возвращают его как varchar2.
--

-- quick_picks_from_query - QP из запроса с двумя столбцами: отображаемые QP и устанавливаемые значения
-- p_item_name - элемент, значения которого устанавливают QP
-- p_query - запрос
-- p_show_clear - отображать QP с пустым значением
-- p_clear_text - отображаемый текст QP с пустым значением
-- p_qp_style - стиль HTML-элемента QP
-- p_qp_class - класс HTML-элемента QP
-- p_container_id - id HTML-элемента, в котором собраны QP (в качестве контейнера используется div)
-- p_container_style - стиль HTML-элемента, в котором собраны QP
-- p_container_class - класс HTML-элемента, в котором собраны QP
function quick_picks_from_query
( p_item_name in apex_application_page_items.item_name%type
, p_query in varchar2
, p_show_clear in varchar2 default 'N'
, p_clear_text in varchar2 default 'Clear'
, p_qp_style in varchar2 default null
, p_qp_class in varchar2 default null
, p_container_id in varchar2 default null
, p_container_style in varchar2 default null
, p_container_class in varchar2 default null)
return varchar2;
-- quick_picks_from_lov - QP на основе LOV из приложения APEX, в котором используются QP
-- p_item_name - элемент, значения которого устанавливают QP
-- p_lov_name - название LOV
-- p_show_clear - отображать QP с пустым значением
-- p_clear_text - отображаемый текст QP с пустым значением
-- p_qp_style - стиль HTML-элемента QP
-- p_qp_class - класс HTML-элемента QP
-- p_container_id - id HTML-элемента, в котором собраны QP (в качестве контейнера используется div)
-- p_container_style - стиль HTML-элемента, в котором собраны QP
-- p_container_class - класс HTML-элемента, в котором собраны QP
function quick_picks_from_lov
( p_item_name in apex_application_page_items.item_name%type
, p_lov_name in apex_application_lovs.list_of_values_name%type
, p_show_clear in varchar2 default 'N'
, p_clear_text in varchar2 default 'Clear'
, p_qp_style in varchar2 default null
, p_qp_class in varchar2 default null
, p_container_id in varchar2 default null
, p_container_style in varchar2 default null
, p_container_class in varchar2 default null)
return varchar2;
-- quick_picks_from_arrays - QP на основе коллекций отображаемых меток QP и устанавливаемых значений. Тип коллекции - dbms_sql.varchar2_table
-- p_item_name - элемент, значения которого устанавливают QP
-- p_texts - отображаемые метки QP
-- p_values - значения, которые устанавливаются QP
-- p_show_clear - отображать QP с пустым значением
-- p_clear_text - отображаемый текст QP с пустым значением
-- p_qp_style - стиль HTML-элемента QP
-- p_qp_class - класс HTML-элемента QP
-- p_container_id - id HTML-элемента, в котором собраны QP (в качестве контейнера используется div)
-- p_container_style - стиль HTML-элемента, в котором собраны QP
-- p_container_class - класс HTML-элемента, в котором собраны QP
function quick_picks_from_arrays
( p_item_name in apex_application_page_items.item_name%type
, p_texts in dbms_sql.varchar2_table
, p_values in dbms_sql.varchar2_table
, p_show_clear in varchar2 default 'N'
, p_clear_text in varchar2 default 'Clear'
, p_qp_style in varchar2 default null
, p_qp_class in varchar2 default null
, p_container_id in varchar2 default null
, p_container_style in varchar2 default null
, p_container_class in varchar2 default null)
return varchar2;

--
-- Набор процедур, который использует htp.p для OWA-вывода сформированного набора QP
--

-- prn_quick_picks_from_query - OWA-вывод сформированных QP из запроса с двумя столбцами: отображаемые QP и устанавливаемые значения
-- p_item_name - элемент, значения которого устанавливают QP
-- p_query - запрос
-- p_show_clear - отображать QP с пустым значением
-- p_clear_text - отображаемый текст QP с пустым значением
-- p_qp_style - стиль HTML-элемента QP
-- p_qp_class - класс HTML-элемента QP
-- p_container_id - id HTML-элемента, в котором собраны QP (в качестве контейнера используется div)
-- p_container_style - стиль HTML-элемента, в котором собраны QP
-- p_container_class - класс HTML-элемента, в котором собраны QP
procedure prn_quick_picks_from_query
( p_item_name in apex_application_page_items.item_name%type
, p_query in varchar2
, p_show_clear in varchar2 default 'N'
, p_clear_text in varchar2 default 'Clear'
, p_qp_style in varchar2 default null
, p_qp_class in varchar2 default null
, p_container_id in varchar2 default null
, p_container_style in varchar2 default null
, p_container_class in varchar2 default null);
-- prn_quick_picks_from_lov - OWA-вывод сформированных QP на основе LOV из приложения APEX, в котором используются QP
-- p_item_name - элемент, значения которого устанавливают QP
-- p_lov_name - название LOV
-- p_show_clear - отображать QP с пустым значением
-- p_clear_text - отображаемый текст QP с пустым значением
-- p_qp_style - стиль HTML-элемента QP
-- p_qp_class - класс HTML-элемента QP
-- p_container_id - id HTML-элемента, в котором собраны QP (в качестве контейнера используется div)
-- p_container_style - стиль HTML-элемента, в котором собраны QP
-- p_container_class - класс HTML-элемента, в котором собраны QP
procedure prn_quick_picks_from_lov
( p_item_name in apex_application_page_items.item_name%type
, p_lov_name in apex_application_lovs.list_of_values_name%type
, p_show_clear in varchar2 default 'N'
, p_clear_text in varchar2 default 'Clear'
, p_qp_style in varchar2 default null
, p_qp_class in varchar2 default null
, p_container_id in varchar2 default null
, p_container_style in varchar2 default null
, p_container_class in varchar2 default null);
-- prn_quick_picks_from_arrays - OWA-вывод сформированных QP на основе коллекций отображаемых меток QP и устанавливаемых значений. Тип коллекции - dbms_sql.varchar2_table
-- p_item_name - элемент, значения которого устанавливают QP
-- p_texts - отображаемые метки QP
-- p_values - значения, которые устанавливаются QP
-- p_show_clear - отображать QP с пустым значением
-- p_clear_text - отображаемый текст QP с пустым значением
-- p_qp_style - стиль HTML-элемента QP
-- p_qp_class - класс HTML-элемента QP
-- p_container_id - id HTML-элемента, в котором собраны QP (в качестве контейнера используется div)
-- p_container_style - стиль HTML-элемента, в котором собраны QP
-- p_container_class - класс HTML-элемента, в котором собраны QP
procedure prn_quick_picks_from_arrays
( p_item_name in apex_application_page_items.item_name%type
, p_texts in dbms_sql.varchar2_table
, p_values in dbms_sql.varchar2_table
, p_show_clear in varchar2 default 'N'
, p_clear_text in varchar2 default 'Clear'
, p_qp_style in varchar2 default null
, p_qp_class in varchar2 default null
, p_container_id in varchar2 default null
, p_container_style in varchar2 default null
, p_container_class in varchar2 default null);
end apex_quick_picks_pkg;
/


Скрипт установки пакета пока находится здесь, возможно, дальше он переместится на что-нибудь более предназначенное для хранения исходников, например, sourceforge.
Как пользоваться этим пакетом для генерации быстрых ссылок:

  1. Создать элемент типа Display Only.

  2. Расположить его где-то рядом с тем элементом, который будут изменять QP. Хорошим вариантом может стать расположение снизу сразу под нужным элементом.

  3. Изменить у него отображение (Display As) на Display As Text (based on PL/SQL, does not save state). Помните, этот тип отображения не доступен изначально при создании, он появляется только при редактировании элемента.

  4. Изменить шаблон метки Template->No Label, очистить поле Label.

  5. Изменить тип источника значения Source Type->PL/SQL Anonymous Block.

  6. И, наконец, в качестве Source value or expression указать соответствующий PL/SQL-блок с вызовом пакета. Например, для создания быстрых значений к элементу P1_TEXT:
    begin
    apex_quick_picks_pkg.prn_quick_picks_from_query
    ( p_item_name=>'P1_TEXT'
    , p_query=>
    'select d, ltrim(to_char(d, ''RЪ'')) r
    from (select 1 d from dual
    union all
    select 2 from dual
    union all
    select 5 from dual)'
    , p_show_clear=>'Y'
    );
    end;




Ну и ещё кое-что для тех, кто не любит каждый раз всё набирать руками. Если Вы используете APEX Builder Plugin, то можно расширить предустановленные наборы (aka Set), которые он добавляет, ещё одним, который установит все необходимые атрибуты у элемента и облегчит написание PL/SQL-кода в Source value or expression (пока что есть набор только для работы с QP на основе LOV). Вот изменённый основной скрипт плагина версии 1.9.1 для FF, им нужно подменить установленный скрипт плагина в GreaseMonkey. Для этого можно открыть следующее: Инструменты->GreaseMonkey->Управление скриптами, выбрать APEX Builder Plugin 1.9, нажать "Изменить", заменить полностью содержимое скрипта текстом скрипта из архива. Затем нужно добавить к уже установленным скриптам плагина новый пользовательский скрипт и выбрать в настройках (Инструменты->GreaseMonkey->Команды скрипта->APEX Builder Plugin Settings) использование пользовательских скриптов для страниц (Adding user scripts for pages). Всё.

Пользуйтесь на здоровье!

PS: Я постараюсь написать нормальную документацию, если этот минипроект будет кому-нибудь интересен, и возникнут вопросы. Кроме того, при возникновении проблем, просьб и интересных мыслей, связанных с этим проектом, буду рад, если они отразятся в комментариях.

Читать далее

понедельник, 15 марта 2010 г.

ORA-38104: Бомба с часовым механизмом

Так сказать, моя небольшая история об неудачном дизайне.

Была задача, которую в двух словах можно описать так: хранить некоторые меняющиеся во времени значения. Одно значение должно сменять другое, без разрывов в периодах.

Нет проблем, подумал я. Всё это реализуется декларативно, через ограничения целостности. Где-то так:


create table test_params
( param_id number -- параметр
, prev_end_date date -- дата окончания прошлой записи
, start_date date -- дата начала текущей записи
, end_date date -- дата конца текущей записи
, value varchar2(10)
, primary key (param_id, start_date)
, unique (param_id, end_date)
, check(start_date - 1 = prev_end_date)
, check(end_date >= start_date)
, check(start_date = trunc(start_date))
, check(end_date = trunc(end_date))
, check(prev_end_date = trunc(prev_end_date)) );

alter table test_params
add constraint test_params_fk_chain
foreign key (param_id, prev_end_date)
references test_params(param_id, end_date)
deferrable
initially immediate;


В реальной системе всё немного сложнее (param_id ссылается на таблицу с определениями параметров), но это хорошо отражает суть.

Всё было отлично, вокруг таблицы создавался PL/SQL-код... А затем мне понадобилось написать в пакете процедуру для обновления start_date и end_date у заданной записи. Очевидно, что при их изменении нужно соответствующим образом изменить предыдущую и следующую запись в цепочке значений параметра. "Если ты можешь сделать это через SQL - сделай это так," - говорит дядя Том. И я решил сделать это через MERGE. И вот тут-то стремление к минимализму при проектировании меня подвело: изменять поле, которое используется в on_clause, MERGE отказался наотрез. ORA-38104, господа и дамы. А пересоздание ограничений откладываемыми привнесёт ещё больше проблем.

Вывод: сэкономив на поле для суррогатного первичного ключа, я потерял время, которое теперь необходимо для того, чтобы его добавить. Дизайн нужно продумывать с учётом ограничений способов, которыми будет вестись работа. :)

Читать далее

четверг, 4 марта 2010 г.

APEX: Автовход

Пользуясь APEX как разработчик, я пару месяцев назад заскучал по одной определённой возможности, а именно - автовходе. Когда работаешь в одном и том же рабочем пространстве под одной и той же учёткой, вводить логин и пароль каждый раз становится лень. Потому я, недолго думая, написал скрипт для GreaseMonkey:
$s("F4550_P1_COMPANY", "MYWORKSPACE");
$s("F4550_P1_USERNAME", "MYLOGIN");
$s("F4550_P1_PASSWORD", "MYPASSWORD");
$x("LOGIN_BUTTON").click();

Вместо MYWORKSPACE, MYLOGIN и MYPASSWORD, конечно, указаны мои рабочее пространство, логин и пароль.

Если кто-то так же ленив, как и я, возможно, это ему пригодится. :)
Читать далее

четверг, 11 февраля 2010 г.

Oracle SQL Developer+Debian GNU/Linux: Нетривиальный баг

Довелось наткнуться на баг не столько самого OSD, сколько используя его. После очередного обновления пакетов Debian при попытке соединения OSD выдавал lo exception: The Network Adapter could not establish the connection - и хоть ты тресни. После поиска в сети оказалось, что это баг #560044: net.ipv6.bindv6only=1 breaks java networking. Быстрый и грязный фикс для тех, кто уже пользуется веткой testing:
sudo sed -i 's/net.ipv6.bindv6only\ =\ 1/net.ipv6.bindv6only\ =\ 0/' \
/etc/sysctl.d/bindv6only.conf && sudo invoke-rc.d procps restart


Надеюсь, Вы ещё не меняли ничего от отчаяния в tnsnames.ora и listener.ora?..
Читать далее

понедельник, 8 февраля 2010 г.

ОФФ: Снова в эфире из дома!

Наконец-то взял новую видеокарту взамен павшего смертью храбрых в борьбе с пылью старичка 8800GT. Не мудрствуя лукаво и не гоняясь с сверхпроизводительностью на FullHD-экранах, выбрал Gainward GT240 512MB GDDR5 - крепкий середнячок с маленьким энергопотреблением. Пока что всё устраивает: неслышный вентилятор, температура в простое - 30 градусов, производительность сравнима.

Моё домашняя машина снова на ходу! Ура.
Читать далее

суббота, 6 февраля 2010 г.

Oracle DB XE+APEX 3.2.1+JasperReports: Инструкция по сборке на Win32 ч.1

Предисловие



Честно говоря, надоело отношение к установке Oracle DB XE, к обновлению включённого в неё APEX до более поздних версий (в частности, 3.2.1) и к интеграции со всем этим добром хорошего и бесплатного генератора отчётов - ко всему этому как к чему-то сложному и непонятному. Можно по-разному бороться с этим уже сложившимся у некоторых мнением, лично я буду бороться с ним, используя простые примеры. Результатом должна стать инструкция по установке и простейшей настройке Oracle Database Express Edition (дальше - Oracle XE или просто XE), APEX 3.2.1 (дальше - APEX), JasperReports (дальше - JR). В качестве ОС пока будет выступать Win32, но надеюсь, что вскоре я реанимирую свою машину с Debian GNU/Linux, и появится аналогичная статья для Debian-based Linux. Поехали!

Установка XE



Если Вы не в курсе, что такое XE, то советую Вам прочитать следующий тынц: Oracle Database 10g Express Edition. Если вкратце, то это та же самая Oracle Database 10.2.0.1, но с ограничениями на размер пользовательских данных (4 ГБ), размер БД вместе с этими данными (5 ГБ), размер используемого ОЗУ (1 ГБ) и количество используемых ядер процессора (1 ядро). Кроме того, она довольно быстро и легко устанавливается и настраивается. Всё это делает её отличным кандидатом в качестве СУБД для небольших проектов и любящих экспериментировать разработчиков и АБД.

Скачать XE для Win32 можно здесь. Поскольку мы хотим хранить в БД данные с русскими символами и (я надеюсь) не хотим пользоваться недокументированным способом по смене кодировки БД после установки, то скачивать нужно Oracle Database 10g Express Edition (Universal) - тогда в качестве кодировки БД будет использоваться AL32UTF8.

После загрузки стоит прочитать руководство по установке и следовать ему. Для тех, у кого проблемы с английским, краткий перевод шагов:
  1. Войдите в систему как Администратор.
  2. Очистите переменную окружения ORACLE_HOME через Панель управления->Система.
  3. Сходите на сайт...
  4. ... и скачайте файл, который Вы уже скачали.
  5. Запустите его.
  6. Если Вы переустанавливаете XE, то появится опция Repair.
  7. Next.
  8. Accept->Next.
  9. Выбираем, куда установить->Next.
  10. При необходимости указываем порты для прослушивателя, MS Transaction Server и APEX. По умолчанию: 1521, 2030 и 8080.
  11. Вводим пароли для пользователей SYS и SYSTEM. По значимости эти пользователи БД близки к Локальному Администратору ОС и пользователю из группы Администраторов. Так что выбирайте сами сложность паролей.
  12. Install, если всё устраивает.
  13. У Вас есть работающая XE! Можете создавать пользователей и работать. При желании, можете зайти на домашнюю страницу БД. Приложение хорошее, но одна проблема: с обновлением APEX до 3-ей версии это приложение со всеми его прелестями администрирования пропадёт. И нам понадобится что-нибудь для работы с БД, помимо SQL Workshop->SQL Commands. Так что я предлагаю следующее...


Oracle SQL Developer



Довольно неплохое бесплатное средство разработки, администрирования и вообще общения с Oracle DB. Oracle SQL Developer может подключаться и к другим СУБД, но нас пока интересует исключительно наша XE. Домашняя страница проекта - здесь. Скачать последнюю версию можно здесь (на текущий момент это версия 2.1). Для начинающих есть пошаговое обучение. Интерфейс дружественный, в чём-то интуитивный, в чём-то - нет. Трудностей при работе возникнуть не должно, если время от времени заглядывать в Help.

Oracle APEX 3.2.1



После установки XE у Вас уже будет APEX, но почему бы не обновить его до последней версии (на данный момент это версия 3.2.1)? Многие считают, что это сложно. Попробую разубедить.

Домашняя страница APEX находится здесь. Загрузим последнюю доступную версию отсюда. Вообще-то, всё отлично получается при использовании руководства по установке. Но я попробую дать пошаговую простую инструкцию по обновлению:
  1. Скачайте архив с APEX и распакуйте их в каталог C:\tmp.
  2. Запустите cmd: Win+R->cmd. Выполните:
    cd c:\tmp\apex
    sqlplus "sys/syspass as sysdba" @apexins SYSAUX SYSAUX TEMP /i/
    

    Начнётся установка и обновление APEX. Можно сходить попить кофе или ещё как-нибудь провести минут 10-15 времени.
  3. Меняем пароль у администратора APEX:
    sqlplus "sys/syspass as sysdba" @apxchpwd
    

  4. Не выходя из SQL*Plus, настраиваем Embedded PL/SQL Gateway:
    @apex_epg_config c:\tmp

  5. Там же разблокируем пользователя ANONYMOUS, под которым APEX работает с БД...
    alter user anonymous account unlock;

  6. ... установим явно http-порт для XML DB...
    EXEC DBMS_XDB.SETHTTPPORT(8080);

  7. ... и разрешим анонимный доступ к файлам в XML DB.
    SET SERVEROUTPUT ON
    DECLARE
    l_configxml XMLTYPE;
    l_value VARCHAR2(5) := 'true'; -- (true/false)
    BEGIN
    l_configxml := DBMS_XDB.cfg_get();
    
    IF l_configxml.existsNode('/xdbconfig/sysconfig/protocolconfig/httpconfig/allow-repository-anonymous-access') = 0 THEN
    -- Add missing element.
    SELECT insertChildXML
    (
    l_configxml,
    '/xdbconfig/sysconfig/protocolconfig/httpconfig',
    'allow-repository-anonymous-access',
    XMLType('' ||
    l_value ||
    ''),
    'xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd"'
    )
    INTO l_configxml
    FROM dual;
    
    DBMS_OUTPUT.put_line('Element inserted.');
    ELSE
    -- Update existing element.
    SELECT updateXML
    (
    DBMS_XDB.cfg_get(),
    '/xdbconfig/sysconfig/protocolconfig/httpconfig/allow-repository-anonymous-access/text()',
    l_value,
    'xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd"'
    )
    INTO l_configxml
    FROM dual;
    
    DBMS_OUTPUT.put_line('Element updated.');
    END IF;
    
    DBMS_XDB.cfg_update(l_configxml);
    DBMS_XDB.cfg_refresh;
    END;
    /
    
    Element updated.

  8. Кроме того, можно открыть удалённый HTTP-доступ:
    exec dbms_xdb.setListenerLocalAccess(l_access => FALSE);

    Чтобы его убрать, достаточно выполнить тот же код, используя в качестве параметра TRUE.


Всё, вы можете заходить на страницу администрирования (http://127.0.0.1:8080/apex/apex_admin), создавать рабочее пространство и администратора для него, потом заходить администратором рабочего пространства в обновлённый APEX (http://127.0.0.1:8080/apex) и добавлять разработчиков и пользователей, потом разработчики могут приниматься за дело... Всё как и должно быть.

В качестве замены встроенного приложения для администрирования в XE можно прочитать здесь список основных задач и способы их выполнения.

О JasperReports и их установке поговорим в следующей части.

Читать далее