OutputBinding not compatible with com.azure.core.models.CloudEvent

Abierto
#720 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
4/5
Tiempo estimado
3-5 días
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Estancado
Stack tecnológico
azure, java
Área
backend, cloud

Línea de trabajo

Comience con src/main/java/com/microsoft/azure/functions/worker/binding/RpcUnspecifiedDataTarget.java y reproduzca el fallo utilizando los ejemplos independientes de Gson incluidos en el issue. Compare su comportamiento de serialización con la implementación de Azure CloudEvent referenciada y verifique que un CloudEvent pueda serializarse sin el StackOverflowError y enviarse a través del enlace de salida de EventGrid.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

area:java-functions Enhancement Needs: Triage (Functions) New Feature reviewed
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.

Lenguaje dominante
Java
Estrellas
103
Forks
74
Merge medio
1 d 11 h
PR fusionados (30 d)
3

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de Azure/azure-functions-java-worker

Todos los issues de Azure/azure-functions-java-worker

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.