|
|
|||||||||||||||||||||||||||||
|
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 2, имеет меньше компонентов и более короткий путь, когда используются сквозные сессионные компоненты. Зеленый прямоугольник - это клиент, а синие - различные интерфейсы и классы фасада. Оранжевый прямоугольник - это общедоступный компонент управления данными. Прямоугольники соединены двунаправленными стрелками, на которых указаны названия протоколов, используемых для взаимодействия между компонентами; синие стрелки изображают Java-вызовы в пределах одной JVM, а красные - удаленные соединения (в данном случае использующие RMI/IIOP). Последовательность стрелок пронумерована (чтобы показать всю последовательность действий) от A1 до A10, что соответствует движению данных от Java-клиента через сессионный компонент в компонент управления данными и обратно, а B1-B4 обозначает движение от клиента непосредственно к компоненту управления данными и обратно. Программная модель извлечения интерфейса сервиса, используемого клиентом, также более проста, хотя это не показано на диаграмме. Извлечение интерфейса сессионного компонента требует поиска его Home в JNDI-контексте и использования его для создания сессии; Home компонента управления данными просто нужно найти, его методы можно активизировать напрямую без создания ссылки на EJB Object. В следующих двух примерах исходного кода показано это отличие. Листинг 1. Обнаружение и активизация метода удаленного сессионного EJB-компонента
Рисунок 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-клиентаОднако создается впечатление, что вы считаете, что самыми важными аспектами слабого связывания являются языковая независимость и асинхронные операции. И Вы правы в том, что необходимость асинхронных операций ведет к использованию управляемых сообщениями компонентов (Message-Driven Beans - MDB) и JMS на стороне сервера. Подход, который используется многими программистами при реализации MDB, заключается в активизации EJB-компонента, представляющего сервис, через его удаленный интерфейс для максимальной независимости от местоположения, как описано выше. В дальнейшем, независимо от того, развернута реализация сервиса локально или удаленно, MDB будет служить просто адаптером, соединяющим MQ-слой с EJB-контейнером, где размещен сервис. JMS может использоваться асинхронным клиентским приложением (если это Java) или MDB-компонентом (обычно для очереди ответов). На рисунке 3 показана эта конфигурация как еще один входной канал для нашей реализации сервиса. Рисунок 3. Сервис, развернутый с MDB-компонентами, обеспечивающими асинхронный клиентский каналПоток C1-C2 показан отдельно от D1-D6 для иллюстрации независимости клиентского и серверного процессов. C2 и D6 просто показывают записывающей стороне "подтверждение" того, что сообщение было записано, и не подразумевают ожидания. В листинге 3 приведена типичная структура MDB-компонента, поясняющая, что он должен делать. Листинг 3. Типичная реализация управляемого сообщениями компонента
Хотелось бы вернуться к проблеме языковой независимости, которую Вы затронули. Такое впечатление, что Вы тесно связываете это требование с требованием асинхронной обработки. Но ничто не мешает Вам разделить эти задачи; способность синтаксически анализировать SOAP-сообщение и использовать его для активизации сессионного компонента должна быть независима от того, выполняется ли асинхронная обработка сообщения (через MQ или другой протокол, по которому проходят эквивалентные JMS сообщения) или синхронная (например, через HTTP или даже IIOP). Фактически некоторые из ранних "изобретений" Web-сервисов на Java EE-приложениях использовали HttpServlet для синтаксического анализа XML-сообщений, передаваемых по HTTP. Этот подход в конечном итоге развился в SOAP/HTTP. На рисунке 4 показан еще один путь, который может быть реализован поверх сервисов, предоставляемых EJB-компонентами. Рисунок 4. Разделение задач нейтральности к языку и асинхронностиСервлет Web-сервиса и управляемый сообщениями компонент могли бы использовать общий код, выполняющий синтаксический анализ объектов передачи данных из потока, извлекаемого из строки сообщения или из HttpServletRequest. Аналогично, ответ мог бы использовать общий код для генерации потока из объекта передачи данных (который мог бы быть экземпляром Exception). Надеюсь, это поможет Вам понять позиционирование Java EE-компонентов, каждый из которых обеспечивает некоторую форму слабого связывания, существенного для сервис-ориентированной архитектуры. Ваш EJB Advocate Все еще слишком много вариантов выбораУважаемый EJB Advocate! Спасибо. До сих пор я не предполагал, что такие сервисы, как JNDI и удаленные интерфейсы обеспечивают аспекты слабого связывания. Теперь я вижу, что мы (как Вы отметили) "тесно связали" идеи SOAP и MQ и должны попытаться разделить их, насколько это возможно. Поэтому имеет смысл реализовать синтаксический анализ и генерирование SOAP-сообщений тоже в виде сервиса, который может повторно использоваться сервлетом Web-сервисов и MDB. Но есть еще кое-что. До этого обсуждения SOA казалась довольно простой - каждый сервис отображал SOAP/MQ-интерфейс. Теперь такое впечатление, что у меня есть много вариантов для выбора, которые нужно рассмотреть. И поскольку я пытаюсь реализовать синтаксический анализ SOAP-сообщений и генерирование в виде сервисов, почему бы мне не сделать отдельный сессионный компонент, инкапсулирующий эти сервисы для повторного использования, как Вы показали на рисунках? Боюсь, что все еще Не все является сервисом: используйте бизнес-модель для принятия решенияУважаемый Disconnected! Данная дискуссия является отличным примером того, что происходит, когда Вы погружаетесь в детали реализации слишком рано. Важной является статья EJB Advocate "Какой тип EJB-компонента должен собирать данные, возвращаемые сервисом?", поскольку в ней описывается подход "сверх вниз" для определения сервисов, напрямую связывающих их с моделью бизнес-процессов. Вот резюме основных деталей реализации такого подхода:
Рисунок 5. Пример диаграммы состояний, показывающей цикл жизни заказа Рисунок 6. Пример диаграммы класса, показывающего "форму" открытого заказа Такой всесторонний подход гарантирует, что:
Данная информация не предоставляется в сигнатуре метода, независимо от того, где она реализуется, но эта информация жизненно важна для хорошей реализации SOA. В противном случае программисты впадут в другую крайность: если сомневаешься - создай заново . Поскольку стоимость разработки для SOA выше (нужно предоставить все промежуточные модули и адаптеры, необходимые для полной реализации слабого связывания, показанного на рисунке 4), такая тенденция, направленная против повторного использования, может минимизировать получаемые преимущества. Что касается проблемы простоты, о которой Вы говорите, - данная информация вовсе не заставляет Вас отображать интерфейсы определенным образом, а EJB Advocate учит, что простота - дело вкуса. Если хотите скрыть варианты выбора, предназначенные для разработчика сервиса, можете просто предоставить все "синие" компоненты, показанные на рисунке 5, для каждого сервиса:
Те, кто беспокоятся о количестве неиспользуемых компонентов, которые будет генерировать данный подход, могут (для упрощения) применить еще один подход, который EJB Advocate любит называть клиент-ориентированной архитектурой (Client-Oriented Architecture - COA) - дать клиенту точно то, чего он хочет, для использования сервиса способом, наиболее подходящим для него. Такой COA-подход требует анализа всех деталей бизнес-процесса и моделей пользовательского интерфейса с целью выбора наиболее вероятных кандидатов для каждого подхода. Например:
Результатами COA-подхода являются компоненты, разрабатываемые "точно в срок". Вот почему EJB Advocate любит его рекомендовать. И последнее замечание, связанное с Вашим вопросом (почему бы не реализовать все в виде сервисов, даже преобразования, связанные с промежуточными модулями (mediators) и адаптерами)? Простой ответ: хорошего не должно быть слишком много. При разработке SOA или COA Java EE-приложений лучше всего рассматривать сервисы как операции в модели бизнес-процесса. Промежуточные модули и соответствующие преобразования ассоциируются с нефункциональными требованиями, такими как надежность, удобство использования, эффективность, простота обслуживания и переносимость. Если Вы будете рассматривать промежуточные модули или соответствующие преобразования как настоящие сервисы, то в конечном итоге сделаете непонятным истинное назначение приложения. Я знаю, что в этом нелегко разобраться, поэтому не стесняйтесь связываться со мной, чтобы получить более подробные разъяснения по применению данных подходов. Ваш EJB Advocate . ЗаключениеДанный диалог продемонстрировал, как Java EE предоставляет полную интегрированную среду реализации приложений, использующих сервис-ориентированную архитектуру, где каждый компонент или API играют важную роль в некоторых аспектах "слабого связывания":
Мы уверены, что Вы найдете и другие аспекты. Проблема заключается в нахождении разумных компромиссов для каждого из них. Этой работы Вам должно хватить до следующего года.
|
|