rest icon indicating copy to clipboard operation
rest copied to clipboard

Specify where to write the MediaType of Sse event ?

Open jimma opened this issue 4 years ago • 8 comments

We can set the Sse event media type with jaxrs api like:

  OutboundSseEvent event = sse.newEventBuilder().name("json")
            .data("{\"a\":\"b\",\"c\":\"d\")
            .mediaType(MediaType.APPLICATION_JSON_TYPE).build();

But this setting isn't write and send to client like what http ContentType header does. Should spec define the behavior to write this information to stream? One possible place is event's comment field :

: application/json
event: json
data: {"a":"b","c":"d"}

jimma avatar Jul 21 '20 05:07 jimma

Hi @jimma,

My understanding of the mediaType(...) method wrt to SSEs is that it is used to determine the MessageBodyWriter that will serialize the event's data object to be sent to the client. That way if you wanted to send back an entity type (e.g. "dog" or "widget", etc.), you could specify the MediaType as application/json or application/xml and then the appropriate MBW (JSON-B or JAXB) would be invoked to serialize it to expected output (JSON or XML).

Because of this, your example should end up sending a single string as JSON rather than an object with fields "a" and "c".

AFAICT, the SSE portion of the HTML5 spec doesn't mention the content type of the events themselves (only that the stream should be UTF-8 encoded).

Since JAX-RS SSE attempts to comply with the HTML5 spec for SSEs, I tend to lean toward not requiring implementations to specify the content type of each event, but not prohibiting it either. That way implementations are free to add the content type as a comment or allow the user to specify the comment.

In general, I think most SSE-based applications will only send events of a single content type on a single connection - i.e. all events are "application/json". App developers could advertise the type used by using mechanisms like OpenAPI - or they could modify their app to allow the client to specify it - for example:

@Produces("text/event-stream")
public void registerForSses(@QueryParam("requestedEventContentType") @DefaultValue("application/json") String eventContentType) { //...

Thanks for raising the issue!

andymc12 avatar Jul 21 '20 14:07 andymc12

I'm just guessing here, but as SSE doesn't define a way to include the content type in an event, the media type was most likely just added to the JAX-RS API to support the standard MBW API for serializing the event payload.

So IMO we shouldn't include the content type in the comment field. Especially because this isn't part of the expected behavior of SSE.

chkal avatar Jul 21 '20 14:07 chkal

Exactly, I agree with @chkal and @andymc12

spericas avatar Jul 21 '20 15:07 spericas

I thought about this a while ago ... given that I don't remember what I was thinking about yesterday, my recollection is a little fuzzy, but

https://www.w3.org/TR/2009/WD-eventsource-20090421/#event-stream-interpretation

says that an unrecognized field will be ignored by SSE. That suggests that a non-standard field could be used to specify the media type. Now, Stephane Epardaud at Red Hat, who I'm happy to defer to, said he couldn't think of a use case for that, so I let it slide until someone asks for it. https://issues.redhat.com/secure/ViewProfile.jspa?name=FroMage

By the way, something we did in RESTEasy was to allow non text content by escaping certain characters. Again, I'm not sure how useful that is, given the ubiquity of JSON, but at least it's something that has been implemented.

Not to hijack the thread ...

-Ron

On 7/21/20 10:37 AM, Andy McCright wrote:

Hi @jimma https://github.com/jimma,

My understanding of the |mediaType(...)| method wrt to SSEs is that it is used to determine the MessageBodyWriter that will serialize the event's data object to be sent to the client. That way if you wanted to send back an entity type (e.g. "dog" or "widget", etc.), you could specify the MediaType as |application/json| or |application/xml| and then the appropriate MBW (JSON-B or JAXB) would be invoked to serialize it to expected output (JSON or XML).

Because of this, your example should end up sending a single string as JSON rather than an object with fields "a" and "c".

AFAICT, the SSE portion of the HTML5 spec https://html.spec.whatwg.org/multipage/server-sent-events.html doesn't mention the content type of the events themselves (only that the stream should be UTF-8 encoded).

Since JAX-RS SSE attempts to comply with the HTML5 spec for SSEs, I tend to lean toward not requiring implementations to specify the content type of each event, but not prohibiting it either. That way implementations are free to add the content type as a comment or allow the user to specify the comment.

In general, I think most SSE-based applications will only send events of a single content type on a single connection - i.e. all events are "application/json". App developers could advertise the type used by using mechanisms like OpenAPI - or they could modify their app to allow the client to specify it - for example:

|@Produces("text/event-stream") public void registerForSses(@QueryParam("requestedEventContentType") @DefaultValue("application/json") String eventContentType) { //... |

Thanks for raising the issue!

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/eclipse-ee4j/jaxrs-api/issues/889#issuecomment-661900484, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAEDP4YTOLD62GA6AM4YJZTR4WRZXANCNFSM4PDFYU7Q.

ronsigal avatar Jul 21 '20 17:07 ronsigal

As @andymc12 said, we added that in JAX-RS so we can use MBWs. It is not intended to be sent to the receiver. So I do not see that the spec needs to define that.

mkarg avatar Jul 21 '20 19:07 mkarg

Thanks all for your inputs.

In general, I think most SSE-based applications will only send events of a single content type on a single connection - i.e. all events are "application/json". App developers could advertise the type used by using mechanisms like OpenAPI - or they could modify their app to allow the client to specify it - for example:

@Produces("text/event-stream")
public void registerForSses(@QueryParam("requestedEventContentType") @DefaultValue("application/json") String ev

I think these are two good ideas to notify the receiver a media type to read event to a java object. Do we need to clarify how does receiver get the correct media type in spec or api doc to read event ?

jimma avatar Jul 23 '20 06:07 jimma

I think these are two good ideas to notify the receiver a media type to read event to a java object. Do we need to clarify how does receiver get the correct media type in spec or api doc to read event ?

Maybe. It seems more like a something I would expect to find in a blog post or "best practices guide" rather than the spec. It might be worthwhile to add some language to the effect of "it is usually a good idea not to mix different media types in events to the same sink, as most clients will only be expecting events of one media type".

andymc12 avatar Jul 23 '20 17:07 andymc12

Maybe. It seems more like a something I would expect to find in a blog post or "best practices guide" rather than the spec. It might be worthwhile to add some language to the effect of "it is usually a good idea not to mix different media types in events to the same sink, as most clients will only be expecting events of one media type".

+1. Actually this is not the business of the spec. The spec is about declaring how JAX-RS works, not about what people aren't expected to do. We can have that in a separate location, like a FAQ or design guide, but not in the spec.

BTW, it makes pretty much sense to have different media types in events, as long as they are compatible. For example, application/fruit-apple+json and application/fruit-pear+json when the overall event stream is described to deliver application/fruit-*+json

mkarg avatar Jul 23 '20 21:07 mkarg