Custom Object Mapper

Pulsar uses an internal shaded Jackson ObjectMapper when de/serializing JSON messages. If you instead want to provide your own Jackson 2 object mapper instance, you can register a SchemaResolverCustomizer and set your mapper on the DefaultSchemaResolver as follows:spring-doc.cn

@Bean
SchemaResolverCustomizer<DefaultSchemaResolver> schemaResolverCustomizer() {
    return (DefaultSchemaResolver schemaResolver) -> {
        var myObjectMapper = obtainMyObjectMapper();
        schemaResolver.setObjectMapper(myObjectMapper);
    };
}
The object mapper in the example above should be an instance of com.fasterxml.jackson.databind.ObjectMapper, not the shaded org.apache.pulsar.shade.com.fasterxml.jackson.databind.ObjectMapper.

This results in your object mapper being used to de/serialize all JSON messages that go through the schema resolution process (i.e. in cases where you do not pass a schema in directly when producing/consuming messages).spring-doc.cn

Under the hood, the resolver creates a special JSON schema which leverages the custom mapper and is used as the schema for all resolved JSON messages.spring-doc.cn

If you need to pass schema instances directly you can use the JSONSchemaUtil to create schemas that respect the custom mapper. The following example shows how to do this when sending a message with the PulsarTemplate variant that takes a schema parameter:spring-doc.cn

void sendMessage(PulsarTemplate<MyPojo> template, MyPojo toSend) {
    var myObjectMapper = obtainMyObjectMapper();
    var schema = JSONSchemaUtil.schemaForTypeWithObjectMapper(MyPojo.class, myObjectMapper);
    template.send(toSend, schema);
}

Pulsar configures its default object mapper in a particular way. Unless you have a specific reason to not do so, it is highly recommended that you configure your mapper with these same options as follows:spring-doc.cn

myObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
myObjectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, false);
myObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
A later version of the framework may instead provide a customizer that operates on the default mapper rather than requiring a separate instance.

Jackson 2 / Jackson 3

In Spring Boot 4 the default version of Jackson is 3 and is auto-configured via the spring-boot-starter-json module. However, Spring for Apache Pulsar expects a Jackson 2 custom mapper.spring-doc.cn

If you are using Jackson 3 in your Spring Boot 4 application and want to use a custom mapper you will need to add Jackson 2 to the classpath. Don’t worry, Spring Boot 4 allows Jackson 2 and 3 to co-exist in an application.spring-doc.cn

A later version of the framework may support using a Jackson 2 or Jackson 3 custom mapper.