43.3. 在逻辑处理程序中处理消息

概述

普通消息处理由 handleMessage() 方法处理。

handleMessage() 方法收到 LogicalMessageContext 对象,提供对消息正文和消息上下文中存储的任何属性的访问。

handleMessage() 方法根据消息处理方式返回 true 或 false。它还可能会引发异常。

获取消息数据

传递给逻辑消息处理程序的 LogicalMessageContext 对象允许使用上下文 getMessage() 方法访问消息正文。getMessage() 方法(如 例 43.2 “在逻辑处理程序中获取消息 Payload 的方法” 所示)返回消息有效负载作为 LogicalMessage 对象。

例 43.2. 在逻辑处理程序中获取消息 Payload 的方法

LogicalMessagegetMessage

具有 LogicalMessage 对象后,就可以使用它来操作消息正文。LogicalMessage 接口(在 例 43.3 “逻辑消息冻结器” 所示)具有 getter 和 setters,以用于实际消息正文。

例 43.3. 逻辑消息冻结器

LogicalMessageSourcegetPayloadObjectgetPayloadJAXBContext上下文setPayloadObjectpayloadJAXBContextcontextsetPayloadSourcepayload

重要

消息有效负载的内容由正在使用的绑定类型决定。SOAP 绑定仅允许访问消息的 SOAP 正文。XML 绑定允许访问整个邮件正文。

将消息正文用作 XML 对象

逻辑消息的一对 getters 和 setters 将消息有效负载用作 javax.xml.transform.dom.DOMSource 对象。

没有参数的 getPayload() 方法将消息有效负载返回为 DOMSource 对象。返回的对象是实际消息有效负载。对返回的对象进行的任何更改都会立即更改消息正文。

您可以使用使用单一 Source 对象的 setPayload() 方法将消息的正文替换为 DOMSource 对象。

将消息正文用作 JAXB 对象

通过另一对 getter 和 setters,您可以将消息有效负载用作 JAXB 对象。它们使用 JAXBContext 对象,将消息有效负载转换为 JAXB 对象。

要使用您要执行以下操作的 JAXB 对象:

  1. 获取可在消息正文中管理数据类型的 JAXBContext 对象。

    有关创建 JAXBContext 对象的详情,请参考 第 39 章 使用 A JAXBContext 对象

  2. 例 43.4 “获取消息正文作为 JAXB 对象” 所示获取消息正文。

    例 43.4. 获取消息正文作为 JAXB 对象

    JAXBContext jaxbc = JAXBContext(myObjectFactory.class);
    Object body = message.getPayload(jaxbc);
  3. 将返回的对象转换为正确的类型。
  4. 根据需要操作消息正文。
  5. 将更新的消息正文放回上下文,如 例 43.5 “使用 JAXB 对象更新消息正文” 所示。

    例 43.5. 使用 JAXB 对象更新消息正文

    message.setPayload(body, jaxbc);

使用上下文属性

传递给逻辑处理程序的逻辑消息上下文是应用消息上下文的实例,可访问其中存储的所有属性。处理程序能够访问 APPLICATION 范围和 HANDLER 范围的属性。

与应用程序的消息上下文一样,逻辑消息上下文是 Java Map 的子类。要访问存储在上下文中的属性,请使用 get() 方法以及从 Map 接口继承的 put() 方法。

默认情况下,您在逻辑处理程序内部的消息上下文中设置的任何属性将被分配为 HANDLER 的范围。如果您希望应用程序代码能够访问您需要使用上下文的 setScope() 方法的 属性,以显式将属性的范围设置为 APPLICATION。

有关在消息上下文中使用属性的更多信息,请参阅 第 42.1 节 “了解上下文”

确定消息的方向

通常务必要知道消息通过处理程序链的方向。例如,您要从传入请求检索安全令牌,并将安全令牌附加到传出响应。

消息方向存储在消息上下文的出站消息属性中。您可以使用 MessageContext.MESSAGE_OUTBOUND_PROPERTY 键从消息上下文中检索出站消息属性,如 例 43.6 “从 SOAP 消息上下文获取消息方向” 所示。

例 43.6. 从 SOAP 消息上下文获取消息方向

Boolean outbound;
outbound = (Boolean)smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

属性存储为 布尔值 对象。您可以使用对象的 booleanValue() 方法来确定属性值。如果该属性设为 true,则消息被出站。如果该属性设为 false,则消息被入站。

确定返回值

handleMessage() 方法如何完成其消息处理会对消息处理处理方式有直接影响。此操作可以通过执行以下操作之一完成:

  1. 向 Apache CXF 运行时返回 true 信号,消息处理应正常继续。下一个处理程序(若有)对其 handleMessage() 调用。
  2. 向 Apache CXF 运行时返回错误错误信号,该信号必须停止正常消息处理。运行时进行的处理方式取决于用于 当前消息的消息 交换模式。

    请求响应消息会交换以下内容:

    1. 消息处理方向会被反转。

      例如,如果请求由服务提供商处理,则消息将停止进入服务的实施对象。相反,它会发回到发起请求的使用者的绑定。

    2. 任何驻留在处理程序链中的消息处理程序都会按照它们驻留在链中的顺序调用它们的 handleMessage() 方法。
    3. 当消息到达处理器链的末尾时,它将被发送。

      对于单向信息会交换以下内容:

    4. 消息处理停止.
    5. 所有之前调用的消息处理程序都具有其 close() 方法调用。
    6. 消息被发送。
  3. 引发 ProtocolException 异常异常,或者此异常的子类(此异常的子类)会发出错误消息处理的请求。运行时进行的处理方式取决于用于 当前消息的消息 交换模式。

    请求响应消息会交换以下内容:

    1. 如果处理程序还没有创建错误消息,则运行时会将消息嵌套在错误消息中。
    2. 消息处理方向会被反转。

      例如,如果请求由服务提供商处理,则消息将停止进入服务的实施对象。相反,它会发回到发起请求的使用者的绑定。

    3. 任何驻留在处理程序链的任何消息处理程序都会在 其处理 方向中调用的顺序按照它们驻留在链中的顺序调用。
    4. 当错误消息到达处理器链的末尾时,它将被发送。

      对于单向信息会交换以下内容:

    5. 如果处理程序还没有创建错误消息,则运行时会将消息嵌套在错误消息中。
    6. 消息处理停止.
    7. 所有之前调用的消息处理程序都具有其 close() 方法调用。
    8. 分配故障消息。
  4. 引发任何其他运行时例外 - 加一个协议Exception 异常异常阻止了消息处理停止的 Apache CXF 运行时。所有之前调用的消息处理程序都具有 close() 方法调用,并被分配异常。如果消息是请求响应消息交换的一部分,则会分配例外,使其返回到发起请求的消费者。

示例

例 43.7 “逻辑消息处理程序消息处理” 显示服务消费者使用的逻辑消息处理程序的 handleMessage() 消息的实施。它会在请求发送到服务供应商之前处理请求。

例 43.7. 逻辑消息处理程序消息处理

public class SmallNumberHandler implements LogicalHandler<LogicalMessageContext>
{
    public final boolean handleMessage(LogicalMessageContext messageContext)
    {
        try
        {
            boolean outbound = (Boolean)messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

            if (outbound)
            {
                LogicalMessage msg = messageContext.getMessage();

                JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
                Object payload = msg.getPayload(jaxbContext);
                if (payload instanceof JAXBElement)
                {
                    payload = ((JAXBElement)payload).getValue();
                }

                if (payload instanceof AddNumbers)
                {
                    AddNumbers req = (AddNumbers)payload;

                    int a = req.getArg0();
                    int b = req.getArg1();
                    int answer = a + b;

                    if (answer < 20)
                    {
                      AddNumbersResponse resp = new AddNumbersResponse();
                      resp.setReturn(answer);
                      msg.setPayload(new ObjectFactory().createAddNumbersResponse(resp),
                                                      jaxbContext);

                      return false;
                    }
                }
                else
                {
                   throw new WebServiceException("Bad Request");
                }
            }
            return true;
        }
        catch (JAXBException ex)
        {
            throw new ProtocolException(ex);
        }
    }
...
}

例 43.7 “逻辑消息处理程序消息处理” 中的代码执行以下操作:

检查消息是否为出站请求。

如果消息是出站请求,处理程序会执行额外的消息处理。

从消息上下文获取消息有效负载的 LogicalMessage representation。

获取实际消息 payload 作为 JAXB 对象。

检查以确保请求是正确类型。

如果出现这种情况,处理程序将继续处理消息。

检查 sum 的值。

如果小于 20 的阈值,则它构建响应并将其返回到客户端。

构建响应。

返回 false 以停止消息处理并返回对客户端的响应。

如果消息不是正确的类型,则抛出运行时异常。

这个异常将返回到客户端。

如果消息是入站响应,则返回 true,或者 sum 不符合阈值。

消息处理正常继续。

如果遇到 JAXB marshalling 错误,则抛出 ProtocolException。

异常会在由当前处理程序和客户端之间处理程序的 handleFault() 方法处理后传回客户端。