After doing some digging I have discovered the following:
1) If I call "cometContext.notify(null, handler);" directly from my "doGet"
method is ignored because in the DefaultNotificationHandler there is a line:
if (cometEvent.getCometContext().isActive(cometHandler)){
and the "cometHandler" is not yet active so I have to keep retrying until it
is active. Is there any way of being notified of the handler becoming
active? Or can the comet context remember what interest ops the handler is
interested in until it is active?
2) When I call "cometContext.registerAsyncWrite(handler)" the SelectionKey's
interest ops are updated but the IO selector is not woken up. This means I
have to wait up to "TCPSelectorHandler.selectTimeout" (1000ms by default)
before I can do the async write which adds extra latency to my app. Shall I
raise a bug for this?
From Richard.
From: Richard Zschech [mailto:richard_at_zschech.net]
Sent: Thursday, 21 January 2010 11:37 AM
To: 'users_at_grizzly.dev.java.net'
Subject: Can't get registerAsyncWrite and CometWriter to work
Hi All,
I have a small example HttpServlet using Grizzly's CometEngine (see below).
Upon receiving a request the test adds a CometHandler, spawns a thread which
waits for a second and notifies the CometHandler using the CometContext.
The CometHandler then receives the notification via its onEvent method and
then calls registerAsyncWrite. The CometHandler is then notified that the
async write is possible and tries to write a large chunk of data using the
CometWriter. The write call returns the number of bytes written and if they
are not all written the CometHandler calls registerAsyncWrite again to be
notified when another non-blocking write can occur otherwise it calls
resumesCometHandler to terminate the connection.
My problems are:
1) If I don't flush the HttpServletResponse before using the CometWriter the
HTTP response headers are written when resumesCometHandler is called which
is after the response data.
2) On Windows XP the non-blocking CometWriter.write does block and writes
the large chunk of data in its entirety. I guess this is just an OS issue.
3) The main problem is sometimes after the second call to registerAsyncWrite
is done the CometHandler never gets another write event so the rest of the
data is never written and the connection is never closed.
I'm using Glassfish v3
Am I doing something wrong?
Has anyone else had issues using CometWriters?
Thanks for any help,
From Richard.
Example code:
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.sun.grizzly.comet.CometContext;
import com.sun.grizzly.comet.CometEngine;
import com.sun.grizzly.comet.CometEvent;
import com.sun.grizzly.comet.CometHandler;
import com.sun.grizzly.comet.CometWriter;
public class GrizzlyServlet extends HttpServlet {
private String topic;
private CometEngine cometEngine;
private CometContext cometContext;
@Override
public void init(ServletConfig config) throws
ServletException {
topic =
config.getServletContext().getContextPath();
cometEngine = CometEngine.getEngine();
cometContext = cometEngine.register(topic);
cometContext.setExpirationDelay(-1);
}
@Override
public void destroy() {
cometEngine.unregister(topic);
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.getWriter().append("BOO");
response.getWriter().flush();
final CometHandlerImpl handler = new
CometHandlerImpl();
handler.attach(response);
cometContext.addCometHandler(handler);
new Thread() {
@Override
public void run() {
try {
Thread.sleep(100);
cometContext.notify(null, handler);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
catch
(IOException e) {
e.printStackTrace();
}
}
}.start();
}
private class CometHandlerImpl implements
CometHandler<HttpServletResponse> {
private HttpServletResponse response;
volatile int index = 0;
int size = 1 << 24;
byte[] bytes = new byte[size];
public CometHandlerImpl() {
for (int i = 0; i < size;
i++) {
bytes[i] =
(byte) (i % 26 + 'A');
}
}
public void attach(HttpServletResponse
response) {
this.response = response;
}
public void onInitialize(CometEvent event)
throws IOException {
System.out.println("onInitialize");
}
public void onInterrupt(CometEvent event)
throws IOException {
System.out.println("onInterrupt");
}
public void onTerminate(CometEvent event)
throws IOException {
System.out.println("onTerminate");
}
public void onEvent(CometEvent event) throws
IOException {
System.out.println("onEvent
" + event.getType() + " " + event.attachment());
if (event.getType() ==
CometEvent.NOTIFY) {
cometContext.registerAsyncWrite(this);
}
else if (event.getType() ==
CometEvent.WRITE) {
CometWriter
writer = (CometWriter) event.attachment();
int write =
writer.write(bytes, index, bytes.length - index);
System.out.println("Written " + write);
index +=
write;
if (index ==
bytes.length) {
cometContext.resumeCometHandler(this);
}
else {
cometContext.registerAsyncWrite(this);
}
}
}
}
}