(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

EJB Advocate: Реализация слабосвязанных SOA-приложений с использованием Java EE (исходники)

Источник: IBM developerWorks Россия

В каждой статье EJB Advocate приводится типичный диалог с реальными пользователями и разработчиками в процессе предоставления рекомендаций по решению какой-либо интересной проблемы. Персональные данные участников диалога не сообщаются, также не используются недостаточно испытанные и закрытые архитектуры.

Не является ли ваше определение слабого связывания слишком жестким?

Поскольку это последняя статья в 2005 году, рассмотрение компонентов Java Platform, Enterprise Edition (Java EE), отличных от сессионных компонентов и компонентов управления данными, - хороший способ подытожить продолжительную дискуссию в данной рубрике и поместить все компоненты в контекст сервис-ориентированной архитектуры.

Проблема: в SOA уделяется слишком много внимания сессиям и логическим объектам

Уважаемый EJB Advocate!

До сих пор Ваша рубрика была посвящена сессионным EJB-компонентам и компонентам управления данными для сервисов, что очень хорошо для напрямую подключающихся Java-приложений, например, HttpServlets для Web-клиентов или Swing-приложений для полнофункциональных (rich), поскольку мы не любим говорить "толстых", клиентов. Однако мы слышали, что в основе сервис-ориентированной архитектуры лежит слабое связывание. Не подразумевается ли здесь использование SOAP для обеспечения языковой независимости и асинхронных протоколов, позволяющих клиентским и серверным приложениям работать независимо, насколько это возможно? Другими словами, почему Вы не так часто говорите о JMS и управляемых сообщениями bean-компонентах?

Feeling Disconnected (Не-присоединившийся)

Существует много аспектов слабого связывания, которые нужно учитывать

Уважаемый Disconnected!

EJB Advocate уделяет больше внимания уровням сервисов приложения по сравнению с клиентской стороной, потому что я большой поклонник старинного изречения " форма следует за функцией ".

Причина неудач многих проектов, основанных на SOA, заключается в том, что они вязли в деталях реализации, не сформировав прежде хорошую модели для определения сервисов.

Эта тенденция в определенном смысле естественна, поскольку большинство людей, с которыми я имел дело в области SOA - это разработчики и программисты, знающие, что дьявол прячется в деталях, и желающие погрузиться в эти детали как можно раньше. То есть, соглашаясь с тем, что хороший сервис - это крупно-модульный (coarse grained), не требующий сохранения состояния, способный быть посредником, адаптируемый сервис, мы очевидностью приходим к тому, что сессионные компоненты с объектами передачи данных будут играть свою роль в реализации.

Но в предыдущей статье возник вопрос, нужен ли сессионный компонент вообще, и была представлена возможность использования компонентов управления данными и их методов Home вместо сессионных компонентов. На рисунке 1 показано одновременное использованиеы обоих подходов.

Рисунок 1. Сервис, реализованный при помощи сессионного EJB-компонента и компонента управления данными, ожидающими использования
Рисунок 1. Сервис, реализованный при помощи сессионного EJB-компонента и компонента управления данными, ожидающими использования

На рисунке 1 показано, что подход только с компонентом управления данными, возможный начиная с EJB 2, имеет меньше компонентов и более короткий путь, когда используются сквозные сессионные компоненты. Зеленый прямоугольник - это клиент, а синие - различные интерфейсы и классы фасада. Оранжевый прямоугольник - это общедоступный компонент управления данными. Прямоугольники соединены двунаправленными стрелками, на которых указаны названия протоколов, используемых для взаимодействия между компонентами; синие стрелки изображают Java-вызовы в пределах одной JVM, а красные - удаленные соединения (в данном случае использующие RMI/IIOP). Последовательность стрелок пронумерована (чтобы показать всю последовательность действий) от A1 до A10, что соответствует движению данных от Java-клиента через сессионный компонент в компонент управления данными и обратно, а B1-B4 обозначает движение от клиента непосредственно к компоненту управления данными и обратно.

Программная модель извлечения интерфейса сервиса, используемого клиентом, также более проста, хотя это не показано на диаграмме. Извлечение интерфейса сессионного компонента требует поиска его Home в JNDI-контексте и использования его для создания сессии; Home компонента управления данными просто нужно найти, его методы можно активизировать напрямую без создания ссылки на EJB Object. В следующих двух примерах исходного кода показано это отличие.

Листинг 1. Обнаружение и активизация метода удаленного сессионного EJB-компонента
                
Context initCtx = new InitialContext();
Object obj = initCtx.lookup("java:comp/env/ejb/OrderEntry");       
OrderEntryHome home = (OrderEntryHome)PortableObjectRemote(
	obj, OrderEntryHome.class
);       
OrderEntry ref = home.create();

// Метод необходимо активизировать ссылкой на сессию
CustomerData data = ref.getOpenOrderForCustomer(cID);

Листинг 2. Обнаружение и активизация эквивалентного метода удаленного EJB Home компонента управления данными

Context initCtx = new InitialContext();
Object obj = initCtx.lookup("java:comp/env/Customer");
CustomerHome ref = (CustomerHome)PortableObjectRemote(
	obj, CustomerHome.class
);

// Обратите внимание, что метод активизируется напрямую    
CustomerData data = ref.getOpenOrder(cID);

Рисунок 1 и соответствующий исходный код показывают реальное преимущество программной модели Java EE, независимо от того, используется ли подход с методом Home компонента управления данными. Программная модель меняется постепенно и обеспечивает обратную совместимость. Коротко говоря, вы можете развивать свои оптимальные методики без необходимости изменять существующие приложения. Кроме того, JNDI-контекст предоставляет аспект слабого связывания, ценность которого нельзя не недооценивать - это независимость реализации.

Удаленные интерфейсы к сессионным EJB-компонентам и компонентам управления данными обеспечивают независимость от местоположения. Использование удаленных интерфейсов делает возможным развертывание клиентского приложения и компонентов сервиса в одной и той же JVM, где это имеет смысл для уменьшения времени реакции, увеличения пропускной способности и более легкого обслуживания системы (например, в случае Web-приложения, использующего HttpServlets). На рисунке 2 показана именно такая конфигурация, в которой сервер приложений корпоративного класса (например, IBM® WebSphere® Application Server) "замыкает накоротко" уудаленный интерфейс на Java и передачу параметров по ссылке, когда клиент и компоненты сервиса развертываются совместно (независимо от того, реализуется ли сервис как метод Home компонента управления данными или как сессионный компонент). Потоки A1-A6 показывают использование HttpServlet, развернутого совместно с компонентом сервиса. Потоки B1-B4 показывают, как он повторно используется удаленным полнофункциональным клиентским Java EE-приложением.

Рисунок 2. Сервис, развернутый локально для Web-приложения и удаленно для полнофункционального Java-клиента
Рисунок 2. Сервис, развернутый локально для Web-приложения и удаленно для полнофункционального Java-клиента

Однако создается впечатление, что вы считаете, что самыми важными аспектами слабого связывания являются языковая независимость и асинхронные операции. И Вы правы в том, что необходимость асинхронных операций ведет к использованию управляемых сообщениями компонентов (Message-Driven Beans - MDB) и JMS на стороне сервера.

Подход, который используется многими программистами при реализации MDB, заключается в активизации EJB-компонента, представляющего сервис, через его удаленный интерфейс для максимальной независимости от местоположения, как описано выше. В дальнейшем, независимо от того, развернута реализация сервиса локально или удаленно, MDB будет служить просто адаптером, соединяющим MQ-слой с EJB-контейнером, где размещен сервис. JMS может использоваться асинхронным клиентским приложением (если это Java) или MDB-компонентом (обычно для очереди ответов). На рисунке 3 показана эта конфигурация как еще один входной канал для нашей реализации сервиса.

Рисунок 3. Сервис, развернутый с MDB-компонентами, обеспечивающими асинхронный клиентский канал
Рисунок 3. Сервис, развернутый с MDB-компонентами, обеспечивающими асинхронный клиентский канал

Поток C1-C2 показан отдельно от D1-D6 для иллюстрации независимости клиентского и серверного процессов. C2 и D6 просто показывают записывающей стороне "подтверждение" того, что сообщение было записано, и не подразумевают ожидания. В листинге 3 приведена типичная структура MDB-компонента, поясняющая, что он должен делать.

Листинг 3. Типичная реализация управляемого сообщениями компонента
public class OrderSubmitMsgHandler implements MessageDrivenBean {
    private transient MessageDrivenContext context = null;

    // Интерфейс, поддерживаемый либо сессионным компонентом,
	либо Home-интерфейсом компонента управления данными
    private transient OrderEntry ref;

    public void ejbCreate() {
        // Кэширование home в соответствии со сниппетом один или два
    }
    public void ejbRemove() {}
    public void setMessageDrivenContext(MessageDrivenContext mdc) {    
        context = mdc; 
    }
    // Подтверждение сообщения и обновление базы данных
    public void onMessage(Message inMessage) {
        // Извлечь информацию о пользователе из сообщения
	try {
	    ref.submit(customer); 
	} 
        catch (CustomerDoesNotExist e) {
            // Послать JMS-сообщение в очередь ответов из исключительной ситуации
        }
        catch (OrderNotOpen e) {
            // Послать JMS-сообщение в очередь ответов из исключительной ситуации
        }
        catch (OrderHasNoItemsException e) {
            // Послать JMS-сообщение в очередь ответов из исключительной ситуации
        }
    }
}

Хотелось бы вернуться к проблеме языковой независимости, которую Вы затронули. Такое впечатление, что Вы тесно связываете это требование с требованием асинхронной обработки. Но ничто не мешает Вам разделить эти задачи; способность синтаксически анализировать SOAP-сообщение и использовать его для активизации сессионного компонента должна быть независима от того, выполняется ли асинхронная обработка сообщения (через MQ или другой протокол, по которому проходят эквивалентные JMS сообщения) или синхронная (например, через HTTP или даже IIOP). Фактически некоторые из ранних "изобретений" Web-сервисов на Java EE-приложениях использовали HttpServlet для синтаксического анализа XML-сообщений, передаваемых по HTTP. Этот подход в конечном итоге развился в SOAP/HTTP. На рисунке 4 показан еще один путь, который может быть реализован поверх сервисов, предоставляемых EJB-компонентами.

Рисунок 4. Разделение задач нейтральности к языку и асинхронности
Рисунок 4. Разделение задач нейтральности к языку и асинхронности

Сервлет Web-сервиса и управляемый сообщениями компонент могли бы использовать общий код, выполняющий синтаксический анализ объектов передачи данных из потока, извлекаемого из строки сообщения или из HttpServletRequest. Аналогично, ответ мог бы использовать общий код для генерации потока из объекта передачи данных (который мог бы быть экземпляром Exception).

Надеюсь, это поможет Вам понять позиционирование Java EE-компонентов, каждый из которых обеспечивает некоторую форму слабого связывания, существенного для сервис-ориентированной архитектуры.

Ваш EJB Advocate

Все еще слишком много вариантов выбора

Уважаемый EJB Advocate!

Спасибо.

До сих пор я не предполагал, что такие сервисы, как JNDI и удаленные интерфейсы обеспечивают аспекты слабого связывания. Теперь я вижу, что мы (как Вы отметили) "тесно связали" идеи SOAP и MQ и должны попытаться разделить их, насколько это возможно. Поэтому имеет смысл реализовать синтаксический анализ и генерирование SOAP-сообщений тоже в виде сервиса, который может повторно использоваться сервлетом Web-сервисов и MDB.

Но есть еще кое-что.

До этого обсуждения SOA казалась довольно простой - каждый сервис отображал SOAP/MQ-интерфейс. Теперь такое впечатление, что у меня есть много вариантов для выбора, которые нужно рассмотреть. И поскольку я пытаюсь реализовать синтаксический анализ SOAP-сообщений и генерирование в виде сервисов, почему бы мне не сделать отдельный сессионный компонент, инкапсулирующий эти сервисы для повторного использования, как Вы показали на рисунках?

Боюсь, что все еще
Feeling Disconnected (Не присоединившийся)

Не все является сервисом: используйте бизнес-модель для принятия решения

Уважаемый Disconnected!

Данная дискуссия является отличным примером того, что происходит, когда Вы погружаетесь в детали реализации слишком рано. Важной является статья EJB Advocate "Какой тип EJB-компонента должен собирать данные, возвращаемые сервисом?", поскольку в ней описывается подход "сверх вниз" для определения сервисов, напрямую связывающих их с моделью бизнес-процессов. Вот резюме основных деталей реализации такого подхода:

  1. Разработать модель бизнес-процессов, показывающую основные этапы в жизненном цикле важного доменного объекта.

    1. Мы использовали для этой модели диаграммы состояний, в которых состояния представляют основные этапы, а переходы представляют события, вызвавшие изменения состояния. Переходы могут рассматриваться как сервисы, предлагаемые приложением (см. рисунок 5).

    2. Мы расширили диаграмму состояний представлением UML "Actor", чтобы показать владельца объекта, находящегося в данном состоянии. Владелец состояния отвечает за инициирование переходов, поэтому управляет моделью системы защиты приложения (см. рисунок 5).

    3. Для каждого состояния в бизнес-процессе мы также моделируем атрибуты каждого доменного объекта и взаимосвязи между ними, необходимые для поддержки действий по переходам. Обычно мы используем представление - диаграмму классов UML (см. рисунок 6). Разделение диаграмм для каждого состояния позволяет нам моделировать изменение "формы" объекта во времени. Эти диаграммы управляют персистентными данными.

  2. Разработать модель потока пользовательского интерфейса, показывающую, как данный участник (actor) бизнес-процесса будет взаимодействовать с системой во время типичного "сеанса".

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

    2. Так же как и для модели бизнес-процесса, мы создаем диаграмму классов для отображения данных, которые должны быть видимы в каждом состоянии, чтобы поддерживать различные варианты выбора. Смысл заключается в том, что эти данные должны извлекаться из действий пользователя и управлять операциями чтения в сервисах в стиле "сверху вниз".

    3. В отличие от модели бизнес-процесса нам не нужно расширять диаграмму состояний представлением Actor, поскольку диаграмма сама может рассматриваться как "один день жизни" одной пользовательской роли.


Рисунок 5. Пример диаграммы состояний, показывающей цикл жизни заказа
Рисунок 5. Пример диаграммы состояний, показывающей цикл жизни заказа

Рисунок 6. Пример диаграммы класса, показывающего "форму" открытого заказа
Рисунок 6. Пример диаграммы класса, показывающий "форму" открытого заказа

Такой всесторонний подход гарантирует, что:

  • Нужные операции группируются в сервис (все переходы и методы чтения, связанные с состоянием в цикле жизни бизнес-процесса).

  • Назначение каждого сервиса хорошо распознаваемо (действия определяются в понятиях связанных с ними бизнес-объектов).

  • Сообщаются предварительные условия (pre-conditions), необходимые для активизации сервиса, и последующие условия (post conditions), которые могут выполняться в результате работы (текущее состояние и возможные ограничения, а также следующее состояние определяется переходом).

  • Указывается пользовательская роль, которая отвечает за активизацию сервиса (с каждым состоянием связывается actor).

Данная информация не предоставляется в сигнатуре метода, независимо от того, где она реализуется, но эта информация жизненно важна для хорошей реализации SOA. В противном случае программисты впадут в другую крайность: если сомневаешься - создай заново . Поскольку стоимость разработки для SOA выше (нужно предоставить все промежуточные модули и адаптеры, необходимые для полной реализации слабого связывания, показанного на рисунке 4), такая тенденция, направленная против повторного использования, может минимизировать получаемые преимущества.

Что касается проблемы простоты, о которой Вы говорите, - данная информация вовсе не заставляет Вас отображать интерфейсы определенным образом, а EJB Advocate учит, что простота - дело вкуса. Если хотите скрыть варианты выбора, предназначенные для разработчика сервиса, можете просто предоставить все "синие" компоненты, показанные на рисунке 5, для каждого сервиса:

  • Интерфейс удаленного сервиса для обеспечения независимого от расположения синхронного доступа Java EE-клиентов к операциям сервиса.

  • MDB, связанный с каждой операцией, обеспечивающей асинхронный доступ не Java-клиентам по JMS-совместимой реализации MQ. При необходимости этот или другой MDB может быть закодирован на ожидание Java-сообщений для JMS-клиентов (чтобы избежать накладных расходов на HTTP Parsing).

  • Сервлет Web-сервиса, связанный с каждой операцией, которая обеспечивает синхронный доступ клиентам по протоколу SOAP over HTTP.

Те, кто беспокоятся о количестве неиспользуемых компонентов, которые будет генерировать данный подход, могут (для упрощения) применить еще один подход, который EJB Advocate любит называть клиент-ориентированной архитектурой (Client-Oriented Architecture - COA) - дать клиенту точно то, чего он хочет, для использования сервиса способом, наиболее подходящим для него.

Такой COA-подход требует анализа всех деталей бизнес-процесса и моделей пользовательского интерфейса с целью выбора наиболее вероятных кандидатов для каждого подхода. Например:

  • Переходы между состояниями в цикле жизни бизнес-процесса являются вероятными кандидатами для асинхронных сервисов, поскольку здесь будет происходить изменение "владельца" связанного доменного объекта. Например, метод submit может упростить изменение состояния заказа на "submitted" в приложении для открытия заказа (в приведенном выше примере мы назвали его OrderEntry) и передать JMS-сообщение для копирования его в приложение для обработки подтвержденных заказов (мы назвали его OrderFulfillment).

  • Переходы в состояниях обычно должны быть синхронными, поскольку здесь нет смены владельца. В качестве примера того, почему эти операции не должны быть асинхронными, представьте, что Вы зашли в Web-приложение по продаже книг и должны подавать запрос и ожидать события публикация-подписка для отображения каталога или товара, добавляемого в корзину покупок! Тем, кто хочет использовать псевдосинхронный стиль по асинхронному каналу, настоятельно предлагаю просмотреть книгу Бобби Вульфа (Bobby Woolf) "Проектирование систем обмена сообщениями".

  • Для сценариев интеграции, в которые вовлечены не Java-клиенты или сервисы, применяйте только SOAP over HTTP или MQ.

Результатами COA-подхода являются компоненты, разрабатываемые "точно в срок". Вот почему EJB Advocate любит его рекомендовать.

И последнее замечание, связанное с Вашим вопросом (почему бы не реализовать все в виде сервисов, даже преобразования, связанные с промежуточными модулями (mediators) и адаптерами)? Простой ответ: хорошего не должно быть слишком много. При разработке SOA или COA Java EE-приложений лучше всего рассматривать сервисы как операции в модели бизнес-процесса. Промежуточные модули и соответствующие преобразования ассоциируются с нефункциональными требованиями, такими как надежность, удобство использования, эффективность, простота обслуживания и переносимость. Если Вы будете рассматривать промежуточные модули или соответствующие преобразования как настоящие сервисы, то в конечном итоге сделаете непонятным истинное назначение приложения.

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

Ваш EJB Advocate .

Заключение

Данный диалог продемонстрировал, как Java EE предоставляет полную интегрированную среду реализации приложений, использующих сервис-ориентированную архитектуру, где каждый компонент или API играют важную роль в некоторых аспектах "слабого связывания":

  • Независимость от операционной системы обеспечивается самим языком Java, поскольку он предоставляет концепцию "написать один раз - выполнять где угодно" для компонентов, что отделяет код от применяемой операционной системы.

  • Независимость от реализации обеспечивается JNDI (Java Naming and Directory Interface), способным связать логическое имя с реализацией во время исполнения.

  • Независимость от местоположения обеспечивается удаленными интерфейсами, использующими RMI over IIOP для не сохраняющих состояния сессионных компонентов или методов home компонентов управления данными, которые инкапсулируют сервисы. RMI/IIOP - это соединение, запоминающее свое состояние и являющееся относительно быстрым, но не слишком хорошо масштабируемым.

  • Независимость от Web-сервера обеспечивается сервлетами HttpServlets, которые могут реагировать на синхронный HTTP-протокол. В отличие от RMI/IIOP, HTTP является (обычно) не сохраняющим состояние протоколом, хорошо масштабируемым, но не очень эффективным из-за больших по размеру сообщений и необходимости каждый раз создавать и разрывать соединение между клиентом и сервером.

  • Независимость от приложения обеспечивается асинхронной Java Messaging Service (или MQ для не Java-клиентов) и управляемыми сообщениями компонентами (для обработчика очереди).

  • Языковая независимость обеспечивается использованием стандартного формата сообщений (например, SOAP), независимо от того, проходят они по RMI/IIOP, HTTP или MQ. Следовательно, SOAP можно использовать во любых компонентах, но важно делать это только там, где необходимо.

Мы уверены, что Вы найдете и другие аспекты. Проблема заключается в нахождении разумных компромиссов для каждого из них. Этой работы Вам должно хватить до следующего года.



 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 17.08.2008 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
FastReport.Mono Single License
ARCHICAD 21, локальная лицензия на 12 месяцев
Купить, скачать Dr.Web Security Space, 1 год, 1 ПК
СУБД Линтер Бастион. Серверная лицензия. 5 клиентских подключений
Dr.Web Security Space, продление лицензии на 1 год, 1 ПК
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Программирование на Microsoft Access
CASE-технологии
OS Linux для начинающих. Новости + статьи + обзоры + ссылки
СУБД Oracle "с нуля"
Все о PHP и даже больше
Adobe Photoshop: алхимия дизайна
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100