43.3. 논리 핸들러에서 메시지 처리

43.3.1. 개요

일반 메시지 처리는 handleMessage() 메서드에서 처리됩니다.

handleMessage() 메서드는 메시지 본문 및 메시지 컨텍스트에 저장된 모든 속성에 대한 액세스를 제공하는 LogicalMessageContext 개체를 수신합니다.

handleMessage() 메서드는 메시지 처리를 계속하는 방법에 따라 true 또는 false를 반환합니다. 또한 예외를 throw할 수 있습니다.

43.3.2. 메시지 데이터 가져오기Get the message data

논리 메시지 처리기로 전달된 LogicalMessageContext 개체를 사용하면 컨텍스트의 getMessage() 메서드를 사용하여 메시지 본문에 액세스할 수 있습니다. 예 43.2. “논리 핸들러에서 메시지 페이로드를 가져오는 방법” 에 표시된 getMessage() 메서드는 메시지 페이로드를 LogicalMessage 오브젝트로 반환합니다.

예 43.2. 논리 핸들러에서 메시지 페이로드를 가져오는 방법

LogicalMessagegetMessage

LogicalMessage 개체가 있으면 이를 사용하여 메시지 본문을 조작할 수 있습니다. 예 43.3. “논리 메시지 보유기” 에 표시된 LogicalMessage 인터페이스에는 실제 메시지 본문을 사용하기 위한 getter 및 setter가 있습니다.

예 43.3. 논리 메시지 보유기

LogicalMessageSourcegetPayloadObjectgetPayloadJAXBContext컨텍스트setPayloadObjectpayload

중요

메시지 페이로드의 내용은 사용 중인 바인딩 유형에 따라 결정됩니다. SOAP 바인딩은 메시지의 SOAP 본문에만 액세스할 수 있습니다. XML 바인딩은 전체 메시지 본문에 액세스할 수 있도록 합니다.

43.3.3. 메시지 본문을 XML 개체로 작업

논리 메시지 쌍은 메시지 페이로드를 javax.xml.transform.dom.DOMSource 개체로 사용하여 작업합니다.

매개 변수가 없는 getPayload() 메서드는 메시지 페이로드를 DOMSource 개체로 반환합니다. 반환된 오브젝트는 실제 메시지 페이로드입니다. 반환된 개체의 모든 변경 사항은 메시지 본문을 즉시 변경합니다.

메시지의 본문을 단일 Source 개체를 사용하는 setPayload() 메서드를 사용하여 DOMSource 개체로 교체할 수 있습니다.

43.3.4. message body를 JAXB 오브젝트로 작업

다른 쌍의 getter 및 setter를 사용하면 메시지 페이로드를 JAXB 오브젝트로 작업할 수 있습니다. JAXBContext 개체를 사용하여 메시지 페이로드를 JAXB 오브젝트로 변환합니다.

JAXB 오브젝트를 사용하려면 다음을 수행합니다.

  1. 메시지 본문에서 데이터 유형을 관리할 수 있는 JAXBContext 개체를 가져옵니다.

    JAXBContext 오브젝트 생성에 대한 자세한 내용은 39장. A JAXBContext 오브젝트 사용 을 참조하십시오.

  2. 예 43.4. “Message Body를 JAXB 오브젝트로 가져오기” 에 표시된 대로 메시지 본문을 가져옵니다.

    예 43.4. Message Body를 JAXB 오브젝트로 가져오기

    JAXBContext jaxbc = JAXBContext(myObjectFactory.class);
    Object body = message.getPayload(jaxbc);
  3. 반환된 개체를 적절한 형식으로 캐스팅합니다.
  4. 메시지 본문을 필요에 따라 조작합니다.
  5. 업데이트된 메시지 본문을 예 43.5. “JAXB 오브젝트를 사용하여 메시지 본문 업데이트” 에 표시된 대로 컨텍스트로 다시 넣습니다.

    예 43.5. JAXB 오브젝트를 사용하여 메시지 본문 업데이트

    message.setPayload(body, jaxbc);

43.3.5. 컨텍스트 속성 작업

논리 처리기로 전달된 논리 메시지 컨텍스트는 애플리케이션의 메시지 컨텍스트 인스턴스이며 이 컨텍스트에 저장된 모든 속성에 액세스할 수 있습니다. 핸들러는 APPLICATION 범위 및 HANDLER 범위 모두에서 속성에 액세스할 수 있습니다.

애플리케이션의 메시지 컨텍스트와 마찬가지로 논리 메시지 컨텍스트는 Java Map의 하위 클래스입니다. 컨텍스트에 저장된 속성에 액세스하려면 get() 메서드 및 put() 메서드를 사용하여 맵 인터페이스에서 상속됩니다.

기본적으로 논리 처리기 내에서 메시지 컨텍스트에서 설정한 모든 속성에는 HANDLER의 범위가 할당됩니다.By default, any properties you set in the message context from inside a logical handler are assigned a scope of HANDLER. 애플리케이션 코드가 컨텍스트의 setScope() 메서드를 사용하여 속성 범위를 APPLICATION으로 명시적으로 설정하는 데 필요한 속성에 액세스할 수 있도록 하려면.

메시지 컨텍스트에서 속성 작업에 대한 자세한 내용은 42.1절. “컨텍스트 이해” 을 참조하십시오.

43.3.6. 메시지의 방향을 결정하는 방법How to determine the direction of the message

메시지가 처리기 체인을 통과하는 방향을 아는 것이 종종 중요합니다. 예를 들어 들어오는 요청에서 보안 토큰을 검색하고 보안 토큰을 나가는 응답에 연결하려고 합니다.

메시지의 방향은 메시지 컨텍스트의 아웃바운드 메시지 속성에 저장됩니다. 예 43.6. “SOAP 메시지 컨텍스트에서 메시지 직접 가져오기” 에 표시된 대로 MessageContext.MESSAGE_OUTBOUND_PROPERTY 키를 사용하여 메시지 컨텍스트에서 아웃바운드 메시지 속성을 검색합니다.

예 43.6. SOAP 메시지 컨텍스트에서 메시지 직접 가져오기

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

속성은 부울 오브젝트로 저장됩니다. 개체의 부울Value() 메서드를 사용하여 속성 값을 확인할 수 있습니다. 속성이 true로 설정되면 메시지는 아웃바운드입니다.If the property is set to true, the message is outbound. 속성이 false로 설정되면 메시지가 인바운드됩니다.If the property is set to false, the message is inbound.

43.3.7. 반환 값 확인

handleMessage() 메서드가 메시지 처리를 완료하는 방법은 메시지 처리가 진행되는 방식에 직접적인 영향을 미칩니다. 다음 작업 중 하나를 수행하여 완료할 수 있습니다.

  1. 메시지 처리가 정상적으로 계속되어야 하는 Apache CXF 런타임으로 true 반환 true 신호를 반환합니다. 다음 처리기에 해당 handleMessage() 가 호출되었습니다.
  2. 일반적인 메시지 처리가 중지되어야 하는 Apache CXF 런타임으로 false-Returning false 신호를 반환합니다. 런타임이 진행되는 방식은 현재 메시지에 사용되는 메시지 교환 패턴에 따라 다릅니다.

    요청-응답 메시지 교환의 경우 다음과 같은 일이 발생합니다.

    1. 메시지 처리의 방향은 반전됩니다.

      예를 들어 서비스 공급자가 요청을 처리하는 경우 메시지는 서비스의 구현 오브젝트로 진행되지 않습니다. 대신 요청을 시작한 소비자로의 반환을 위해 바인딩으로 다시 전송됩니다.

    2. 새 처리 방향에서 처리기 체인을 따라 있는 모든 메시지 처리기에는 체인에 있는 순서대로 handleMessage() 메서드가 호출됩니다.
    3. 메시지가 처리기 체인의 끝에 도달하면 디스패치됩니다.

      단방향 메시지 교환의 경우 다음과 같은 일이 발생합니다.

    4. 메시지 처리가 중지됩니다.
    5. 이전에 호출한 모든 메시지 핸들러에는 close() 메서드가 호출되었습니다.
    6. 메시지가 디스패치되어 있습니다.
  3. ProtocolException 예외를 throw - ProtocolException 예외 또는 이 예외의 하위 클래스를 throw하면 오류 메시지 처리가 시작되는 Apache CXF 런타임이 시작됩니다. 런타임이 진행되는 방식은 현재 메시지에 사용되는 메시지 교환 패턴에 따라 다릅니다.

    요청-응답 메시지 교환의 경우 다음과 같은 일이 발생합니다.

    1. 처리기가 오류 메시지를 아직 생성하지 않은 경우 런타임은 메시지를 오류 메시지로 래핑합니다.
    2. 메시지 처리의 방향은 반전됩니다.

      예를 들어 서비스 공급자가 요청을 처리하는 경우 메시지는 서비스의 구현 오브젝트로 진행되지 않습니다. 대신 요청을 시작한 소비자로의 반환을 위해 바인딩으로 다시 전송됩니다.

    3. 새 처리 방향에서 처리기 체인을 따라 있는 모든 메시지 처리기에는 체인에 상주하는 순서대로 handleFault() 메서드가 호출됩니다.
    4. 오류 메시지가 처리기 체인의 끝에 도달하면 디스패치됩니다.

      단방향 메시지 교환의 경우 다음과 같은 일이 발생합니다.

    5. 처리기가 오류 메시지를 아직 생성하지 않은 경우 런타임은 메시지를 오류 메시지로 래핑합니다.
    6. 메시지 처리가 중지됩니다.
    7. 이전에 호출한 모든 메시지 핸들러에는 close() 메서드가 호출되었습니다.
    8. 오류 메시지가 디스패치되어 있습니다.
  4. 다른 런타임 예외를 throw - ProtocolException 예외 이외의 런타임 예외는 메시지 처리가 중지되는 Apache CXF 런타임을 알리는 신호입니다. 이전에 호출한 모든 메시지 핸들러에는 close() 메서드가 호출되고 예외가 디스패치됩니다. 메시지가 요청 응답 메시지 교환의 일부인 경우 요청이 발생한 소비자에게 반환되도록 예외가 디스패치됩니다.

43.3.8. 예제

예 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 표현을 가져옵니다.

JAXB 오브젝트로 실제 메시지 페이로드를 가져옵니다.

요청이 올바른 유형인지 확인합니다.

이 경우 핸들러는 메시지를 계속 처리합니다.

합계의 값을 확인합니다.

임계값 20보다 작으면 응답을 작성하고 클라이언트에 반환합니다.

응답을 빌드합니다.

메시지 처리를 중지하고 클라이언트에 대한 응답을 반환하는 false를 반환합니다.

메시지가 올바른 유형이 아닌 경우 런타임 예외를 throw합니다.

이 예외는 클라이언트에 반환됩니다.

메시지가 인바운드 응답이거나 합계가 임계값을 충족하지 않으면 true를 반환합니다.Return true if the message is an inbound response or the sum does not meet the threshold.

메시지 처리는 정상적으로 계속됩니다.

JAXB 마샬링 오류가 발생하는 경우 ProtocolException을 throw합니다.

현재 처리기와 클라이언트 간의 처리기의 handleFault() 메서드에서 처리한 후 예외는 클라이언트에 다시 전달됩니다.