0

New Tag request: java-ee-8

It's got a new feature, called jsonb. With jsonb, I cannot get nested serialization working. See bold printed below.

So, I wrote a jaxrs-application. This application's got a messagebodywriter using jsonb:

final JsonbConfig defaultConfig = new JsonbConfig()
        .withFormatting(Boolean.TRUE)
        .withNullValues(Boolean.TRUE)
        .withSerializers(
            new QueryParamEntrySerializer(),
            new ApiResponseDtoSerializer())
        .withAdapters(new ResponseStatusJsonbAdapter());
    final Jsonb jsonb = JsonbBuilder.create(defaultConfig);

ApiResponseDto is like following:

@Value.Immutable
@JsonbTypeSerializer(ApiResponseDtoSerializer.class)
public interface ApiResponseDto {

  ResponseStatus status();

  String message();

  Optional<? extends Object> data();
}

ResponseStatus is an enumm and gets serialized via the above TypeAdapter just fine. For this class I wrote the ApiResponseDtoSerializer.

@Provider
public class ApiResponseDtoSerializer implements JsonbSerializer<ImmutableApiResponseDto> {

  @Override
  public void serialize(
      final ImmutableApiResponseDto obj,
      final JsonGenerator generator,
      final SerializationContext ctx) {
    generator.writeStartObject();
    ctx.serialize("status", obj.status(), generator);
    ctx.serialize("data", obj.data(), generator);
    ctx.serialize("message", obj.message(), generator);
    generator.writeEnd();
  }

}

Now the Optional data() shall contain an ImmutableSet of QueryParamEntry like this:

@Value.Immutable
@JsonbTypeSerializer(ImmutableQueryParamEntrySerializer.class)
public interface QueryParamEntry {
  @Value.Parameter
  String key();

  @Value.Parameter
  Optional<String> value();
}

The type adapter is this one:

@Provider
public class ImmutableQueryParamEntrySerializer implements JsonbSerializer<ImmutableQueryParamEntry> {

  private static final Logger LOG = LoggerFactory.getLogger(ImmutableQueryParamEntrySerializer.class);

  @Override
  public void serialize(
      final ImmutableQueryParamEntry obj,
      final JsonGenerator generator,
      final SerializationContext ctx) {
    generator.writeStartObject();
    LOG.debug("Writing: key = [{}].", obj.key());
    ctx.serialize("key", obj.key(), generator);
    ctx.serialize("value", obj.value(), generator);
    generator.writeEnd();
  }

}

The final output is:

{
    "status": "success",
    "data": [
        {
            "key": null,
            "value": null
        }
    ],
    "message": "Returning query param values."
}

As you can see, the nested serialization did not work. Jsonb seems to find the correct type (because otherwise it wouldn't serialize an object at all). But even the log statement from my SerializerClass is never called.

Btw: You need Guava 22 and immutables.github.io to compile this code, and slf4j obviously:

   <dependency>
      <groupId>org.jboss.resteasy</groupId>
      <artifactId>jaxrs-api</artifactId>
      <version>3.0.2.Final</version>
      <scope>provided</scope>
    </dependency>

    <!-- JSON-P API -->
    <dependency>
      <groupId>javax.json</groupId>
      <artifactId>javax.json-api</artifactId>
      <version>1.1</version>
      <scope>provided</scope>
    </dependency>

    <!-- https://mvnrepository.com/artifact/javax.json.bind/javax.json.bind-api -->
    <dependency>
      <groupId>javax.json.bind</groupId>
      <artifactId>javax.json.bind-api</artifactId>
      <version>1.0</version>
      <scope>provided</scope>
    </dependency>

    <dependency>
      <groupId>org.immutables</groupId>
      <artifactId>value</artifactId>
    </dependency>

    <dependency>
      <groupId>com.google.guava</groupId>
      <artifactId>guava</artifactId>
    </dependency>
Benjamin Marwell
  • 1,173
  • 1
  • 13
  • 36
  • 1
    Re your request for a new tag **java-ee-8**, it is there now. – skomisa Apr 30 '18 at 17:45
  • Also, what are you using for the the serialization? (i.e. What code is implementing SerializationContext?) – skomisa Apr 30 '18 at 17:48
  • @skomisa i was using the implementation which ships with openliberty. – Benjamin Marwell Apr 30 '18 at 20:37
  • OK, thanks. I might try that since [I am also having deserialization problems](https://github.com/eclipse-ee4j/yasson/issues/118), but I am using Yasson. – skomisa Apr 30 '18 at 21:10
  • FYI OpenLiberty ships Yasson as its JSON-B implementation, so I would expect behavior to be the same whether you are running in OpenLiberty or directly using Yasson. AFAIK the immutables lib generates some classes automatically, and I don't think that has been tested well with JSON-B/Yasson. If you could include the generated classes that would be helpful to determine the problem. – Andy Guibert Dec 11 '18 at 18:58
  • I created this issue: https://github.com/eclipse-ee4j/yasson/issues/164 – Benjamin Marwell Dec 12 '18 at 06:20

1 Answers1

0

So here is what it takes to make it work.

I got rid of the custom Serializers. As mentioned in my comment, they are broken before the unreleased version 1.0.3 anyway.

Instead, rename your methods to getStatus(), getMessage() and getData() (notice the get-Prefix). For getData();, return just an Optional<Object>, not Optional<? extends Object>. Otherwise, immutables will refuse the special treatment of Optional.

After that, all just worked nicely.

Benjamin Marwell
  • 1,173
  • 1
  • 13
  • 36