IBM®
Перейти к тексту
    в России и странах СНГ [изменить]    Условия использования
 
 
   
    Главная страница    Продукты    Услуги и решения    Поддержка и загрузка    Мой профиль    
Перейти к тексту

developerWorks Россия  >  Технология Java  >

JCA 1.5: Часть 3. Внедрение сообщений

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

developerWorks
Опции документа

Опции документа, требующие включения JavaScript, не отображаются

Обсудить


Выскажите мнение об этой странице

Помогите нам улучшить содержание


Уровень сложности: средний

Дэвид Карри, штатный инженер-программист, IBM UK Ltd

06.03.2008

В этой последней части серии из трех статей, посвященных новейшей версии J2EE™ Connector Architecture (JCA), Дэвид Карри представляет новое соглашение по внедрению сообщений (message-inflow contract). Это новшество позволяет адаптеру ресурсов активизировать приложение в асинхронном режиме через управляемый сообщениями компонент (message-driven bean). Данная серия имеет большое значение для тех, кто хочет использовать эту функциональность в существующем адаптере ресурсов или задумывается над написанием нового JCA 1.5-совместимого адаптера ресурсов. Также она должна быть интересна тем, кто пишет приложения, использующие адаптеры ресурсов и хочет знать больше о том, что происходит за кулисами.

В первой части данной серии статей о новых возможностях JCA 1.5, новейшей версии архитектуры J2EE Connector Architecture, были рассмотрены методы оптимизации, которые ускоряют работу адаптеров ресурсов, и дополнения, которые позволяют адаптерам ресурсов начать новую самостоятельную жизнь. Во второй части было рассмотрено новое соглашение JCA по управлению работой, которое позволяет адаптеру ресурсов создавать таймеры для отложенного или периодического выполнения работы и выполнять ее с использованием потоков сервера приложений. В данной статье я расскажу, как новое соглашение по внедрению сообщений устраняет сложности, присущие старому соглашению Java Message Service (JMS) Application Server Facilities, и дает возможность управляемым сообщениями компонентам начать новую жизнь. Я также покажу, как администрируемые объекты позволяют администратору настроить JavaBeans-компоненты, определенные адаптером ресурсов, и подключить их к пространству имен приложения.

Управляемые сообщениями компоненты EJB 2.0

Во времена J2EE 1.3 и EJB 2.0 управляемые сообщениями компоненты (Message-Driven Beans, MDB) выполняли довольно ограниченную роль. Они позволяли приложению асинхронно принимать сообщения, переданные в JMS-назначение. MDB должны были реализовывать интерфейс javax.jms.MessageListener, показанный в листинге 1.


Листинг 1. Интерфейс javax.jms.MessageListener
public interface MessageListener {

    void onMessage(Message message);

}

MDB-компоненты также должны были реализовывать интерфейс MessageDrivenBean. Как результат, типичный класс должен был выглядеть примерно так, как ExampleMdb в листинге 2.


Листинг 2. Пример EJB 2.0 MDB
public class ExampleMdb implements MessageDrivenBean, MessageListener {

    public void ejbCreate() throws CreateException { ... }
    public void ejbRemove() { ... }
    public void setMessageDrivenContext(MessageDrivenContext ctx) { ... }
    public void onMessage(Message message) {

        if (msg instanceof TextMessage) {
            String text = ((TextMessage) message).getText();
            InitialContext context = new InitialContext();
            ExampleHome home = (ExampleHome)context.lookup("java:comp/env/ejb/Example");
            Example bean = home.create();
            bean.operation(text);
        }

    }

}

(Во всех примерах данной серии статей я для простоты исключил логику обработки исключительных ситуаций.)

Если вы следовали рекомендации спецификации EJB 2.0, как это сделано в листинге 2, то метод onMessage отвечал за разбор содержимого сообщений и мог активизировать какие-либо другие EJB-компоненты для выполнения актуальной бизнес-логики.

Не поймите меня не правильно - EJB 2.0 MDB-компоненты обладали определенными достоинствами. Начинающим не нужно было писать домашний, удаленный или локальный интерфейс, поскольку MDB не активизировались клиентом. Еще одно важное преимущество - несколько экземпляров могли выполняться одновременно. При отсутствии MDB-компонентов приложение могло постоянно опрашивать адресат для получения сообщения в синхронном режиме, но, не имея возможности распределить работу в другой поток, оно должно было обработать первое сообщение до перехода к следующему.

Аналогично другим EJB-компонентам MDB-компоненты могли использовать управляемые компонентом или контейнером транзакции. Хотя последние имели некоторые особенности для MDB-компонентов. Во-первых, разрешено было использовать только два атрибута транзакции: Required и NotSupported. Это было очень разумно. Поскольку клиент не активизирует MDB-компонент, не нужно наследовать транзакцию, поэтому все, что необходимо – это способность сообщить, должен компонент работать в транзакции или нет. Во-вторых, и это более важно, если вы указывали атрибут транзакции Required, передаваемое в MDB-компонент сообщение принималось как часть этой транзакции. Если что-то произошло не так, и транзакция была отменена, сообщение передавалось обратно адресату для повторной обработки.

Как видно из листинга 3, тот факт, что MDB использовался только для JMS, был также отражен в дескрипторе развертывания.


Листинг 3. Дескриптор развертывания EJB 2.0
<ejb-jar>
  <enterprise-beans>
    <message-driven>
      <ejb-name>Example MDB</ejb-name>
      <ejb-class>example.ExampleMDB</ejb-class>
      <transaction-type>Bean</transaction-type>
      <acknowledge-mode>Auto-acknowledge</acknowledge-mode>
      <message-driven-destination>
        <destination-type>javax.jms.Topic</destination-type>
        <subscription-durability>Durable</subscription-durability>
      </message-driven-destination>
      <message-selector>
        JMSType = 'car' AND color = 'red'
      </message-selector>
    </message-driven>
  </enterprise-beans>
</ejb-jar>

В листинге 3 вы можете увидеть, что некоторые элементы в дескрипторе развертывания соответствуют JMS-концепциям режима подтверждения (acknowledge mode), долговечности подписки (subscription durability) и селектора сообщений (message selector). Еще один элемент указывает тип адресата сообщения, который должен быть либо javax.jms.Queue, либо javax.jms.Topic.



В начало


Управляемые сообщениями компоненты EJB 2.1

Как же изменилось состояние дел в J2EE 1.4 с EJB 2.1? Имеется одно главное отличие: MDB-компонент может теперь реализовать любой интерфейс. Именно так - любой интерфейс. Например, JCA Common Client Interface (CCI) определяет интерфейс, приведенный в листинге 4, который должен реализовываться MDB-компонентом, желающим управляться асинхронно CCI-коннектором.


Листинг 4. Интерфейс javax.resource.cci.MessageListener
public interface MessageListener {

    Record onMessage(Record inputData)
            throws ResourceException;

}

Интерфейс CCI демонстрирует некоторые преимущества этой новой гибкости. Во-первых, MDB не должен передаваться JMS-сообщением. В интерфейсе из листинга 4 передается объект Record. Прибытие JMS-сообщения адресату может не быть активизатором вызова метода. Спецификация JCA не налагает никаких ограничений на обстоятельства, которые привели к выполнению MDB-компонентов. Они могут быть результатом получения адаптером ресурсов каких-нибудь внешних стимулов от сервера хранения данных либо просто внешним событием, возможно даже управляемым по таймеру. Во-вторых, как показано в листинге 4, активизированный метод тоже может иметь возвращаемый параметр. В этом случае обратно передается второй объект Record, но, как показано в первом методе интерфейса ExampleListener в листинге 5, типы не должны быть одинаковыми.


Листинг 5. Пример интерфейса прослушивателя
public interface ExampleListener {

    ExampleOutput process(ExampleInput input);

    String getData();

    void request(int id, ExampleRequest request);

}

Возвращаемый параметр из метода обычно используется для предоставления ответа инициатору события, которое привело к активизации метода, то ли это был адаптер ресурсов, то ли какая-либо другая система. Однако, как демонстрирует второй метод интерфейса ExampleListener, можно было бы вызвать MDB без каких-либо параметров и использовать его просто для получения определенного значения. Третий метод демонстрирует, что количество параметров, которое может принять метод, неограниченно. Это означает, что адаптер ресурсов мог бы, к примеру, разобрать инициирующее событие на несколько значений для передачи в MDB-компонент. Также можно увидеть, что параметры метода могут быть примитивными типами или объектами. Наконец, было бы правильным использовать интерфейс ExampleListener даже тогда, когда он имеет несколько методов. Тогда решение о выборе метода для активизации принимал бы адаптер ресурсов, основываясь на событии.

Итак, после снятия с MDB-интерфейса всех ограничений, связанных с JMS, что стало с дескриптором развертывания? В листинге 6 показан пример дескриптора развертывания EJB 2.1 для MDB-компонента, реализующего интерфейс ExampleListener.


Листинг 6. Дескриптор развертывания EJB 2.1
<ejb-jar>
  <enterprise-beans>
    <message-driven>
      <ejb-name>Example MDB</ejb-name>
      <ejb-class>example.ExampleMdb</ejb-class>
      <messaging-type>example.ExampleListener</messaging-type>
      <transaction-type>Bean</transaction-type>
      <activation-config>
        <activation-config-property>
          <activation-config-property-name>
            HostName
          </activation-config-property-name>
          <activation-config-property-value>
            example.com
          </activation-config-property-value>
        </activation-config-property>
        <activation-config-property>
          <activation-config-property-name>
            DefaultId
          </activation-config-property-name>
          <activation-config-property-value>
            2001
          </activation-config-property-value>
        </activation-config-property>
      </activation-config>
    </message-driven>
  </enterprise-beans>
</ejb-jar>

В листинге 6 можно увидеть, что элемент messaging-type содержит имя класса интерфейса, который реализует MDB-компонент. Если этот элемент отсутствует, предполагается старое значение javax.jms.MessageListener. Специфичные для JMS элементы были заменены набором общих пар имя-значение, известных как свойства активизации-конфигурации (activation-configuration properties). В листинге 6 видно, что для свойств HostName и DefaultId указываются значения example.com и 2001 соответственно.

Возможность написать MDB-компонент, реализующий любой интерфейс, звучит слишком хорошо, чтобы быть правдой - и это так и есть. Дело в том (и это не является неожиданным), что вы должны найти адаптер ресурсов, готовый вызвать данный интерфейс. Адаптер ресурсов сообщает об интерфейсах (которых может быть больше одного), которые готов поддерживать, используя элемент messagelistener-type в своем дескрипторе развертывания, как показано в листинге 7.


Листинг 7. Дескриптор развертывания для входящего адаптера ресурсов
<connector>

 <display-name>Example Inbound Resource Adapter</display-name>
 <vendor-name>Example COM</vendor-name>
 <eis-type>Example EIS</eis-type>
 <resourceadapter-version>1.0</resourceadapter-version>

 <resourceadapter>

  <resourceadapter-class>
   example.ExampleRaImpl
  </resourceadapter-class>

  <inbound-resourceadapter>
   <messageadapter>
    <messagelistener>
     <messagelistener-type>example.ExampleListener</messagelistener-type>
     <activationspec>
      <activationspec-class>example.ExampleActivationSpecImpl</activationspec-class>
      <required-config-property>
       <config-property-name>HostName</config-property-name>
      </required-config-property>
      <required-config-property>
       <config-property-name>PortNumber</config-property-name>
      </required-config-property>
     </activationspec>
    </messagelistener>
   </messageadapter>
  </inbound-resourceadapter>

 </resourceadapter>
</connector>

Стоит рассмотреть этот пример дескриптора развертывания более подробно. Он начинается с обычных вещей: отображаемого имени, имени поставщика, типа корпоративной информационной системы (EIS), к которой подключается адаптер ресурсов, и версии адаптера. Затем следует один элемент resourceadapter, первый подэлемент которого содержит имя реализации адаптером интерфейса ResourceAdapter, с которым вы сталкивались в первой части данной серии статей. Затем идет элемент inbound-resourceadapter, который, в свою очередь, содержит несколько экземпляров messageadapter. Каждый экземпляр messageadapter ассоциирован с одним элементом messagelistener-type. То есть можно написать один входящий адаптер ресурсов, поддерживающий несколько интерфейсов, используя несколько элементов messageadapter. Однако вы должны гарантировать, что каждый messageadapter указывает другой интерфейс.

Каждый элемент messageadapter содержит также имя класса, реализующего интерфейс ActivationSpec. В следующем разделе я покажу, как этот класс используется для хранения конфигурационной информации о каждом развернутом MDB-компоненте.



В начало


Развертывание MDB-компонента

Как было указано в предыдущем разделе, каждый MDB-интерфейс, который адаптер ресурсов поддерживает, предоставляет имя класса, реализующего интерфейс ActivationSpec, показанный в листинге 8.


Листинг 8. Интерфейс javax.resource.spi.endpoint.ActivationSpec
public interface ActivationSpec extends ResourceAdapterAssociation {

    void validate() throws InvalidPropertyException;

}

Этот класс реализации соответствует стандарту JavaBean и может определять несколько свойств через названные соответствующим образом методы getter и setter. Этот класс используется при развертывании MDB-компонента на сервере приложений следующим образом:

  1. Сервер приложений определяет интерфейс, который реализует ваш MDB-компонент, просматривая содержимое элемента messaging-type в дескрипторе развертывания MDB.

  2. Сервер приложений затем находит развернутые адаптеры ресурсов, которые поддерживают данный интерфейс, а вы выбираете один из них, при помощи которого хотите развернуть MDB-компонент.

  3. Сервер приложений создает экземпляр класса ActivationSpec, соответствующий выбранному адаптеру ресурсов и интерфейсу, а затем использует интроспекцию для определения свойств данного класса вместе со значениями по умолчанию.

  4. Значения свойств по умолчанию переопределяются любыми свойствами с этими же названиями, настроенными в родительском классе ResourceAdapter.

  5. Затем вы можете выбрать любые значения этих свойств для переопределения.

  6. Свойства переопределяются опять любыми значениями, указанными в свойствах activation-config дескриптора развертывания MDB-компонента.

  7. Сервер приложений проверяет, все ли свойства компонента, указанные в дескрипторе развертывания адаптера ресурсов в качестве необходимых (в данном примере HostName и PortNumber), имеют значения.

Из этого следует, что свойства, которые, в конечном счете, используются с развернутым MDB-компонентом, могут браться из нескольких источников, и важно помнить порядок старшинства. Обратите внимание на то, что дескриптор развертывания MDB-компонента не обязан содержать все свойства, требуемые адаптером ресурсов.

После установки всех свойств сервер приложений может вызвать метод ActivationSpec validate или отложить вызов этого метода до момента запуска приложения. Адаптер ресурсов может использовать данный метод для проверки того, что числовые свойства находятся в приемлемом диапазоне, или проверки корректности строкового свойства, предоставляющего значение из списка. Адаптер ресурсов должен также проверить согласованность окончательного набора свойств; например, значения некоторых свойств могут быть ограничены или зависимы от значений других свойств. Если одна или несколько проверок заканчиваются неудачно, должна генерироваться исключительная ситуация InvalidPropertyException, содержащая массив неправильных свойств.

Успешная проверка не обязательно означает, что развернутый MDB-компонент запустится успешно. Адаптеру ресурсов разрешено выполнять только статические проверки, то есть те, которые можно выполнить без подключения к рабочему серверу. Только после запуска приложения адаптер ресурсов может проверить корректность установки таких свойств как имена хостов и номера портов.



В начало


Управление циклом жизни MDB-компонента

После успешного развертывания приложения, содержащего MDB-компонент на сервере приложений, следующим этапом является запуск приложения. Сервер приложений уведомляет адаптер ресурсов о событиях в цикле жизни отдельного MDB-компонента (называемого в спецификации оконечной точкой (endpoint)), используя два метода интерфейса ResourceAdapter, показанные в листинге 9.


Листинг 9. Методы цикла жизни оконечной точки в интерфейсе ResourceAdapter
public interface ResourceAdapter {

    void endpointActivation(MessageEndpointFactory endpointFactory,
            ActivationSpec spec) throws ResourceException;

    void endpointDeactivation(MessageEndpointFactory endpointFactory,
            ActivationSpec spec);

    ...

}

После запуска приложения метод endpointActivation активизируется один раз для каждого развернутого MDB-компонента. Первый параметр (который я опишу более подробно в следующем разделе) - это класс фабрики для создания экземпляров оконечной точки. Второй параметр метода - это ActivationSpec, который вы настроили в предыдущем разделе. Это точка, из которой адаптер ресурсов может обычно создать определенного рода удаленное соединение с серверной системой, используя информацию из ActivationSpec. Если в процессе данного действия адаптер ресурсов обнаруживает некорректность в конфигурационной информации, он должен сгенерировать исключительную ситуацию NotSupportedException.

Обратите внимание на то, что адаптер ресурсов не должен блокироваться в этом методе. При необходимости последующей обработки (например, для периодического опроса соединения для обнаружения новых событий) адаптер ресурсов должен использовать интерфейс WorkManager, который я представил во второй части данной серии статей, для того чтобы запланировать работу на выполнение в другом потоке.

При остановке приложения, содержащего MDB-компонент, или во время нормального завершения работы сервера приложений, вызывается соответствующий метод endpointDeactivation. Передаваемые в этот метод параметры являются точно такими же объектами, которые передаются в endpointActivation. Более того, поскольку спецификация JCA предписывает, чтобы новый экземпляр MessageEndpointFactory создавался для активизации каждой оконечной точки, объект, передаваемый при деактивизации, может использоваться в качестве ключа для коррелирования обоих действий. Например, созданные при активизации ресурсы могли бы помещаться в карту, ключами которой является MessageEndpointFactory, а затем извлекаться при деактивизации для очистки.



В начало


Активизация MDB-компонента

Теперь все готово для активизации адаптером ресурсов MDB-компонента. Во времена J2EE 1.3 на этом шаге использовался довольно запутанный механизм Application Server Facilities, являвшийся частью спецификации JMS. Взаимодействия были сложными и кое-где недостаточно специфицированы, что приводило к различной интерпретации требований производителями программного обеспечения. К счастью для нас, спецификация JCA не только разрешает MDB-компоненту реализовать любой интерфейс, но также значительно упрощает работу.

В листинге 10 показан интерфейс MessageEndpointFactory, реализуемый объектом, переданным в метод endpointActivation.


Листинг 10. Интерфейс javax.resource.spi.endpoint.MessageEndpointFactory
public interface MessageEndpointFactory {

    boolean isDeliveryTransacted(Method method) throws NoSuchMethodException

    MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException;

}

Метод isDeliveryTransacted позволяет адаптеру ресурсов определить, ожидает ли соответствующий MDB-компонент активизации указанного метода в транзакции. Если MDB-компонент использует транзакции, управляемые контейнером, возвращается значение true, а для используемого метода атрибут transaction установлен в значение Required. Если атрибут transaction установлен в другое допустимое значение NotSupported или MDB-компонент использует транзакции, управляемые компонентом, возвращается значение false.

Я рассмотрю транзакции в следующем разделе, а сейчас давайте предположим, что isDeliveryTransacted возвращает false (или, в качестве альтернативы, что адаптер ресурсов не поддерживает транзакций). Это означает, что вы можете передать null в качестве параметра XAResource при вызове метода createEndpoint. Этот метод возвращает объект, реализующий интерфейс MessageEndpoint, который показан в листинге 11.


Листинг 11. Интерфейс javax.resource.spi.endpoint.MessageEndpoint
public interface MessageEndpoint {

    void release();

    void beforeDelivery(Method method)
            throws NoSuchMethodException, ResourceException

    void afterDelivery() throws ResourceException;

}

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

Возвращаемый из createEndpoint объект, очевидно, не является экземпляром класса, реализованного разработчиком приложения, поскольку этот класс не реализует интерфейс MessageEndpoint. Это прокси-объект (proxy), созданный сервером приложений. Сервер приложений может использовать поддержку динамических прокси, появившуюся в Java 1.4, для создания объекта на лету, либо сгенерировать необходимый класс во время развертывания приложения. Контейнер использует прокси-объект для помещения в него оконечной точки, для того чтобы предоставить такие сервисы как транзакции и защиту. Сравните прокси-объект со ссылкой на локальный интерфейс не запоминающего состояния сессионного компонента. При использовании сессионного компонента вы можете активизировать только методы, объявленные в локальном интерфейсе. При использовании прокси-объекта вы можете активизировать только методы, объявленные в дескрипторе развертывания MDB-компонента.

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

Я говорил, что здесь представлен простой случай. Спецификация JCA называет это доставкой сообщений Option A. В качестве примера необходимости использования альтернативной доставки Option B представьте ситуацию, когда адаптер ресурсов является частью системы обмена сообщениями, передающую сериализованные Java-объекты по поручению приложений. Метод MDB-компонента, который вы хотите вызвать, принимает в качестве параметра десериализованный объект. К сожалению, класс, соответствующий сериализованному объекту, является частью J2EE-приложения и, следовательно, имеется в classpath приложения, а не адаптера ресурсов. Option B искусно решает эту проблему при помощи методов beforeDelivery и afterDelivery. Вызов beforeDelivery рано выполняет некоторые из операций контейнера, которые обычно происходят между активизацией прокси-объекта и вызовом метода в реальной оконечной точке. К этим операциям относится ассоциирование загрузчика класса (classloader) приложения с потоком. При наличии beforeDelivery адаптер ресурсов может теперь десериализовать объект, используя classloader потока, и передать его в необходимый метод интерфейса MDB-компонента.

Контейнер знает о том, что он уже выполнил некоторые из необходимых операций с этим прокси-объектом оконечной точки и пропустит их при активизации реального метода MDB-компонента. Однако вызванный метод должен соответствовать объекту Method, переданному в beforeDelivery, иначе сгенерируется исключительная ситуация RuntimeException. После вызова метода адаптер ресурсов должен вызвать afterDelivery для выполнения соответствующих операций контейнера, которые должны выполняться после активизации метода. Это позволяет адаптеру ресурсов, например, сериализовать возвращенный из метода объект, опять используя classloader приложения.

На рисунке 1 показано сравнение двух вариантов доставки сообщений.


Рисунок 1. Варианты доставки сообщений
XML error: The image is not displayed because the width is greater than the maximum of 572 pixels. Please decrease the image width.

Для Option A можно заметить, что логика preinvoke и postinvoke выполняется как часть одной активизации метода, в то время как для Option B они разделены и выполняются методами beforeDelivery и afterDelivery соответственно.



В начало


MDB-компоненты и транзакции

Если адаптер ресурсов поддерживает XA-транзакции (глобальные), а isDeliveryTransacted указывает на то, что MDB-компонент ожидает от контейнера запуск одной из них, тогда адаптер ресурсов должен передать реализацию интерфейса XAResource при вызове createEndpoint. XA-транзакции - это сложная тема, а рассмотрение их специфики, не связанной с JCA, выходит за рамки данной статьи. Более подробная информация приведена в спецификации Java Transaction API (см. раздел "Ресурсы").

Адаптер ресурсов имеет два варианта работы. Он может связать транзакционную работу с выполнением непосредственно с ее объектом XAResource. Адаптер ресурсов может затем использовать вариант доставки сообщений Option A. При активизации прокси-объекта контейнер зачисляет XAResource в транзакцию путем вызова метода start. В этот момент адаптер ресурсов может ассоциировать указанный Xid с работой, которую нужно выполнить. Прокси выполняет активизацию экземпляра оконечной точки. После возврата из метода оконечной точки контейнер завершает транзакцию. Когда XAResource получает вызов для prepare, он должен убедиться, что может успешно завершить необходимую работу перед возвратом XA_OK. Наконец, когда XAResource получает commit или rollback, он должен зафиксировать или отменить выполненную работу.

В качестве альтернативы адаптер ресурсов может использовать доставку сообщений Option B. В этом случае транзакция начинается как часть beforeDelivery. Это позволяет адаптеру ресурсов извлекать Xid из XAResource до активизации метода MDB-компонента. Такой вариант понадобится, например, если адаптер ресурсов должен передать Xid на рабочий сервер до того как сможет создать параметр, передаваемый в метод. Как и ожидается, в данной ситуации транзакция завершается при вызове afterDelivery.

Если на сервере приложений происходит сбой в работе в период между вызовом prepare и commit или rollback, восстановление транзакций должно выполняться при перезапуске сервера. Для выполнения работ по восстановлению сервер приложений должен получить XAResource для каждого менеджера ресурсов. Сервер приложений достигает этого путем записи объекта ActivationSpec, ассоциированного с оконечной точкой, в постоянное хранилище перед вызовом prepare. Во время восстановления сервер считывает список объектов ActivationSpec для всех адаптеров ресурсов, которые соответствуют транзакциям, подозреваемым в незавершенности. Этот массив объектов передается затем в метод getXAResources интерфейса ResourceAdapter, показанного в листинге 12.


Листинг 12. Метод восстановления транзакций интерфейса ResourceAdapter
public interface ResourceAdapter {

    XAResource[] getXAResources(ActivationSpec[] specs)
            throws ResourceException;

    ...

}

Сервер приложений вызывает recover в каждом объекте XAResource для определения транзакций, которые подготовил менеджер ресурсов. Затем он вызывает commit или rollback для каждой транзакции.

Во второй части данной серии статей вы узнали, как можно использовать ExecutionContext совместно с WorkManager для импорта транзакции на сервер приложений. Если метод оконечной точки с атрибутом транзакции Required активизируется в потоке с импортированной транзакцией, метод будет наследовать эту транзакцию. В данном случае любой XAResource, переданный в createEndpoint, не зачисляется в транзакцию.



В начало


Администрируемые объекты

В этом завершающем разделе я рассмотрю тему, которая, несмотря на то, что описана в спецификации по JCA в главе по внедрению сообщений, одинаково применима как для входящих, так и для исходящих адаптеров ресурсов. Одной из целей спецификации версии 1.5 является разрешение реализовывать JMS-провайдер как адаптер ресурсов JCA. Если вы знакомы с JMS, то знаете, что она содержит два типа администрируемых объекта: фабрики соединений и адресаты. Посредством фабрик управляемых соединений и их свойств, определенных в дескрипторе развертывания адаптера ресурсов, JCA всегда обеспечивала механизм, позволяющий администратору определять фабрики соединений, которые могли быть найдены развернутыми приложениями через JNDI (Java Naming and Directory Interface). Но JMS-адресаты не являются фабриками, а лишь объектами с различными свойствами, описывающими очередь или тему, которую они предоставляют. Как же тогда создать JMS-адресат?

Спецификация JCA 1.5 определяет концепцию администрируемых объектов (administered object) для заполнения этого пробела. Дескриптор развертывания адаптера ресурсов может содержать один или несколько элементов adminobject, как, например, в листинге 13.


Листинг 13. Сниппет дескриптора развертывания, демонстрирующий администрируемые объекты
  <adminobject>
   <adminobject-interface>example.ExampleAdminObject</adminobject-interface>
   <adminobject-class>example.ExampleAdminObjectImpl</adminobject-class>
   <config-property>
    <config-property-name>Color</config-property-name>
    <config-property-type>java.lang.String</config-property-type>
     <config-property-value>Red</config-property-value>         
   </config-property>
   <config-property>
    <config-property-name>Depth</config-property-name>
    <config-property-type>java.lang.Integer</config-property-type>
   </config-property>
  </adminobject>

В данном случае подразумевается, что приложение ищет в JNDI (через ссылку resource-environment) объект, реализующий интерфейс example.ExampleAdminObject. Дескриптор развертывания предоставляет имя JavaBean-класса, который обеспечивает реализацию этого объекта. Он также предоставляет несколько именованных свойств, каждое из которых имеет тип и необязательное значение по умолчанию во многом аналогично фабрикам управляемых соединений. Когда администратор желает определить один из данных объектов, инструментальные средства сервера приложений должны позволять ему выбрать адаптер ресурсов и интерфейс администрируемого объекта, а затем запросить у него значения для каждого свойства. Сервер приложений связывает ссылку, содержащую эту информацию, в JNDI. Когда сервер приложений выполняет поиск, создается экземпляр администрируемого объекта, а перед возвратом объекта в приложение устанавливаются его свойства.

Теперь вы должны знать, как адаптер ресурсов JCA будет предоставлять объекты JMS-адресатов, используя администрируемые объекты. Но не забывайте о том, что можно использовать администрируемые объекты для любого JavaBean-компонента (отличного от фабрики соединений), который вы хотите открыть для конфигурирования администратором и сделать доступными через JNDI.



В начало


Заключение

В данной статье я рассмотрел изменения в управляемых сообщениями компонентах в версиях J2EE 1.3 и 1.4, а также то, как они могут теперь реализовать любой интерфейс. Вы увидели, как можно использовать соглашение JCA по внедрению сообщений для настройки адаптера ресурсов, для того чтобы он мог извлекать экземпляры и активизировать методы в MDB-компоненте. Я также подробно рассмотрел варианты активизации методов компонентов и влияние вызовов транзакционных методов. Наконец, я объяснил, как администрируемые объекты позволяют адаптеру ресурсов настроить JavaBeans-компоненты и сделать их доступными через JNDI.

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



Ресурсы



Об авторе

Дэвид Карри (David Currie) недавно пришел в IBM Software Services for WebSphere, базирующуюся в Hursley, Великобритания. До этого он занимался разработкой WebSphere Application Server, сначала транзакциями, а затем проектированием и реализацией JCA-адаптеров ресурсов для поддержки систем обмена сообщениями. Связаться с ним можно по адресу david_currie@uk.ibm.com.




Выскажите мнение об этой странице


Пожалуйста, найдите минутку и заполните форму, чтобы повысить уровень сервиса.



ДаНетНе знаю
 


 


12345
 


В начало


IBM обладает всеми авторскими правами касательно информации, расположенной на developerWorks. Использование информации приведенной на этом ресурсе без явного письменного разрешения от IBM или первоначального автора запрещены. Если Вы желаете использовать информацию с developerWorks, пожалуйста воспользуйтесь регистрационной формой для того, чтобы связаться с нами запрос на использование материалов developerWorks Россия.

    IBM в России Конфиденциальность Контакты