users@jax-rs-spec.java.net

[jax-rs-spec users] Re: SSE Draft

From: Markus KARG <markus_at_headcrashing.eu>
Date: Sat, 14 Nov 2015 16:30:00 +0100

Sergey, thank you for your explanations. Please find my comments inlined.

 

From: Sergey Beryozkin [mailto:sberyozkin_at_talend.com]
Sent: Donnerstag, 12. November 2015 11:49
To: jsr370-experts_at_jax-rs-spec.java.net
Subject: Re: [jax-rs-spec users] SSE Draft

 

Hi Markus

Well, thanks for keeping commenting, and while I'm tempted to give up, I'll keep replying just for the sake of making sure that what I suggested is at least clearly understood, and given your comments, it is not, which is entirely my fault as I'm failing to explain..., so
On 11/11/15 17:39, Markus KARG wrote:

First, you added a special annotation for the sole purpose of SSE. Oracle's proposal simply used the existing solution to cover this case without adding any special functionality.

Look at the signature of the sample code posted by Marek (I do like what he prototyped and what I'm talking about here is arguably an optimization). So a method returns an SSE handler which (I'm sorry if I'm wrong) is responsible for formatting the overall output payload on the per-even basis, including I guess sticking text/sse-stream.

In JAX-RS 1) @Produces affects does the intersection and the final response CT - 2) which affects the selection of MessageBodyWriter - 3) which formats the response data.
I agree @Produces(text/sse-stream) can be used to intersect - but it is not affecting the selection of MBW for the purpose of formatting the overall response.
So I'd say neither proposal reusing the existing solution. So what I suggested is to keep using @Produces for selecting MBW for formatting indiv event data pieces. @SSEProduces was a 'response' to Santiago comments, and the idea there is to make it obvious that there are two Media Types which are in play here, one is text/event-stream - which is a MT for the overall SSE response, and another MT - the one needed to select a MessageBodyWriter for formatting the event data pieces



Actually I need to object here, as I would use the two annotations completely reversed for sake of JAX-RS API alignment: As text/sse-stream is the definition of the frame format the events are wrapped in, there must be an MBW doing exactly that job of providing that SSE stream format: This is *is* the format of the response data -- not "Book" but "SSE Stream"! Hence, the SSE CT actualy _does_ select the MBW. What you mean is something different: You want to select an _additional_ MBW which provides the syntax for solely the _data_ field of each event. This is a new kind of problem not existing in JAX-RS so far: Customizing _internals_ of an MBW! If we would like to define an API for _that_, the correct way (aligned with the JAX-RS 2 spec) would be to define an annotation which is specific to this kind of problem (i. e. define the *wrapped* type), and which is simply consumed by MBW#isWriteable and MBW#writeTo's annotations[] array. As I said, no need for any kind of SSE-magic, but all completely covered by _existing_ APIs. Hence, @Produces will still select the "global" MBW (here: the one providing the SSE stream syntax), and @SSEProduces would select the "inner" MBW (here: the one providing the syntax for the "data" field).

 

Second, your proposal fixes the content type of all events to be the same, while Oracle's proposal did not.

 

I don't believe you keep saying it about my proposal :-).

I'm sure you know, without SSE, when we have

@Produces("application/json")
@GET
public Book getBook() {
    return Response.ok(new Book()).type("application/xml").build();
}

the final CT to be used for selecting MBW is "application/xml". I.e, if the application code does not set "application/xml" then the default application/json is set, but the application can override it.

This is exactly what I suggested:

@Produces("application/json")
@SseProduces
public SseOutputChannel get() {
    // set MT for a given event to application/bar
}

or

@SseProduces
@Produces("application/json")
public SseOutputChannel get() {
    // all events data are JSON - why set it for every event if non-SSE users can avoid doing by having @Produces ?
}

or

@SseProduces
public SseOutputChannel get() {
    // all events data MTs are set individually
}
  

However I'm agreeing that

'_at_SseProduces' is a special approach. Hmm...

So what can be done to make this (non SSE)

@Produces("application/json")
@GET
public Book getBook() {
    return Response.ok(new Book()).build();
}

where a user does not have to set a type on every response working for SSE too ?

By the way, Marek are you interested at all in discussing it :-) ? I know it is been in Jersey for nearly a year now so may it is all already written in stone and no point spending time on discussing it further...

Thanks, Sergey

As I said above, for the sake of JAX-RS 2 alignment I would simply prefer this way to define the "default data:-CT":

 

@Produces("text/sse-stream") // Selects SSE-MBW

@SSEProduces("application/json") // Configures SSE-MBW to use JSON-MBW for "data:" field => Passed into "writeTo"'s annotation[] array.

@GET

public Provider<Book> {

  …

}

 

("Provider" makes it clear to everybody that the result will be asynchronous and unbound, which is typical for SSE and other (future) types of push protocols.)

 

Anyway, I agree with you that this is a special optimization for "always-the-same" data: CT. In case one need multiple / changing data: CTs, the builder is needed anyways.

 

-Markus