Outbox message should be in the CloudEvent format
Context
Using the Outbox API:
public Response createWithOutbox(OrderRequest request) {
Log.info("Receiving request for creating an Order: " + request);
String uuid = UUID.randomUUID().toString();
Order order = new Order(uuid,
request.items().stream().map(i -> new Order.OrderItem(i.id(), i.name(), i.price())).toList());
/* outbox.yaml: metadata.name */
ExecuteStateTransactionRequest transactionRequest = new ExecuteStateTransactionRequest("postgres-outbox");
List<TransactionalStateOperation<?>> ops = new ArrayList<>();
Map<String, String> metadata = new HashMap<>();
metadata.put("datacontenttype", "application/json");
State<Order> state = new State<>(order.id(), order, null, metadata, new StateOptions(Consistency.STRONG, Concurrency.FIRST_WRITE));
TransactionalStateOperation<Order> upsertOps = new TransactionalStateOperation<>(
TransactionalStateOperation.OperationType.UPSERT, state);
ops.add(upsertOps);
transactionRequest.setOperations(ops);
dapr.executeStateTransaction(transactionRequest).block();
Log.info("Event (order.created) sent to 'rabbitmq' and order saved to the database using Outbox pattern");
return Response
.ok(new OrderResponse(order.id(), order.status(), order.items().stream()
.map(item -> new OrderRequest.OrderItemRequest(item.id(), item.name(), item.price())).toList()))
.build();
}
I am facing a wrong behavior, which is not the same as documented here https://docs.dapr.io/developing-applications/building-blocks/pubsub/pubsub-cloudevents/#dapr-generated-cloudevents-example
Actual behavior
{"data":"{\"id\":\"dd1f1122-cb3a-4dc4-8ab6-e16ff6599a61\",\"status\":\"RECEIVED\",\"items\":[{\"id\":1,\"name\":\"Quarkus Stickers\",\"price\":19.99}]}","datacontenttype":"text/plain","id":"outbox-06af412d-e21b-4151-8f25-9c6c7273a95c","pubsubname":"rabbitmq","source":"orders-api","specversion":"1.0","time":"2025-10-22T18:40:26Z","topic":"order.created","traceid":"00-dc2464c8d9432109a3d1f13469aa739a-ed59c9a3d2829220-01","traceparent":"","tracestate":"","type":"com.dapr.event.sent"}
Expected behavior
{"data": { "id": "dd1f1122-cb3a-4dc4-8ab6-e16ff6599a61","status":"RECEIVED","items":[{"id":1,"name":"Quarkus Stickers","price":19.99}]}","datacontenttype":"application/json","id":"outbox-06af412d-e21b-4151-8f25-9c6c7273a95c","pubsubname":"rabbitmq","source":"orders-api","specversion":"1.0","time":"2025-10-22T18:40:26Z","topic":"order.created","traceid":"00-dc2464c8d9432109a3d1f13469aa739a-ed59c9a3d2829220-01","traceparent":"","tracestate":"","type":"com.dapr.event.sent"}
The data field is coming as string not a object, I tried to use cloudevent.datacontentype but without success too.
/assign
It is the same issue reported here https://github.com/dapr/dapr/issues/7113 but for .NET client
@artur-ciocanu @salaboy @cicoyle @siri-varma I think that I found the problem. The gRPC field is bytes, and is mapped to a ByteString on Java side.
gRPC definition: https://github.com/dapr/dapr/blob/7d652ff7e69e106157f527f4fb7a1b0435537d29/dapr/proto/common/v1/common.proto#L112
ByteString.copyFrom: https://github.com/dapr/java-sdk/blob/6e9ee5adc4a7300ae96822264f9be65458aa0880/sdk/src/main/java/io/dapr/client/DaprClientImpl.java#L858C7-L858C57
It transforms the value to a JSON string format instead a JSON object.
One solution that I have in mind is to map this one on the consumer side (in the framework code, before the user code), but it only solves the consumer, if we look into a database, the data is in JSON string too.
@mcruzdev hmm.. let me raise this with the dotnet folks. If someone reported the same in another SDK, does that mean that that we need to change our protos? Wouldn't that be easier than making a change on the SDK?