Monday, December 7, 2015

Play Framework websocket connection keep-alive with play.libs.F.Timeout

Hello,

Play Framework has web socket capability. However, if you are using web socket protocol with F5 load-balancer, it's possible that inactive connection will be dropped by F5 and your socket connection will be lost forever.

I suggested sending null message to the client side frequently if there is no new data to keep-alive the connection. However, what if you job takes too much time to complete? You cannot send anything, not even null to the client side. Here is what I found as a solution to this problem:

public static void getLatestAval()
{
        while(inbound.isOpen())
        {
            //send null every 100 seconds if the job does not finish
            Promise task = StatefulModel.instanceAval.eventAval.nextEvent();
            Either<List<Object>, Timeout> r = await(Promise.waitEither(task, play.libs.F.Timeout(1000000)));

            for(Timeout t : r._2)
            {              
                if(task.isDone())
                {
                    if(outbound.isOpen())
                        outbound.sendJson(r._1);                  
                }
                else if(t.isDone()) //timeout
                {
                     if(outbound.isOpen())                    
                        outbound.sendJson(null);                   
                }
            }
       }
 }

Cheers,

Thursday, October 30, 2014

Play Framework WebSocketController connection drop by Big-IP F5

Hi,

I'd like to talk about an issue bothering me for a long time. My web socket implementation started to hang after a while when I moved my application behind F5 load-balancer.

It turns out that, F5 somehow drops the web socket connection after a while. Probably there is a timeout value that drops inactive connections. Our F5 admins couldn't figure out the issue so I had to implement a workaround that basicly sends mock events even if there is no new server sent data.

My workaround is highlighted below:

On the server side:
// check the job result has new values to sent to the clients
if (coll.isNew()) {
        responseList.add(PointDate);
        responseList.add(point);
        responseList.add(count);          
        StatefulModel.instance.event.publish(responseList);   
}
else {
       // sending mock data to keep connection alive
        responseList.add(null);   
        StatefulModel.instance.event.publish(responseList);    

 }

On the client side:
 ws = new WebSocket('@@{Total.getLatest}');
 ws.onmessage = function(evt)  {
       var data = JSON.parse(evt.data); 
       if (data[0] != null) {
            var date = data[0];
            var point = data[1];       
            var count = data[2];
             
            print("containerMax", count, point, date);
        }
  }

Note:
Here is a great article about web socket implementation with Play Framework 1.2.7:
http://playframework.wordpress.com/2011/04/25/websockets-in-play/


Bye...

Thursday, February 6, 2014

DataTables colorful cells

Hi,

First of all, I'd like to mention that DataTables is a great jQuery plugin for tables:
http://datatables.net/

Lastly, requirement of giving colors to multiple cells locally according to their values dynamically raised but I couldn't find enough amount of examples about it on the web.

Finally, I found a solution:




"aoColumnDefs": [
                                
  {
             "aTargets":[4],
             "fnCreatedCell": function(nTd, sData, oData, iRow, iCol)
              {
                         if(sData == 'A')                                         
                                 $(nTd).css('background-color', 'rgb(255,0,0,0.7)');                                             
                         else if(sData == 'B')                                        
                                 $(nTd).css('background-color', 'rgb(255,128,0,0.7)');                                          
                         else if(sData == 'C')
                                  $(nTd).css('background-color', 'rgb(255,178,0,0.7)');                                          
                          else                                          
                                  $(nTd).css('background-color', 'rgb(0,153,153,0.7)');
                                                                                   
               }
   },                           
   {
                                       
              "aTargets":[5],
              "fnCreatedCell": function(nTd, sData, oData, iRow, iCol)
               {
                          var count = parseInt(sData);
                          if(count >= 10)                                           
                                    $(nTd).css('background-color', 'rgb(255,0,0,0.7)');                                           
                          else if(count < 10 && count >= 5)
                                    $(nTd).css('background-color', 'rgb(255,128,0,0.7)');                      
                          else if(count < 5 && count > 2)                                           
                                   $(nTd).css('background-color', 'rgb(255,178,0,0.7)');                                       
                          else
                                   $(nTd).css('background-color', 'rgb(0,153,153,0.7)');
                      
                  }                    
      }
  ]   


Hope it helps...

Friday, January 24, 2014

TableTools in JQuery modal bug

Hi,

It really annoyed me that DataTable-TableTools (http://datatables.net/extras/tabletools/) export to Excel button did not work on my page with Chrome and IE whereas it worked with Firefox. I digged out everything about browsers and flash support etc. Changed the code,  searched the web and everything... No solution! So I quit (a very rare situation :))...

After a while, I did use the same TableTools code on another page and it worked in all of these browsers. So I figured it out that this bug was about Jquery modal because in the first case, TableTools table was placed in a modal. I did a refined search and immediately found this:

$('.dialog').dialog({
                    modal: true,
                    zIndex: 1
                });
 
 
"JQuery UI has a bug where if ran in a modal, it removes the click functions from certain elements due to its default z-index."


I added this extra property: zIndex: 1 to my problematic page and it worked like a charm.

Cheers,



Tuesday, January 14, 2014

Play Framework manual access log

Hi,

I needed access log in my Play Framework project but neither I had time for installing&integrating another webserver nor the following module supports X-Forwarded-For (from now on: XFF) IP:
http://www.playframework.com/modules/accesslog

So I wrote my own... The following methods generate the following output whether the client reaches your application directly (bypassing the loadbalancer) or using load balancer so that its real IP is given in header's XFF key value (of course if your loadbalancer supports that... In my case, it is F5-BigIP):

ACCESS LOG(BSM) - <IP> - <ComputerName> - Tue Jan 14 13:12:30 EET 2014

    public static void getAuth(String page)
    {  
        String direct_ip = Http.Request.current.get().remoteAddress;
        String xff_ip = null;
        if (Http.Request.current.get().headers.get("x-forwarded-for")!=null)
            xff_ip = Http.Request.current.get().headers.get("x-forwarded-for").toString();    

        String lookableIP = direct_ip;       
        if (xff_ip!=null)
        {
            xff_ip = xff_ip.substring(1,xff_ip.length()-1);            
            lookableIP = xff_ip;
        }       
        String computerName = nslookup(lookableIP);
        Date date = new Date();
        Logger.warn("ACCESS LOG("+page+") - " + lookableIP + " - " + computerName + " - " + date);       
   
    }
    private static String nslookup(String host)
    {
        try {
            InetAddress inetHost = InetAddress.getByName(host);
            return inetHost.getHostName();
            } catch(UnknownHostException ex) {
            return "N/A";
        }
    }


Note: Play Framework version: 1.2

Bye,

Jquery template (jquery-tmpl) with Play Framework

Hi,

In order to use Jquery templates in your Play Framework project here is what you need to do in your html:

<script id="template" type="text/x-jquery-tmpl">
<div>${'$'}{rating}</div>
 </script>

Play will convert this into ${rating}, which should be the documented case:
https://github.com/BorisMoore/jquery-tmpl

Note: In this case, I used Play Framework 1.2

Cheers,


Monday, December 30, 2013

Highcharts - Setting new minimum maximum values (extremes) for Y-axis


I use the following code to define min-max values of a chart:

    var min1 = Math.min.apply(Math, data1);  
    var min2 = Math.min.apply(Math, data2);  
    var min3 = Math.min.apply(Math, data3);  
    var min = Math.min(min1, min2, min3);
   
    var max1 = Math.max.apply(Math, data1);  
    var max2 = Math.max.apply(Math, data2);  
    var max3 = Math.max.apply(Math, data3);  
    var max = Math.max(max1, max2, max3);                       
    .
    .
    .



    yAxis: {
                min: min,
                max: max,


However, after modifications made to the chart like adding/removing points, these values need to be updated. Here is how you can do it:

   var max = chart1.yAxis[0].getExtremes().dataMax;
   var min = chart1.yAxis[0].getExtremes().dataMin;
   chart1.yAxis[0].setExtremes(min, max);
   chart1.redraw();