1

I'm trying a custom serialiser for Order objects in Jakarta EE. The problem is that it works properly on one machine, while the other complains about incomplete JSON. It's the exact same code pulled from our Github, including pom.xml, server.xml, and other files that handle dependencies. The only difference is that one machine uses Maven 3.6.0, while the other has Maven 3.6.3. The order being serialised is also exactly the same.

The API function being called:

    @Path("/{id}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response getOrder(@PathParam("id") long id) {
        Order o = orderManager.find(id);

        if (o == null) {
            return Response.status(Response.Status.NOT_FOUND).entity("Order not found.").build();
        }

        return Response.ok(o).build();
    }

The custom serialiser:

public class OrderSerializer implements JsonbSerializer<Order> {
    @Override
    public void serialize(Order order, JsonGenerator jsonGenerator, SerializationContext serializationContext) {
        jsonGenerator.writeStartObject();
        jsonGenerator.write("id", order.getId());
        jsonGenerator.write("dateCreated", order.getDateCreated().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        jsonGenerator.write("total", order.getTotalPrice());
        jsonGenerator.write("deliveryAddress", order.getDeliveryAddress());

        if (order.getCustomer() != null) {
            jsonGenerator.writeStartObject("customer");
            jsonGenerator.write("id", order.getCustomer().getId());
            jsonGenerator.write("name", order.getCustomer().getName());
            jsonGenerator.write("email", order.getCustomer().getEmail());
            jsonGenerator.write("telephone", order.getCustomer().getTelephone());
            jsonGenerator.write("billingAddress", order.getCustomer().getBillingAddress());
            jsonGenerator.writeEnd();
        }

        if (order.getNote() != null) {
            jsonGenerator.write("note", order.getNote());
        }
        jsonGenerator.write("status", order.getStatus().toString());

        jsonGenerator.writeStartArray("products");
        for (ProductInOrder pio : order.getProducts()) {
            jsonGenerator.writeStartObject();
            jsonGenerator.write("id", pio.getProduct().getId());
            jsonGenerator.write("name", pio.getProduct().getName());
            jsonGenerator.write("amount", pio.getAmount());
            jsonGenerator.writeEnd();
        }
        jsonGenerator.writeEnd();

        if (order.getPlan() != null) {
            jsonGenerator.writeStartObject("plan");
            jsonGenerator.write("id", order.getPlan().getId());
            jsonGenerator.write("date", order.getPlan().getDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
            jsonGenerator.write("difficulty", order.getPlan().getDifficulty());
            jsonGenerator.write("completed", order.getPlan().isCompleted());
            jsonGenerator.writeEnd();
        }

        if (order.getDelivery() != null) {
            jsonGenerator.writeStartObject("delivery");
            jsonGenerator.write("id", order.getDelivery().getId());
            jsonGenerator.write("date", order.getDelivery().getDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
            if (order.getDelivery().getDeliveredOn() != null) {
                jsonGenerator.write("deliveredOn", order.getDelivery().getDeliveredOn().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            }
            if (order.getDelivery().getDriver() != null) {
                jsonGenerator.writeStartObject("driver");
                jsonGenerator.write("id", order.getDelivery().getDriver().getId());
                jsonGenerator.write("name", order.getDelivery().getDriver().getName());
                jsonGenerator.write("email", order.getDelivery().getDriver().getEmail());
                jsonGenerator.writeEnd();
            }
            jsonGenerator.writeEnd();
        }


        jsonGenerator.writeEnd();

    }

}

The error being thrown by our Open Liberty server:

[ERROR   ] Generating incomplete JSON
[INFO] [WARNING ] CWPMI2006W: The MicroProfile Metrics exception mapper detected and is handling an unhandled exception from the RESTful web service application. 
[INFO]                                                                                                                jakarta.json.bind.JsonbException: Internal error: null
[INFO]     at org.eclipse.yasson.internal.SerializationContextImpl.marshall(SerializationContextImpl.java:137)
[INFO]     at [internal classes]
[INFO]     at com.ourproject.rest.OrderAPI.getOrder(OrderAPI.java:62)
[INFO]     at com.ourproject.rest.OrderAPI$Proxy$_$$_WeldSubclass.getOrder(Unknown Source)
[INFO]     at jdk.internal.reflect.GeneratedMethodAccessor1515.invoke(Unknown Source)
[INFO]     at java.base/java.lang.reflect.Method.invoke(Method.java:566)
[INFO]     at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
[INFO]     at [internal classes]
[INFO] Caused by: java.lang.NullPointerException
[INFO]     at org.eclipse.parsson.JsonGeneratorImpl.writeEscapedString(JsonGeneratorImpl.java:539)
[INFO]     at [internal classes]
[INFO]     at com.ourproject.serialisation.OrderSerializer.serialize(OrderSerializer.java:25)
[INFO]     at com.ourproject.serialisation.OrderSerializer.serialize(OrderSerializer.java:11)
[INFO]     at org.eclipse.yasson.internal.serializer.UserDefinedSerializer.serialize(UserDefinedSerializer.java:35)
stitch123
  • 197
  • 9
  • Are the Java versions exactly the same on each machine too? – Scott Kurz Apr 29 '23 at 13:51
  • I just checked and yes, 11.0.18 on both machines. – stitch123 Apr 29 '23 at 13:55
  • 1
    Which line is line #25 from the stack trace `at com.ourproject.serialisation.OrderSerializer.serialize(OrderSerializer.java:25)` ? Noticing that if order.getPlan().getDate() is `null` it looks like you'd hit an NPE. – Scott Kurz Apr 29 '23 at 14:31
  • It wasn't about the plan attribute, it was the telephone attribute, which prompted me to check the Customer object the Order was associated with (didn't think of that for some reason). I was sending semanticaly incorrect Customer JSON on the other machine, which resulted in customer's telephone field being NULL and the NPE when my serialiser tried to access this field. Thanks a lot! If you want, you can write an answer to this thread telling me to check line 25 in OrderSerializer.java, I'll accept it as correct. – stitch123 Apr 29 '23 at 15:05
  • 1
    Thanks for the offer. It seems like the answer might be real specific to the details of your data types so maybe we can just leave it at that. Glad to help though. – Scott Kurz Apr 29 '23 at 15:25

1 Answers1

1

The issue was implementation specific, I noticed my Customer JSON was wrong on one of the machines. The Customer then got assigned to the Order, and the serialiser tried to access the Customer's phone number which was NULL because of an error on my part. Thanks to Scott Kurz for pointing me in the right direction.

stitch123
  • 197
  • 9