onMessage method is not called

classic Classic list List threaded Threaded
25 messages Options
12
Reply | Threaded
Open this post in threaded view
|

onMessage method is not called

Bezel
Hello,

I've been playing around with Atmosphere framework using Tomcat 6.1.18 and JDK 1.5.0_14.
The problem I have is that by some reason onMessage method from my AtmosphereHandler implementation is not called...

Here is my source:

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.atmosphere.cpr.AtmosphereEvent;
import org.atmosphere.cpr.AtmosphereHandler;
import org.atmosphere.cpr.Broadcaster;


public class ChatAtmosphereHandler implements AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {

    public ChatAtmosphereHandler() {
    }

    /**
     * When a client send a request to its associated {@link AtmosphereHandler}, it can decide
     * if the underlying connection can be suspended (creating a Continuation)
     * or handle the connection synchronously.
     *
     * It is recommended to only suspend request for which HTTP method is a GET
     * and use the POST method to send data to the server, without marking the
     * connection as asynchronous.
     *
     * @param event an {@link AtmosphereEvent}
     * @return the modified {@link AtmosphereEvent}
     */
    public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws
            IOException {
   
        System.out.println("ChatAtmosphereHandler.onEvent()");
                       
        event.suspend(5000);

        return event;
    }

    /**
     * This method is invoked when the {@link Broadcaster} execute a broadcast
     * operations. When this method is invoked its associated {@link Broadcaster}, any
     * suspended connection will be allowed to write the data back to its
     * associated clients.
     *
     * @param event an {@link AtmosphereEvent}
     * @return the modified {@link AtmosphereEvent}
     */
    public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws
            IOException {
   
        System.out.println("ChatAtmosphereHandler.onMessage()");
       
        return event;
    }
}
 

and below is my Tomcat output that does not show any probems with initialization:

Apr 29, 2009 4:40:30 PM org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: C:\Java\jdk1.5.0_14\bin;.;C:\WINXP\system32;C:\WINXP;C:/Program Files/Java/jre6/bin/client;C:/Program Files/Java/jre6/bin;C:\Oracle11g\product\11.1.0\db_1\bin;C:\WINXP\system32;C:\WINXP;C:\WINXP\System32\Wbem;C:\Program Files\Windows Imaging\;C:\Program Files\TortoiseSVN\bin;C:\Java\frameworks\openAIM;C:\Program Files\QuickTime\QTSystem\;C:\Java\JProbe 8.0.1\bin;C:\Program Files\Common Files\Intuit\QBPOSSDKRuntime;C:\WINXP\system32\WindowsPowerShell\v1.0
Apr 29, 2009 4:40:30 PM org.apache.tomcat.util.net.NioSelectorPool getSharedSelector
INFO: Using a shared selector for servlet write/read
Apr 29, 2009 4:40:30 PM org.apache.coyote.http11.Http11NioProtocol init
INFO: Initializing Coyote HTTP/1.1 on http-8080
Apr 29, 2009 4:40:30 PM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 801 ms
Apr 29, 2009 4:40:30 PM org.apache.catalina.core.StandardService start
INFO: Starting service Catalina
Apr 29, 2009 4:40:30 PM org.apache.catalina.core.StandardEngine start
INFO: Starting Servlet Engine: Apache Tomcat/6.0.18
Apr 29, 2009 4:40:30 PM org.atmosphere.cpr.AtmosphereServlet loadAtmosphereDotXml
INFO: Sucessfully loaded com.msnger.atmosphere.ChatAtmosphereHandler@1e1dadb mapped to context-path /atmosphereHandler
Apr 29, 2009 4:40:30 PM org.atmosphere.cpr.AtmosphereServlet autoDetectContainer
INFO: Atmosphere Framework running under container Tomcat version 6.0.x
Apr 29, 2009 4:40:31 PM org.apache.coyote.http11.Http11NioProtocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
Apr 29, 2009 4:40:31 PM org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
Apr 29, 2009 4:40:31 PM org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/31  config=null
Apr 29, 2009 4:40:31 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 489 ms
ChatAtmosphereHandler.onEvent()


I use IE to execute handler URL directly and I see my request hanging around for expected 5 seconds before I get response with empty page. Everything is fine, but why onMessage() is not called?
What did I miss here?

Thanks
Reply | Threaded
Open this post in threaded view
|

Re: onMessage method is not called

Jeanfrancois Arcand
Salut,

Bezel wrote:

> Hello,
>
> I've been playing around with Atmosphere framework using Tomcat 6.1.18 and
> JDK 1.5.0_14.
> The problem I have is that by some reason onMessage method from my
> AtmosphereHandler implementation is not called...
>
> Here is my source:
>
> import java.io.IOException;
> import java.util.logging.Logger;
> import javax.servlet.http.HttpServletRequest;
> import javax.servlet.http.HttpServletResponse;
>
> import org.atmosphere.cpr.AtmosphereEvent;
> import org.atmosphere.cpr.AtmosphereHandler;
> import org.atmosphere.cpr.Broadcaster;
>
>
> public class ChatAtmosphereHandler implements
> AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
>
>     public ChatAtmosphereHandler() {
>     }
>
>     /**
>      * When a client send a request to its associated {@link
> AtmosphereHandler}, it can decide
>      * if the underlying connection can be suspended (creating a
> Continuation)
>      * or handle the connection synchronously.
>      *
>      * It is recommended to only suspend request for which HTTP method is a
> GET
>      * and use the POST method to send data to the server, without marking
> the
>      * connection as asynchronous.
>      *
>      * @param event an {@link AtmosphereEvent}
>      * @return the modified {@link AtmosphereEvent}
>      */
>     public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
> throws
>             IOException {
>    
>         System.out.println("ChatAtmosphereHandler.onEvent()");
>                        
>         event.suspend(5000);
>
>         return event;
>     }
>
>     /**
>      * This method is invoked when the {@link Broadcaster} execute a
> broadcast
>      * operations. When this method is invoked its associated {@link
> Broadcaster}, any
>      * suspended connection will be allowed to write the data back to its
>      * associated clients.
>      *
>      * @param event an {@link AtmosphereEvent}
>      * @return the modified {@link AtmosphereEvent}
>      */
>     public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
> throws
>             IOException {
>    
>         System.out.println("ChatAtmosphereHandler.onMessage()");
>        
>         return event;
>     }
> }
>  
>
> and below is my Tomcat output that does not show any probems with
> initialization:

You need to invoke Broadcaster.broadcast(anObject) to push data to your
suspended connection. Take a look here as an example:

https://atmosphere.dev.java.net/nonav/xref/org/atmosphere/samples/chat/ChatAtmosphereHandler.html#105

Hope that help.

Thanks

-- Jeanfrancois



>
> Apr 29, 2009 4:40:30 PM org.apache.catalina.core.AprLifecycleListener init
> INFO: The APR based Apache Tomcat Native library which allows optimal
> performance in production environments was not found on the
> java.library.path:
> C:\Java\jdk1.5.0_14\bin;.;C:\WINXP\system32;C:\WINXP;C:/Program
> Files/Java/jre6/bin/client;C:/Program
> Files/Java/jre6/bin;C:\Oracle11g\product\11.1.0\db_1\bin;C:\WINXP\system32;C:\WINXP;C:\WINXP\System32\Wbem;C:\Program
> Files\Windows Imaging\;C:\Program
> Files\TortoiseSVN\bin;C:\Java\frameworks\openAIM;C:\Program
> Files\QuickTime\QTSystem\;C:\Java\JProbe 8.0.1\bin;C:\Program Files\Common
> Files\Intuit\QBPOSSDKRuntime;C:\WINXP\system32\WindowsPowerShell\v1.0
> Apr 29, 2009 4:40:30 PM org.apache.tomcat.util.net.NioSelectorPool
> getSharedSelector
> INFO: Using a shared selector for servlet write/read
> Apr 29, 2009 4:40:30 PM org.apache.coyote.http11.Http11NioProtocol init
> INFO: Initializing Coyote HTTP/1.1 on http-8080
> Apr 29, 2009 4:40:30 PM org.apache.catalina.startup.Catalina load
> INFO: Initialization processed in 801 ms
> Apr 29, 2009 4:40:30 PM org.apache.catalina.core.StandardService start
> INFO: Starting service Catalina
> Apr 29, 2009 4:40:30 PM org.apache.catalina.core.StandardEngine start
> INFO: Starting Servlet Engine: Apache Tomcat/6.0.18
> Apr 29, 2009 4:40:30 PM org.atmosphere.cpr.AtmosphereServlet
> loadAtmosphereDotXml
> INFO: Sucessfully loaded com.msnger.atmosphere.ChatAtmosphereHandler@1e1dadb
> mapped to context-path /atmosphereHandler
> Apr 29, 2009 4:40:30 PM org.atmosphere.cpr.AtmosphereServlet
> autoDetectContainer
> INFO: Atmosphere Framework running under container Tomcat version 6.0.x
> Apr 29, 2009 4:40:31 PM org.apache.coyote.http11.Http11NioProtocol start
> INFO: Starting Coyote HTTP/1.1 on http-8080
> Apr 29, 2009 4:40:31 PM org.apache.jk.common.ChannelSocket init
> INFO: JK: ajp13 listening on /0.0.0.0:8009
> Apr 29, 2009 4:40:31 PM org.apache.jk.server.JkMain start
> INFO: Jk running ID=0 time=0/31  config=null
> Apr 29, 2009 4:40:31 PM org.apache.catalina.startup.Catalina start
> INFO: Server startup in 489 ms
> ChatAtmosphereHandler.onEvent()
>
>
> I use IE to execute handler URL directly and I see my request hanging around
> for expected 5 seconds before I get response with empty page. Everything is
> fine, but why onMessage() is not called?
> What did I miss here?
>
> Thanks

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: onMessage method is not called

Bezel
I expected it to be called when the response times out as well, is it correct?
Reply | Threaded
Open this post in threaded view
|

Re: onMessage method is not called

Jeanfrancois Arcand
Salut,

Bezel wrote:
> I expected it to be called when the response times out as well, is it
> correct?

Hum...I agree you need to be notified, but looking at my own code :-)
the onEvent() should be called. So you found an issue. Can you file an
issue here:

https://atmosphere.dev.java.net/issues/

Now I'm interested to learn why you were under the impression the
onMessage was supporsed to be invoked. IS it in the documentation?

Working on a fix.

Thanks!!!

-- Jeanfrancois

>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: onMessage method is not called

Bezel
Thanks for your crazy fast replies.
Yes, I got this impression based on the javadocs for onMessage method in your ChatAtmosphereHandler implementation:

"Invoked when a call to {@link Broadcaster#broadcast(java.lang.Object)} is
issued or when the response times out, e.g whne the value {@link AtmosphereEvent#suspend(long)}
expires."

Now I see that javadoc for AtmosphereHandler interface does not mention it :)


Jeanfrancois Arcand wrote
Salut,

Bezel wrote:
> I expected it to be called when the response times out as well, is it
> correct?

Hum...I agree you need to be notified, but looking at my own code :-)
the onEvent() should be called. So you found an issue. Can you file an
issue here:

https://atmosphere.dev.java.net/issues/

Now I'm interested to learn why you were under the impression the
onMessage was supporsed to be invoked. IS it in the documentation?

Working on a fix.

Thanks!!!

-- Jeanfrancois

>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@atmosphere.dev.java.net
For additional commands, e-mail: users-help@atmosphere.dev.java.net
Reply | Threaded
Open this post in threaded view
|

Re: onMessage method is not called

Bezel
I'm sorry for being slow or stupid, but I still can't get the concept of broadcasting messages.

Here is my class:

public class ChatAtmosphereHandler implements AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {

    public ChatAtmosphereHandler() {
    }
   
    public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws
            IOException {
   
        System.out.println("ChatAtmosphereHandler.onEvent()");
       
        HttpServletRequest req = event.getRequest();
        HttpServletResponse res = event.getResponse();

        res.setContentType("text/html");
        res.addHeader("Cache-Control", "private");
        res.addHeader("Pragma", "no-cache");
        res.getWriter().flush();
                                   
        event.suspend(5000);
       
        event.getBroadcaster().broadcast("broadcast message");
        res.getWriter().write("success");
        res.getWriter().flush();              

        return event;
    }
   
    public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws
            IOException {
   
        System.out.println("ChatAtmosphereHandler.onMessage()");
       
        return event;
    }
}

Idea is simple - I send a request that should be suspended with timeout (5 secs for example) and than other thread would broadcast a message to this request using event. For simplicity I did not do any tricks with multiple threads here and simply after suspending the event tried to do the broadcast. Is it correct or it MUST be another thread doing a broadcast?

In my example I still don't see onMessage() method invocation...
Reply | Threaded
Open this post in threaded view
|

Re: onMessage method is not called

Jeanfrancois Arcand
In reply to this post by Bezel
Salut,

Bezel wrote:

> Thanks for your crazy fast replies.
> Yes, I got this impression based on the javadocs for onMessage method in
> your ChatAtmosphereHandler implementation:
>
> "Invoked when a call to {@link Broadcaster#broadcast(java.lang.Object)} is
> issued or when the response times out, e.g whne the value {@link
> AtmosphereEvent#suspend(long)}
> expires."
>
> Now I see that javadoc for AtmosphereHandler interface does not mention it
> :)

ah I will fix that :-) Actually the more I think of it calling onMessage
makes more sense as you will get access to the req/response object
before they can marked dirty. So you can always write a last message.

Testing the fix now, will reply here once commited/uploaded. Sorry about
that :-)

Thanks

-- Jeanfrancois


>
>
>
> Jeanfrancois Arcand wrote:
>> Salut,
>>
>> Bezel wrote:
>>> I expected it to be called when the response times out as well, is it
>>> correct?
>> Hum...I agree you need to be notified, but looking at my own code :-)
>> the onEvent() should be called. So you found an issue. Can you file an
>> issue here:
>>
>> https://atmosphere.dev.java.net/issues/
>>
>> Now I'm interested to learn why you were under the impression the
>> onMessage was supporsed to be invoked. IS it in the documentation?
>>
>> Working on a fix.
>>
>> Thanks!!!
>>
>> -- Jeanfrancois
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: onMessage method is not called

Bezel
Agree.
onEvent will be called for new events and onMessage for something happened with the existing events.
It will make it easier to avoid event status check in onEvent method.

Jeanfrancois Arcand wrote
Salut,

Bezel wrote:
> Thanks for your crazy fast replies.
> Yes, I got this impression based on the javadocs for onMessage method in
> your ChatAtmosphereHandler implementation:
>
> "Invoked when a call to {@link Broadcaster#broadcast(java.lang.Object)} is
> issued or when the response times out, e.g whne the value {@link
> AtmosphereEvent#suspend(long)}
> expires."
>
> Now I see that javadoc for AtmosphereHandler interface does not mention it
> :)

ah I will fix that :-) Actually the more I think of it calling onMessage
makes more sense as you will get access to the req/response object
before they can marked dirty. So you can always write a last message.

Testing the fix now, will reply here once commited/uploaded. Sorry about
that :-)

Thanks

-- Jeanfrancois


>
>
>
> Jeanfrancois Arcand wrote:
>> Salut,
>>
>> Bezel wrote:
>>> I expected it to be called when the response times out as well, is it
>>> correct?
>> Hum...I agree you need to be notified, but looking at my own code :-)
>> the onEvent() should be called. So you found an issue. Can you file an
>> issue here:
>>
>> https://atmosphere.dev.java.net/issues/
>>
>> Now I'm interested to learn why you were under the impression the
>> onMessage was supporsed to be invoked. IS it in the documentation?
>>
>> Working on a fix.
>>
>> Thanks!!!
>>
>> -- Jeanfrancois
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe@atmosphere.dev.java.net
>> For additional commands, e-mail: users-help@atmosphere.dev.java.net
>>
>>
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@atmosphere.dev.java.net
For additional commands, e-mail: users-help@atmosphere.dev.java.net
Reply | Threaded
Open this post in threaded view
|

Re: onMessage method is not called

Jeanfrancois Arcand
In reply to this post by Bezel
Salut,

Bezel wrote:
> I'm sorry for being slow or stupid, but I still can't get the concept of
> broadcasting messages.

Not at all.

>
> Here is my class:
>
> public class ChatAtmosphereHandler implements
> AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
>
>     public ChatAtmosphereHandler() {
>     }
>    
>     public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
> throws
>             IOException {
>    
>         System.out.println("ChatAtmosphereHandler.onEvent()");
>        
>         HttpServletRequest req = event.getRequest();
>         HttpServletResponse res = event.getResponse();
>
>         res.setContentType("text/html");
>         res.addHeader("Cache-Control", "private");
>         res.addHeader("Pragma", "no-cache");
>         res.getWriter().flush();
>                                    
>         event.suspend(5000);
>        
>         event.getBroadcaster().broadcast("broadcast message");
>         res.getWriter().write("success");
>         res.getWriter().flush();              
>
>         return event;
>     }
>    
>     public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
> throws
>             IOException {
>    
>         System.out.println("ChatAtmosphereHandler.onMessage()");
>        
>         return event;
>     }
> }
>
> Idea is simple - I send a request that should be suspended with timeout (5
> secs for example) and than other thread would broadcast a message to this
> request using event. For simplicity I did not do any tricks with multiple
> threads here and simply after suspending the event tried to do the
> broadcast. Is it correct or it MUST be another thread doing a broadcast?
>
> In my example I still don't see onMessage() method invocation...

Hum you should but your found a corner case where the Broadcaster
doesn't get called if you do suspend() then broadcast() on the same
request it doesn't work. I will fix that as well now.

Wow thanks! I will attach the new jar in 10 minutes or so. Just need to
test :-)

--Jeanfrancois





---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: (fixed) onMessage method is not called

Jeanfrancois Arcand
Salut,

I've filled:

https://atmosphere.dev.java.net/issues/show_bug.cgi?id=5
https://atmosphere.dev.java.net/issues/show_bug.cgi?id=6

I'm attaching the atmosphere-cpr new jar to this email.

Notes:

(1) On Tomcat, you need to add, in server.xml, the following Valve in
order to get timed out event.

<Valve className="org.apache.catalina.valves.CometConnectionManagerValve"/>

(2) The onMessages(...) will be invoked on times out connection. You can
detect by doing:

AtmosphereEvent.isResumedOnTimeout()


Let me know how it goes.

A+

-- Jeanfrancois

Jeanfrancois Arcand wrote:

> Salut,
>
> Bezel wrote:
>> I'm sorry for being slow or stupid, but I still can't get the concept of
>> broadcasting messages.
>
> Not at all.
>
>>
>> Here is my class:
>>
>> public class ChatAtmosphereHandler implements
>> AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
>>
>>     public ChatAtmosphereHandler() {
>>     }
>>         public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
>> throws
>>             IOException {
>>        
>>         System.out.println("ChatAtmosphereHandler.onEvent()");
>>                 HttpServletRequest req = event.getRequest();
>>         HttpServletResponse res = event.getResponse();
>>
>>         res.setContentType("text/html");
>>         res.addHeader("Cache-Control", "private");
>>         res.addHeader("Pragma", "no-cache");
>>         res.getWriter().flush();
>>                                             event.suspend(5000);
>>                 event.getBroadcaster().broadcast("broadcast message");
>>         res.getWriter().write("success");
>>         res.getWriter().flush();              
>>         return event;
>>     }
>>         public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
>> throws
>>             IOException {
>>        
>>         System.out.println("ChatAtmosphereHandler.onMessage()");
>>                 return event;
>>     }
>> }
>>
>> Idea is simple - I send a request that should be suspended with
>> timeout (5
>> secs for example) and than other thread would broadcast a message to this
>> request using event. For simplicity I did not do any tricks with multiple
>> threads here and simply after suspending the event tried to do the
>> broadcast. Is it correct or it MUST be another thread doing a broadcast?
>>
>> In my example I still don't see onMessage() method invocation...
>
> Hum you should but your found a corner case where the Broadcaster
> doesn't get called if you do suspend() then broadcast() on the same
> request it doesn't work. I will fix that as well now.
>
> Wow thanks! I will attach the new jar in 10 minutes or so. Just need to
> test :-)
>
> --Jeanfrancois
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

atmosphere-portable-runtime-0.2-SNAPSHOT.jar (86K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: (fixed) onMessage method is not called

Bezel
Thanks for the patch. It definitelly improved the situation and I was able to receive onMessage() events based on timeout. And I was also getting onMessage() for the broadcast calls that comes right after suspend(). Basically all my old questions are answered and I got the idea how it should work.

But that's not the end of story and I'll continue to bug you with more issues/questions :)

In order to move forward I want to archive the following logic - if broadcast message received by onMessage() method (and I can identify that it's not by timeout using your new isResumedOnTimeout() method), I would like to commit the request and do not wait till timeout happens.
I've tried to do it by the following adjustement in my test class:

public class ChatAtmosphereHandler implements AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {

    public ChatAtmosphereHandler() {
    }
   
    public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws
            IOException {
   
        System.out.println("ChatAtmosphereHandler.onEvent()");
       
        HttpServletRequest req = event.getRequest();
        HttpServletResponse res = event.getResponse();

        res.setContentType("text/html");
        res.addHeader("Cache-Control", "private");
        res.addHeader("Pragma", "no-cache");
        res.getWriter().flush();
                                   
        event.suspend(5000);
       
        event.getBroadcaster().broadcast("broadcast message");
        res.getWriter().write("success");
        res.getWriter().flush();              

        return event;
    }
   
    public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws
            IOException {
   
        System.out.println("ChatAtmosphereHandler.onMessage() " + event.isResumedOnTimeout());
        if(!event.isResuming())
        event.resume();
        else
        System.out.println("already resuming");
       
               
        return event;
    }
}

Honestly I'm not sure if "if(!event.isResuming())" is a valid check in here, but without it it gets even worse :) The problem is that if I run this code and execute this test handler class via atmosphere servlet it performs correctly for the FIRST http request. Here is my output:

ChatAtmosphereHandler.onEvent()
ChatAtmosphereHandler.onMessage() false

But if I call this request one more time (simply refresh page in IE), output becomes funny:

ChatAtmosphereHandler.onEvent()
ChatAtmosphereHandler.onMessage() false
ChatAtmosphereHandler.onMessage() false
already resuming
ChatAtmosphereHandler.onMessage() false
already resuming
ChatAtmosphereHandler.onMessage() false
already resuming

THIRD time is even more buggy:

ChatAtmosphereHandler.onEvent()
ChatAtmosphereHandler.onMessage() false
ChatAtmosphereHandler.onMessage() false
already resuming
ChatAtmosphereHandler.onMessage() false
already resuming
ChatAtmosphereHandler.onMessage() false
already resuming
ChatAtmosphereHandler.onMessage() false
already resuming
ChatAtmosphereHandler.onMessage() false
already resuming


So, somehow onMessage() is getting called many times instead of one + you can see that "if(!event.isResuming())" check is true for some of them...

P.S. If I try to remove "if(!event.isResuming())"  check from my code and do event.resume() all the time I get my code into the infinite loop that does onMessage() all the time...

P.S.S. Are you sure <Valve className="org.apache.catalina.valves.CometConnectionManagerValve"/> goes into my Tomcat server.xml? I was not sure where to put it there, google it and found that somebody put it into application context.xml... I tried without it and with this valve inside context.xml and timeout actually work in both cases :)
Reply | Threaded
Open this post in threaded view
|

Re: (fixed) onMessage method is not called

Jeanfrancois Arcand
Salut,

Bezel wrote:
> Thanks for the patch. It definitelly improved the situation and I was able to
> receive onMessage() events based on timeout situations. And I was also
> getting onMessage() for the broadcast calls that comes right after
> suspend(). Basically all my old question are answered and I got the idea how
> it should work.

Great!

>
> But that's not the end of story and I'll continue to bug you with more
> issues/questions :)

Great :-)

>
> In order to move forward I want to archive the following logic - if
> broadcast message received by onMessage() method (and I can identify that
> it's not by timeout using your new isResumedOnTimeout() method), I would
> like to commit the request and do not wait till timeout happen.
> I've tried to do it by the following adjustement in my test class:
>
> public class ChatAtmosphereHandler implements
> AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
>
>     public ChatAtmosphereHandler() {
>     }
>    
>     public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
> throws
>             IOException {
>    
>         System.out.println("ChatAtmosphereHandler.onEvent()");
>        
>         HttpServletRequest req = event.getRequest();
>         HttpServletResponse res = event.getResponse();
>
>         res.setContentType("text/html");
>         res.addHeader("Cache-Control", "private");
>         res.addHeader("Pragma", "no-cache");
>         res.getWriter().flush();
>                                    
>         event.suspend(5000);
>        
>         event.getBroadcaster().broadcast("broadcast message");
>         res.getWriter().write("success");
>         res.getWriter().flush();              
>
>         return event;
>     }
>    
>     public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
> throws
>             IOException {
>    
>         System.out.println("ChatAtmosphereHandler.onMessage() " +
> event.isResumedOnTimeout());
>         if(!event.isResuming())
>         event.resume();
>         else
>         System.out.println("already resuming");
>        
>                
>         return event;
>     }
> }
>
> Honestly I'm not sure if "if(!event.isResuming())" is a valid check in here,
> but without it it gets even worse :)

isSuspended will return true so you can always use it as well.


  The problem is that if I run this code

> and execute this test handler class via atmosphere servlet it performs
> correctly for the FIRST http request. Here is my output:
>
> ChatAtmosphereHandler.onEvent()
> ChatAtmosphereHandler.onMessage() false
>
> But if I call this request one more time (simply refresh page in IE), output
> becomes funny:
>
> ChatAtmosphereHandler.onEvent()
> ChatAtmosphereHandler.onMessage() false
> ChatAtmosphereHandler.onMessage() false
> already resuming
> ChatAtmosphereHandler.onMessage() false
> already resuming
> ChatAtmosphereHandler.onMessage() false
> already resuming
>
> THIRD time is even more buggy:

Here is what I think happens. When you refresh, the previous connection
gets closed and the associated AtmosphereEvent/Handler get notified. I
suspect if you output request.getRequestURI() you will see that the
onMessage is called because:

Atmosphere detect the client closed the connection and gives you a
chance to "clean up" associated resources. The issue here is calling
event.resume() should throw an IllegalStateException as the operation is
  invalid. I will add that support.

Now you should check for isResuming() and isResumedOnTimeout() before
calling event.resume(). I'm tempted to add a new API called
isBroadcasted() Or something like that to make the experience easier. In
your case it will means you just need to check if isBroadcasted()
returns true to resume the connection.




>
> ChatAtmosphereHandler.onEvent()
> ChatAtmosphereHandler.onMessage() false
> ChatAtmosphereHandler.onMessage() false
> already resuming
> ChatAtmosphereHandler.onMessage() false
> already resuming
> ChatAtmosphereHandler.onMessage() false
> already resuming
> ChatAtmosphereHandler.onMessage() false
> already resuming
> ChatAtmosphereHandler.onMessage() false
> already resuming
>
>
> So, somehow onMessage() is getting called many times instead of one + you
> can see that "if(!event.isResuming())" check is true for some of them...
>
> P.S. If I try to remove "if(!event.isResuming())"  check from my code and do
> event.resume() all the time I

Exactly. I need to fix that.

  get my code into the infinite loop that does
> onMessage() all the time...
>
> P.S.S. Are you sure <Valve
> className="org.apache.catalina.valves.CometConnectionManagerValve"/> goes
> into my Tomcat server.xml? I was not sure where to put it there, google it
> and found that somebody put it into application context.xml... I tried
> without it and with this valve inside context.xml and timeout actually work
> in both cases :)

context.xml will works as well, but per application.

Thanks for the feedback!!! Working on fix!

--Jeanfrancois



---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: (Resume/Suspend in same transaction) (fixed) onMessage method is not called

Jeanfrancois Arcand
Salut,

I've found one issue with the code I sent your yesterday. Mainly it
produced the loop when resuming (nice catch!). Attached is the. Now
looking at your example, there is a problem as you are doing:

(a) suspend(5000);
(b) broadcast()

and then inside onMessage()

(c) event.resume()

So as soon as you broadcast (b), you will resume (c) so (a) timed out
will never happen. So I think you need to change the time you broadcast
as it automatically resume() the response. One way is to broadcast an
Object in (b) and in onMessage avoid resuming when (b) broadcast.

How does that sound?

Thanks!

-- Jeanfrancois


Jeanfrancois Arcand wrote:

> Salut,
>
> Bezel wrote:
>> Thanks for the patch. It definitelly improved the situation and I was
>> able to
>> receive onMessage() events based on timeout situations. And I was also
>> getting onMessage() for the broadcast calls that comes right after
>> suspend(). Basically all my old question are answered and I got the
>> idea how
>> it should work.
>
> Great!
>
>>
>> But that's not the end of story and I'll continue to bug you with more
>> issues/questions :)
>
> Great :-)
>
>>
>> In order to move forward I want to archive the following logic - if
>> broadcast message received by onMessage() method (and I can identify that
>> it's not by timeout using your new isResumedOnTimeout() method), I would
>> like to commit the request and do not wait till timeout happen.
>> I've tried to do it by the following adjustement in my test class:
>>
>> public class ChatAtmosphereHandler implements
>> AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
>>
>>     public ChatAtmosphereHandler() {
>>     }
>>         public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
>> throws
>>             IOException {
>>        
>>         System.out.println("ChatAtmosphereHandler.onEvent()");
>>                 HttpServletRequest req = event.getRequest();
>>         HttpServletResponse res = event.getResponse();
>>
>>         res.setContentType("text/html");
>>         res.addHeader("Cache-Control", "private");
>>         res.addHeader("Pragma", "no-cache");
>>         res.getWriter().flush();
>>                                             event.suspend(5000);
>>                 event.getBroadcaster().broadcast("broadcast message");
>>         res.getWriter().write("success");
>>         res.getWriter().flush();              
>>         return event;
>>     }
>>         public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
>> throws
>>             IOException {
>>        
>>         System.out.println("ChatAtmosphereHandler.onMessage() " +
>> event.isResumedOnTimeout());
>>         if(!event.isResuming())
>>             event.resume();
>>         else
>>             System.out.println("already resuming");
>>                                 return event;
>>     }
>> }
>>
>> Honestly I'm not sure if "if(!event.isResuming())" is a valid check in
>> here,
>> but without it it gets even worse :)
>
> isSuspended will return true so you can always use it as well.
>
>
>  The problem is that if I run this code
>> and execute this test handler class via atmosphere servlet it performs
>> correctly for the FIRST http request. Here is my output:
>>
>> ChatAtmosphereHandler.onEvent()
>> ChatAtmosphereHandler.onMessage() false
>>
>> But if I call this request one more time (simply refresh page in IE),
>> output
>> becomes funny:
>>
>> ChatAtmosphereHandler.onEvent()
>> ChatAtmosphereHandler.onMessage() false
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>>
>> THIRD time is even more buggy:
>
> Here is what I think happens. When you refresh, the previous connection
> gets closed and the associated AtmosphereEvent/Handler get notified. I
> suspect if you output request.getRequestURI() you will see that the
> onMessage is called because:
>
> Atmosphere detect the client closed the connection and gives you a
> chance to "clean up" associated resources. The issue here is calling
> event.resume() should throw an IllegalStateException as the operation is
>  invalid. I will add that support.
>
> Now you should check for isResuming() and isResumedOnTimeout() before
> calling event.resume(). I'm tempted to add a new API called
> isBroadcasted() Or something like that to make the experience easier. In
> your case it will means you just need to check if isBroadcasted()
> returns true to resume the connection.
>
>
>
>
>>
>> ChatAtmosphereHandler.onEvent()
>> ChatAtmosphereHandler.onMessage() false
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>>
>>
>> So, somehow onMessage() is getting called many times instead of one + you
>> can see that "if(!event.isResuming())" check is true for some of them...
>>
>> P.S. If I try to remove "if(!event.isResuming())"  check from my code
>> and do
>> event.resume() all the time I
>
> Exactly. I need to fix that.
>
>  get my code into the infinite loop that does
>> onMessage() all the time...
>>
>> P.S.S. Are you sure <Valve
>> className="org.apache.catalina.valves.CometConnectionManagerValve"/> goes
>> into my Tomcat server.xml? I was not sure where to put it there,
>> google it
>> and found that somebody put it into application context.xml... I tried
>> without it and with this valve inside context.xml and timeout actually
>> work
>> in both cases :)
>
> context.xml will works as well, but per application.
>
> Thanks for the feedback!!! Working on fix!
>
> --Jeanfrancois
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

atmosphere-portable-runtime-0.2-SNAPSHOT.jar (86K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

RE: (fixed) onMessage method is not called

Bezel
In reply to this post by Jeanfrancois Arcand
Sorry, but I don't think I got a clear understanding why onMessage() is being called multiple times for subsequent requests.
 
Here is how I've modified onMessage method in my test class:
 

public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws

IOException {

System.out.println("ChatAtmosphereHandler.onMessage() " + event.isResumedOnTimeout() + " " + event.isResuming() + " " + event.isSuspended() + " | " + event.getRequest().getQueryString());

if(event.isSuspended())

event.resume();

else

System.out.println("already resuming");

return event;

}
 
Basically it gives me idea about all event status conditions + I've added getQueryString() output to clearly see what requests an event method call belongs to.
 
Results:
 
#1. I execute http://localhost:8080/iloveim/atmosphereHandler?1 in IE and I get that in the output:
 

ChatAtmosphereHandler.onEvent()

ChatAtmosphereHandler.onMessage() false false true | 1
 
#2. I execute http://localhost:8080/iloveim/atmosphereHandler?2 and the output is:
 

ChatAtmosphereHandler.onEvent()

ChatAtmosphereHandler.onMessage() false false true | 2

ChatAtmosphereHandler.onMessage() false true false | 2

already resuming

ChatAtmosphereHandler.onMessage() false true false | 2

already resuming

ChatAtmosphereHandler.onMessage() false true false | 2

already resuming

 
#3. I execute http://localhost:8080/iloveim/atmosphereHandler?3 and the output is:
 

ChatAtmosphereHandler.onEvent()

ChatAtmosphereHandler.onMessage() false false true | 3

ChatAtmosphereHandler.onMessage() false true false | 3

already resuming

ChatAtmosphereHandler.onMessage() false true false | 3

already resuming

ChatAtmosphereHandler.onMessage() false true false | 3

already resuming

ChatAtmosphereHandler.onMessage() false true false | 3

already resuming

ChatAtmosphereHandler.onMessage() false true false | 3

already resuming
 
Based on that I clearly see that event.resume() is being called only once per request (as I expected) and isSuspended() status works 100% correct :)
It's also look like all subsequent onMethod() calls are being produced AFTER event.resume() was executed and status of these calls always show event.isResuming()=true.
 
My questions would be:
 
1. Why onMethod() is called after I resumed the event?
2. Why the number of times onMethod() is called per request is getting increased? I've added request.getQueryString()  into the output to be 100% clear that there is no interractions with my old requests which are exected to be committed by that time (but I wanted to make sure).
Reply | Threaded
Open this post in threaded view
|

Re: (Resume/Suspend in same transaction) (fixed) onMessage method is not called

Bezel
In reply to this post by Jeanfrancois Arcand
Sorry, I did not notice this post before replying to you...

I just tried new JAR and it seems to me event.resume() does not work anymore.
Now I get onMessage() called 2 times:
 - right after broadcast message is sent (this is expected and my code execute event.resume() to commit the response)
 - I don't see response commited and in 5 seconds (my timeout) onMessage() is called again with event.isResumedOnTimeout()=true

It's not the way it has to work, right?


Jeanfrancois Arcand wrote
Salut,

I've found one issue with the code I sent your yesterday. Mainly it
produced the loop when resuming (nice catch!). Attached is the. Now
looking at your example, there is a problem as you are doing:

(a) suspend(5000);
(b) broadcast()

and then inside onMessage()

(c) event.resume()

So as soon as you broadcast (b), you will resume (c) so (a) timed out
will never happen. So I think you need to change the time you broadcast
as it automatically resume() the response. One way is to broadcast an
Object in (b) and in onMessage avoid resuming when (b) broadcast.

How does that sound?

Thanks!

-- Jeanfrancois


Jeanfrancois Arcand wrote:
> Salut,
>
> Bezel wrote:
>> Thanks for the patch. It definitelly improved the situation and I was
>> able to
>> receive onMessage() events based on timeout situations. And I was also
>> getting onMessage() for the broadcast calls that comes right after
>> suspend(). Basically all my old question are answered and I got the
>> idea how
>> it should work.
>
> Great!
>
>>
>> But that's not the end of story and I'll continue to bug you with more
>> issues/questions :)
>
> Great :-)
>
>>
>> In order to move forward I want to archive the following logic - if
>> broadcast message received by onMessage() method (and I can identify that
>> it's not by timeout using your new isResumedOnTimeout() method), I would
>> like to commit the request and do not wait till timeout happen.
>> I've tried to do it by the following adjustement in my test class:
>>
>> public class ChatAtmosphereHandler implements
>> AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
>>
>>     public ChatAtmosphereHandler() {
>>     }
>>         public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
>> throws
>>             IOException {
>>        
>>         System.out.println("ChatAtmosphereHandler.onEvent()");
>>                 HttpServletRequest req = event.getRequest();
>>         HttpServletResponse res = event.getResponse();
>>
>>         res.setContentType("text/html");
>>         res.addHeader("Cache-Control", "private");
>>         res.addHeader("Pragma", "no-cache");
>>         res.getWriter().flush();
>>                                             event.suspend(5000);
>>                 event.getBroadcaster().broadcast("broadcast message");
>>         res.getWriter().write("success");
>>         res.getWriter().flush();              
>>         return event;
>>     }
>>         public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
>> throws
>>             IOException {
>>        
>>         System.out.println("ChatAtmosphereHandler.onMessage() " +
>> event.isResumedOnTimeout());
>>         if(!event.isResuming())
>>             event.resume();
>>         else
>>             System.out.println("already resuming");
>>                                 return event;
>>     }
>> }
>>
>> Honestly I'm not sure if "if(!event.isResuming())" is a valid check in
>> here,
>> but without it it gets even worse :)
>
> isSuspended will return true so you can always use it as well.
>
>
>  The problem is that if I run this code
>> and execute this test handler class via atmosphere servlet it performs
>> correctly for the FIRST http request. Here is my output:
>>
>> ChatAtmosphereHandler.onEvent()
>> ChatAtmosphereHandler.onMessage() false
>>
>> But if I call this request one more time (simply refresh page in IE),
>> output
>> becomes funny:
>>
>> ChatAtmosphereHandler.onEvent()
>> ChatAtmosphereHandler.onMessage() false
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>>
>> THIRD time is even more buggy:
>
> Here is what I think happens. When you refresh, the previous connection
> gets closed and the associated AtmosphereEvent/Handler get notified. I
> suspect if you output request.getRequestURI() you will see that the
> onMessage is called because:
>
> Atmosphere detect the client closed the connection and gives you a
> chance to "clean up" associated resources. The issue here is calling
> event.resume() should throw an IllegalStateException as the operation is
>  invalid. I will add that support.
>
> Now you should check for isResuming() and isResumedOnTimeout() before
> calling event.resume(). I'm tempted to add a new API called
> isBroadcasted() Or something like that to make the experience easier. In
> your case it will means you just need to check if isBroadcasted()
> returns true to resume the connection.
>
>
>
>
>>
>> ChatAtmosphereHandler.onEvent()
>> ChatAtmosphereHandler.onMessage() false
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>> ChatAtmosphereHandler.onMessage() false
>> already resuming
>>
>>
>> So, somehow onMessage() is getting called many times instead of one + you
>> can see that "if(!event.isResuming())" check is true for some of them...
>>
>> P.S. If I try to remove "if(!event.isResuming())"  check from my code
>> and do
>> event.resume() all the time I
>
> Exactly. I need to fix that.
>
>  get my code into the infinite loop that does
>> onMessage() all the time...
>>
>> P.S.S. Are you sure <Valve
>> className="org.apache.catalina.valves.CometConnectionManagerValve"/> goes
>> into my Tomcat server.xml? I was not sure where to put it there,
>> google it
>> and found that somebody put it into application context.xml... I tried
>> without it and with this valve inside context.xml and timeout actually
>> work
>> in both cases :)
>
> context.xml will works as well, but per application.
>
> Thanks for the feedback!!! Working on fix!
>
> --Jeanfrancois
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@atmosphere.dev.java.net
> For additional commands, e-mail: users-help@atmosphere.dev.java.net
>

 
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@atmosphere.dev.java.net
For additional commands, e-mail: users-help@atmosphere.dev.java.net
Reply | Threaded
Open this post in threaded view
|

Re: (Resume/Suspend in same transaction) (fixed) onMessage method is not called

Jeanfrancois Arcand
Salut,

Bezel wrote:
> Sorry, I did not notice this post before replying to you...
>
> I just tried new JAR and it seems to me event.resume() does not work
> anymore.
> Now I get onMessage() called 2 times:
>  - right after broadcast message is sent (this is expected and my code
> execute event.resume() to commit the response)

Right, and when you do that, you also resume the request, right?


>  - I don't see response commited and in 5 seconds (my timeout) onMessage()
> is called again with event.isResumedOnTimeout()=true
>
> It's not the way it has to work, right?

I agree the isResumedOnTimeout should not happens and the response
should be commited. That scenario I didn't tested enough I guess.
Working on it.

A+

-- Jeanfrancois


>
>
>
> Jeanfrancois Arcand wrote:
>> Salut,
>>
>> I've found one issue with the code I sent your yesterday. Mainly it
>> produced the loop when resuming (nice catch!). Attached is the. Now
>> looking at your example, there is a problem as you are doing:
>>
>> (a) suspend(5000);
>> (b) broadcast()
>>
>> and then inside onMessage()
>>
>> (c) event.resume()
>>
>> So as soon as you broadcast (b), you will resume (c) so (a) timed out
>> will never happen. So I think you need to change the time you broadcast
>> as it automatically resume() the response. One way is to broadcast an
>> Object in (b) and in onMessage avoid resuming when (b) broadcast.
>>
>> How does that sound?
>>
>> Thanks!
>>
>> -- Jeanfrancois
>>
>>
>> Jeanfrancois Arcand wrote:
>>> Salut,
>>>
>>> Bezel wrote:
>>>> Thanks for the patch. It definitelly improved the situation and I was
>>>> able to
>>>> receive onMessage() events based on timeout situations. And I was also
>>>> getting onMessage() for the broadcast calls that comes right after
>>>> suspend(). Basically all my old question are answered and I got the
>>>> idea how
>>>> it should work.
>>> Great!
>>>
>>>> But that's not the end of story and I'll continue to bug you with more
>>>> issues/questions :)
>>> Great :-)
>>>
>>>> In order to move forward I want to archive the following logic - if
>>>> broadcast message received by onMessage() method (and I can identify
>>>> that
>>>> it's not by timeout using your new isResumedOnTimeout() method), I would
>>>> like to commit the request and do not wait till timeout happen.
>>>> I've tried to do it by the following adjustement in my test class:
>>>>
>>>> public class ChatAtmosphereHandler implements
>>>> AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
>>>>
>>>>     public ChatAtmosphereHandler() {
>>>>     }
>>>>         public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>>>> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event)
>>>> throws
>>>>             IOException {
>>>>        
>>>>         System.out.println("ChatAtmosphereHandler.onEvent()");
>>>>                 HttpServletRequest req = event.getRequest();
>>>>         HttpServletResponse res = event.getResponse();
>>>>
>>>>         res.setContentType("text/html");
>>>>         res.addHeader("Cache-Control", "private");
>>>>         res.addHeader("Pragma", "no-cache");
>>>>         res.getWriter().flush();
>>>>                                             event.suspend(5000);
>>>>                 event.getBroadcaster().broadcast("broadcast message");
>>>>         res.getWriter().write("success");
>>>>         res.getWriter().flush();              
>>>>         return event;
>>>>     }
>>>>         public AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>>>> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>>>> event)
>>>> throws
>>>>             IOException {
>>>>        
>>>>         System.out.println("ChatAtmosphereHandler.onMessage() " +
>>>> event.isResumedOnTimeout());
>>>>         if(!event.isResuming())
>>>>             event.resume();
>>>>         else
>>>>             System.out.println("already resuming");
>>>>                                 return event;
>>>>     }
>>>> }
>>>>
>>>> Honestly I'm not sure if "if(!event.isResuming())" is a valid check in
>>>> here,
>>>> but without it it gets even worse :)
>>> isSuspended will return true so you can always use it as well.
>>>
>>>
>>>  The problem is that if I run this code
>>>> and execute this test handler class via atmosphere servlet it performs
>>>> correctly for the FIRST http request. Here is my output:
>>>>
>>>> ChatAtmosphereHandler.onEvent()
>>>> ChatAtmosphereHandler.onMessage() false
>>>>
>>>> But if I call this request one more time (simply refresh page in IE),
>>>> output
>>>> becomes funny:
>>>>
>>>> ChatAtmosphereHandler.onEvent()
>>>> ChatAtmosphereHandler.onMessage() false
>>>> ChatAtmosphereHandler.onMessage() false
>>>> already resuming
>>>> ChatAtmosphereHandler.onMessage() false
>>>> already resuming
>>>> ChatAtmosphereHandler.onMessage() false
>>>> already resuming
>>>>
>>>> THIRD time is even more buggy:
>>> Here is what I think happens. When you refresh, the previous connection
>>> gets closed and the associated AtmosphereEvent/Handler get notified. I
>>> suspect if you output request.getRequestURI() you will see that the
>>> onMessage is called because:
>>>
>>> Atmosphere detect the client closed the connection and gives you a
>>> chance to "clean up" associated resources. The issue here is calling
>>> event.resume() should throw an IllegalStateException as the operation is
>>>  invalid. I will add that support.
>>>
>>> Now you should check for isResuming() and isResumedOnTimeout() before
>>> calling event.resume(). I'm tempted to add a new API called
>>> isBroadcasted() Or something like that to make the experience easier. In
>>> your case it will means you just need to check if isBroadcasted()
>>> returns true to resume the connection.
>>>
>>>
>>>
>>>
>>>> ChatAtmosphereHandler.onEvent()
>>>> ChatAtmosphereHandler.onMessage() false
>>>> ChatAtmosphereHandler.onMessage() false
>>>> already resuming
>>>> ChatAtmosphereHandler.onMessage() false
>>>> already resuming
>>>> ChatAtmosphereHandler.onMessage() false
>>>> already resuming
>>>> ChatAtmosphereHandler.onMessage() false
>>>> already resuming
>>>> ChatAtmosphereHandler.onMessage() false
>>>> already resuming
>>>>
>>>>
>>>> So, somehow onMessage() is getting called many times instead of one +
>>>> you
>>>> can see that "if(!event.isResuming())" check is true for some of them...
>>>>
>>>> P.S. If I try to remove "if(!event.isResuming())"  check from my code
>>>> and do
>>>> event.resume() all the time I
>>> Exactly. I need to fix that.
>>>
>>>  get my code into the infinite loop that does
>>>> onMessage() all the time...
>>>>
>>>> P.S.S. Are you sure <Valve
>>>> className="org.apache.catalina.valves.CometConnectionManagerValve"/>
>>>> goes
>>>> into my Tomcat server.xml? I was not sure where to put it there,
>>>> google it
>>>> and found that somebody put it into application context.xml... I tried
>>>> without it and with this valve inside context.xml and timeout actually
>>>> work
>>>> in both cases :)
>>> context.xml will works as well, but per application.
>>>
>>> Thanks for the feedback!!! Working on fix!
>>>
>>> --Jeanfrancois
>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>  
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: (Resume/Suspend in same transaction) (fixed) onMessage method is not called

Jeanfrancois Arcand
Salut,

try the attachment and let me know :-)

Thanks!

-- Jeanfrancois

Jeanfrancois Arcand wrote:

> Salut,
>
> Bezel wrote:
>> Sorry, I did not notice this post before replying to you...
>>
>> I just tried new JAR and it seems to me event.resume() does not work
>> anymore.
>> Now I get onMessage() called 2 times:
>>  - right after broadcast message is sent (this is expected and my code
>> execute event.resume() to commit the response)
>
> Right, and when you do that, you also resume the request, right?
>
>
>>  - I don't see response commited and in 5 seconds (my timeout)
>> onMessage()
>> is called again with event.isResumedOnTimeout()=true
>>
>> It's not the way it has to work, right?
>
> I agree the isResumedOnTimeout should not happens and the response
> should be commited. That scenario I didn't tested enough I guess.
> Working on it.
>
> A+
>
> -- Jeanfrancois
>
>
>>
>>
>>
>> Jeanfrancois Arcand wrote:
>>> Salut,
>>>
>>> I've found one issue with the code I sent your yesterday. Mainly it
>>> produced the loop when resuming (nice catch!). Attached is the. Now
>>> looking at your example, there is a problem as you are doing:
>>>
>>> (a) suspend(5000);
>>> (b) broadcast()
>>>
>>> and then inside onMessage()
>>>
>>> (c) event.resume()
>>>
>>> So as soon as you broadcast (b), you will resume (c) so (a) timed out
>>> will never happen. So I think you need to change the time you
>>> broadcast as it automatically resume() the response. One way is to
>>> broadcast an Object in (b) and in onMessage avoid resuming when (b)
>>> broadcast.
>>>
>>> How does that sound?
>>>
>>> Thanks!
>>>
>>> -- Jeanfrancois
>>>
>>>
>>> Jeanfrancois Arcand wrote:
>>>> Salut,
>>>>
>>>> Bezel wrote:
>>>>> Thanks for the patch. It definitelly improved the situation and I
>>>>> was able to
>>>>> receive onMessage() events based on timeout situations. And I was also
>>>>> getting onMessage() for the broadcast calls that comes right after
>>>>> suspend(). Basically all my old question are answered and I got the
>>>>> idea how
>>>>> it should work.
>>>> Great!
>>>>
>>>>> But that's not the end of story and I'll continue to bug you with more
>>>>> issues/questions :)
>>>> Great :-)
>>>>
>>>>> In order to move forward I want to archive the following logic - if
>>>>> broadcast message received by onMessage() method (and I can identify
>>>>> that
>>>>> it's not by timeout using your new isResumedOnTimeout() method), I
>>>>> would
>>>>> like to commit the request and do not wait till timeout happen.
>>>>> I've tried to do it by the following adjustement in my test class:
>>>>>
>>>>> public class ChatAtmosphereHandler implements
>>>>> AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
>>>>>
>>>>>     public ChatAtmosphereHandler() {
>>>>>     }
>>>>>         public AtmosphereEvent<HttpServletRequest,
>>>>> HttpServletResponse>
>>>>> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>>>>> event)
>>>>> throws
>>>>>             IOException {
>>>>>                System.out.println("ChatAtmosphereHandler.onEvent()");
>>>>>                 HttpServletRequest req = event.getRequest();
>>>>>         HttpServletResponse res = event.getResponse();
>>>>>
>>>>>         res.setContentType("text/html");
>>>>>         res.addHeader("Cache-Control", "private");
>>>>>         res.addHeader("Pragma", "no-cache");
>>>>>         res.getWriter().flush();
>>>>>                                             event.suspend(5000);
>>>>>                 event.getBroadcaster().broadcast("broadcast message");
>>>>>         res.getWriter().write("success");
>>>>>         res.getWriter().flush();                      return event;
>>>>>     }
>>>>>         public AtmosphereEvent<HttpServletRequest,
>>>>> HttpServletResponse>
>>>>> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse>
>>>>> event)
>>>>> throws
>>>>>             IOException {
>>>>>                
>>>>> System.out.println("ChatAtmosphereHandler.onMessage() " +
>>>>> event.isResumedOnTimeout());
>>>>>         if(!event.isResuming())
>>>>>             event.resume();
>>>>>         else
>>>>>             System.out.println("already resuming");
>>>>>                                 return event;
>>>>>     }
>>>>> }
>>>>>
>>>>> Honestly I'm not sure if "if(!event.isResuming())" is a valid check
>>>>> in here,
>>>>> but without it it gets even worse :)
>>>> isSuspended will return true so you can always use it as well.
>>>>
>>>>
>>>>  The problem is that if I run this code
>>>>> and execute this test handler class via atmosphere servlet it performs
>>>>> correctly for the FIRST http request. Here is my output:
>>>>>
>>>>> ChatAtmosphereHandler.onEvent()
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>>
>>>>> But if I call this request one more time (simply refresh page in
>>>>> IE), output
>>>>> becomes funny:
>>>>>
>>>>> ChatAtmosphereHandler.onEvent()
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> already resuming
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> already resuming
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> already resuming
>>>>>
>>>>> THIRD time is even more buggy:
>>>> Here is what I think happens. When you refresh, the previous
>>>> connection gets closed and the associated AtmosphereEvent/Handler
>>>> get notified. I suspect if you output request.getRequestURI() you
>>>> will see that the onMessage is called because:
>>>>
>>>> Atmosphere detect the client closed the connection and gives you a
>>>> chance to "clean up" associated resources. The issue here is calling
>>>> event.resume() should throw an IllegalStateException as the
>>>> operation is  invalid. I will add that support.
>>>>
>>>> Now you should check for isResuming() and isResumedOnTimeout()
>>>> before calling event.resume(). I'm tempted to add a new API called
>>>> isBroadcasted() Or something like that to make the experience
>>>> easier. In your case it will means you just need to check if
>>>> isBroadcasted() returns true to resume the connection.
>>>>
>>>>
>>>>
>>>>
>>>>> ChatAtmosphereHandler.onEvent()
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> already resuming
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> already resuming
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> already resuming
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> already resuming
>>>>> ChatAtmosphereHandler.onMessage() false
>>>>> already resuming
>>>>>
>>>>>
>>>>> So, somehow onMessage() is getting called many times instead of one +
>>>>> you
>>>>> can see that "if(!event.isResuming())" check is true for some of
>>>>> them...
>>>>>
>>>>> P.S. If I try to remove "if(!event.isResuming())"  check from my
>>>>> code and do
>>>>> event.resume() all the time I
>>>> Exactly. I need to fix that.
>>>>
>>>>  get my code into the infinite loop that does
>>>>> onMessage() all the time...
>>>>>
>>>>> P.S.S. Are you sure <Valve
>>>>> className="org.apache.catalina.valves.CometConnectionManagerValve"/>
>>>>> goes
>>>>> into my Tomcat server.xml? I was not sure where to put it there,
>>>>> google it
>>>>> and found that somebody put it into application context.xml... I tried
>>>>> without it and with this valve inside context.xml and timeout
>>>>> actually work
>>>>> in both cases :)
>>>> context.xml will works as well, but per application.
>>>>
>>>> Thanks for the feedback!!! Working on fix!
>>>>
>>>> --Jeanfrancois
>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>>
>>>  
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

atmosphere-portable-runtime-0.2-SNAPSHOT.jar (90K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: (Resume/Suspend in same transaction) (fixed) onMessage method is not called

Bezel
Sorry, I've been out for couple of days.

I've tried your patch and it looks good now.
My test class works exactly as expected.

I'll move forward now to use your framework in the real application and let you know if I have issues.

Thanks a lot for your assistance!
Reply | Threaded
Open this post in threaded view
|

Re: (Resume/Suspend in same transaction) (fixed) onMessage method is not called

Jeanfrancois Arcand


Bezel wrote:
> Sorry, I've been out for couple of days.
>
> I've tried your patch and it looks good now.
> My test class works exactly as expected.
>
> I'll move forward now to use your framework in the real application and let
> you know if I have issues.
>
> Thanks a lot for your assistance!

Thanks for the feedback! Let me know if you face any other issues.

-- Jeanfrancois


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: (Resume/Suspend in same transaction) (fixed) onMessage method is not called

Bezel
Oh man... I have new issues to report.
I've tried to do a broadcast from an external thread and I'm getting really strange results.
Here is my code to make is easier:

public class TestAtmosphereHandler implements AtmosphereHandler<HttpServletRequest, HttpServletResponse>  {
       
        private static final String CONTENT_TYPE = "text/html;charset=UTF-8";


    public TestAtmosphereHandler() {
    }

    /**
     * When a client send a request to its associated {@link AtmosphereHandler}, it can decide
     * if the underlying connection can be suspended (creating a Continuation)
     * or handle the connection synchronously.
     *
     * It is recommended to only suspend request for which HTTP method is a GET
     * and use the POST method to send data to the server, without marking the
     * connection as asynchronous.
     *
     * @param event an {@link AtmosphereEvent}
     * @return the modified {@link AtmosphereEvent}
     */
    public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onEvent(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws IOException {
   
    System.out.println("\n\n" + new java.util.Date() + " ChatAtmosphereHandler.onEvent() for " + event.getRequest().getQueryString());
       
        event.suspend(5000);
       
        // option 1
        //event.getBroadcaster().broadcast("message for : " + event.getRequest().getQueryString());
       
        // option 2
        TestRunner runner = new TestRunner(event);
        Thread thread = new Thread(runner);
        thread.start();
               
        return event;
    }

    /**
     * This method is invoked when the {@link Broadcaster} execute a broadcast
     * operations. When this method is invoked its associated {@link Broadcaster}, any
     * suspended connection will be allowed to write the data back to its
     * associated clients.
     *
     * @param event an {@link AtmosphereEvent}
     * @return the modified {@link AtmosphereEvent}
     */
    public AtmosphereEvent<HttpServletRequest, HttpServletResponse> onMessage(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) throws
            IOException {
   
    System.out.println("ChatAtmosphereHandler.onMessage() | isResumedOnTimeout: " + event.isResumedOnTimeout() + " | isResuming: "  + event.isResuming() + " | isSuspended: " + event.isSuspended() + " | ");
   
    try {
            HttpServletRequest request = event.getRequest();
            HttpSession session = request.getSession();
            String sessionId = session.getId();
                           
                if(event.isResumedOnTimeout()) {
                // timeout, no response
                System.out.println(new java.util.Date() + " ChatAtmosphereHandler.onMessage() - timeout situation");
                outputMessage("", event);                
                }
                else {        
                System.out.println(new java.util.Date() + " ChatAtmosphereHandler.onMessage() - NOT a timeout situation");
                // event was resumed by a sender. need to send broadcasted message
                String message = (String) event.getMessage();
                outputMessage(message, event);
                }
                       
               
            }
    catch(Exception e) {
    e.printStackTrace();
    }
       
        return event;
    }
   
    public static void outputMessage(String messageText, AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) {
    HttpServletResponse response = event.getResponse();
    HttpServletRequest request = event.getRequest();
    try {    
    response.setContentType(CONTENT_TYPE);
    response.addHeader("Pragma","No-cache");
    response.addHeader("Cache-Control","no-cache");
    response.addHeader("Expires","1");
       
    PrintWriter writer = response.getWriter();
    writer.println(messageText);
    writer.flush();
    writer.close();    
   
    System.out.println(new java.util.Date() + " ChatAtmosphereHandler.outputMessage(): " + request.getQueryString());
    }
    catch(Exception e) {
    e.printStackTrace();
    }
    }
       
}

public class TestRunner implements Runnable {
       
        private AtmosphereEvent<HttpServletRequest, HttpServletResponse> event;
       
        public TestRunner(AtmosphereEvent<HttpServletRequest, HttpServletResponse> event) {
                this.event = event;
        }

        public void run() {
                // TODO Auto-generated method stub
                try {
                        Thread.currentThread().sleep(2000);
                        System.out.println("Broadcasting message...");
                        event.getBroadcaster().broadcast(String.valueOf(System.currentTimeMillis()));
                }
                catch(Exception e) {
                        e.printStackTrace();
                }

        }

}

You can see that onEvent() method does the suspend(5000) and kicks off the external thread that broadcasts a message in 2 secs. I expect to receive ONE onMessage event from the handler with event.isResumedOnTimeout=false...
The fact is that I get this as expected BUT in 5 more seconds I get one more onEvent call!!! And it follows up with TWO onMessage events (which don't include session object and gives me NullPointerException).

Here is my output for http://localhost:8080/test/testAtmosphereHandler?1 request:

Wed May 13 17:52:15 EDT 2009 ChatAtmosphereHandler.onEvent() for 1
Broadcasting message...
ChatAtmosphereHandler.onMessage() | isResumedOnTimeout: false | isResuming: false | isSuspended: true |
Wed May 13 17:52:17 EDT 2009 ChatAtmosphereHandler.onMessage() - NOT a timeout situation
Wed May 13 17:52:17 EDT 2009 ChatAtmosphereHandler.outputMessage(): 1


Wed May 13 17:52:22 EDT 2009 ChatAtmosphereHandler.onEvent() for 1
Broadcasting message...
ChatAtmosphereHandler.onMessage() | isResumedOnTimeout: false | isResuming: false | isSuspended: true |
java.lang.NullPointerException
        at com.test.atmosphere.TestAtmosphereHandler.onMessage(TestAtmosphereHandler.java:72)
        at org.atmosphere.cpr.DefaultBroadcaster.broadcast(DefaultBroadcaster.java:117)
        at org.atmosphere.cpr.DefaultBroadcaster.broadcast(DefaultBroadcaster.java:75)
        at com.test.atmosphere.TestRunner.run(TestRunner.java:21)
        at java.lang.Thread.run(Thread.java:595)
ChatAtmosphereHandler.onMessage() | isResumedOnTimeout: false | isResuming: false | isSuspended: true |
java.lang.NullPointerException
        at com.test.atmosphere.TestAtmosphereHandler.onMessage(TestAtmosphereHandler.java:72)
        at org.atmosphere.cpr.DefaultBroadcaster.broadcast(DefaultBroadcaster.java:117)
        at org.atmosphere.cpr.DefaultBroadcaster.broadcast(DefaultBroadcaster.java:75)
        at com.test.atmosphere.TestRunner.run(TestRunner.java:21)
        at java.lang.Thread.run(Thread.java:595)

Please assist here.
12