Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Deserialization of event without data produces null. #540

Open
alexec opened this issue Mar 23, 2023 · 5 comments
Open

Bug: Deserialization of event without data produces null. #540

alexec opened this issue Mar 23, 2023 · 5 comments

Comments

@alexec
Copy link
Contributor

alexec commented Mar 23, 2023

If you serialize an event that does not have a data field using CloudEventSerializer using default setting, and then try to deserialize using CloudEventDeserializer you get a null value.

This is a bug surely.

@alexec alexec changed the title Deserialization of event without data produces null. Bug: Deserialization of event without data produces null. Mar 23, 2023
@alexec
Copy link
Contributor Author

alexec commented Mar 23, 2023

Work-around:

.withData("text/plain", "".getBytes(StandardCharsets.UTF_8))

@skepticoitusInteruptus
Copy link
Contributor

...This is a bug surely....

Not according to that class' contract [emphasis mine]:

——

deserialize

T deserialize(String topic, byte[] data)

Deserialize a record value from a byte array into a value or object.

Parameters:

topic - topic associated with the data

data - serialized bytes; may be null; implementations are recommended to handle null by returning a value or null rather than throwing an exception.

Returns:

deserialized typed data; may be null

——

@alexec
Copy link
Contributor Author

alexec commented Mar 24, 2023

The Kafka contract does not apply here. The bug is simply that no CloudEvent is returned, even though the record clearly contains a CloudEvent.

If this was not the case, I could not work-around the bug by putting some dummy data into the event.

I believe it is likely to do with the code that auto-detects whether binary or structured deserialization was used.

@alexec
Copy link
Contributor Author

alexec commented Mar 24, 2023

Example of record that fail:

ProducerRecord(topic=api-logs-local, partition=null, headers=RecordHeaders(headers = [], isReadOnly = false), key=urn:assetalias:External.asset.alias:prd, value=CloudEvent{id='7e139926-6b86-4cf3-9e77-aa11ba2e1f78', source=xxx.asset.alias, type='http_transaction.created.v1', time=2023-03-24T08:03:14.957447-07:00, extensions={endpoint=https://foo.api.xxx.com/v1/bar/{id}, method=GET, requestid=b5d1ad97-9da6-4134-81f5-eca830a72185, clientip=196.128.0.1, useragent=curl, status=200}}, timestamp=null)

@skepticoitusInteruptus
Copy link
Contributor

…The bug is simply that no CloudEvent is returned, even though the record clearly contains a CloudEvent…

That IS interesting. For sure, @alexec.

Especially given this precondition…

If you serialize an event that does not have a data field

Let me ask you this…

  1. How closely does the following reproduce what you've described in your original report?
  2. Is my understanding correct that you would expect the assertions at 3, 4 and 5 in the code below to all fail?
import io.cloudevents.CloudEvent;
import io.cloudevents.core.message.Encoding;
import io.cloudevents.core.message.MessageReader;
import io.cloudevents.core.test.Data;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

public class CloudEventIssue540ReproducerTest {

   private final CloudEvent eventHasNoDataField = CloudEventBuilder.v1()
        .withId(…)
        .withType(…)
        .withSource(…)
        .withoutData() // (0) An event that does not have a data field
        .withSubject(…)
        .build();

    @Test
    public void ceIssue540DeserializerShouldWork() {
        String topic = "test";
        CloudEventMessageDeserializer deserializer = new CloudEventMessageDeserializer();

        ProducerRecord<Void, byte[]> inRecord = KafkaMessageFactory.createWriter(topic)
            .writeBinary(eventHasNoDataField); // (1) "…serialize an event that does not have a data field…" — @alexec 
        MessageReader outMessage = deserializer
            .deserialize(topic, inRecord.headers(), inRecord.value()); // (2) "…then try to deserialize…" — @alexec 
        assertThat(eventHasNoDataField.getData())
            .isNotNull(); // (3) "…you get a null value…" — @alexec 
        assertThat(outMessage.toEvent())
            .isNotNull(); // (4) "…no CloudEvent is returned…" — @alexec
        assertThat(outMessage.toEvent())
            .isEqualTo(eventHasNoDataField );
        assertThat(outMessage.toEvent().getData())
            .isNotNull(); // (5) "…you get a null value…" — @alexec 
    }
}

TIA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants