OutputBinding not compatible with com.azure.core.models.CloudEvent
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
Research direction
Start with src/main/java/com/microsoft/azure/functions/worker/binding/RpcUnspecifiedDataTarget.java and reproduce the failure using the standalone Gson examples in the issue. Compare its serialization behavior with the referenced Azure CloudEvent implementation and verify that a CloudEvent can be serialized without the StackOverflowError and sent through the EventGrid output binding.
Written by the indexing model from the issue text.
Description
Investigative information
Please provide the following:
- Timestamp:
- Function App name:
- Function name(s) (as appropriate):
- Invocation ID:
- Region:
I'm not sure what the format of a CosmosDBTrigger is, and I am unable to provide this information for my current setup at the time.
Repro steps
As a function:
Trigger a function with com.azure.core.models.CloudEvent as the type of the OutputBinding in combination with @EventGridOutput.
final @EventGridOutput(
name = "OutputEvent",
topicEndpointUri = "EventGridTopicEndpoint",
topicKeySetting = "EventGridTopicKey")
OutputBinding<CloudEvent> eventGridOutput
As a standalone issue:
package org.example.functions;
import com.azure.core.models.CloudEvent;
import com.azure.core.models.CloudEventDataFormat;
import com.azure.core.util.BinaryData;
import com.google.gson.Gson;
public class Foo {
public static void main(String[] args) {
CloudEvent cloudEvent = new CloudEvent("mySource", "myType", BinaryData.fromObject(new Object()), CloudEventDataFormat.JSON, "application/json");
Gson gson = new Gson();
gson.toJson(cloudEvent);
}
}
More specific, it's the serialization of com.azure.core.implementation.util.SerializableContent, used by com.azure.core.util.BinaryData#fromObject(java.lang.Object) that causes the issue
package org.example.functions;
import com.azure.core.implementation.serializer.DefaultJsonSerializer;
import com.google.gson.Gson;
public class Bar {
public static void main(String[] args) {
Gson gson = new Gson();
gson.toJson(new SerializableContent(new Object(), new DefaultJsonSerializer()));
}
}
Expected behavior
The CloudEvent is serialized and sent to the desired output binding.
Actual behavior
The runtime is unusable after one trigger due a (swallowed?) StackOverflowError and nothing is sent to the output as a result.
Known workarounds
- Create a custom class that implements the CloudEvent spec.
Related information
Provide any related information
Basically it all boils down to Jackson vs Gson. The CloudEvent uses Jackson annotations to imply serialization rules while the azure-functions-java-worker uses Gson for serialization. Ironically, the last change on RpcUnspecifiedDataTarget.java, was switching from Jackson to Gson.
Note that com.azure.core.models.CloudEvent#binaryData is annotated with @JsonIgnore. This property is what causes the StackOverflowError when serializing with Gson.
I'm using java 8 to dodge the issues caused by reflection due modularization in java 9.
@CosmosDBTrigger as trigger
@EventGridOutput as output binding
Ideally, there is a consensus in using Jackson vs Gson throughout the azure java projects to prevent such issues in the future.
Furthermore, the CloudEvent implementation doesn't even work with Jackson due to com.azure.core.models.CloudEvent#getData not returning the actual data. Instead it serializes to SerializableContent.
@JsonProperty("data")
private JsonNode data;
public BinaryData getData() {
if (this.binaryData == null) {
if (this.data != null) {
this.binaryData = BinaryData.fromObject(this.data, SERIALIZER);
} else if (this.dataBase64 != null) {
this.binaryData = BinaryData.fromBytes(Base64.getDecoder().decode(this.dataBase64));
}
}
return this.binaryData;
}
Serializing CloudEvent with Jackson:
package org.example.functions;
import com.azure.core.models.CloudEvent;
import com.azure.core.models.CloudEventDataFormat;
import com.azure.core.util.BinaryData;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Jackson {
public static void main(String[] args) throws Exception {
CloudEvent cloudEvent = new CloudEvent("mySource", "myType", BinaryData.fromObject(new Object()), CloudEventDataFormat.JSON, "application/json");
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(cloudEvent));
}
}
Output:
{"id":"19b834e0-803b-4c12-9d21-4e6efea3f3b9","source":"mySource","data":{"replayable":true,"length":2},"data_base64":null,"type":"myType","time":null,"specversion":"1.0","dataschema":null,"datacontenttype":"application/json","subject":null}
Note that the data property is the serialized representation of SerializableContent through 'replayable' and 'length'.
The CloudEvent implementation for Event Grid is unusable at this point without changes to the azure-sdk-for-java.
https://github.com/Azure/azure-sdk-for-java/issues/36000
Please let me know if you require addition info.
- Dominant language
- Java
- Stars
- 103
- Forks
- 74
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 3
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Azure/azure-functions-java-worker
-
Difficulty 4/5 3-5 days Newbie friendliness 50/100
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
-
mcp-extension
Difficulty 5/5 Over a week Newbie friendliness 25/100
-
mcp-extension
Azure/azure-functions-java-worker#863 · 1 assignee ·
All issues in Azure/azure-functions-java-worker
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
infinispan/infinispan#18150 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
opensearch-project/k-NN#3597 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 82/100