ジャクソンを使用してラクダのルートでJSONとの間でPOJOをシリアル化および逆シリアル化しようとしています。これらの一部にはJava 8 LocalDateフィールドがあり、整数の配列としてではなく、YYYY-MM-DD文字列としてシリアル化する必要があります。
Spring BootアプリケーションではJava構成のみを使用するため、XML Camel構成は使用しません。
これを依存関係に追加することで、システムの他の部分で使用されている、私が望むことを実行するObjectMapperを正常に作成しました。
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
これをアプリケーション構成に追加します。
@Bean
public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
return builder
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
}
発信の例REST route:
@Component
public class MyRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
restConfiguration().component("servlet").contextPath("/mycontext")
.port(8080).bindingMode(RestBindingMode.json);
rest("/myendpoint)
.get()
.route()
.to("bean:myService?method=myMethod()");
}
}
受信メッセージルートの例:
@Component
public class MyRouteBuilder extends RouteBuilder {
@Autowired
private MyBean myBean;
@Override
public void configure() {
from(uri)
.unmarshal().json(JsonLibrary.Jackson)
.bean(myBean);
}
}
ただし、デフォルトでは、Camelは独自のObjectMapperインスタンスを作成するため、Jackson2ObjectMapperBuilder
が自動的に追加するJSR310シリアライザー/デシリアライザー、または無効なWRITE_DATES_AS_TIMESTAMPS
機能のいずれも取得しません。 Camel JSON のドキュメントを読みましたが、Spring構成を使用してカスタムDataFormatを追加する方法や、すべてのタイプにグローバルカスタマイズを適用する方法は示されていません。
では、Spring Boot Java configurationのみを使用して、ObjectMapperを使用するようにCamelに指示するにはどうすればよいですか?
ラクダのコードをステップスルーして解決策を見つけました。したがって、私が望んでいることは行いますが、ドキュメント化されておらず、サポートされていない可能性があるため、将来のバージョンのCamelでは動作しない可能性があります。
私がしているのは、質問のObjectMapper
Beanに加えて、Spring構成に次のBeanを追加することだけです。
@Bean(name = "json-jackson")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public JacksonDataFormat jacksonDataFormat(ObjectMapper objectMapper) {
return new JacksonDataFormat(objectMapper, HashMap.class);
}
注意すべき重要な点:
JacksonDataFormat
を取るObjectMapper
のコンストラクターはありません。ただし、デフォルトのコンストラクターでは、非整列化型が指定されていないときにHashMap.class
が使用されるため、それを使用します。いくつかの魔法によって、これはすべてのPOJOタイプの非整列化に慣れるように見えます。他のクラスのより具体的なデータ形式も必要な場合は、それらにもObjectMapper
を設定する必要があります。DataFormat
の新しいインスタンスを取得することを期待しているため、BeanのスコープをSCOPE_PROTOTYPE
に設定する必要があります。詳細は CAMEL-788 を参照してください) =。JavaコードでJacksonDataFormat
を作成し、必要な機能を有効/無効にして、キャメルルートでそのインスタンスを使用します。
.unmarshal(myInstanceGoesHere).
ObjectMapper for Camelをorg.Apache.camel:camel-jackson-starter:2.20.0
これは、Springアプリケーションのプロパティを介した構成に役立つObjectMapperプロパティの一部を公開します。たとえば、WRITE_DATES_AS_TIMESTAMPSは、application.yamlまたはapplication.propertiesファイルから直接設定できます。
詳細については、JacksonDataFormatConfigurationクラスを探してください。
また、いくつかのMixinを使用する必要があったため、SpringのObjectMapperを使用するようにCamelを構成する必要がありました。私はこれで終わりました:
構成Bean:
@Bean
public Jackson2ObjectMapperBuilderCustomizer customizer() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder builder) {
builder.mixIn(Person.class, PersonMixin.class);
}
}
}
application.yaml:
camel:
dataformat:
json-jackson:
disable-features: WRITE_DATES_AS_TIMESTAMPS
object-mapper: jacksonObjectMapper
ここで、jacksonObjectMapper
は、構成されたJackson2ObjectMapperBuilderによって構築されたObjectMapper Beanの名前です。
SpringとCamel 2.18.1を使用して、次の依存関係を追加することで同じことを実現できました。
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.6.1</version>
</dependency>
CamelContextConfiguration
クラスでは、クラスパスモジュールの検出とシリアル化オプションの構成を構成するためにJacksonDataFormat
を自動配線します。
@Configuration
public class CamelContextConfig implements CamelContextConfiguration {
@Autowired
public JacksonDataFormat jacksonDataFormat;
@Override
public void beforeApplicationStart(CamelContext camelContext) {
}
@Override
public void afterApplicationStart(CamelContext camelContext) {
jacksonDataFormat
.getObjectMapper()
.findAndRegisterModules()
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
}
これまでのところ、@ david-edwardsの提案のみが機能しました。最初に、「json-jackson」というIDのデータ形式Beanを定義しました
<bean id="json-jackson" class="com.mydomain.JacksonDataFormatExt" />
次に、フォーマットクラス:
public class JacksonDataFormatExt extends JacksonDataFormat{
public JacksonDataFormatExt(){
super();
setPrettyPrint(true);
setEnableFeatures(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS.name());
SimpleModule s = new SimpleModule();
s.addSerializer(CustomEnum.class, new CustomEnumSerializer());
addModule(s);
}
}
そして、CustomEnumSerializerクラス:
public class CustomEnumSerializer extends JsonSerializer<CustomEnum> {
@Override
public void serialize(CustomEnumvalue, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
String stringValue = value.getNlsText();
if(stringValue != null && !stringValue.isEmpty() && !stringValue.equals("null")) {
jgen.writeString(stringValue);
} else {
jgen.writeNull();
}
}
}
他の誰かが修正を使用する方法を疑問に思っている場合は、ver。 2.17 ..このxml設定を使用して動作させました:
<camel:camelContext id="defaultCamelContext">
.....
<camel:dataFormats>
<camel:json id="json" library="Jackson" objectMapper="myObjectMapper"/>
</camel:dataFormats>
</camel:camelContext>
..ここで、myObjectMapperは、ObjectMapperタイプのSpring Beanの名前です。
どの例も機能しませんでした。これが回避策を読むことからかなり複雑であることに少しがっかりした。
私の意見では、キャメルはアプリケーションに付属しているものと同じジャクソンBeanを使用して、Springのデフォルトのオブジェクトマッパーを簡単に使用できるようにする必要があります。
私は.json()
の使用を忘れて、プロセッサと交換しました。
次のように、これはSpringが提供するobjectMapperを使用しました。
ルート
from(CONSUME_TAG)
.process("jsonProcessor")
.to("direct:anotherRoute")
.end();
Generic ProcessorこのAutowireがどのようにSpring Boot ObjectMapper Beanに接続するかに注意してください。
@Component
public class JsonProcessor implements Processor {
@Autowired
ObjectMapper objectMapper;
@Override
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody(objectMapper.writeValueAsString(exchange.getIn().getBody()));
}
}
Camelで問題が発生した場合は、直接Beanを使用するように戻します。
マーシャリングとアンマーシャリングを実行し、事前構成されたObjectMapperを自動配線できる小さなJsonユーティリティを作成するだけです。
ハーネスキャメルは、ユーティリティを呼び出してルート内のメッセージを変換するための素晴らしいSpring Bean統合です。例:
from(uri)
.unmarshal().json(JsonLibrary.Jackson)
.beanRef("jsonUtil", "unmarshal")
.bean(myBean);
ジャクソン依存関係をpomに含めることで解決しました
<dependency>
<groupId>org.Apache.camel</groupId>
<artifactId>camel-jackson-starter</artifactId>
<version>${camel.version}</version>
</dependency>
次に、ルート構成にJacksonDataFormatを追加するだけです
public void configure() throws Exception {
JacksonDataFormat jsonDf = new JacksonDataFormat(Card.class);
jsonDf.setPrettyPrint(true);
from("direct:endpoint")
.marshal(jsonDf)
.convertBodyTo(String.class)
.....
}