Skip to main content

Web Application Notifications

About a 5 minute read



    A popular part of an application is its ability to receive notifications. For instance, a social application such as Facebook, needs to notify its users when they have new friend requests, feed updates, and updates to their posts. There are many frameworks that provide the capability to do this but I'm going to experiment on making my own simple implementation. I'm going to use JavaScript for the client-side code and Java for the server-side code. The approach I will take is to use Server-Sent Events (SSE).

What are server-sent events?

    Server-sent events are a publish-subscribe model. 

    Traditionally, a browser requests information from the server which then the server responds with such information. However, this is inefficient for a notification system because the browser doesn't know when such information is available. So, we need a way for the server to alert the browser with information when it is ready. There is a way called polling, which uses the traditional method but continues to send requests after it receives a response. So, it would send a request to a server, and receive either the information it requested or a "not available" message, which it then will re-subscribe or request data again. This method is inefficient as well because it uses too much network access, constantly requesting and receiving.  

    There is another pub-sub method called long-polling, which is similar to polling but it keeps the request open. So, the browser requests information from the server. The server then holds onto this request until information becomes available. Once information becomes available, it sends it back to the browser, which the browser must re-subscribe or request information from the server again if it expects to keep receiving updates. 

    Server-sent events are very similar to long-polling. The major difference being that once the browser receives the requested information, it doesn't need to re-subscribe; the connection stays on indefinitely (until the connection is manually closed or the user leaves the application). 


Client-side

    The JavaScript server-sent event API comes from the EventSource Interface which most modern browser versions implement with the exclusion of Internet Explorer (not positive). My client-side code:

    (function(){
      var eventSource = new EventSource("/notify");
      eventSource.onmessage = function(e){
        alert("Notification message " + e.data);
      };
    })();

    The above code subscribes the eventSource object to listen for notifications from the specified URI, in this case "/notify". The URI specified in the EventSource constructor, usually points to the location of a server-side script, but since I'm using Java for the back-end, I provided the URI mapping to a Servlet I will create. After I created the new object, I provided a function for its onmessage event. When a message is received from the server, this function will be called. The message received is available within the event object's data attribute (e.data). Also, I could have registered an event listener on the EventSource object and listen to specified events. More information on SSE's here. Now, time for the server-side code.


Server-side

    As to my knowledge, there's no specific built in Java API for SSE's. But that's okay because we can just use Servlets.  My server-side code:

    @WebServlet(urlPatterns = {"/notify"})
    public class NotifyServlet extends HttpServlet {

      @Override
      protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
        //needed for server-sent events
        response.setContentType("text/event-stream");
        response.setCharacterEncoding("UTF-8");

        //will write message to client
        PrintWriter writer = response.getWriter();
        writer.write("data: " + "Status Update \n\n"); //notification message to send to the client. needs to start with "data: " and end with "\n\n" (line breaks).
      }

    }

    The EventSource object in the JavaScript code "subscribes" to this Servlet, which then this Servlet can send the client a response when it needs to. Of course, this is just an extremely simple implementation which returns a response ("Status Update") to the client as soon as it gets the initial request. But this is just to illustrate the ability to interact with the client through SSE's. Obviously, a more useful model would have to implement more features such as using asynchronous calls on the Servlet, providing and storing a unique user ID per connected user, and having a query system to see if anything has changed for a particular user. All of this is far beyond the scope of this article, but I will no doubt implement such a thing and perhaps I'll update this article with the finished code (if I remember to do so). If you find any errors in my code or writings or just have something to say please feel free to leave a comment, thanks!

Comments

Popular posts from this blog

Face detection and live filters

Live video filters are becoming a popular trend fueled by Facebook (through their purchase of Msqrd) and Snapchat incorporating the features into their apps. These filters apply images or animations to your face using face tracking software. This technology has been around for awhile but is becoming increasingly more common due to the powerful CPU's that our mobile phones now have. Google provides an API that provides face tracking abilities through the Google Play Services library called Mobile Vision. I'm going to use their API to build a basic live filter app. The end result will look something like this:


    The bounding box wraps around the detected face and the sunglasses are the filter I chose (which is just a PNG image) which are drawn over the eyes. You could use any PNG image (with alpha for the background) you want, you will just have to adjust the layout according to where the image should be displayed. As you move your head, the box and sunglasses are redrawn…

Setting Up Connection Pooling With Elastic Beanstalk

Amazon's Elastic Beanstalk is a service which automatically scales your application when needed. It uses Amazon's Elastic Compute Cloud (EC2) instances as deployable containers which when your app requires more resources more containers will be deployed. This removes the need to manually configure your EC2 instance whenever you need more connections or resources and attempts to add simplicity to the maintenance aspect of your application. So, when you get more users of your app, your app will scale accordingly.

    Unfortunately, along with the ability to scale automatically, comes less control and configuration. Things you would normally have the ability to configure to your liking, such as your server, you no longer can. Amazon attempts to address this issue with configuration files. You can provide configuration files which can set up your server. These files are either written in JSON or the horrible format YAML. Though these files provide some level of control, you ca…

Android Guitar Tuner

Recently I created a guitar tuner application for Android that is written with pure Java (no C++ or NDK usage). The design was inspired by the Google Chrome team's guitar tuner web app using the WebAudio API. I wanted to code a version written natively for Android that didn't have to rely on a WebView, the WebAudio APIs, or server-side logic. Also, I wanted this application to be available to as many versions of Android as possible (whereas the WebAudio API may only be supported in more recent versions of WebView available only on newer flavors of Android). So, I coded it from scratch. I used a portion of the open source TarsosDSP project (their YIN algorithm) to help with the pitch detection.

    The application is available in the Google Play Store for Android: https://play.google.com/store/apps/details?id=com.chrynan.guitartuner. The project is completely open source and the code can be found on the GitHub repository: https://github.com/chRyNaN/Android-Guitar-Tuner. Fi…