IcePush integration to web-application


Push notifications are fast as Running Flash
In one of the previous post I show an example of how a4j-push and a4j-poll were used together. It help to solve several things and optimize code/requests a bit. But in reality it was not “real” push – it just execute periodic lightweight requests (ping server) and asks him – “do you have something new for me ?”. It has serious cons:

  • number of requests to server is linearly depends on the number of browser windows opened, so more simultaneous users we have connected to the server – the higher loading it will have. So, actually server can be just “overloaded” by that simple requests
  • with regards to previous point we have to increase the period between requests (to make less impact on the server) – but it is not good for user experience, since it will see the updates with a larger delay

What I expect from Push is that server itself initiate the push-notification to the client. So it does that right at the moment he have to say something new to the client. There is no need to say that such server-to-client communication open a lot of great features and possibilities to web apps.
Here is the diagram from the IcePush docs

It probably not that visible, but in short – “It works great”. IcePush client (javascript) send the list of subscribed topics he want to listen, server genberate the unique ID for him, after that client establish the connection with the server which listen for response from server. Server will notify the client once he will have notifications to send to him. Client call the callback function in which you may do anything (you may call any javascript function as well the a4j:jsFunction if you want to do something through JSF)

As a result, the client browser will be notified right after the event will occur on the server. It will be immediately pushed to the client and after that client is free to do anything he want to react to the notification.

The good thing is that it’s fairly easy to integrate IcePush technology with existent java-web application. The requirement here is just to have a servlet container.
In my case it was existent Richfaces/Seam-2/JSF application (I was afraid that IcePush may conflict with Richfaces, but it is not the case, IcePush can be integrated completely transparent to the JSF/Seam application, since it integrates on Servlet level).
IcePush has a number of ways to integrate, but I’ve chooses the jQuery Integration
You can find all the necessary information about IcePush integration here. I will show the example of integration of IcePush with existent web-application (Seam/Richfaces). I think the integration could be the same for GWT or any other app which is deployed in the Servlet-Container.

  1. Downloaded jQuery integration package
  2. Added the icepush.jar to the WEB-INF/lib
  3. Added the following definition to web.xml
        <servlet>
            <servlet-name>icepush</servlet-name>
            <servlet-class>org.icepush.servlet.ICEpushServlet</servlet-class>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>icepush</servlet-name>
            <url-pattern>*.icepush</url-pattern>
        </servlet-mapping>
    
  4. on the web-page initialized the IcePush with
    //loaded required scripts
            <script type="text/javascript" src="#{request.contextPath}/code.icepush"></script>
            <script type="text/javascript" src="#{request.contextPath}/js/icepush/jquery.icepush.js"></script>
    //initialized the icepush client
        <script type="text/javascript">
            var myPushNotificationCallback = function(){
               //do something on push callback. 
               //it may be ajax request to the server based on jQuery-ajax or a4j:jsFunction, whatever
               //for simplicity I will just call alert
               alert("Push notification arrived");
            }
            jQuery(document).ready(function () {
                //set the uriPrefix so icepush will make requests to the correct URL
                ice.push.configuration.uriPrefix = '#{baseAppPath}/';
                //register the icepush client, based on the user-primary-key
                jQuery.push.listenToGroup("myPushGroup_UsR_#{loggedInUser.pk}", myPushNotificationCallback);
            });
        </script>
    
    
  5. On the server side call the IcePush in the places I want to send notification (as a reaction to some event)
    We can call method pushToUserList directly, but I wrapped it so it become asynchronous call, so it don’t slow-down the http-request processing (it may send notifications to several clients and as long it is network operation, it’s may cause a significant delay)

    @Name("pushAsyncExecutor")
    @Scope(ScopeType.APPLICATION)
    public class PushAsyncExecutor implements Serializable {
    
        private static Log log = Logging.getLog(PushAsyncExecutor.class);
    
        @Asynchronous
        @SuppressWarnings("unused")
        public QuartzTriggerHandle  pushToUserList (@Expiration Date when,
                                                    String pushGroup, Collection<Long> userIds) {
            pushToUserList(pushGroup, userIds);
            return null;
        }
    
        public static void pushToUserList(String pushGroup, Collection<Long> userIds) {
            log.trace("Started pushToUserListImpl");
            try {
                PushContext pushContext = PushContext.getInstance(SeamComponentFactory.getServletContext());
                for (Long userId : userIds) {
                    pushContext.push(getUserNotificationGroupName(pushGroup, userId));
                }
            } catch (Throwable ex){
                log.error("Failed to push updates", ex);
            }
            log.trace("Finished pushToUserListImpl");
        }
    
        /**
         * this method generate the push-id for the userId and "pushGroup"
         */
        private static String getUserNotificationGroupName(String pushGroup, Long userId) {
            return new StringBuilder(pushGroup.length() + 16).append(pushGroup).append("_UsR_").append(userId).toString();
        }
    }
    
  6. Advertisements

    https://www.facebook.com/achorniy

Tagged with: , , , , , , , , , , ,
Posted in Software Development, Tips and Tricks
4 comments on “IcePush integration to web-application
  1. Steve Maryka says:

    Nice to here that you succeeded in your integration effort with ICEpush. We built it with the intention of being very lightweight, and easily integrable. Of course if you are looking for an off-the-shelf integration with JSF, ICEfaces provides it with Ajax Push. See…

    http://www.icesoft.org/projects/ICEfaces/ajax-push.jsf

    Steve

    • Andrey Chorniy says:

      Yeah, I considerd to use IceFaces with integrated push initially, but I was afraid that Richfaces will conflict with IceFaces (our app use Richfaces)
      for example http://www.icefaces.org/JForum/posts/list/19044.page
      and that one http://www.icefaces.org/JForum/posts/list/5278.page directly says that it’s not possible to use them both

      It’s not that help is being refused, it simply is not possible to use them both together. As Judy explained above RichFaces uses a Servlet Filter to achieve some (all? don’t remember) of it’s AJAX functionality. ICEfaces uses a Servlet. Filters are run before the request hits the servlet, and those two (the RichFaces filter and ICEfaces Servlet) don’t play together well. You’ll have to chose one or the other.

      So, in the end I’ve give the IcePush a try and it work great, the integration was quite easy. I didn’t try if it will work in a clustered architecture well (it seems that it will have problems with clustered servers, since connection is established with one of the servers and the event may be produced on another). Probably it’s what Enterprise Push Server is care about and we’ll need o invent something to make this working (some layer which will help us to fire notification on the cluster-server which hold the connection – probably, just fire/replicate the notification event on all servers)

      • Steve Maryka says:

        Yes, you are correct. ICEfaces and Richfaces do not play well together in the same page.

        EPS is indeed what you need to cluster ICEpush. EPS is currently available for evaluation under the ICEfaces EE license. You need “Standard” support level to get deployment licensing. Our intention is to release an ICEpush EE, which will include EPS, but that plan has not yet risen to the top of our priority list. I am sure we could work something out if you are interested in pursuing access to EPS. Beats trying to write one yourself.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: