Разработка веб-служб средствами Java. Ильдар ХабибуллинРазработкаWebслужбсредствами
Скачать 9.24 Mb.
|
294 Разработка Web-служб средствами Java /> В листинге 6.10 приведен конфигурационный файл jaxrpc-ri.xml компилято- ра нашей примерной Web-службы Листинг 6.10. Конфигурационный файл компилятора jaxrpc-ri.xml urlPatternBase="/ws"> implementation="bookinfo.BookInfoImpl" /> urlPattern="/bookinfo" /> После того как компилятор wsdeploy закончит работу, устанавливаем соз- данный им архив portable.war в Web-контейнер. Для Web-контейнера Tomcat в пакете WSDP есть графическая утилита установки Она запускается из командной строки при работающем Tomcat просто на- бором ее имени $ depioytool После ее запуска на экране последовательно появляется ряд окон с подроб- ными объяснениями процесса установки. Глава 6. Детали создания Web Services 295 После установки Web-службы в Web-контейнер, можно проверить ее нали- чие, открыв на сервере браузер и набрав в нем адрес http://localhost:8080/services/bookinfo. В окне браузера появится список ус- тановленных Web-служб. Слово "services" в этом адресе — это контекст сервлета, созданный в про- цессе установки. Он может получить другое название. Слово вместе с начальной наклонной чертой — это значение атрибута элемента записанного в файле jaxrpc-ri.xml. Итак, Web-служба создана, установлена в Web-контейнер, контейнер запу- щен и ждет, когда пойдут запросы. Теперь можно перейти к созданию кли- ента. Создание клиента Система JAX-RPC позволяет создавать клиентские приложения трех типов. Проще всего использовать в приложении заранее созданные заглушки (generated stubs). Их создает старый компилятор с флагом -client, например, так: $ -client -d bookclient config.xml или новый компилятор работающий из командной строки при- мерно следующим образом: $ wscompile bookclient config.xml Оба компилятора читают предварительно написанный конфигурационный файл config.xml и записывают создаваемые файлы в каталог, указанный параметром -d, в примере это каталог с именем bookclient. Кроме того, компилятор хгрсс использует Web-службы, а компилятор wscompile — описание WSDL, причем компилятор смотрит это описание через Web-службу по адресу, например, Поэтому Web-служба уже должна быть установле- на в Web-контейнер, а контейнер должен работать. Итак, перед созданием заглушек надо написать конфигурационный файл config.xml. Рассмотрим его структуру. Конфигурационный файл компилятора config.xml Корневой элемент конфигурационного файла В корневой элемент вкладывается один из трех элементов: • элемент 296 Web-служб средствами Java • элемент если Web-служба строится по WSDL-описанию; • элемент если описание находится в другом файле. У элемента • Атрибут name задает название создаваемой Web-службы. • Атрибут определяет имя пакета, в котором будут располо- жены создаваемые классы. • Атрибут targetNamespace содержит идентификатор пространства имен создаваемого описания WSDL. • Атрибут typeNamespace содержит идентификатор пространства имен ти- пов, определяемых в создаваемом описании WSDL. В элемент Web-службы. Полное имя SEI- интерфейса записывается обязательным атрибутом name, полное имя реали- зующего его класса-служителя — атрибутом servantName. Необязательные атрибуты soAPAction и soAPActionBase задают одноименные поля MIME- заголовка. У элемента два обязательных атрибута. Атрибут location содержит строку URI с адресом описания WSDL, атрибут packageName — имя пакета с классами Web-службы. Остальные элементы конфигурационного файла необязательны. Они пока- заны на следующей схеме, показывающей структуру конфигурационного файла. Глава 6. Детали создания Web Services 297 нестандартных типов —> > В листинге приведен конфигурационный файл нашей примерной Web- службы Bookinfo для создания Web-службы по ее SEI-интерфейсу. Листинг__Конфигурационный_файл_компилятора_SEl-интерфейса'>Листинг Конфигурационный файл компилятора SEl-интерфейса 298 Разработка Web-служб средствами Java Кроме заглушки BookInfoPort_Stub.class, имя которой составлено из имени и сопутствующих классов, компилятор создает WSDL-описание Web-службы, в нашем примере это файл и файл свойств Web-службы, в примере это файл Имена этих файлов содержат себе название Web-службы, заданное атри- бутом name элемента Конфигурационный файл config.xml для компилятора создающе- го Web-службу по ее описанию WSDL, написан в листинге 6.12. Листинг Конфигурационный файл компилятора WSDL-описания Клиент, использующий заранее созданные заглушки Методы использования заглушки описаны в интерфейсе stub пакета Они задают и читают свойства заглушки. Это методы public void name, Object value); public Object name); public Iterator В интерфейсе описаны четыре стандартных свойства заглушки: • — строка типа string с именем пользователя Web- службы; • — строка типа string с паролем пользователя Web- службы; Глава 6. Детали создания Web Services 299 • — строка типа string с Web- службы; • — объект ТИПа Boolean, указывающий, СОЗ- давать сеанс связи с Web-службой или нет. По умолчанию сеанс не соз- дается. Поскольку заглушка — в нашем примере это класс — уже создана, можно создать ее экземпляр как объект обычного класса и обра- щаться к методам этого объекта. Например: Stub stub = new info = Book book = Однако удобнее использовать вспомогательный класс создан- ный вместе с заглушкой. Метод этого класса getxxxPort где — назва- ние Web-службы, взятое из атрибута name элемента Листинг Клиент, использующий существующую заглушку import import public class public static void args){ try{ Stub stub = (Stub)(new BooklnfoPort bip = Book book = bip.getInfo("5-94157-041-4"); 300 Разработка Web-служб средствами Java e){ Клиент, использующий описание WSDL Клиенты второго типа обращаются к Web-службе по ее описанию, сделан- ному на языке WSDL. При этом обращении создается заглушка и пересыла- ется на клиентскую машину. Методы, помогающие клиенту системы JAX- RPC обратиться к WSDL-описанию Web-службы, описаны в интерфейсе Service пакета Интерфейс service предназначен для связи с SOAP-сервером и получения информации о вызываемой Web-службе. Объект типа service создается уже знакомым путем с помощью класса- фабрики ServiceFactory: ServiceFactory sf = Service serv = serviceName); При создании объекта serv сразу указывается название Web-службы serviceName. Второй метод создания объекта типа service public Service QName serviceName); требует указать адрес wsdl WSDL-описания Web-службы. После как объект типа создан, можно получить заглушку од- ним ИЗ МетОДОВ getPort (). Если объект serv был создан первым способом и адрес wsdl WSDL- описания ему еще неизвестен или описание содержит несколько SEI- интерфейсов, то применяем метод public Remote wsdlName, Class sei); в котором аргумент wsdlName содержит имя Если же эти сведения уже указаны, то можно применить второй метод public Remote sei); В листинге 6.14 показан пример клиента нашей Web-службы об- ращающегося к ней через описание WSDL. . Листинг 6.14. Клиент, использующий описание import import Глава 6. Детали создания Web Services 301 import import bookinfo.*; public class BookInfoProxyClient{ public s t a t i c void args){ try{ String ns = "http://bookinfo.com/wsdl/"; URL = new ServiceFactory sf = Service serv = new "Bookinfo")); bip = "BooklnfoPort"), Book book = bip.getInfo("5-94157-041-4"); ex)( Клиент, динамически получающий Web-услуги В тех случаях, когда нет заранее созданных заглушек и недоступно WSDL- описание Web-службы, клиент может динамически получить Web-услуги методами, описанными в интерфейсе Методы интерфейса c a l l задают аргументы вызываемой Web-услуги, вызывают ее и получают результат. Для их использования не нужен даже SEI-интерфейс и сопутствующие ему клас- сы. Достаточно знать название Web-службы, имя и сигна- туру метода вызываемой Web-услуги. 302 Разработка Web-служб средствами Java Объект типа c a l l создается одним из методов интерфейса Получив объект serv типа применяем один из следующих его методов: public Call public Call public Call portName, QName public Call portName, String operationName); Аргумент — это имя Web-службы, представленное в виде объекта класса QName. Аргумент operationName — это имя метода, предоставляющего Web-услугу. После создания объекта типа c a l l , его нужно дополнить недостающими сведениями. Для этого в интерфейсе описаны методы public void operationName); public void portType); public void public void address); Кроме того, надо описать типы аргументов вызываемого метода. Это вы- полняется методами public void name, QName mode); public void name, QName xmlType, Class javaType, ParameterMode mode); Первые аргументы задают произвольное имя для аргумента name, его XSD- тип xmlType, соответствующий тип Java javaType, если для этого типа нет стандартного соответствия типов XML и Java. Последний аргумент mode — это одна из трех констант класса ParameterMode: — указывает, что описываемый аргумент является входным аргументом метода; • — указывает, что описываемый аргумент является выходным аргументом метода; • — указывает, что описываемый аргумент может быть и входным и выходным аргументом метода. Наконец, определяются свойства объекта типа например, имя и па- роль пользователя. Свойства устанавливаются методом public void name, Object value); Глава 6. Детали создания Services 303 В интерфейсе определены имена некоторых свойств. • — строка типа string с именем пользователя Web- службы; • — строка типа string с паролем пользователя Web- службы; • — ТИПа S t r i n g С пространства имен типов; • — объект ТИПа Boolean, указывающий, СОЗ- давать сеанс связи с Web-службой или нет. По умолчанию сеанс не соз- дается. • — ИЛИ "document", ОПредеЛЯЮ- щая процедурный или документный стиль SOAP-послания; • — объект ТИПа Boolean, указывающий, ИС- пользовать или нет поле ion заголовка SOAP-послания; по умол- чанию это поле не используется; • — ТИПа S t r i n g С ПОЛЯ заголовка SOAP-послания. После того как объект типа сформирован, можно обратиться к Web- службе и сразу получить Web-услугу одним из методов public Remote args); public Remote args}; public void args); В листинге 6.15 приведен пример динамического получения Web-услуги от нашей Web-службы о. Клиент, вызов import import public class private static String = "http://bookinfo.com/wsdl/"; private static String private static String NS_XSD = "http://www.w3.org/2001/XMLSchema"; 304 Разработка Web-служб средствами Java private static String = "http://schemas.xmlsoap.org/soap/encoding/"; public static void args){ try{ ServiceFactory sf = ; Service serv = ; port = new Call call = new " " ) ; QName = new "string"); xsdString, = { "5-94157-041-4" }; String title = ,• e){ ГЛАВА 7 Web Services как часть J2EE В предыдущих главах мы видели, что Web-службы легко и естественно создаются сервлетами и страницами JSP. Сервлеты и страницы JSP, но- сящие общее название Web-компоненты, работают под управлением спе- циального программного модуля, называемого Web-контейнером. В пре- дыдущих главах мы использовали самый популярный на сегодняшний день Web-контейнер Tomcat, созданный сообществом Apache Software Foundation. Он встраивается в Web-сервер как один из его модулей. Чаще всего Web-сервер со своими дополнительными модулями является частью сервера приложений (application server), который, кроме того, ведет электронную почту, службу сообщений, распределенные каталоги, созда- ет и передает распределенные объекты, соединяется с базами данных и предоставляет другие услуги. Сейчас наиболее известны серверы прило- жений BEA WebLogic, IBM WebSphere, JBoss, Sun ONE Application Server, Application Server, Borland Enterprise Server. Сервер приложений, в свою очередь, расширяется компонентами EJB, работающими под управлением еще одного программного модуля — EJB-контейнера. Вся эта конструкция чаще всего управляется интер- фейсами и классами, входящими в состав J2EE (Java 2 Enterprise Edition), и называется Набор J2EE свободно распростра- няется фирмой Sun со своего сайта http://java.sun.com/j2ee/. Каждый производитель сервера приложений стремится сделать его совместимым с набором J2EE, чтобы Web-компоненты, компоненты Web- службы и другие серверные приложения выполнялись на нем без вся- ких переделок. У Web-службы, развернутой на появляется возможность использовать не только сервлеты и страницы JSP, но и компоненты EJB. Они описаны подробно в книгах [7, 10]. Напомним их структуру. 306 Разработка Web-служб средствами Java Компоненты EJB Компоненты EJB, как следует из их названия, должны обладать той же осо- бенностью, что и компоненты JavaBeans, а именно — легко и без всяких изменений встраиваться в создаваемые приложения. В случае компонентов EJB это условие означает — встраиваться в любой и работать под управлением любого EJB-контейнера. Для этого компоненты EJB должны строго соблюдать интерфейс с Этот интерфейс — интерфейс EnterpriseBean — на удивление прост. Он не содержит ни кон- стант, ни заголовков методов, а только расширяет интерфейс Это означает, что каждый компонент EJB должен быть сериализуемым. На самом деле интерфейс EnterpriseBean — это только суперинтерфейс для интерфейсов, описывающих конкретные типы компонентов EJB. На сего- дняшний день существует три типа компонентов EJB, описанных тремя расширениями интерфейса EnterpriseBean — интерфейсами SessionBean, EntityBean и MessageDrivenBean. Каждый компонент EJB должен реализо- вать один из этих интерфейсов. Компоненты типа SessionBean предназначены для работы с клиентом EJB- приложения, которым может быть сервлет, страница JSP, отдельное прило- жение, другой компонент EJB. Мы будем называть их session-компонентами. Клиенты session-компонента могут быть удаленными (remote) или локальны- ми (local). Локальные клиенты работают на той же самой виртуальной ма- шине Java, что и компонент. Удаленные клиенты работают на другой вирту- альной машине Java. Есть две разновидности session-компонентов: компоненты, не сохраняющие свое текущее состояние для последующих вызовов клиента (Stateless Session Beans), и компоненты, сохраняющие свое состояние в оперативной памяти, но не на постоянном носителе информации (Stateful Session Beans). Первые удобны для создания Web-служб, поскольку Web-службы не создают сеанс связи с клиентом. Последние удобны для создания сеанса связи с клиентом и в Web-службах не применяются. Компоненты типа EntityBean предназначены для хранения данных, извле- ченных из постоянных хранилищ, в виде объектов Java. Мы будем называть их entity-компонентами. Клиенты entity-компонента могут изменить его со- держимое. Entity-компоненты поддерживают связь с источником данных и сохраняют свое содержимое в постоянном хранилище при всяком измене- нии своего состояния. Они не применяются для создания Web-служб, а ис- пользуются ими когда Web-службам надо получить информацию из базы данных или сохранить информацию в базе данных. Компоненты ТИПа MessageDrivenBean ВЫПОЛНЯЮТ Те Же фуНКЦИИ, ЧТО И session-компоненты без сохранения состояния, но действуют асинхронно. Глава 7. Web Services как часть J2EE 307 Мы будем называть их Они удобны для создания асин- хронных Web-служб документного стиля. Итак, для создания Web-служб процедурного стиля удобны session- компоненты без сохранения состояния, а для создания Web-служб доку- ментного стиля — MDB-компоненты. Рассмотрим подробнее устройство этих компонентов EJB. Session-компоненты Как ясно из сказанного выше, session-компонент — это класс или несколь- ко классов, реализующих интерфейс SessionBean. Интерфейс SessionBean описывает всего четыре метода. Три метода предназначены для EJB- контейнера. Метод public void throws автоматически выполняется EJB-контейнером при каждом обращении кли- ента к компоненту, в него можно записать действия, активизирующие ком- понент, например, восстанавливающие его предыдущее состояние. Метод public void throws EJBException, RemoteException автоматически выполняется EJB-контейнером, когда он решает, что пора сохранить состояние session-компонента. К а к ВИДНО ИЗ ЭТОГО Краткого ОПИСаНИЯ, МеТОДЫ И ejbPassivate о полезны только для session-компонентов с сохранением со- стояния. Для Web-служб делается пустая реализация этих методов. Третий метод public void throws EJBException, RemoteException выполняется EJB-контейнером при завершении работы с контейнером. В него можно записать завершающие действия компонента. Четвертый метод public void ctx) throws EJBException, RemoteException позволяет session-компоненту получить контекст, в котором он работает, в виде объекта типа SessionContext. 308 Разработка Web-служб средствами Java Интересно то, что никакой клиент не может обратиться к session- компоненту напрямую. Вместо этого клиент обращается к EJB-контейнеру, который активизирует session-компонент и передает ему запрос клиента. Результаты выполнения методов компонента опять-таки передаются клиен- ту через EJB-контейнер. Контейнер взаимодействует с клиентом через спе- циальные remote- и home-интерфейсы. Remote-интерфейс session-компонента Для взаимодействия с удаленным клиентом EJB-контейнер предоставляет ему интерфейс типа Разработчик Web-службы должен расширить этот интерфейс, описав в расширении Web-услуги реализуемой компонен- том Web-службы. Разработчик не должен реализовать интерфейс каким- либо классом, реализацию делает EJB-контейнер. Соответствующий интер- фейс локального клиента называется Интерфейс EJBObject расширяет интерфейс Remote, а значит, описывает распределенный объект. Будем называть интерфейс EJBObject и всякое его расширение remote-интерфейсом session-компонента. Web-услуги, описанные в remote-интерфейсе, должны следовать правилам распределенных мето- дов — выбрасывать исключение класса RemoteException и не иметь аргу- ментов и возвращаемых значений, которые сами являются распределенны- ми объектами. Интерфейс EJBObject описывает пять методов, которые реализуются самим EJB-контейнером. Разработчику Web-службы можно не беспокоиться о реа- лизации этих методов, но он может воспользоваться ими для получения сведений о компоненте. Метод public throws RemoteException возвращает объект типа EJBHome — home-интерфейс, о котором речь пойдет чуть ниже. Метод public Handle throws RemoteException возвращает идентификатор компонента типа Handle. Идентификатор хранит ссылку на объект типа EJBObject, которую можно получить методом (). Необходимость в этом методе возникает тогда, когда ком- поненту надо сослаться на себя, поскольку использовать ссылку t h i s в компонентах EJB нельзя. Метод public boolean throws RemoteException Глава 7. Web Services как часть J2EE 309 заменяет обычный метод сравнения объектов equals о, тоже не используе- мый в распределенных объектах, из-за того, что они выполняются на раз- ных виртуальных машинах Java. Метод public void remove 0 throws RemoteException, удаляет компонент. Последний, пятый, метод интерфейса public throws RemoteException используется только в entity-компонентах для получения первичного ключа. В remote-интерфейсе локального клиента четыре метода: отсутствует метод (), а метод public throws EJBException возвращает ссылку на home-интерфейс локального клиента. Home-интерфейс session-компонента Еще один интерфейс — интерфейс типа EJBHome, тоже расширяющий ин- терфейс Remote — предназначен для создания экземпляров session- компонента по требованию клиента. Мы будем называть всякое расширение интерфейса EJBHome Интерфейс EJBHome описывает че- тыре метода, реализуемые Разработчик Web-службы не должен беспокоиться об этих методах — они реализуются EJB-контейнером — но может воспользоваться ими для получения сведений о компоненте. Метод public throws RemoteException возвращает объект типа EJBMetaData, из которого клиент может извлечь некоторые сведения о компоненте. Метод public HomeHandle throws RemoteException возвращает объект типа HomeHandle, содержащий всего один метод getEJBHome о . Этот метод используется вместо ссылки t h i s . Два метода public void handle) throws RemoteException, RemoveException 310 Разработка Web-служб средствами Java public void throws on удаляют компонент, заданный идентификатором или первичным ключом. В home-интерфейсе локального клиента всего один метод public void throws Разработчик Web-службы должен расширить интерфейс EJBHome, и/или ин- терфейс EJBLocalHome, если у компонента будут локальные клиенты, запи- сав в расширении метод с именем create о без аргументов. Метод create () home-интерфейса удаленного клиента, как всякий метод распределенного объекта, должен выбрасывать исключение класса RemoteException. Кроме того, он должен выбрасывать исключение класса CreateException. Метод о должен возвращать объект, тип которого совпадает с типом remote-интерфейса, поэтому он не описан в интерфейсах и EJBLocalHome. Именно этим методом клиент дает указание EJB- контейнеру создать экземпляр session-компонента. Выполнив это указание, EJB-контейнер возвращает клиенту ссылку на remote-интерфейс созданного компонента. Клиент пользуется полученной ссылкой для обращения к Web- услугам, описанным в remote-интерфейсе. Интерфейс адресата Web-службы У session-компонента без сохранения состояния могут быть не только уда- ленные и локальные клиенты, но и клиенты Web-службы. Для них session- компонент предоставляет не remote- и home-интерфейсы, а интерфейс адре- сата Web-службы (Web Service Endpoint Interface). Будем называть его session-компонента. В отличие от remote- и home-интерфейсов, расширяет непосредственно интерфейс Remote, то есть является распределенным объ- ектом. Он включается в систему JAX-RPC, описанную в главе 6, и должен следовать правилам этой системы. Это означает, что ти- пы аргументов и возвращаемых значений его методов должны быть типа- ми JAX-RPC, а сами методы должны выбрасывать исключение класса RemoteException. В частности, нельзя использовать объекты типов EJBObject и Разработчику компонента не надо реализо- вать WSEI-интерфейс, это сделает EJB-контейнер. Для каждого метода в классе session-компонента должен присутствовать соответствующий метод с тем же заголовком. При установке компонента в EJB-контейнер, WSEI-интерфейс описывается в конфигурационном файле элементом вложенном в элемент Глава 7. Web Services как часть J2EE 311 Приведем самый простой пример session-компонента, который только мож- но придумать. Клиент посылает session-компоненту свое имя name, исполь- зуя для этого метод session-компонента. Компонент отвечает: "Привет, добавляя имя клиента. Назовем этот компонент Пусть у него будут только удаленные клиенты и клиенты Web- службы, но не будет локальных клиентов. Сначала напишем remote-интерфейс, описывающий метод Он приведен в листинге 7.1. ; Листинг 7.1. Remote-интерфейс session-компонента package hello; import j import javax.ejb.*; public interface Hello extends String name) throws RemoteException; Потом записываем home-интерфейс, описывающий метод create о, это сделано в листинге 7.2. Листинг 7.2. Home-интерфейс session-компонента package hello; import import javax.ejb.*; public interface extends Hello throws CreateException, RemoteException; Напишем и WSEI-интерфейс session-компонента. Он приведен в листинге 7.3. | Листинг 7.3. WSEI-интерфейс session-компонента package hello; import j Разработка Web-служб средствами Java public interface HelloPort extends String name) throws RemoteException; } После этого пишем сам класс session-компонента. Это сделано в листинге 7.4. | 7.4, Класс session-компонента - package hello; import j import javax.ejb.*; public class HelloBean implements SessionBean{ private SessionContext ctx; public public String name) throws return "Привет, " + name + "!"; public void ctx) = ctx; public void ejbCreate (){} public void public void public void ejbRemove(){} } В листинге 7.4 сделана пустая реализация трех методов интерфейса SessionBean и реализован метод Обратите внимание на то, что в классе компонента EJB обязательно должен быть открытый (public) конструктор по умолчанию, хотя бы пустой. Еще один обязатель- ный метод ejbCreate о соответствует методу create о home-интерфейса, не Глава 7. Web Services как часть J2EE 313 являясь его реализацией. В отличие от метода create о он не возвращает никакого значения и не выбрасывает исключений. В нем записываются на- чальные действия компонента, которые будут выполнены, когда клиент об- ращается К методу create () . Обратите внимание на соглашение об именах, принятое для компонентов EJB. Создавая компонент мы называем remote-интерфейс компо- нента именем Hello, home-интерфейс называем а класс компо- нента — HelloBean. Компонент создан, теперь его надо установить (deploy) в EJB-контейнер. При установке или до нее создается конфигурационный XML-файл с именем Установка выполняется какой-либо утилитой, входя- щей в состав EJB-контейнера. В набор J2EE входит графическая утилита deploytool, запускаемая из командной строки. Работа с этой утилитой под- робно описана в книге [10]. В процессе установки компонент регистриру- ется в системе именования JNDI [10], обычно в контексте java:comp/env/ejb/. Для клиентов Web-служб рекомендуется создавать кон- текст Пусть наш session-компонент HelioEJB зарегистрирован под hello. Тогда удаленный клиент может обратиться к нему так, как показано в листинге 7.5. Листинг 7.5. Удаленный клиент session-компонента package hello; import j import public class HelloClient{ public static void try{ InitialContext ctx new home = HeiioHome Hello h = 314 Разработка Web-служб средствами Java e){ Клиент Web-службы обращается к компоненту по обычным правилам сис- темы JAX-RPC, изложенным в предыдущей главе 6. Создавая session-компонент, сначала создает экземпляр класса компонента методом о с помощью конструктора по умолчанию, который обязательно должен присутствовать в классе ком- понента. Затем EJB-контейнер создает объект типа sessionContext и уста- навливает его в компонент методом о . После этого EJB- контейнер метод ejbCreate () . Посмотрим, что может получить класс компонента от объекта Контекст session-компонента Интерфейс предоставляет ссылки на remote-интерфейсы типа EJBObject и методами public EJBObject public EJBLocalObject ; Версия EJB 2.1 добавила еще один метод, доступный только для адресатов Web-служб: public Этот метод предоставляет объект типа MessageContext, содержащий свойст- ва сообщения. Он описан в главе 6. Кроме ТОГО, SessionContext расширяет EJBContext И, следовательно, обладает его методами public public public UserTrasaction public boolean public Principal предоставляющими ссылки на home-интерфейсы, сведения о транзакции, в которой участвует компонент, и сведения о клиенте компонента. Все эти сведения можно использовать в классе компонента. Глава 7. Web Services как часть J2EE 315 Компоненты типа MDB (Message Beans) работают асинхронно под управлением EJB-контейнера. Контейнер получает сообщение от клиента, точнее говоря, от службы сообщений, через которую действует клиент, ак- тивизирует MDB-компонент и обращается к его методам. Клиент никак не связан с MDB-компонентом, более того, клиент не подозревает о его суще- ствовании. Клиент обращается только к службе сообщений. Поэтому для MDB-компонента не нужны ни remote- ни home-интерфейсы, он состоит только из одного или нескольких классов. Класс MDB-компонента должен реализовать MessageDrivenBean. Интерфейс MessageDrivenBean описывает всего два метода public void ctx) throws EJBException public void throws EJBException реализуемые EJB-контейнером. Интерфейс MessageDrivenContext, расширяющий EJBContext, ничего не добавляет к методам интерфейса EJBContext. Поэтому класс MDB-компонента может получить только сведения о транзакции, если он участвует в какой-либо транзакции. Более того, он не может воспользовать- ся методами интерфейса EJBContext, предоставляющими сведения о клиен- те и ссылки на remote- и home-интерфейсы. EJB-контейнер создает экземпляр MDB-компонента так же, как экземпляр поэтому в нем должен быть открытый конструктор по умолчанию и метод без аргументов. В этом методе можно за- писать начальные действия компонента. Главное, что должен сделать класс MDB-компонента — это реализовать ин- терфейс-слушатель службы сообщений. Если MDB-компонент связан со службой сообщений JMS (Java Message Service), то он должен реализовать интерфейс MessageListener. Если MDB-компонент с пакетом JAXM, то он реализует интерфейс OnewayListener или интерфейс Об этих интерфейсах говорилось в предыдущей главе 6. Каждый из этих интерфейсов описывает по одному методу в котором и заключена основная работа MDB-компонента. Правила реализации интерфейса MessageListener описаны в книгах [7, 10]. Заголовок его единственного метода имеет следующий вид: public void Аргумент msg, передаваемый этому методу контейнером, содержит получен- ное сообщение в виде объекта типа Message. Интерфейс Message содержит 316 Разработка Web-служб средствами Java множество методов доступа к различным заголовкам и частям сообщения системы JMS. Он подробно описан в книге [10]. Приведем в листинге 7.6 простейший пример MDB-компонента, отправ- ляющего сведения о полученных сообщениях в стандартный вывод. Листинг 7.6. Простейший MDB-компонент import javax.ejb.*; import import j a v a . u t i l . * ; public c l a s s implements MessageDrivenBean, public void try{ сообщение " + + " для адресата " + хранения " + > 0 ? new : "не послать: " + сообщения " + if (msg instanceof TextMessage) сообщения:\n" + e){ Глава 7. Web Services как часть J2EE 317 public void ejbCreate(){} public void public void Конфигурационный файл EJB-приложения В процессе установки компонентов EJB в контейнер сведения о компонен- тах заносятся в конфигурационный файл с именем хранящийся в каталоге архива EJB-приложения. Для каждого EJB- приложения создается только один конфигурационный файл. Именно этот файл связывает класс session-компонента с относящимися к нему remote-, home- и В этом файле MDB-компонент привязывает- ся к определенной службе сообщений. Здесь указываются ссылки на другие компоненты EJB и определяются переменные окружения. Структура файла ear-jar.xml понятна без всяких объяснений. В листинге 7.7 показан конфигурационный файл, содержащий сведения о компонентах и созданных в предыдущих листингах. Листинг 7.7. Конфигурационный файл ear-jar.xml EJB-приложения version="1.0" encoding="UTF-8"?> ejb-jar PUBLIC '-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans |