Salut,
Vrignaud Etienne wrote:
> Hi,
>
> I am writing a Grizzly Adapter that compute asynchronously several
> requests and return the results as they are computed in the server. It
> means that my UI make a single GET and just have, in a streaming way,
> each request result as they are computed on the server side.
>
> To implement this I use grizzly 1.8.6.1 and the CometEngine. On each
> service() call a CometContext and a CometHandler are created in order to
> send back the results as they are computed.
>
> My first question is that I am not sure that it's a good design to
> create a CometContext and a CometHandler on each service() call. Of
> course, on each service() call different requests are computed. So I use
> different CometContext to ensure that the right UI will get the right
> results.
You might have a single CometContext with several CometHandler, and
notify a specific handler using:
> notify(E attachment, int eventType, int cometHandlerID)
> Notify a single CometHandler.
See:
https://grizzly.dev.java.net/nonav/apidocs/com/sun/grizzly/comet/CometContext.html#notify(E,%20int,%20int)
What I would propose is you cache the cometHandlerID (which is the
result of CometHandler.hasCode() returned value). Then when a request
comes, you get the cometHandlerId and invoke it directly.
An alternative is to write your own NotificationHandler:
https://grizzly.dev.java.net/nonav/apidocs/com/sun/grizzly/comet/NotificationHandler.html
When you call CometContext.notify(E), E could contains a field that
contains to which CometHandler the notification is for. Inside your
NotificationHandler, you can retrieve the proper CometHandler based on
that field and notify only that one.
I can work with you on the NotificationHandler, as this is clearly the
best design you could have instead of having a one to one mapping
(CometContext -> CometHandler).
>
> The problem that I have is to understand how to manage correctly the
> case when all the asynchronous requests are completed. What I want to do
> is to send back an end notification to my UI and to finish the request.
> I tried many different ways and each of them falls into issues.
> What about simply resuming the request and finishing it?
Inside the CometHandler.onEvent(), just do
{
//write the response
cometEvent.getCometContext().resumeCometHandler(this);
}
So as soon as your CometHandler is notified by an event, you write the
response and then resume the connection.
>
> If I try to use the CometEngine in a normal way (as I can read in the
> documentation) I fall also into issues. On the last message at the end
> of all the requests, I send a cometContext.notify(message,
> CometEvent.TERMINATE) and in the onTerminate() handler of my
> CometHandler I call the cometContext.removeCometHandler(). This way
> everything works fine but the CometContext instances are not removed
> from the CometEngine.
Hum....Do you have a test case I can look at? It should work.
>
> So after a while, I have many CometContext instances registered into the
> CometEngine and I have issues.
> I tried to call the unregister() method of the CometEngine but it cause
> many issues.
> Could you tell me if there is an automatic unregistration mechanism or
> what is the good way to do that?
Wow sorry for all the trouble. Can you share a test case (send it to me
privately if you can't share publicly).
>
> PS: In my case, when I speak about issues it means that I have error
> stack trace on my java console. Something like:
> ---------------------------------------------------------------------------
> com.sun.grizzly.DefaultProtocolChain executeProtocolFilter
> GRAVE: ProtocolChain exception
> java.lang.NullPointerException
> at com.sun.grizzly.Context.getProtocol(Context.java:601)
> at com.sun.grizzly.filter.ReadFilter.execute(ReadFilter.java:133)
> at com.sun.grizzly.filter.ReadFilter.execute(ReadFilter.java:98)
> at
> com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:136)
> at
> com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:103)
> at
> com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:89)
> at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)
> at com.sun.grizzly.comet.CometTask.doTask(CometTask.java:248)
> at com.sun.grizzly.http.TaskBase.call(TaskBase.java:359)
> at
> com.sun.grizzly.util.WorkerThreadImpl.processTask(WorkerThreadImpl.java:325)
> at com.sun.grizzly.util.WorkerThreadImpl.run(WorkerThreadImpl.java:184)
Bizarre. J'ai vraiment besoin de voir ton code :-)
> ---------------------------------------------------------------------------
> com.sun.grizzly.http.DefaultProcessorTask invokeAdapter
> GRAVE: HTTP Processing error
> java.nio.channels.ClosedChannelException
> at
> sun.nio.ch.SocketChannelImpl.ensureWriteOpen(SocketChannelImpl.java:126)
> at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:324)
> at
> com.sun.grizzly.util.OutputWriter.flushChannel(OutputWriter.java:105)
> at
> com.sun.grizzly.util.OutputWriter.flushChannel(OutputWriter.java:73)
> at
> com.sun.grizzly.http.SocketChannelOutputBuffer.flushChannel(SocketChannelOutputBuffer.java:175)
> at
> com.sun.grizzly.http.SocketChannelOutputBuffer.flushBuffer(SocketChannelOutputBuffer.java:208)
> at
> com.sun.grizzly.http.SocketChannelOutputBuffer.flush(SocketChannelOutputBuffer.java:186)
> at
> com.sun.grizzly.http.SocketChannelOutputBuffer.realWriteBytes(SocketChannelOutputBuffer.java:150)
> at
> com.sun.grizzly.tcp.http11.InternalOutputBuffer$OutputStreamOutputBuffer.doWrite(InternalOutputBuffer.java:864)
> at
> com.sun.grizzly.tcp.http11.filters.IdentityOutputFilter.doWrite(IdentityOutputFilter.java:155)
> at
> com.sun.grizzly.tcp.http11.InternalOutputBuffer.doWrite(InternalOutputBuffer.java:620)
> at com.sun.grizzly.tcp.Response.doWrite(Response.java:623)
> ---------------------------------------------------------------------------
>
> Thanks for your help.
> Don't hesitate if you want more details.
Merci!!
-- Jeanfrancois
>
> Regards,
> Etienne VRIGNAUD
>