суббота, 4 октября 2014 г.

Пятая часть освоения SOA

Требуется изучить:

Выполнить задание:

  • Сенсоры и BAM:
    • По книге Getting Started With Oracle SOA Suite 11gR1 изучить и выполнить задания по главе 16 (посвящённой Oracle BAM);
    • Сделать композит (с BPEL-процессом), который будет вызывать внешний сервис (который нужно так же реализовать). Этот внешний сервис периодически возвращает ошибку (например такая логика: если минута в текущем времени четная, то вернуть ошибку). Нужно сделать отчёт средствами Oracle BAM содержащий информацию по общему кол-ву запущенных инстансов и сколько из них с ошибками
  • REST:
    • Сделать композит взаимодействующий с RESTful-сервисом (сам RESTful-сервис создайте его любым удобным средством).

пятница, 3 октября 2014 г.

Четвертая часть освоения SOA

Требуется изучить:


Выполнить задание:

  • MDS: задеплоить в MDS артефакты (XSD, WSDL, fault policy file) и сделать простой композит использующий данные артефакты.
  • Resequencing: сделать композит иллюстрирующий работу  всех вариантов Resequencing – Standard, FIFO, Best effort.
  • EDN
    • Сделать композит с WS-интерфейсом, который генерирует событие (EDN), а другой композит слушает это событие и записывает информацию в БД. 
    • Сделать отдельный композит который слушает события от HumanTask (в качестве композита с HumanTask предлагаю взять таковой из tutorial) и записать информацию (как минимум: идентификатор задачи, кто сделал (логина достаточно), что сделал (действие) и когда сделал(время)) в БД

четверг, 2 октября 2014 г.

Третья часть освоение SOA

Выполнить задания:

  • Задачка 1
Сделать композит, который периодически опрашивает (polling) таблицу БД на наличие строк со статусом READY и при их появлении пишет в файловую директорию cvs-файлы.

  • Задачка 2

Сделать композит, который периодически опрашивает (polling) файловую директорию на наличие csv-файлов следующей структуры:
First name,Last name,ID,E-mail
John,Doe,01234567,john.doe@domain.com
Alex,Smith,88888888,alex.smith@domain.com
Необходимо записать данные из csv-файлов в таблицу БД (сделать табличку с теми же полями и первичный ключ по всем полям). 

  • Задачка 3

Сделать композит, который «слушает» очереди JMS и AQ (т.е. две очереди; внутри XML-сообщения) и записывает данные сообщения в таблицу БД через вызов API-процедуры.

  • Задачка 4

Добавить в существующий композит (см. задачку 2) дополнительную операцию (интерфейс WS), входная переменная которой получает полный путь к локальному csv-файлу (структура та же).  Необходимо записать данные из указанного файла в таблицу БД.

  • Задачка 5

Добавить обработку ошибок в композите (см. задачку 2)  и в случае ошибки вставки в таблицу БД (ошибка по первичному ключу) переводить на администратора (humanIntervention), который может изменить значения полей и завершить выполнение композита

среда, 1 октября 2014 г.

Вторая часть освоения SOA

Требуется изучить:

Выполнить tutorial. Есть следующие полезные книги:
  • Getting Started With Oracle SOA Suite 11gR1 (главы 1-10,13-15,17)
  • Oracle SOA Suite 11g R1 Developers Guide (главы 1-8,11,13-14,18-21)
  • WS-BPEL 2.0 for SOA Composite Applications with Oracle SOA Suite 11g (главы 1-7 включительно)
Книги однотипные, главы связанные с BAM (Business Activity Monitorung) и OSB (Oracle Service Bus) пока не рассматриваем. Первые две книги содержат tutorial-ы. Пройдите от начала до конца одину из них (см. указанные главы). Обрати внимание, что оба tutorial-а по немного более старой версии SOA (например по 11.1.1.5), хотя на данный момент чаще всего используется версии 11.1.1.6 и 11.1.1.7 - поэтому скриншоты в книгах могут немного не совпадать.
После завершения tutorial просмотреть остальные книги на непроработанный/незатронутый функционал.

Выполнить задание:

  1. Создать две JMS Queue в Weblogic;
  2. Создать MDB, который перекладывает сообщения из одной очереди в другую;
  3. Развернуть на сервере и протестировать.

Полезные ссылки:

  1. Рекомендую использовать официальный developers guide по Oracle SOA, как справочник.
  2. Хороший блог по Oracle SOA на русском языке
  3. Блоги на английском:

вторник, 30 сентября 2014 г.

Первая часть освоения SOA

Требуется изучить:

Книг по XML много, в том числе и на русском. Дополнительно полезно знать XQuery. Нужно понимание функциональности и возможностей XQuery по сравнению с XSL. Рекомендую книгу «W3C XML: Xquery от экспертов. Руководство по языку запросов» или в оригинале «XQuery from the Experts: A Guide to the W3C XML Query Language».

  • Weblogic. Требуется разобраться:
    • Как минимум, в следующих технологиях:
      • JMS (Java Message Service)
      • MDB (Message Driven Bean)
      • JTA & JTS (Java Transaction API & Java Transaction Service)
    • В основах администрирования.

Полезные ссылки:

Освоение Oracle SOA

За основу данного набора статей взята моя переписка с начинающими разработчиками SOA, целью которой было вырастить разработчиков Oracle SOA Suite. Кроме переписки было обсуждение вопросов и задач через Skype. Формат следующий:

  • Что нужно изучить с ссылками на материалы;
  • Простейшие практические задачки;
  • Полезные ссылки.

Обращаю внимание, что этот набор статей не охватывает весь функционал Oracle SOA Suite, а включает только наиболее часто используемый функционал. Так же смотрите на полезные ссылки в постах пройдя по которым можно изучить неохваченный функционал.

Этот пост подержит ссылки на все посты из данного набора:

P.S. рекомендации приветствуются J

понедельник, 29 сентября 2014 г.

Список необходимых патчей для Oracle SOA & BPM Suite 11g PS6 (11.1.1.7)

Перечень патчей которые необходимо развернуть для Oracle SOA & BPM Suite 11g PS6 (11.1.1.7):
  • Patch 17294404: XSDCOMPLEXTYPE.GETCHILDELEMENTS() IS NOT THREAD SAFE
  • Patch 18325165: MERGE REQUEST ON TOP OF 11.1.1.7.0 FOR BUGS 16319620 16487002
  • Patch 18609527: SOA BUNDLE PATCH 11.1.1.7.4
  • Patch 18366461: NULLPOINTEREXCEPTION AT WEBSERVICEEXTERNALBINDINGCOMPONENT.GETINVOCATIONMETADATA
Скачать эти патчи можно c support.oracle.com.

P.S. список патчей будет дополняться (при необходимости).
P.P.S. рекомендации по патчам приветствуются :-)

вторник, 13 мая 2014 г.

ADF: Ошибка InvalidOwnerException JBO-25030 при одновременном создании master- и detail-записей

Ошибка:
При создании Master- и Detail-записи последовательно через ADF Data Binding, например как в следующем коде:
  public String createMasterDetail() {
  
   BindingContainer bindings = getBindings();  
   OperationBinding operationBinding =  
   bindings.getOperationBinding("CreateInsertMaster");  
   Object result = operationBinding.execute();  

   OperationBinding operationBinding1 =  
   bindings.getOperationBinding("CreateInsertDetail");  
   result = operationBinding1.execute();  

   return null;  
  }  
Причина:
При создании новой строки через ADF Data Binding её статус будет STATUS_INITIALIZED. А когда Detail-запись пытается найти Master-запись в кеше (у которой статус STATUS_INITIALIZED), то будет брошено исключение InvalidOwnerException.

Решение:
  1. Установить флаг Сascade Update Key Attributes в ассоциации между Master- и Detail-сущностями;
  2. Сгенерировать View Row Class (...ViewRowImpl) для Master-сущности и переопределить в нём следующий метод:
      @Override  
      public void setNewRowState(byte b) {  
       if (b!=Row.STATUS_INITIALIZED || getNewRowState()!=Row.STATUS_NEW){  
       super.setNewRowState(b);  
       }  
      }  
    
Пример простейшего ADF-приложения здесь.

понедельник, 13 января 2014 г.

SoapUI: подстановка вычисляемых значений с помощью вставок на Groovy

Целей функционального тестирования композитных приложений иногда используются заглушки и/или SoapUI,EM и прочие средства. Но как правило необходимо отправлять сообщения с отличающимися данными, например: документ на согласование с различными идентификатором и текущей датой отправки. Можно каждый раз перед отправкой менять значения вручную, но удобнее например для числовых идентификаторов использовать случайное число из определённого диапазона, а для даты подставлять например текущую дату. В SoapUI есть поддержка Groovy и подобное поведение делается очень легко (выделено красным):
Итак, в качестве значения поля для генерации:
  • числового значения в диапазоне от 0 до 10000 нужно подставить:
     ${=(int)(Math.random()*10000)}  
    
  • текущей даты нужно подставить:
     ${=new Date().format(‘yyyy-MM-dd’)}  
    

понедельник, 6 января 2014 г.

Планировщик заданий в Weblogic Server

Реализовать планировщик заданий можно, как средствами встроенных в операционную систему(ОС) планировщиков заданий так и встроенных СУБД, но при изменении ОС (например, с Windows на AIX) либо изменении СУБД (например, с Oracle на MySQL) потребуется переработка компонента планировщика. Рассмотрим реализацию планировщика заданий работающего внутри Weblogic Server, который не зависит от ОС и СУБД.
Данный планировщик представляет собой простейшее Web-приложение и будет выполнять задачу через каждые 5 секунд, а задача при выполнении будет писать в лог строку с временем выполнения (никто не запрещает сделать более сложную логику). А так же будет создан сервлет для управления заданием (действия - остановить выполнение и запустить выполнение). Более того при создании не будут использоваться внешние библиотеки, только те которые есть в Weblogic Server.
  1. Открываем Oracle JDeveloper и создаём новое приложение (с именем SampleScheduler):
  2. Затем добавляем в проект необходимые библиотеки.
  3. Создаём новый класс для описания задания(с именем HelloWorldJob):
     package com.blogspot.stan1slav.sample.jobs;  
       
     import commonj.timers.CancelTimerListener;  
     import commonj.timers.Timer;  
     import commonj.timers.TimerListener;  
       
     import java.io.Serializable;  
       
     import java.util.Date;  
       
     public class HelloWorldJob implements Serializable, TimerListener,  
                        CancelTimerListener {  
       private Date timerDate = null;  
       
       public HelloWorldJob() {  
         super();  
       }  
       
       public void timerExpired(Timer timer) {  
         timerDate = new Date(timer.getScheduledExecutionTime());  
         System.out.println("HelloWorldJob timer expired called on " +  
                   timerDate);  
       }  
       
       public void timerCancel(Timer timer) {  
         timerDate = new Date(timer.getScheduledExecutionTime());  
         System.out.println("HelloWorldJob timer cancelled called on " +  
                   timerDate);  
       }  
     }  
    
    Следует обратить внимание на выделенное красным, это те классы которые должны быть имплементированы и методы которые должны быть реализованы (один при срабатывании задачи и другой для отмены/остановки задачи). Инициализацию задания можно вынести в конструктор.
  4. Создаём сервлет для старта/остановки задания, а так же автозапуска:
     package com.blogspot.stan1slav.sample;  
       
     import com.blogspot.stan1slav.sample.jobs.HelloWorldJob;  
       
     import commonj.timers.Timer;  
     import commonj.timers.TimerManager;  
       
     import java.io.IOException;  
     import java.io.PrintWriter;  
       
     import java.util.Date;  
       
     import javax.naming.InitialContext;  
       
     import javax.servlet.ServletConfig;  
     import javax.servlet.ServletException;  
     import javax.servlet.http.HttpServlet;  
     import javax.servlet.http.HttpServletRequest;  
     import javax.servlet.http.HttpServletResponse;  
       
     public class JobsServlet extends HttpServlet {  
       private Timer helloWorldJobTimer = null;  
       private TimerManager tm = null;  
       
       public void init(ServletConfig config) throws ServletException {  
         super.init(config);  
         System.out.println("InitJobsServlet is initialized ");  
       
         try {  
           InitialContext ic = new InitialContext();  
           tm = (TimerManager)ic.lookup("java:comp/env/tm/TimerManager");  
           helloWorldJobTimer =  
               tm.schedule(new HelloWorldJob(), new Date(), 5000); //5 seconds  
         } catch (Exception ne) {  
           ne.printStackTrace();  
         }  
       }  
       
       public void service(HttpServletRequest req,  
                 HttpServletResponse res) throws IOException {  
         res.setContentType("text/html");  
         PrintWriter out = res.getWriter();  
         out.println("<h4>JobsServlet is working!</h4>");  
         String cmd = req.getParameter("cmd");  
         if (cmd != null && cmd.equals("cancel") && helloWorldJobTimer != null) {  
           helloWorldJobTimer.cancel();  
           helloWorldJobTimer = null;  
         }  
         if (cmd != null && cmd.equals("start") && helloWorldJobTimer == null) {  
           helloWorldJobTimer =  
               tm.schedule(new HelloWorldJob(), new Date(), 5000);  
         }  
         if (helloWorldJobTimer != null) {  
           out.println("<h6>HelloWorldJob started</h6>");  
         } else {  
           out.println("<h6>HelloWorldJob calceled</h6>");  
         }  
       }  
     }  
    
  5. В web.xml прописать ссылку на ресурс (т.е. на наш TimerManager):
     <?xml version = '1.0' encoding = 'UTF-8'?>  
     <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
          xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"  
          version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">  
      <servlet>  
       <servlet-name>JobsServlet</servlet-name>  
       <servlet-class>com.blogspot.stan1slav.sample.JobsServlet</servlet-class>  
       <load-on-startup>100</load-on-startup>  
      </servlet>  
      <servlet-mapping>  
       <servlet-name>JobsServlet</servlet-name>  
       <url-pattern>/jobsservlet</url-pattern>  
      </servlet-mapping>  
      <resource-ref>  
       <res-ref-name>tm/TimerManager</res-ref-name>  
       <res-type>commonj.timers.TimerManager</res-type>  
       <res-auth>Container</res-auth>  
       <res-sharing-scope>Unshareable</res-sharing-scope>  
      </resource-ref>
     </web-app>  
    
  6. Деплоим на сервер (как WAR-архив) и проверяем работоспособность (смотрим в out-лог сервера)
    1. Задание выполняется после деплоя:
    2. С использованием сервлета остановим выполнение задания (для этого при вызове добавляем ?cmd=cancel):
    3. В логе появилась запись об остановке (отмене) задания:
    4. С использованием сервлета стартуем снова задание (для этого при вызове добавляем ?cmd=start):
    5. В логе появились записи о выполнении задания:
Полезная информация: