jsr370-experts@jax-rs-spec.java.net

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

From: Sergey Beryozkin <sberyozkin_at_talend.com>
Date: Tue, 10 Nov 2015 21:22:22 +0000

If you attempt to check this thread you'd find the line (to which I
recall you said you were hearing what I wanted to say) that indeed, no,
no strong need to use @Produces (application/json) - the builder still
has a chance to set MT, but if each event data piece is JSON (i.e the
uniform format between multiple events) then @Produces
(application/json) would let users to avoid setting MT on the builder
every time the event is sent

By the way, Santiago, you said you could consider supporting a 'default'
MT for the purpose of selecting MBW for a given event data entity if a
user does not set a MT on the builder. So that Object.toString() does
not escape. So what is your solution ?

Thanks. Sergey
On 10/11/15 17:40, Markus KARG wrote:
>
> Sergey, you simply do not need that additional annotation, because
> each single event of an event stream can have a different content type
> as the "data:" payload. Hence, the only working solution is to have an
> event builder API that accepts a ".contentType(…)" method per created
> event.
>
> -Markus
>
> *From:*Sergey Beryozkin [mailto:sberyozkin_at_talend.com]
> *Sent:* Dienstag, 10. November 2015 16:52
> *To:* jsr370-experts_at_jax-rs-spec.java.net
> *Subject:* Re: [jax-rs-spec users] SSE Draft
>
> On 10/11/15 15:19, Santiago Pericasgeertsen wrote:
>
> On Nov 10, 2015, at 9:58 AM, Sergey Beryozkin
> <sberyozkin_at_talend.com <mailto:sberyozkin_at_talend.com>> wrote:
>
> On 10/11/15 14:50, Santiago Pericasgeertsen wrote:
>
> On Nov 8, 2015, at 12:52 PM, Sergey Beryozkin
> <sberyozkin_at_talend.com <mailto:sberyozkin_at_talend.com>>
> wrote:
>
> Hi Santiago
>
> I guess the source of my own 'confusion' is this one:
>
> - text/sse-stream CT has no relationship to the actual
> content being returned
> while in a normal HTTP a CT has a direct
> relationship (so much for SSE being HTTP friendly)
>
> No, this is not true. The stream that you’re returning
> looks like this:
>
> event: foo
>
> data: { “a” : “b”}
>
> event: bar
>
> data: { “c” : “d”}
>
> …
>
> Well, obviously I referred to the 'data' piece, so indeed
> text/sse-stream has no relation to
> { “c” : “d”}
>
> It does in the sense that you’re sending “text”, which in this
> example happens to be JSON. In fact, every data event can have a
> different “type” of text in same stream: an event’s data could be
> application/json and another event’s data could be text/plain.
> This is why a default makes more sense than an annotation that we
> normally use to refer to the entire stream not a single event.
>
> So given this line about 'text' being also 'json' why with
> @Produces(text/event-stream) users still has to set application/json
> on the builder when writing event beans that are meant to be written
> as JSON ?
>
> My answer: because @Produces has been overloaded, i.e, SseOuputChannel
> is obviously taking care of formatting the SSE payload.
> @Produces(text/event-stream) does not help a bit in selecting
> SseOuputChannel - the method returns it for the runtime to use.
>
> I did not propose to remove 'text/event-stream'. I'm saying that lets
> keep @Produces for what it always does in JAX-RS - for affecting the
> selection of MBW, while also letting SSE users know that the overall
> production is an SSE output channel (@SseProduces, or implicitly -
> SseOutputChannel response type)
>
> Sergey
>
>
>
>
>
> — Santiago
>
>
>
>
>
> The overall structure is SSE and not JSON.
>
> - @Produces in JAX-RS has always had an effect on selecting the
> response CT, *but also* on MBR - while
> a @Produces("text/sss-stream") does not help with selecting MBR
> which implies that in this case we partially overload it.
>
> Look above, someone needs to insert the tags “event:”, “data:”, the
> right spacing, etc.
>
> Well, so given what I've just clarified, where is the conflict, or
> rather a worse version of supporting SSE compared to the current
> version, in what I did propose ?
>
> Sergey
>
>
> — Santiago
>
>
>
> @POST
> @SseProduces
> @Produces(MediaType.APPLICATION_JSON)
> public SseEvenOutput startDomain() {
> }
>
> would be neater IMHO - @SseProduces is a reference to a technical
> aspect of SSE, i.e. its req to have text/event-stream.
> The meaning of @Produces(MediaType.APPLICATION_JSON) (only if it is
> set - the builder is still available for event specific MT)
> is the same as it is known to JAX-RS developers now - perhaps
> something like APPLICATION_JSON
> can be used to set that internal CT property (in the actual given
> SSE payload) Markus referred to earlier - in which case it would be
> completely consistent...
>
> Sergey
>
>
> On 04/11/15 00:14, Santiago Pericasgeertsen wrote:
>
> Sergey,
>
> Hmm, I see what you mean, but I think that violates the spec. A
> method-level @Produces is supposed to override a class-level one,
> ultimately resulting in the value of Content-Type in the response.
>
> I think what you proposed will introduce a lot of confusion.
> Alternatively, we could provide a default MT programmatically for
> all events to be created instead, if that addresses the issue that
> you have in mind.
>
> — Santiago
>
> On Nov 3, 2015, at 1:28 PM, Sergey Beryozkin
> <sberyozkin_at_talend.com <mailto:sberyozkin_at_talend.com>> wrote:
>
> https://github.com/mpotociar/api/blob/46d81cf3c5826f62e5824d5330fa4d59ffa0d98f/examples/src/main/java/jaxrs/examples/sse/ServerSentEventsResource.java#L103
> (1)
>
> Replace @Produces(text/event-stream) with
> Produces(application/json) and add @SSE and that works neatly,
> otherwise if we keep
> @Produces(text/event-stream) there and have
> Produces(application/json) at this level
>
> https://github.com/mpotociar/api/blob/46d81cf3c5826f62e5824d5330fa4d59ffa0d98f/examples/src/main/java/jaxrs/examples/sse/ServerSentEventsResource.java#L62
> (2)
>
> then when I do
>
> https://github.com/mpotociar/api/blob/46d81cf3c5826f62e5824d5330fa4d59ffa0d98f/examples/src/main/java/jaxrs/examples/sse/ServerSentEventsResource.java#L112
> (3)
>
> (but use MyBean instead to be serialized as JSON) the class
> level Produces(application-json) (ref (2) above) it will be
> ignored and the only way to set application/json is to use the
> builder.
>
> Sergey
>
> On 03/11/15 16:55, Santiago Pericasgeertsen wrote:
>
> On Nov 3, 2015, at 4:10 AM, Sergey Beryozkin
> <sberyozkin_at_talend.com <mailto:sberyozkin_at_talend.com>>
> wrote:
>
> Hi Santiago
>
> So I'm wondering if inserting a special MT would
> interfere with the regular policy of figuring out what
> MT should be allocated to a given data piece.
> Example if I do not use SSE, I can put Produces on
> Class or on Method or in Response. If we keep
> depending on a special MT to make a method initiating
> an SSE output then the only mechanism to set an event
> data MT is to use a builder, neither Class or Method
> Produces can be used which would be unfortunate IMHO.
>
> I’m not sure I follow. The MT of the
> method/class/response is always text/event-stream, so
> indeed any other MT will be supplied while constructing
> each SSE event. Is that what you meant? If not, please
> provide some code :)
>
> — Santiago
>
>
> I'm not proposing to block text/event-stream but
> rather treat it as a technical aspect of implementing
> SSE, i.e, it is an SSE protocol specific 'demarcation'
> MT which does not have any relevance to the format of
> the actual data (referring here to the MT/format used
> to select JAXRS providers) pushed inside this
> text/event-stream 'envelope'. Example, having both
> @SSE for the purpose of marking the method and
> @Produces for the purpose of specifying the *default*
> MT for the event data fragments (while letting users
> override if with a builder if needed) can work well.
>
>
>
> Sergey
>
> On 29/10/15 13:17, Santiago Pericasgeertsen wrote:
>
> Sergey,
>
> Inlined.
>
> My understanding the format of the message is
> expected to be known to the client (example,
> it is JSON all the time in a known
> representation, etc),
>
> Yes, there is nothing in the SSE protocol about
> an event's MT. There is a single MT returned in
> the response, and that is text/event-stream. The
> reason for the MT proposal is simply so that
> JAX-RS can find the correct MBW.
>
>
>
> I was more curious about the default MT that would
> be used for selecting MBW for serializing a custom
> event object…
>
> In my view, this ought to be consistent with the
> way we handle the return of an entity in a
> resource method without an @Produces. In other
> words, it should be consistent with the algorithm
> in Section 3.8.
>
> — Santiago
>
>
>
> If a builder media type property is not set then
> at least for String toString() will produce a
> meaningful message, but a Object.toString() should
> not be allowed to escape if a user forgets to set
> a MT builder property
>
>
> Sergey
> On 28/10/15 18:55, Markus KARG wrote:
>
> Quoted from W3C: <The default event type is
> "message">.
>
> Actually there is problem with MIME and SSE:
> W3C does not define how to transfer the
> Content-Type. They do specify that one can add
> any name to a field (like "content-type") but
> that name is not mandatory. Without it, our
> only chance is assuming "String", actually --
> even if this means "toString()".
>
> *From:*Sergey Beryozkin
> [mailto:sberyozkin_at_talend.com]
> *Sent:*Mittwoch, 28. Oktober 2015 19:18
> *To:*jsr370-experts_at_jax-rs-spec.java.net
> <mailto:jsr370-experts_at_jax-rs-spec.java.net>
> *Subject:*Re: [jax-rs-spec users] SSE Draft
>
> Either by the return type or otherwise by
> something like @SSE, please see the prototype
> below
>
> By the way, this is probably orthogonal, but
> what is the default MT (for the purpose of
> selecting MBW) if the event object is not
> String but say MyEvent.
> Is toString() a default ? That would work for
> String but would look not good for custom objects
>
> Sergey
>
>
> On 28/10/15 17:59, Markus KARG wrote:
>
> Understood. So how to detect SSE then if
> not by MT? By return type?
>
> *From:*Sergey Beryozkin
> [mailto:sberyozkin_at_talend.com]
> *Sent:*Mittwoch, 28. Oktober 2015 00:26
> *To:*jsr370-experts_at_jax-rs-spec.java.net
> <mailto:jsr370-experts_at_jax-rs-spec.java.net>
> *Subject:*Re: [jax-rs-spec users] SSE Draft
>
> Or per-event MT approach can still work
> where, if set, it overrides a method
> specific Produces, exactly as it works
> with a regular JAX-RS response.
> So I guess the only thing I suggest is to
> make setting text/event-stream implicit
> and keep Produces for specifying the event
> format if preferred...
>
> Sergey
> On 27/10/15 23:22, Sergey Beryozkin wrote:
>
> Hi Markus, I'm not suggesting to
> redefine, I'm suggesting to make the
> way SSE is implemented in JAX-RS a
> little bit less technical as far as
> users working with it are concerned ?
> Re restricting to a single MT for all
> the events inside a single channel, is
> it a bad thing ? I'm not sure. We can
> always assume that in theory it is
> possible, but lets face it, I doubt
> anyone can come up with a practical
> example where multiple MTs are mixed
> in. In fact supporting per-event MT
> can be added later on at a builder
> level if such a freedom of formatting
> is ever needed...
>
>
> Cheers, Sergey
> On 27/10/15 22:32, Markus KARG wrote:
>
> But Sergey, we only should define
> an API how SSE can be mapped upon
> JAX-RS. We cannot redefine how SSE
> works. And it is simply the W3C
> that defined that SSE is initiated
> by sending that particular MT and
> that each single event can
> definitively have different entity
> type. What you propose certainly
> looks more familiar, but would
> redefine the W3C-defined semantics
> of SSE.
>
> *From:*Sergey Beryozkin
> [mailto:sberyozkin_at_talend.com]
> *Sent:*Dienstag, 27. Oktober 2015
> 23:25
> *To:*jsr370-experts_at_jax-rs-spec.java.net
> <mailto:jsr370-experts_at_jax-rs-spec.java.net>
> *Subject:*Re: [jax-rs-spec users]
> SSE Draft
>
> Hi
>
> I have to admit I'm still
> uncomfortable about a specialized
> Produces(text/event-stream) in
> this case. I could not figure why
> until yesterday... Basically this
> is what the SSE spec requires to
> accompany the data going to the
> SSE channel - but it is orthogonal
> to the act of converting the data
> into event specific formats such
> as JSON or plain text.
> When myself and possibly other
> users see Produces they think this
> is the format of the response data.
> Having an SSE-required MT in a
> method @Produces does not fit well
> into a JAX-RS state of 'mind'.
>
> Letting people set MT for
> individual events actually loosens
> the API - i.e, the API makes it
> very easy to do what is obviously
> not meant to be, mixing different
> formats in a single channel, 1st
> event is JSON, next is XML. Of
> course we can say the users needs
> to know what to do, but it is
> different from having an API which
> does not explicitly allows such
> nonsense operations...In 2.0 one
> can also do it, say mess up with
> writing into StreamingOutput - but
> the user needs to try hard :-)
>
> I'd like to return to discussing
> this idea:
>
> @POST
> @Produces(MediaType.APPLICATION_JSON)
> public SseEvenOutput startDomain() {
> }
>
> or
>
> @POST
> @Produces(MediaType.APPLICATION_JSON)
> @SSE
> public Response startDomain() {
> }
>
> In either case, setting
> text/event-stream is the
> responsibility of the runtime,
> something that will be documented
> in the spec/API, it is implicit, while
> @Produces(MediaType.APPLICATION_JSON)
> represents the format of the every
> event fragment for a given SSE
> output channel...
>
> Sergey
>
> On 22/10/15 16:11, Sergey
> Beryozkin wrote:
>
> Hi Santiago
> On 22/10/15 15:29, Santiago
> Pericasgeertsen wrote:
>
> Sergey,
>
> This is how I reason
> about media types
> associated with events.
> First, sometimes the data
> associated with an event
> is structured, most
> notably these days it’s
> JSON. JAX-RS already has a
> facility for mapping Java
> objects to representations
> (MBR/MBW) whose selection
> is based on MTs.
>
> This mechanism is there
> for entities, but it is
> only natural to see if it
> can be extended for SSE
> event data. To do so, you
> need to specify an MT for
> the event’s data. If we
> don’t allow re-usability
> of this mechanism, we’d
> either only support string
> messages or build a
> completely different
> mechanism, which seems
> like an overkill.
>
> Sure, +1, indeed reusing
> MBR/MBW for this is perfect
>
>
>
>
>
> I’m still unsure about
> interceptors: to me
> interceptors and MBR/MBW’s are
> inseparable, but at the same
> time it’s not clear what
> advantages they bring in this
> case.
>
> I've no strong opinion right
> now about it. I can imagine
> some confusion about the
> response interceptors/filters
> meant for processing 'main'
> HTTP channel responses being
> also used for filtering sse
> events, though I can also
> imagine may me some events
> being blocked by filters if
> needed, not really sure right
> now :-)
>
> Sergey
>
>
>
>
>
> — Santiago
>
> On Oct 21, 2015, at 4:46
> PM, Sergey Beryozkin
> <sberyozkin_at_talend.com
> <mailto:sberyozkin_at_talend.com>>
> wrote:
>
> Hi Markus - OK, thanks.
> Still looks like a foreign
> body, this @Produces...
>
> The question about
> formatting the event data
> fragments still remains,
> If we are including MBW
> then surely not because we
> need a help with writing
> String into output stream.
> Oh, actually.
>
> https://github.com/mpotociar/api/blob/master/jaxrs-api/src/main/java/javax/ws/rs/sse/OutboundSseEvent.java#L108
>
> So ended up doing some
> home work after all :-)
>
> Sergey
>
>
>
>
>
> On 21/10/15 19:05, Markus
> KARG wrote:
>
> Sergey,
>
> maybe there is a
> misunderstanding: The
> W3C SSE specification
> clearly says that the
> initiation of a SSE
> channel _is_ by
> declaring a content
> type of
> text/event-stream.
> Hence this is not a
> marker made up by
> JAX-RS, but it
> definitivel _is_
> correct according to
> the W3C.
>
> -Markus
>
> *From:*Sergey
> Beryozkin
> [mailto:sberyozkin_at_talend.com]
> *Sent:*Mittwoch, 21.
> Oktober 2015 13:26
> *To:*jsr370-experts_at_jax-rs-spec.java.net
> <mailto:jsr370-experts_at_jax-rs-spec.java.net>
> *Subject:*Re:
> [jax-rs-spec users]
> SSE Draft
>
> Hi Marek
>
> Few comments/questions,
>
> Re the special
> MediaType vs the
> MediaType for
> individual event writes,
>
> How is a Media Type
> for an event data
> fragment is specified ?
> And can we assume that
> the same MediaType is
> used for all the event
> writes ?
>
> If it is a single
> Media Type then I'd
> object to the idea of
> a *special* MT,
> example, if every
> event write is a JSON
> payload, why do
>
> @POST
> @Produces(MediaType.SERVER_SENT_EVENTS)
> public SseEvenOutput
> startDomain() {
> }
>
> This actually appears
> to be a bit off the
> JAX-RS style because
> we use
> MediaType.SERVER_SENT_EVENTS
> as a marker of the
> method which initiates
> SseEvenOutput but not
> the *format* of the
> response event data
> chunks, it overloads
> the concept of
> Produces IMHO.
>
> Should we just have
>
> @POST
> @Produces(MediaType.APPLICATION_JSON)
> public SseEvenOutput
> startDomain() {
> }
>
> Which is more in line
> with a StreamingOutput
> like pattern ?
>
> The runtime can mark
> startDomain() as
> needed given the
> response type is
> SseEvenOutput and if
> Response (or
> AsyncResponse ?) are
> allowed then
> we can do
>
> @POST
> @Produces(MediaType.APPLICATION_JSON)
> @SSE
> public Response
> startDomain() {
> }
>
>
> Thoughts ?
>
> Cheers, Sergey
>
>
>
>
>
>
>
>
>
> On 21/10/15 11:42,
> Marek Potociar wrote:
>
> At the same time,
> it is the spec
> lead job to steer
> the EG and the JSR
> outcome. And since
> it was me and
> Santiago who
> submitted the JSR
> charter, EG does
> not need to find
> interpretations,
> EG can simply ask
> the spec leads to
> provide the
> explanation. 😉
>
> In case of CDI,
> our intention was
> to improve the
> alignment of
> @Inject and scope
> support. FWIW,
> we’re still hoping
> that CDI 2.0 will
> become more
> modularized so
> that we do not
> have to formally
> deal with the
> whole spec (that
> becomes more and
> more bloated by
> features less and
> less relevant to
> “context and
> dependency
> injection”
> problem), only
> with it’s core
> pieces. So once,
> again, our CDI
> alignment is about
> aligning the
> JAX-RS injection
> support with CDI.
> It is NOT about
> integration with
> CDI eventing (for
> SSE support or
> whatever other
> purpose).
>
> Hope the
> explanation above
> is clear enough
> and does not
> require further
> interpretation in EG.
>
> As for the SSE
> support, we want
> to provide a
> facility that fits
> well into JAX-RS
> programming model.
> And since SSE is
> really just a
> (special) media
> type, the proposed
> API is building on
> top of the
> existing support
> for entity
> providers in
> JAX-RS. So to
> touch on the
> questions you
> raised in more
> detail:
>
> - Yes, we plan to
> leverage message
> body readers and
> writers for each
> single SSE event.
> We do not plan to
> engage Filters and
> Interceptors with
> each event, those
> should only be
> engaged when the
> request or
> response is initiated.
>
> - Injectable
> SseEventOutput is
> certainly an
> option to
> consider. At the
> same time, we do
> need to find a way
> how to provide
> access to event
> builder and
> broadcaster, so
> rather than
> injecting three
> separate things,
> it so far seems to
> me simpler to just
> inject the context
> and use it to get
> access to all of
> the important
> components. In any
> case, we can
> simply look into
> this further to
> see what can be
> done to make the
> API simpler.
>
> - To your comment
> "/I do not see why
> creating the
> SseOutput from an
> SseContext should
> be the
> responsibility of
> the application
> programmer./”, my
> response is that
> SSE stream is a
> representation of
> a resource in the
> JAX-RS philosophy.
> So it is only
> natural that the
> JAX-RS resources
> return the new
> instance of SSE
> stream from a
> resource method.
> That’s the common
> JAX-RS programming
> model.
>
> - To respond to
> your item #3,
> other than my CDI
> related comments
> earlier in this
> email, SSE is a
> standardized spec
> with well defined
> standard APIs. It
> IMO begs for a
> dedicated API.
> Otherwise it would
> not make any sense
> to provide a
> special support
> for it. It is only
> good that we can
> come up with a
> really small API
> (8 classes) that
> fits well the
> JAX-RS programming
> model and is
> tailored to
> support this
> technology. SSE is
> a specific
> technology that
> covers important,
> but again specific
> use cases. Coming
> up with some
> clever
> abstractions is
> not going to
> provide any real
> user value, I’m
> afraid.
>
> Cheers,
>
> Marek
>
> On 20 Oct
> 2015, at
> 22:53, Markus
> KARG
> <markus_at_headcrashing.eu
> <mailto:markus_at_headcrashing.eu>>
> wrote:
>
> Well,
> according to
> the JCP
> bylaws, it is
> the expert
> group to
> define the
> outcome of the
> JSR. So it is
> up to us to
> interpret the
> charter as we
> like. ;-)
>
> -----Original
> Message-----
> From: Sergey
> Beryozkin
> [mailto:sberyozkin_at_talend.com]
> Sent:
> Dienstag, 20.
> Oktober 2015 22:43
> To:jsr370-experts_at_jax-rs-spec.java.net
> <mailto:jsr370-experts_at_jax-rs-spec.java.net>
> Subject: Re:
> SSE Draft
>
> Hi Markus
>
> I suspect it
> is about
> better support
> for Inject,
> etc, but not sure
>
> Cheers, Sergey
> On 20/10/15
> 21:37, Markus
> KARG wrote:
>
>
>
>
>
> If we cannot,
> why did the
> JCP accept the
> JSR 370
> charter, which
> clearly
> requests CDI
> integration?
>
> -----Original
> Message-----
> From: Sergey
> Beryozkin
> [mailto:sberyozkin_at_talend.com]
> Sent:
> Dienstag, 20.
> Oktober 2015 22:23
> To:jsr370-experts_at_jax-rs-spec.java.net
> <mailto:jsr370-experts_at_jax-rs-spec.java.net>
> Subject: Re:
> SSE Draft
>
> Can a 2.1 (non
> major version)
> introduce a
> strong CDI dep
> ? MVC is a diff
> story.
>
> Sergey
>
> On 20/10/15
> 16:26, Bill
> Burke wrote:
>
>
>
>
>
>
> On 10/19/2015
> 5:19 PM,
> Markus KARG wrote:
>
>
>
>
>
> (1) Maybe I
> missed the
> code line, but
> will it be
> possible to
> send an
> entity so
> MBWs, Filters
> and
> Interceptors
> are getting
> involved? In the
> end, we do not
> write an SSE
> server, but
> actually do
> add SSE to JAX-RS.
>
> Like:
> sseContext.newEvent().name("custom-message").data(myEntity);
> =>
> use MBW to
> stream entity,
> applying all
> filters and
> interceptors that
> are registered
> for the
> resource class
> that owns this
> SSE channel.
>
> (2) I am not
> convinced that
> the complexity
> is needed. Why
> is there a
> SseEventOutput
> and an
> SseContext?
> Can't we
> simply inject
> an SseOutput
> in the
> resource
> automatically?
> I do not see
> why creating the
> SseOutput from
> an SseContext
> should be the
> responsibility
> of the
> application
> programmer.
>
> (3) I am not
> convinced that
> the technology
> of SSE should
> also bring
> with it its
> own eventing
> subsystem.
> Wouldn't it
> make more sense to
> rely on CDI
> events? Using
> CDI events we
> could allow
> events origin
> from other
> Java EE
> components
> (like JCA, MDB
> or timed EJBs)
> to be
> forwarded in a
> protocol-transparent
> way into the
> JAX-RS container,
> which then is
> the only one
> that has to
> know that SSE
> is used to
> transport the
> event to the
> http client.
> As JAX-RS is
> an integral part
> of Java EE,
> and as SSE is
> a web-only
> technology, I
> don't like the
> idea that
> either
> non-web-components
> are polluted
> by SSE, or
> non-web-events
> couldn't be
> forwarded to
> SSE clients.
>
> What would SSE
> over CDI look
> like?
>
>
>
>
>