Open abhupadh opened 1 month ago
This expected json for extension was working fine with CloudEvent 1.0 , and ExtensionFormat
/ InMemoryFormat
marshaling / unmarshaling feature.
+1
+1
In the CloudEvents spec, the type system for metadata https://github.com/cloudevents/spec/blob/main/cloudevents/spec.md#type-system describes the type "String" but what you expect is a JSON value ?
"recipient":{"userid":"9CE048DB5E8F485XXXXXXXXX@AdobeOrg"}
Also please, add the full steps to reproduce the issue that I can and paste
Thanks @pierDipi for responding. Yes, that is the correct expectation (receiving a json value). Below is the code and steps to reproduce the issues while trying both the ways of setting an extension to a CloudEvent
------- Issue 1 ---------
Recipient
object
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Recipient {
@JsonProperty("userid")
private final String userid;
@JsonProperty("clientid")
private final String clientid;
public Recipient(String userid) {
this.userid = userid;
this.clientid = null;
}
@JsonCreator
public Recipient(
@JsonProperty("userid") String userid, @JsonProperty("clientid") String clientid) {
this.userid = userid;
this.clientid = clientid;
}
// ------------------------------------------------------------------------------------------------
// Accessors
// ------------------------------------------------------------------------------------------------
public String getUserid() {
return userid;
}
public String getClientid() {
return clientid;
}
// ------------------------------------------------------------------------------------------------
@Override
public String toString() {
return "Recipient{" + "userid='" + userid + '\'' + ", clientid='" + clientid + '\'' + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Recipient recipient = (Recipient) o;
return Objects.equals(userid, recipient.userid) && Objects.equals(clientid, recipient.clientid);
}
@Override
public int hashCode() {
return Objects.hash(userid, clientid);
}
}
Creating a custom extension RecipientExtension
using the Recipient
object
public class RecipientExtension implements CloudEventExtension {
public static final String RECIPIENT_KEY_EXTENSION_NAME = "recipient";
private static final Set<String> KEY_SET = Set.of(RECIPIENT_KEY_EXTENSION_NAME);
private Recipient recipient;
public RecipientExtension(String userId, String clientId) throws IOException {
this.recipient = new Recipient(userId, clientId);
}
public Recipient getRecipient() {
return recipient;
}
@Override
public void readFrom(CloudEventExtensions cloudEventExtensions) {
Object tp = cloudEventExtensions.getExtension(RECIPIENT_KEY_EXTENSION_NAME);
if (tp != null) {
this.recipient = tp instanceof Recipient ? (Recipient) tp : null;
}
}
@Override
public Object getValue(String key) throws IllegalArgumentException {
switch (key) {
case RECIPIENT_KEY_EXTENSION_NAME:
return this.recipient;
default:
throw ExtensionUtils.generateInvalidKeyException(this.getClass(), key);
}
}
@Override
public Set<String> getKeys() {
return KEY_SET;
}
@Override
public String toString() {
return "RecipientExtension{" + "recipient=" + recipient + '}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RecipientExtension that = (RecipientExtension) o;
return Objects.equals(recipient, that.recipient);
}
@Override
public int hashCode() {
return Objects.hash(recipient);
}
}
Create the CloudEvent object using CloudEventBuilder.v1()
private static CloudEvent getCloudEvent()
throws JsonProcessingException {
return CloudEventBuilder.v1()
.withSource(URI.create("some_source"))
.withType("some_event_type")
.withId("some_id")
.withDataContentType("application/json")
.withData(JsonCloudEventData.wrap(convertToJsonNode("some_data")))
.withDataSchema(URI.create("some_schema"))
.withExtension("requestidext", "some_request_id")
.withExtension(new RecipientExtension(userId, null))
.build();
}
Now serialize the CloudEventV1
object
public static final SimpleModule simpleModule =
getCloudEventJacksonModule(JsonFormatOptions.builder().build());
private static final ObjectMapper OBJECT_MAPPER =
JsonMapper.builder()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.serializationInclusion(Include.NON_NULL)
.addModule(
simpleModule)
.build();
public static String serialize(final CloudEvent object) throws JsonProcessingException {
Preconditions.checkNotNull(object, THE_OBJECT_INSTANCE_CAN_NOT_BE_NULL);
return OBJECT_MAPPER.writeValueAsString(object);
}
the above serialization will fail with JsonMappingException
with the underlying stacktrace showing failing at the readContext of CloudEventSerializer
-------- Issue 2 --------
Instead of using the custom extension object, if we use the serialized string of it using
withExtension(String key, String value)
we are not getting the json representation of it
var recipientExt = new RecipientExtension(userId, clientId);
get the Recipient
object using the recipientExt.getRecipient() and set as extension while constructing CloudEvent
with its serialized version
.withExtension("recipient", serialize(recipientExt.getRecipient()));
Hi @pierDipi, is there any update on this? We are blocked with our java17 upgrade due to this.
creating a custom extension object implementing
CloudEventExtension
, when using the extension (customExt
) as below, and then serializing the CloudEvent, the serialization for the CloudEvent is failing with JsonMappingException.here is how the extension looks like. The
customExt
is theRecipient
objectAlso, if using the other supported methods
withExtension
(with key, value) as below, I had to send the string version of the customExt, and then if serialized the output is not in the expected format (see below). It can break our customers event integrations. Kindly suggest.expected serialized CloudEvent custom extension
actual serialized CloudEvent custom extension
The serialization is failing while reading extensions here, as I believe the
Object
typevalue
is not supported.