JBI组件和NMR通过DeliveryChannel接口进行交互。传输通道使得组件可以: · 接收和发送消息 · 创建消息交换工厂。
2.9.1 消息交换工厂API(Message Exchange Factory API)
所有的消息交换实例使用消息交换工厂的实例来创建。使用组件的传输通道,通过以下三种方式之一可以创建消息交换工厂:
· createMessageExchangeFactory(ServiceEndpoint)创建一个工厂,设置所有创建的交换实例的endpoint属性为给定的端点。当处理显式选择的端点或动态解析的端点时是很有用的。
· createMessageExchangeFactory(QName interfaceName)创建一个工厂,设置所有创建的交换实例的interfaceName属性为给定的接口名称。
· createMessageExchangeFactory()创建一个工厂,设置消息交换的所有属性都为默认值(null或空)。
· createMessageExchangeFactoryForService(QName serviceName)创建一个工厂,设置工厂创建的所有交换实例的service属性为给定的服务名称。
2.9.2 创建消息交换(Creating Message Exchanges)
MessageExchangeFactory提供三种不同的方法创建新的消息交换实例,支持三种不同的需要:
· createExchange(serviceName,operationName)根据服务名称和操作名称创建。允许组件快速装配一个消息交换实例,不用检查服务元数据中的MEP。
· createExchange(URI)根据MEP URI创建。允许支持MEP的扩展。
· createInOnlyExchange()等。使用指定MEP的方法创建。在编码时确定了MEP需求时使用此方法便于创建标准消息交换。
2.9.3 发送消息交换(Sending Message Exchanges)
DeliveryChannel提供两种基本方式发送消息交换:
· Send(exchange).异步消息传输:此方法不会阻塞。交换可和调用那个send()的线程并发执行。
Page 26 of 67
· SendSync(exchange).同步消息传输;此方法必须阻塞当前执行的线程直到消息交换返回。
后者用一个变量存放超时参数。JBI组件可以使用简单同步消息交换而不用在消息交换没有按预期返回时管理“粘滞”线程。为支持超时特点,sendSync()方法返回一个布尔值来表示消息交换实例是否成功返回。如果第一个超载,sendSync(exchange)一般返回真。如果第二个超载,sendSync(exchange,long)返回假,消息交换被设置为
ExchangeStatus.ERROR状态。如果一个提供者组件试图发送一个这样一个消息交换(例如一个因sendSync()超时而失败的消息交换),实现必须停止调用send()并抛出一个相关的MessagingException异常。
当一个消息交换实例使用一种sendSync方法发送时,JBI实现设置消息交换实例的以下属性:
Javax.jbi.messaging.sendSync. 这个属性
注意,在异步消息交换的情况下,无法保证被接收的消息交换(通过接收者调用accept(),下节讨论)就是最初发送的同一个对象。相反,唯一的保证是消息交换的ID必须是相同的。
2.9.4 接收消息交换(Rreceiving Message Exchanges)
DeliveryChannel提供两种方式接收消息交换:
· accept().此方法在从NMR接收到一个消息交换实例之前是阻塞的。
· accept(timeoutMS).此方法作用类似accept(),当超过给定的时间之后,方法返回null,表明没有接收到任何消息。
消息接收一般符合“拉”模型:JBI组件用自己的执行线程从传输通道把消息交换实例“拉”出来。组件可能会使用不止一个这样的线程做到并发消息接收。JBI实现可满足一个组件以任意的顺序发出的多个accept()请求。
2.9.5 关闭传输通道(Closing Down a DeliveryChannel)
组件可调用一个传输通道deactive所有的服务端点: · close().此方法关闭所有组件激活的活动端点。
Page 27 of 67
· deactivateEndpoint().调用此方法作用同上。
一旦传输通道这样关闭就不能再次开放了。相反,要想使组件继续和NMR交互,需要创建一个新的传输通道实例。
当一个传输通道关闭之后,该通道创建的所有消息交换工厂实例都不能正常工作;所有试图使用这样的工厂创建消息交换实例都将导致抛出一个消息异常,表明相关的传输通道已经关闭。
2.9.6 服务描述SPI(Service Description SPI)
使用组件接口,组件使用getServiceDescription(ServiceEndpoint)方法提供服务相关的元数据。方法返回一个DOM文件,给出某个端点提供的服务的WSDL描述。如果端点不是激活的或者端点不是由该组件提供的,getServiceDescription(ServiceEndpoint)方法返回null。
该DOM文件可以是WSDL2.0兼容的或者WSDL1.1兼容的,有以下附加属性: · 文件不能使用
2.9.7 消息交换模式APIs(Message Exchange Pattern APIs)
下图显示了所有内嵌的MEP的消息交换模式API:
Page 28 of 67
图17 MEP API类图
所有的消息交换实例都必须由消息交换工厂(MessageExchangeFactory)的实例提供的工厂来创建。
消息交换实例的拥有者可以是起始组件、服务或NMR。创建或接收一个消息交换实例就等于把所有权授给创建(或接收)的那个组件。一旦对某个消息交换实例调用send()方法,组件就立即交出了它对这个消息交换实例的所有权。
sendSync()在调用该方法的过程中交出其对消息交换实例的所有权。当调用过程结束(返回真),组件恢复对该消息实例的拥有权。
Page 29 of 67
对一个消息交换实例的拥有权意味着拥有者可以读写这个消息交换实例。如果一个组件(或NMR)对一个消息交换实例不具备拥有权,就不能读写这个实例,但是可以读取消息交换的状态,因为状态的访问可以不必考虑拥有权问题。如果一个组件不是当前消息交换实例的拥有者,而试图对该实例调用任何方法(除了getStatus()),就会抛出一个相应的java.lang.IllegalStateException异常。
2.9.8 消息交换(MessageExchange)
父接口MessageExchange,提供一般方法给实现某个特定消息交换模式的API。MessageExchange实例为一串规格化消息交换和状态交换提供上下文环境,可被看作一个带状态的规格化消息的容器。
每个消息交换实例都可以通过MessageExchange API访问以下特征:
· 状态。ExchangeStatus在一个消息交换实例生命周期中提供其状态的可能值。(安全类
型枚举(type-safe enumeration))。一个新消息交换实例在其生命周期内是激活的,直到状态转变为DONE或ERROR。可分别通过getStatus()和setStatus()来获得和设置该状态。
· 出错状态源。实例可保留一个处理错误的根源(Java异常)。见· 交换
getError()和setError()。
ID。每个MessageExchange实例必须拥有一个JBI实现赋予的唯一的标识字符串。
JBI组件可以用这个标识把异步的响应和初始的请求关联起来。
· 交换模式。每个
MessageExchange实例拥有一个交换模式标识。标准消息交换模式由
WSDL2.0赋值的URI来标识。
· 交换角色。当一个组件创建或接收某个消息交换实例,它必须认识到自己在交换中的角
色。在简单交换模式中可以使用交换的状态、消息和故障等特点很容易地确定组件的角色。在复杂的交换模式下,组件使用getRole()方法可以更容易地确定其在交换中的角色。
· 服务名称。交换调用的服务的限定名。 · 操作名称。交换调用的操作的限定名。
· 服务端点名称。服务提供者端点可选的限定名。(服务名称加端点名称)。
· 规格化消息。交换实例相关的规格化消息的工厂。提供一些方法来创建、设置和查询这
些消息。见createMessage(),setMessage()和getMessage()。
Page 30 of 67