Skip to main content

HTML5 Canvas nightmares with JSF

The last couple of days have been one of those 'why is this so difficult' moments. I essentially lost more than a day trying to figure out how to get HTML5 canvases to show up in one of our JSF applications. Here is the background on the stack:

  • JBoss AS 7.2.0
  • JDK 1.7.x
  • Seam (JSF Framework) v2.2.0
  • Richfaces v3.3.3
Essentially we wanted to introduce a canvas to our page in order to graphical represent a numeric value and where it falls upon its normal range and possible range of values.  

The page was leveraging a <ui:include> in order to display the results section.  It was a common component used among multiple pages and therefore the reason being pulled in via an include.  A richfaces commandLink was being used to initiate an AJAX request that would pull back none, one or many results and re-render the display within a JSF panelGroup.  

Canvas Background: 

If you look at any of the examples of using HTML5 canvases, you generally will see the definition of the <canvas> tag and its appropriate attributes and then a javascript function defined.  The javascript function gets called usually on page load to paint the actual canvas(es).  We were utilizing JQuery in order to bind the painting function to all canvas elements within our page div.  We set up the JQuery selector to select canvases with a certain id (i.e <canvas id="numberRange" ... ></canvas>).

The Path:

It was pretty easy to set up the number range displays as we already had an existing javascript library that included the function for painting the canvas.  We included the library into our .xhtml page and defined the canvas locations.  We defined our handoff function which included the JQuery selector. The selector identified the applicable elements and then called the paintCanvas() javascript function for each matched element.

The initial result:
Initially what we saw was when initial load happened on the page the canvas(es) showed up appropriately.  

Then after the date range was changed and the search was clicked, an AJAX request initiated, the resulting display did not show any canvases.

The common issue:  
Generally these type of issues can be caused by the fact that you need to remember there is just a partial page load occurring.  An AJAX request that repaints a section of the screen does not result in a reload of the full page/DOM; therefore the document.load() is not re-triggered.  This would mean the JQuery $(document).ready would not be triggered and therefore our painting of canvases would not be initiated.

However we were using the commandLink from richfaces.  The component allows you to specify a javascript function to call when the AJAX request completes.  We double checked the component definition and the proper function was being included on the oncomplete attribute of the tag.


<a4j:commandlink action="#{controller.search}" onclick="ajaxSpinOn();showSearching();" oncomplete="ajaxSpinOff();paintCanvases();" rerender="content" value="Search">
</a4j:commandlink>

What's up?: Was there a Javscript error? What was being returned. The what's up is always the part that ends up eating up hours or days. I'm not going to go through all of the tribal and tribulations, but will point out the key points along the way to the solution.

A key tool in this whole discovery were the developer tools available within Chrome. If you are not familiar, certainly get familiar with them or at least the respective developer tools within your browser of choice. We monitored the javascript execution within our logic. There were no errors and the paintCanvases() function was appropriately getting called.

The key hint: It wasn't until I decided to monitor and inspect the state of the DOM post the AJAX call that it triggered something odd was happening. None of the content for the canvas tags was being included in the response. The canvas tags and all attributes were disappearing. All of the other dynamic content created from the AJAX request was being included appropriately.

The resolution: Richfaces uses a filter for correction of code on an AJAX request. The default configuration was removing all of the canvas related content. You can read up on the filter configuration here. We switched the configuration to use the NEKO filter.

Switching to the NEKO Filter

  1. First we needed to add the maven dependency for the NEKO library.  The library is not pre-packaged with the rich-faces library so you must explicitly include the library. This POST may be helpful in regards to miscellaneous setup for Richfaces 3.3.3
  2.         
       <dependency>
          <groupId>nekohtml</groupId>
          <artifactId>nekohtml</artifactId>
          <version>1.9.6.2</version>
          <scope>runtime</scope>
       </dependency>
    
  3. In your web.xml file add the following context-param for the filter configuration (changing from the default, TIDY).
  4.     
        <context-param>
            <param-name>org.ajax4jsf.xmlparser.ORDER</param-name>
            <param-value>NEKO</param-value>
        </context-param>
    
    
    

Finally

Then with a rebuild and deploy, canvases starting displaying appropriately.  Hopefully this may save a few other developers a few hours.  

Comments

Popular posts from this blog

WSO2: Simple Pass through proxy (REST to REST with HTML Reply)

Today I set out on trying to set up a simple passthrough proxy that would allow for a GET request to be made to REST style backend services that replies with HTML content. The proxy services was being set up on WS02 ESB v4.8.0.  I thought this was really going to be as simple as walking though their wizard and setting up a new proxy endpoint that just handed off to the behinds the scene service. It was straight forward to set up the proxy, but then unfortunately when called it just didn't respond. It took quite awhile to figure out what the issues was.  At first I was using the ESB admin console and review the System and Application Logs.  The Application Logs were certainly more useful, but they still truncated stack traces which made it hard to clue in on the real issue. It wasn't until I went and review the logs on the server that I was able to detect the cause.   <wso2_esb_root>/repository/logs/wso2-esb-errors.log 2015-03-19 16:09:43,001 [-] [Pass

Where to start on AngularJS for Java Developer

Background: If you are a Java developer who is comfortable using Eclipse (JEE Developer version) you may be asking yourself where to start with AngularJS. There is all kinds of documentation out there in regards to AngularJS and https://angularjs.org/ provides, to the point, tutorials on how to get started. You can certainly go that route and use node.js embedded server and possibly a Javascript focused IDE like WebStorm. However I wanted to try and stay in a comfort zone, my comfort zone, of Eclipse and be in a position to deploy an Angular application to a container like Tomcat. This blog entry will present the trail I took to try and accomplish it. Note: This is an adventure into Angular 1.x, not 2.x.  I would imagine this could all work with 2.x as well as it is focused on the dev environment setup. Start: Well the one consistent thing you will find to get started is to install the AngularJS Plugin, provided by Angelo ZERR.  You can use the Eclipse 4.5 (Mars) plugin inst