1. 개요
Apache Camel 은 알려진 여러 엔터프라이즈 통합 패턴을 구현하는 강력한 오픈 소스 통합 프레임워크 입니다.
일반적으로 Camel을 사용하여 메시지 라우팅 작업을 할 때 지원되는 많은 플러그형 데이터 형식 중 하나를 사용하려고 합니다 . JSON이 대부분의 최신 API 및 데이터 서비스에서 널리 사용된다는 점을 감안하면 당연한 선택이 됩니다.
이 예제에서는 camel-jackson 구성 요소를 사용하여 JSON 배열 을 Java 객체 List으로 비정렬화할 수 있는 몇 가지 방법을 살펴보겠습니다 .
2. 의존성
먼저 pom.xml에 camel-jackson 의존성 을 추가해 보겠습니다 .
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jackson</artifactId>
<version>3.6.0</version>
</dependency>
그런 다음 Maven Central 에서도 사용할 수 있는 단위 테스트를 위해 특별히 낙타 테스트 의존성을 추가합니다 .
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-test</artifactId>
<version>3.6.0</version>
</dependency>
3. 과일 도메인 클래스
이 예제 전체에서 우리는 과일 도메인을 모델링 하기 위해 몇 가지 가벼운 POJO 객체를 사용할 것 입니다.
과일을 나타내는 id와 이름으로 클래스를 정의해 봅시다.
public class Fruit {
private String name;
private int id;
// standard getter and setters
}
다음으로, Fruit 객체 의 List을 담을 컨테이너를 정의할 것입니다 :
public class FruitList {
private List<Fruit> fruits;
public List<Fruit> getFruits() {
return fruits;
}
public void setFruits(List<Fruit> fruits) {
this.fruits = fruits;
}
}
다음 두 섹션에서는 과일 List을 나타내는 JSON 문자열을 이러한 도메인 클래스로 비정렬화하는 방법을 볼 것입니다. 궁극적으로 우리가 찾고 있는 것은 작업할 수 있는 List<Fruit> 유형의 변수입니다 .
4. JSON 과일 List 언마샬링
이 첫 번째 예에서는 JSON 형식을 사용하여 간단한 과일 List을 나타낼 것입니다.
{
"fruits": [
{
"id": 100,
"name": "Banana"
},
{
"id": 101,
"name": "Apple"
}
]
}
무엇보다도 이 JSON이 우리의 배열을 포함하는 과일 이라는 속성을 포함하는 객체를 나타낸다는 점을 강조해야 합니다 .
이제 역직렬화를 수행하기 위해 Apache Camel 경로 를 설정해 보겠습니다 .
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:jsonInput")
.unmarshal(new JacksonDataFormat(FruitList.class))
.to("mock:marshalledObject");
}
};
}
이 예에서는 이름이 jsonInput 인 직접 엔드포인트를 사용합니다 . 다음으로 지정된 데이터 형식을 사용하여 Camel 교환에서 메시지 본문을 비정렬화하는 비 정렬화 메서드를 호출 합니다.
우리는 사용자 정의 비정렬 유형의 FruitList 와 함께 JacksonDataFormat 클래스를 사용하고 있습니다. 이것은 본질적으로 Jackon ObjectMapper를 둘러싼 간단한 래퍼 이며 JSON과 마샬링할 수 있습니다.
마지막으로 unmarshal 메서드 의 결과를 marshalledObject 라는 모의 끝점 으로 보냅니다 . 앞으로 살펴보겠지만 이것이 올바르게 작동하는지 확인하기 위해 경로를 테스트하는 방법입니다.
이를 염두에 두고 첫 번째 단위 테스트를 작성해 보겠습니다.
public class FruitListJacksonUnmarshalUnitTest extends CamelTestSupport {
@Test
public void givenJsonFruitList_whenUnmarshalled_thenSuccess() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:marshalledObject");
mock.expectedMessageCount(1);
mock.message(0).body().isInstanceOf(FruitList.class);
String json = readJsonFromFile("/json/fruit-list.json");
template.sendBody("direct:jsonInput", json);
assertMockEndpointsSatisfied();
FruitList fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(FruitList.class);
assertNotNull("Fruit lists should not be null", fruitList);
List<Fruit> fruits = fruitList.getFruits();
assertEquals("There should be two fruits", 2, fruits.size());
Fruit fruit = fruits.get(0);
assertEquals("Fruit name", "Banana", fruit.getName());
assertEquals("Fruit id", 100, fruit.getId());
fruit = fruits.get(1);
assertEquals("Fruit name", "Apple", fruit.getName());
assertEquals("Fruit id", 101, fruit.getId());
}
}
진행 상황을 이해하기 위해 테스트의 주요 부분을 살펴보겠습니다.
- 먼저 유용한 테스트 유틸리티 기본 클래스인 CamelTestSupport 클래스 를 확장하여 시작합니다.
- 그런 다음 테스트 기대치를 설정합니다. 우리의 모의 변수는 하나의 메시지를 가지고 있어야하고, 메시지 유형은해야 FruitList
- 이제 우리는이 돼있어로 JSON 입력 파일을 보낼 준비가 문자열 받는 직접 우리가 이전에 정의 된 엔드 포인트
- 모의 기대치가 충족되었는지 확인한 후 자유롭게 FruitList 를 검색 하고 내용이 예상대로인지 확인합니다.
이 테스트는 경로가 제대로 작동하고 JSON이 예상대로 비정렬화되고 있는지 확인합니다. 엄청난!
5. JSON 과일 배열의 비정렬화
반면에 우리는 과일 객체를 담기 위해 컨테이너 객체를 사용하는 것을 피하고 싶습니다 . 과일 배열을 직접 보유하도록 JSON을 수정할 수 있습니다.
[
{
"id": 100,
"name": "Banana"
},
{
"id": 101,
"name": "Apple"
}
]
이번에는 경로가 거의 동일하지만 특별히 JSON 배열과 함께 작동하도록 설정했습니다.
@Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from("direct:jsonInput")
.unmarshal(new ListJacksonDataFormat(Fruit.class))
.to("mock:marshalledObject");
}
};
}
보시다시피, 이전 예제와 유일한 차이점 은 사용자 지정 비정렬 유형 과일 과 함께 ListJacksonDataFormat 클래스를 사용하고 있다는 것 입니다. 이것은 List 작업을 위해 직접 준비된 Jackson 데이터 형식 유형 입니다.
마찬가지로, 우리의 단위 테스트는 매우 유사합니다.
@Test
public void givenJsonFruitArray_whenUnmarshalled_thenSuccess() throws Exception {
MockEndpoint mock = getMockEndpoint("mock:marshalledObject");
mock.expectedMessageCount(1);
mock.message(0).body().isInstanceOf(List.class);
String json = readJsonFromFile("/json/fruit-array.json");
template.sendBody("direct:jsonInput", json);
assertMockEndpointsSatisfied();
@SuppressWarnings("unchecked")
List<Fruit> fruitList = mock.getReceivedExchanges().get(0).getIn().getBody(List.class);
assertNotNull("Fruit lists should not be null", fruitList);
// more standard assertions
}
그러나 이전 섹션에서 본 테스트와 관련하여 두 가지 미묘한 차이점이 있습니다.
- 먼저 List.class 가 있는 본문을 직접 포함하도록 모의 기대치를 설정합니다.
- 메시지 본문을 List.class 로 검색하면 유형 안전성에 대한 표준 경고가 표시됩니다. 따라서 @SuppressWarnings("unchecked")를 사용합니다.
6. 결론
이 짧은 기사에서 우리는 낙타 메시지 라우팅과 낙타-잭슨 구성 요소를 사용하여 JSON 배열을 비정렬화하는 두 가지 간단한 접근 방식을 보았습니다 .