4.3. Java Objects 간에 마샬링

4.3.1. HTTP를 통한 전송을 위해 Java 오브젝트 마샬링

REST 프로토콜을 사용하는 가장 일반적인 방법 중 하나는 메시지 본문에 Java 빈의 내용을 전송하는 것입니다. 이 기능이 작동하려면 적절한 데이터 형식으로 Java 개체를 마샬링하는 메커니즘이 필요합니다. Java 오브젝트 인코딩에 적합한 다음 데이터 형식은 REST DSL에서 지원합니다.

JSON

JSON (JavaScript 개체 표기법)은 Java 오브젝트에 쉽게 매핑할 수 있는 경량 데이터 형식입니다. JSON 구문은 간결하고 쉽게 입력되며 사람이 읽고 쓸 수 있습니다. 이러한 모든 이유로 JSON은 REST 서비스의 메시지 형식으로 널리 사용되고 있습니다.

예를 들어 다음 JSON 코드는 속성 필드가 idname사용자 빈을 나타낼 수 있습니다.

{
    "id" : 1234,
    "name" : "Jane Doe"
}
JAXB

CryostatB (Java Architecture for XML Binding)는 Java 오브젝트에 쉽게 매핑할 수 있는 XML 기반 데이터 형식입니다. XML을 Java 객체로 마샬링하려면 사용하려는 Java 클래스에도 주석을 달아야 합니다.

예를 들어 다음 CryostatB 코드는 속성 필드 idname 이라는 두 개의 속성 필드가 있는 User VLAN을 나타낼 수 있습니다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<User>
  <Id>1234</Id>
  <Name>Jane Doe</Name>
</User>
참고

Camel 2.17.0에서 CryostatB 데이터 형식 및 유형 변환기는 Cryostat Root Cryostat 대신 ObjectFactory 를 사용하는 클래스의 XML에서 Cryostat로 변환을 지원합니다. 또한 camel 컨텍스트에는 값이 true인 CamelJaxbObjectFactory 속성이 포함되어야 합니다. 그러나 최적화로 인해 기본값은 false입니다.

4.3.2. REST DSL과 JSON 및 CryostatB 통합

물론 메시지 본문을 Java 개체로 변환하거나 직접 변환하는 데 필요한 코드를 작성할 수 있습니다. 그러나 REST DSL은 이러한 변환을 자동으로 수행할 수 있는 편의성을 제공합니다. 특히 JSON 및 CryostatB와 REST DSL을 통합하면 다음과 같은 이점이 있습니다.

  • Java 개체까지 마샬링이 자동으로 수행됩니다(적절한 구성).
  • REST DSL은 데이터 형식(JSON 또는 CryostatB)을 자동으로 감지하고 적절한 변환을 수행할 수 있습니다.
  • REST DSL은 추상화 계층 을 제공하므로 작성하는 코드는 특정 JSON 또는 CryostatB 구현에 국한되지 않습니다. 따라서 나중에 구현을 전환하여 애플리케이션 코드에 최소한의 영향을 미칠 수 있습니다.

4.3.3. 지원되는 데이터 형식 구성 요소

Apache Camel은 JSON 및 CryostatB 데이터 형식의 다양한 구현을 제공합니다. 다음 데이터 형식은 현재 REST DSL에서 지원합니다.

  • JSON

    • jackson 데이터 형식 (camel-jackson) (기본값)
    • gson 데이터 형식 (camel-gson)
    • XStream 데이터 형식(camel-xstream)
  • JAXB

    • CryostatB 데이터 형식(camel-jaxb)

4.3.4. 개체 마샬링 활성화 방법

REST DSL에서 오브젝트 마샬링을 활성화하려면 다음 사항을 관찰합니다.

  1. bindingMode 옵션을 설정하여 바인딩 모드를 활성화합니다. 바인딩 모드를 설정할 수 있는 여러 수준이 있습니다. 자세한 내용은 “바인딩 모드 구성”을 참조하십시오.
  2. type 옵션(필수)과 outType 옵션(선택 사항)을 사용하여 들어오는 메시지에서 변환할 Java 유형을 지정합니다(선택 사항).
  3. Java 오브젝트를 CryostatB 데이터 형식으로 변환하려면 적절한 CryostatB 주석으로 Java 클래스에 주석을 답니다.
  4. restConfiguration 빌더에 지정할 수 있는 jsonDataFormat 옵션 및/또는 xmlDataFormat 옵션을 사용하여 기본 데이터 형식 구현(또는 구현)을 지정합니다.
  5. 경로에서 반환 값을 제공하는 경우 일반적으로 교환 본문의 Out 메시지를 CryostatB 주석이 있는 클래스의 인스턴스로 설정해야 합니다. 그러나 XML 형식으로 직접 CryostatB 반환 값을 제공하려는 경우 dataFormatProperty 를 key, xml.out.mustBeJAXB Cryostat , false 로 설정합니다( restConfiguration 빌더에 지정할 수 있음). 예를 들어 XML DSL 구문에서 다음을 수행합니다.

    <restConfiguration ...>
      <dataFormatProperty key="xml.out.mustBeJAXBElement"
                          value="false"/>
      ...
    </restConfiguration>
  6. 프로젝트 빌드 파일에 필요한 종속 항목을 추가합니다. 예를 들어 Maven 빌드 시스템을 사용하고 Jackson 데이터 형식을 사용하는 경우 Maven POM 파일에 다음 종속성을 추가합니다.

    <?xml version="1.0" encoding="UTF-8"?>
    <project ...>
      ...
      <dependencies>
        ...
        <!-- use for json binding --> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jackson</artifactId> </dependency>
        ...
      </dependencies>
    </project>
  7. OSGi 컨테이너에 애플리케이션을 배포할 때 선택한 데이터 형식에 필요한 기능을 설치해야 합니다. 예를 들어 jackson 데이터 형식(기본값)을 사용하는 경우 다음 Karaf console 명령을 입력하여 camel-jackson 기능을 설치합니다.

    JBossFuse:karaf@root> features:install camel-jackson

    또는 Fabric 환경에 배포하는 경우 Fabric 프로필에 기능을 추가합니다. 예를 들어 프로필 MyRestProfile 을 사용하는 경우 다음 console 명령을 입력하여 기능을 추가할 수 있습니다.

    JBossFuse:karaf@root> fabric:profile-edit --features camel-jackson MyRestProfile

4.3.5. 바인딩 모드 구성

bindingMode 옵션은 기본적으로 꺼져 있으므로 Java 개체를 마샬링할 수 있도록 명시적으로 구성해야 합니다. Cryostat에는 지원되는 바인딩 모드 목록이 표시됩니다.

참고

Camel 2.16.3부터 JSon/JAXB로의 바인딩 이후 content-type 헤더에 json 또는 xml 가 포함된 경우에만 발생합니다. 이를 통해 메시지 본문을 바인딩을 사용하여 마샬링하지 않아야 하는 경우 사용자 정의 콘텐츠 유형을 지정할 수 있습니다. 예를 들어 메시지 본문이 사용자 지정 바이너리 페이로드인 경우 유용합니다.

표 4.2. REST DSL BInding 모드

바인딩 모드설명

off

바인딩이 꺼져 있습니다 (기본값)입니다.

auto

JSON 및/또는 XML에 대한 바인딩이 활성화됩니다. 이 모드에서 Camel은 들어오는 메시지의 형식에 따라 JSON 또는 XML(JAXB)을 자동으로 선택합니다. 두 종류의 데이터 형식을 모두 활성화할 필요는 없지만 JSON 구현, XML 구현 또는 둘 다 클래스 경로에 제공할 수 있습니다.

json

JSON에만 바인딩이 활성화됩니다. 클래스 경로에 JSON 구현을 제공해야 합니다 (기본적으로 Camel은 camel-jackson 구현을 활성화하려고 시도합니다).

xml

XML에만 바인딩이 활성화됩니다. 클래스 경로에 XML 구현을 제공해야 합니다 (기본적으로 Camel이 camel-jaxb 구현을 사용하려고 함).

json_xml

JSON 및 XML 모두에 바인딩이 활성화됩니다. 이 모드에서 Camel은 들어오는 메시지의 형식에 따라 JSON 또는 XML(JAXB)을 자동으로 선택합니다. 클래스 경로에 두 종류의 데이터 형식을 모두 제공해야 합니다.

Java에서 이러한 바인딩 모드 값은 다음 열거 유형의 인스턴스로 표시됩니다.

org.apache.camel.model.rest.RestBindingMode

다음과 같이 bindingMode 를 설정할 수 있는 여러 가지 수준이 있습니다.

REST DSL 구성

다음과 같이 restConfiguration 빌더에서 bindingMode 옵션을 설정할 수 있습니다.

restConfiguration().component("servlet").port(8181).bindingMode(RestBindingMode.json);
서비스 정의 기본 부분

다음과 같이 rest() 키워드( verb 절 전) 다음에 즉시 bindingMode 옵션을 설정할 수 있습니다.

rest("/user").bindingMode(RestBindingMode.json).get("/{id}").VerbClause
verb 절

다음과 같이 verb 절에서 bindingMode 옵션을 설정할 수 있습니다.

rest("/user")
    .get("/{id}").bindingMode(RestBindingMode.json).to("...");

4.3.6. 예제

서블릿 구성 요소를 REST 구현으로 사용하여 REST DSL을 사용하는 방법을 보여주는 전체 코드 예제를 보려면 Apache Camel camel-example-servlet-rest-blueprint 예제를 살펴보십시오. 이 예제는 Fuse 설치의 extras/ 하위 디렉터리에 제공되는 독립 실행형 Apache Camel 배포 apache-camel-2.21.0.fuse-760027-redhat-00001.zip 을 설치하여 찾을 수 있습니다.

독립 실행형 Apache Camel 배포를 설치한 후 다음 디렉터리에서 예제 코드를 찾을 수 있습니다.

ApacheCamelInstallDir/examples/camel-example-servlet-rest-blueprint

4.3.7. Servlet 구성 요소를 REST 구현으로 구성

camel-example-servlet-rest-blueprint 예제에서 REST DSL의 기본 구현은 Servlet 구성 요소에서 제공합니다. 서블릿 구성 요소는 예 4.1. “REST DSL을 위한 서블릿 구성 요소 구성” 에 표시된 것처럼 블루프린트 XML 파일에 구성됩니다.

예 4.1. REST DSL을 위한 서블릿 구성 요소 구성

<?xml version="1.0" encoding="UTF-8"?>
<blueprint ...>

  <!-- to setup camel servlet with OSGi HttpService -->
  <reference id="httpService" interface="org.osgi.service.http.HttpService"/>

  <bean class="org.apache.camel.component.servlet.osgi.OsgiServletRegisterer"
        init-method="register"
        destroy-method="unregister">
    <property name="alias" value="/camel-example-servlet-rest-blueprint/rest"/>
    <property name="httpService" ref="httpService"/>
    <property name="servlet" ref="camelServlet"/>
  </bean>

  <bean id="camelServlet" class="org.apache.camel.component.servlet.CamelHttpTransportServlet"/>
  ...
  <camelContext xmlns="http://camel.apache.org/schema/blueprint">

    <restConfiguration component="servlet"
                       bindingMode="json"
                       contextPath="/camel-example-servlet-rest-blueprint/rest"
                       port="8181">
      <dataFormatProperty key="prettyPrint" value="true"/>
    </restConfiguration>
    ...
  </camelContext>

</blueprint>

REST DSL을 사용하여 Servlet 구성 요소를 구성하려면 다음 세 계층으로 구성된 스택을 구성해야 합니다.

REST DSL 계층
REST DSL 계층은 component 속성을 값인 서블릿 으로 설정하여 Servlet 구성 요소와 통합되는 restConfiguration 요소로 구성됩니다.
서블릿 구성 요소 계층
Servlet 구성 요소 계층은 클래스 인스턴스인 CamelHttpTransportServlet 의 인스턴스로 구현됩니다. 여기서 example 인스턴스에 빈 ID인 camelServlet.
HTTP 컨테이너 계층

서블릿 구성 요소는 HTTP 컨테이너에 배포해야 합니다. Karaf 컨테이너는 일반적으로 포트 8181 포트에서 HTTP 요청을 수신 대기하는 기본 HTTP 컨테이너(a Cryostatty HTTP 컨테이너)로 구성됩니다. Servlet 구성 요소를 기본 Cryostatty 컨테이너에 배포하려면 다음을 수행해야 합니다.

  1. org.osgi.service.http.HttpService OSGi 서비스에 대한 OSGi 참조를 가져옵니다. 이 서비스는 OSGi의 기본 HTTP 서버에 대한 액세스를 제공하는 표준 OSGi 인터페이스입니다.
  2. 유틸리티 클래스인 OsgiServletRegisterer 인스턴스를 생성하여 HTTP 컨테이너에 Servlet 구성 요소를 등록합니다. OsgiServletRegisterer 클래스는 Servlet 구성 요소의 라이프사이클 관리를 단순화하는 유틸리티입니다. 이 클래스의 인스턴스가 생성되면 Cryostat Service OSGi 서비스에서 registerServlet 메서드를 자동으로 호출하고 인스턴스가 삭제되면 unregister 메서드를 자동으로 호출합니다.

4.3.8. 필수 종속 항목

이 예제에는 다음과 같이 REST DSL에 중요한 두 가지 종속성이 있습니다.

서블릿 구성 요소

REST DSL의 기본 구현을 제공합니다. Maven POM 파일에 다음과 같이 지정됩니다.

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-servlet</artifactId>
  <version>${camel-version}</version>
</dependency>

또한 OSGi 컨테이너에 애플리케이션 번들을 배포하기 전에 다음과 같이 서블릿 구성 요소 기능을 설치해야 합니다.

JBossFuse:karaf@root> features:install camel-servlet
jackson 데이터 형식

JSON 데이터 형식 구현을 제공합니다. Maven POM 파일에 다음과 같이 지정됩니다.

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-jackson</artifactId>
  <version>${camel-version}</version>
</dependency>

또한 OSGi 컨테이너에 애플리케이션 번들을 배포하기 전에 다음과 같이 Jackson 데이터 형식 기능을 설치해야 합니다.

JBossFuse:karaf@root> features:install camel-jackson

4.3.9. 응답을 위한 Java 유형

예제 애플리케이션은 HTTP 요청 및 응답 메시지에서 User 유형 오브젝트를 다시 전달합니다. 사용자 Java 클래스는 예 4.2. “JSON 응답을 위한 사용자 클래스” 에 표시된 대로 정의됩니다.

예 4.2. JSON 응답을 위한 사용자 클래스

// Java
package org.apache.camel.example.rest;

public class User {

    private int id;
    private String name;

    public User() {
    }

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

User 클래스는 JSON 데이터 형식에서 비교적 간단한 표현입니다. 예를 들어 JSON 형식으로 표시된 이 클래스의 일반적인 인스턴스는 다음과 같습니다.

{
    "id" : 1234,
    "name" : "Jane Doe"
}

4.3.10. JSON 바인딩이 있는 샘플 REST DSL 경로

이 예제의 REST DSL 구성 및 REST 서비스 정의는 예 4.3. “JSON 바인딩을 사용하는 REST DSL 경로” 에 표시됩니다.

예 4.3. JSON 바인딩을 사용하는 REST DSL 경로

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           ...>
  ...
  <!-- a bean for user services -->
  <bean id="userService" class="org.apache.camel.example.rest.UserService"/>

  <camelContext xmlns="http://camel.apache.org/schema/blueprint">

    <restConfiguration component="servlet"
                       bindingMode="json"
                       contextPath="/camel-example-servlet-rest-blueprint/rest"
                       port="8181">
      <dataFormatProperty key="prettyPrint" value="true"/>
    </restConfiguration>

    <!-- defines the REST services using the  base path, /user -->
    <rest path="/user" consumes="application/json" produces="application/json">
      <description>User rest service</description>

      <!-- this is a rest GET to view a user with the given id -->
      <get uri="/{id}" outType="org.apache.camel.example.rest.User">
        <description>Find user by id</description>
        <to uri="bean:userService?method=getUser(${header.id})"/>
      </get>

      <!-- this is a rest PUT to create/update a user -->
      <put type="org.apache.camel.example.rest.User">
        <description>Updates or create a user</description>
        <to uri="bean:userService?method=updateUser"/>
      </put>

      <!-- this is a rest GET to find all users -->
      <get uri="/findAll" outType="org.apache.camel.example.rest.User[]">
        <description>Find all users</description>
        <to uri="bean:userService?method=listUsers"/>
      </get>

    </rest>

  </camelContext>

</blueprint>

4.3.11. REST 작업

예 4.3. “JSON 바인딩을 사용하는 REST DSL 경로” 의 REST 서비스는 다음 REST 작업을 정의합니다.

GET /camel-example-servlet-rest-blueprint/rest/user/{id}
{id} 에서 식별한 사용자의 세부 정보를 가져옵니다. 여기서 HTTP 응답이 JSON 형식으로 반환됩니다.
PUT /camel-example-servlet-rest-blueprint/rest/user
사용자 세부 정보가 JSON 형식으로 인코딩되는 PUT 메시지의 본문에 포함된 새 사용자를 생성합니다( 사용자 오브젝트 유형과 일치).
GET /camel-example-servlet-rest-blueprint/rest/user/findAll
HTTP 응답이 사용자 배열로 반환되는 모든 사용자에 대한 세부 정보를 JSON 형식으로 가져옵니다.

4.3.12. REST 서비스를 호출할 URL

예 4.3. “JSON 바인딩을 사용하는 REST DSL 경로” 에서 REST DSL 정의를 검사하여 각 REST 작업을 호출하는 데 필요한 URL을 통합할 수 있습니다. 예를 들어 지정된 ID가 있는 사용자의 세부 정보를 반환하는 첫 번째 REST 작업을 호출하려면 URL은 다음과 같이 빌드됩니다.

http://localhost:8181
restConfiguration 에서 프로토콜은 기본적으로 http 로 설정되고 포트는 명시적으로 8181 로 설정됩니다.
/camel-example-servlet-rest-blueprint/rest
restConfiguration 요소의 contextPath 속성에 의해 지정됩니다.
/user
rest 요소의 경로 특성에 따라 지정됩니다.
/{id}
get verb 요소의 uri 속성으로 지정됩니다.

따라서 명령줄에서 다음 명령을 입력하여 curl 유틸리티를 사용하여 이 REST 작업을 호출할 수 있습니다.

curl -X GET -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user/123

마찬가지로 다음 샘플 명령을 입력하여 curl 을 사용하여 나머지 REST 작업을 호출할 수 있습니다.

curl -X GET -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user/findAll

curl -X PUT -d "{ \"id\": 666, \"name\": \"The devil\"}" -H "Accept: application/json" http://localhost:8181/camel-example-servlet-rest-blueprint/rest/user