Skip navigation

The AeroGear project had it's official launch last week and I want to review what we're doing and where we're headed. For starters, AeroGear is focused on... [read post]

Screen Shot 2012-02-09 at 3.06.20 PM.PNG

Here's the hotness. As you can see on the right, I have 2 chat windows open and on the left we have a member registration. Users are chatting across a raw WebSocket connection and when another user registers, the CDI event is fired all the way through to the browser as a JavaScript alert via the connected WebSocket clients. And did I mention this is all on AS7? ohh yeah, that's right...


With WebSockets, we have a new development model for server side applications; event based programming. There are 3 out-of-box events associated with WebSockets: onopen, onmessage, and onclose. For starters, we must wire up these three ... continue reading on my kick ass awestruct blog...

The Atlanta JBoss User Group kicked off with a much greater than expected turnout. Developers from the Atlanta area poured in to learn the latest in JBoss technologies.

 

Thanks to Shadow Soft for providing a place to meet and refreshments (not to mention volunteering to lead the group)! Overall we had a good time and I'm looking forward to next month. Want to speak? ping us on twitter @wesleyhales or @shadowsoftnews

 

image_1.jpeg

 

 

Check out the talk here:

 

In this, the very first, meetup of the Atlanta JBoss User Group, Wesley Hales reviews the current landscape of HTML5 and the mobile web.

He shows attendees how to setup a POH5 (HTML5+RESTful) mobile web app and how to deploy apps to openshift using the newly available (M5) features in JBoss Tools.

 

 

Apologies for the chopped up video.. the camera would automatically turn off after a certain amount of time.

I thought I'd explain why I wrote a (very simple) DOM framework to handle RichFaces mobile compatibility - and why we didn't use jQuery Mobile, or any of the other mobile web frameworks. The RichFaces Mobile Showcase was recently modified to give users a way to run their existing JSF based applications on mobile browsers. So this is the typical case of converting an existing application for the mobile web...

 

To get an idea of our existing web app, the RichFaces Mobile Showcase receives around 50,000 visits on a monthly basis, so this is a well reviewed application and it is a constant reference point for any JSF developer.

Screen Shot 2011-11-28 at 2.59.58 PM.PNG

 

I think jQuery (or any other DOM framework for that matter) has its place and there are times when it makes sense to use it. But when doing mobile development, jQuery is not the answer. Its main strengths are for desktop based browsers and inconsistencies between older ones. If you look at the jQuery source, you will see all the hacks and workarounds that are performed when checking for each browser and features therein. And even though the IE6 specific jQuery code doesn't actually run on a mobile browser, you are still carrying this bloat around with you.

 

Bottom line: jQuery is not a framework created for mobile environments - just like JSF, it was created for desktop environments.

 

Brian LeRoux of PhoneGap fame, explains this in the first couple of minutes here:

http://mobile.minutewith.com/pages/20110126

 

To truly get an optimized mobile web application - which runs as close to the metal as possible, you should understand and work with the core DOM APIs to get the best performance on a per app basis. Of course, there were other issues to deal with as JSF rewrites the markup and doesn't allow the data-* passthrough attributes, so that just fueled the fire to roll our own approach.

 

Today, jQuery minified is sitting at 94KB and if you couple that with jQuery Mobile at 82KB, you have 172KB for your user to download.

 

If you try to roll your own for your specific project needs, as we did with the RichFaces Mobile Showcase, you could end up with:

rf-mobile.css 5KB

slidfast.css 1.5KB

slidfast.js 1.6KB

A whopping total of a little over 8KB! (after minification). This little home grown framework is not perfect by any means, and I'm not begging you to include it in your project. All I'm saying is that it gets the job done and works for our target browsers.

 

If you take it a step further and focus on today's modern browsers which use features such as document.querySelectorAll() instead of document.getElementByID() and completely remove the desire to care about compatibility issues with older browsers, then the performace would be even better.

 

It all comes down to performance vs. ease of development, and in this case, I chose both . I'm not saying one way is better than the other and I think all the folks writing these frameworks are doing a great job. As Brian mentioned in his podcast, I just like to mess with my co workers and make fun of jQuery It always gets a heated conversation going...

atlhtml5.jpgTomorrow, Thursday October 27th, Patrick Brandt and Kevin Smith will be giving a talk on augmented reality (AR) and the Argon project.

Argon is the completely open standards augmented reality browser that allows rapid development and deployment of Web 2.0 style augmented reality content.

 

Best of all, we have some killer sponsorship this month with Anteo Group who will be providing BEER! and gourmet sandwiches from Jimmy Johns.

So if you are in ATL, head over and RSVP on the Atlanta HTML5 meetup page . We are depending on the head count here for refreshments ordering so it will be a strict meetup in regards to food/beer - I will be the bouncer and beer guard

 

Also, many thanks to our sponsors from last month, the Atlanta Java User Group and The Creative Group!

I gave one of the ten talks based on HTML5 at JavaOne this year. It mainly focused on bridging the gap between HTML5 and JavaEE along with best practices and tips for mobile devices.

It seems like most developers already know how to provide (some form of) an accessible and scalable architecture on the server side, but the big question was "How can I get a native look and feel web app on mobile devices?"

 

photo.jpg

(Note: I took this photo early... before the room filled up

 

So with my 8:30 am slot on Wednesday, I was expecting to hear crickets, but instead I was happy to see the majority of chairs filled.

The talk should be up soon on Parleys here. As of this writing, only a few are available and you can view my slides here.

 

Luckily, I was able to work with the folks at HTML5Rocks.com to get my article HTML5 Techniques for Optimizing Mobile Performance published just a few days before the talk. So all questions at the end were easily answered by the article.

article.jpg

 

What next? Be looking for much more HTML5 goodness coming your way from the folks here at JBoss. We have quite a few things which will hopefully be announced soon. In the meantime, we have a few webinars which you might want to check out over the coming weeks/months:

http://www.jboss.org/webinars

 

Mobile JSF for the Java Web Developer

Date: Wednesday, November 2, 2011

 

@wesleyhales

Building on my first article in this series, we're now going to add bookmarkable URL's and back button support to our AJAX driven pages.

 

For our specific usecase, we want to render an AJAX region within the same page which includes an external page (via ui:include). Again, this is to keep the smooth native look and feel of sliding transitions.

 

Here, we mimic the same AJAX call which drives our main navigation (rich:panelMenu) with a4j:jsFunction.

 

<a4j:jsFunction name="handleHashChange" render="@form" oncomplete="slideTo('component-page')">
            <f:param name="demo" value="param1"/>
            <f:param name="sample" value="param2"/>
</a4j:jsFunction>

 

This says, when our JavaScript function "handleHashChange()" receives the 2 parameters (param1 and param2), we render the same form as in (part1) and call our transition.

 

Now that we have the JavaScript tie into the AJAX driven JSF page, we can use some quick code to give us bookmarkability and back button support.

 

function locationHashChanged() {
 if(location.hash === "#home"){
     slideTo('home-page')
 }else{
//let's see if we have an acceptable hash
     var hashArray = location.hash.split(':');
     var id;
     var sample;
     if(hashArray.length === 2){
//it's good so format it for our a4j:javascript function
         id = hashArray[0].replace('#','');
         sample = hashArray[1];
//call the a4j:javascript method
         handleHashChange(id,sample);
     }
 }
}

//every time the app changes the hash, call the method above 
window.onhashchange = locationHashChanged;

window.addEventListener('load', function(e) {
if(location.hash == ''){
//it's the initial load, so let's go home
     slideTo('home-page');
     location.hash='home';
}else{
//page has been bookmarked, so take em there 
    locationHashChanged();
}
}, false);
         

 

Now, every time the hash changes on an AJAX call it goes into our mobile page history. So from our original navigation handler rich:panelMenu, we would do the following "location.hash=" after the AJAX call completes:

 

<rich:panelMenuItem oncomplete="location.hash='#{d.id}:#{demoNavigator.currentSample.id}'" render="@form" ...

 

That's it!

The user can hit the back button, refresh, or bookmark the page and the correct markup will be rendered.

You will see this code in action in the upcoming RichFaces Mobile Showcase.

I'm extremely stoked to announce that the JBoss Portlet Bridge is passing the JSR-329 TCK and has been approved by Oracle. This has been a challenging and fun ride down the road of standards due to the fact that this spec covers 2 others, JSR-286 (portlet 2.0) and JSR-314 (JSF 1.2).

 

I would like to personally thank the people who made this project a success:

The JBoss Community - Without the constant feedback and support, we would not have made it to this point.

Alexander Smirnov - The wizard behind the curtain, founder of Ajax4JSF, and overall brilliant guy.

Michael Freedman - Whose tireless effort towards making portals a better place with JSF is greatly appreciated. Mike's knowledge and dedication to the spec had been awesome to witness. Here's to JSF 2.0 in portals!

 

My excitement for this day and the future of the JBoss Portlet Bridge can be best compared to this youtube video about double rainbows (this is how I felt after passing all the tests)...

 

If you would like to run this TCK against our implementation, here are the instructions:

  1. Download and locally build the JBoss Portlet Bridge 2.1.1.CR1
  2. Download Pluto 2.0.0
  3. Checkout the JSR-329 TCK
  4. Run the TestSuite and build the TestHarness wars
    1. mvn clean install -DincludeJSF=mojarra -Dmojarra.version=1.2_13 -Dtck.generate-war=pluto2.0 -DincludeBridge -Dportlet-bridge.groupId=org.jboss.portletbridge -Dportlet-bridge.api.artifactId=portletbridge-api -Dportlet-bridge.impl.artifactId=portletbridge-impl -Dportlet-bridge.version=2.1.1.CR1
  5. Deploy the 3 wars to your pluto 2.0 portal:
    1. portlet-bridge-tck-main-jsr329-1.0.0.war

    2. portlet-bridge-tck-section3-2-lifecycle-set-jsr329-1.0.0.war

    3. portlet-bridge-tck-section6-2-configured-response-wrapper-jsr329-1.0.0.war

  6. Start the server and ensure all 211 pages deployed (http://localhost:8080/pluto)
  7. Stop the server and download the attachments from this Jira issue and put them in the appropriate spot as declared by the TCK User Guide.
  8. Start the server and issue the following command to run the TestHarness (replace paths with your environment paths):
    1. mvn surefire-report:report -Dtck.external-server=run-test -Dbridge.tck.test.file=/Users/wesleyhales/projects/JSRs/jsr329/trunk_2.0.x/test.xml -Dbridge.tck.login-file=/Users/wesleyhales/projects/JSRs/jsr329/trunk_2.0.x/login.properties -Dbridge.tck.browser="*firefox /Applications/Firefox3.6.app/Contents/MacOS/firefox-bin"
  9. Some tests will fail, this is normal and noted in the TCK User Guide from Oracle. You must run the failed tests individually. See the test.xml file for notes and instructions on running the individual tests.
  10. If you have any issues, review the PBR-254 jira for anything you may have missed.

I thought it would be a good idea if I document the problems as I run into them. Starting with a problem within the JSF 2 spec (http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-1024), you cannot have something like:

 

<h:form>
   <f:ajax .. render="some-panel-id"/>
<h:form>

<a4j:outputPanel id="some-panel-id">
   <ui:include src="#{a dynamically generated URI}" />
</a4j:outputPanel>

 

If the ui:include contains another h:form, it will not work on the first request. But it will work on the second one This is because the first render does not include the hidden javax.faces.ViewState input.

 

To resolve this issue, it was fairly simple. Take the code from above and note the changes:

 

<h:form>
   <f:ajax .. render="@form"/>

   <ui:include src="#{a dynamically generated URI}" />

<h:form>

 

So remove the outputPanel and allow the form from the include to be nested. This gives us a ViewState for the form(s) on first request.

 

Why would you want an ui:include within the same markup as your navigation? The main reason is because the "mobile web way" is to put all your content within one page. This allows you to use divs as mock pages and gives you the smooth sliding transitions without an HTTP request. With RichFaces 4, you can just render these regions on ajax requests - thus giving you an easy way to take an existing site to the mobile web.

Let's talk about a very experimental approach for loading images. Every external file request is expensive over a 3G connection. Sure, things are getting better and speeds are improving, but 3G will be the IE6 of the mobile era.
During the writing of TweetStream, a mobile app which aggregates twitter - filtering out tweets for certain hashtags, I found that each tweet’s user icon was costly when loading the app. You can’t view a tweet without an image next to it, so it wouldn’t feel right without loading the image. The problem was with one image out of the 100’s that were being loaded. It took this one image over a second to load.
Seeing the problem and feeling helpless about the bottleneck, I came up with the following prototype. The only problem is that CORS (Cross-Origin Resource Sharing) served images are new and not served up by many public image services...yet. Luckily, Google is doing it with Picasa images and I’m not sure who else is, so please comment if you know of any others.
The concept is simple - load the image via Javascript, draw it into a canvas tag, base64 the image data, store it into localStorage, and return the base64 url back to the DOM when offline or on a slow connection. In conjunction with the applicationCache you would have the ability to create a ass kicking off line mobile application. localStorage is limited to 5MB, but it still gives you an option that isn’t available out of the box today.

 

In this code, we provide an image URL and base64 it via the canvas tag. Note the use of “crossOrigin” attribute. This is a feature recently provided in the Webkit nightly build.

function cacheExternalImage(url) {
    var img = new Image(); // width, height values are optional params
    //http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
    //remote server has to support CORS
    img.crossOrigin = '';
    img.src = url;
    img.onload = function() {
        if(img.complete){
            //this is where you could proxy server side
            load(img);
        }
    }
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;


    // Copy the image contents to the canvas
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0,0);
    img.src = ctx.canvas.toDataURL("image/png");
    return img
}


Again, this is very experimental and still needs some polish. If you had to use external images that are not being served up with CORS headers, you can proxy the image server side and use the same approach making the image seem local. It would probably be even more efficient to do the base64 server side in this case.
This is just a proposal and not a production solution. Let us know if you have had a better experience.

I'm extremely excited to be speaking to and mingling with mobile/HTML5 related developers over the coming months. I will be speaking at the following events...

 

 

  • HTML5 User Group - Sept 22nd - Atlanta Ga.
    http://www.meetup.com/AtlantaHTML5/events/29823121/
    The Mobile Web - HTML5 on Mobile Devices
    About the talk:
    HTML5 is the new hotness and so is the "Mobile Web". In this kick-off meeting of the Atlanta HTML5 User Group, Wesley will discuss topics such as hardware acceleration by way of the device GPU, Caching via localStorage, client side Profiling tools, and overall performance tips and techniques when using HTML5, CSS3, and Javascript.

 

  • JavaOne 2011 - October 2-6 - San Francisco Ca.
    https://oracleus.wingateweb.com/scheduler/modifySession.do?SESSION_ID=19080
    Going Mobile with Java-Based Technologies Today
    ...Attendees will learn which front-end mobile frameworks work best with Java-based technologies and how they can be used to kick-start your own applications. The presentation begins with an overview of technologies used to create the demo and then jumps into the code for a step-by-step tutorial.



If you're in Atlanta, I highly encourage you to go ahead and sign up for the first 2 events if you're interested in HTML5. The User Group meeting caps out at 68 people and we are already at 46 RSVPs. We've received amazing support and response from the Atlanta community for these events!

And as for JavaOne, I'm looking forward to speaking on how we can make the mobile web faster with JBoss middleware!

 

If you have any questions, please ask!

Wesley


The most common approach for receiving markup from an Ajax request is to use innerHTML for placement of the responseText. This method has been widely used (and argued) since the inception of XHR, but it surprises me that it's still being recommended and used not only on desktop browsers but mobile ones as well.

3 or 4 years have passed since many folks raised their concerns with innerHTML:

 

 

From Javascript The Good Parts:

 

“If the HTML text contains a <script> tag or its equivalent, then an evil script will run. .. This danger is a direct consequence of JavaScript’s global object which is far and away the worst part of JavaScript’s many bad parts.”

 

 

Not only is innerHTML bad, it is the root cause of many problems... from browser memory leaks (it destroys/replaces existing elements that may have event handlers attached) to failing completely on iOS’s Mobile Safari. Yes, that's right, it just flakes out.

 

So even if you use Crockford’s purge method to fix the memory leaks and sanitize your response string returned from the server, you still have a showstopping flaw when running any mobile web solution that uses innerHTML on iOS devices

 

Just to name a few mobile frameworks that use this flawed innerHTML approach:

JQuery Mobile (uses jQuery’s .html() wich is a wrapper for innerHTML)

Phone Gap

Sencha

 

A possible solution:

Disclaimer: I have not done any benchmarking so performance is unknown.

 

We all know that innerHTML is a favorite for it’s speed and ease of use but speed doesn’t really matter when it doesn’t work at all. So one solution is through use of some new features in HTML5 and the DOM api:

 

Let's start with the scenario that you've made your XHR and received the responseText.

First thing we'll do is create a temporary iFrame element. This isn't any ordinary iframe, it received a major security enhancement with HTML5 and we have some new sanitizing features with the "sandbox" attribute.

 

From the spec:

The sandbox attribute, when specified, enables a set of extra restrictions on any content hosted by the iframe. Its value must be an unordered set of unique space-separated tokens that are ASCII case-insensitive. The allowed values are allow-forms, allow-same-origin, allow-scripts, and allow-top-navigation. When the attribute is set, the content is treated as being from a unique origin, forms and scripts are disabled, links are prevented from targeting other browsing contexts, and plugins are disabled.

To limit the damage that can be caused by hostile HTML content, it should be served using the text/html-sandboxed MIME type.

 

 

function getFrame() {
    var frame = document.getElementById("temp-frame");
    if (!frame) {
        // create frame
        frame = document.createElement("iframe");
        frame.setAttribute("id", "temp-frame");
        frame.setAttribute("name", "temp-frame");
        frame.setAttribute("seamless", "");
        frame.setAttribute("sandbox", "");
        frame.style.display = 'none';
        document.documentElement.appendChild(frame);
    }
    return frame.contentDocument;
}

 

Now, we get our ajax response and write it to the iframe:

 

var frame = getFrame();
frame.write(responseText);

 

The beauty of this solution is the fact that we don't have to deal with a javascript text to DOM parser. We're allowing the browser to do what it does best... parse the HTML and build a DOM. And we don't have to worry about parsing the response and removing a blacklist of prohibited security risk elements and other XSS hacking pitas.

 

After writing the response to the iframe, you now have a ready to use sanitized DOM. Next you can use the DOM API to grab any part of the new document.

 

 var incomingElements = frame.getElementsByClassName('elementClassName');

 

Safari correctly refuses to implicitly move a node from one document to another. An error is raised if the new child node was created in a different document. So here we use adoptNode to add the incomingElements to our existing page.

 

 document.getElementById(elementId).appendChild(document.adoptNode(incomingElements));

 

The only thing left to do now is benchmarking. As I said earlier, working with the DOM has been notably slower than using innerHTML in the past. So there may be a derivative of this proposed solution that is faster? or there may not be a huge difference in execution time? Let me know....

 

Update: @_boye has created a perf test which shows the performance of this solution. Remarkably, This iFrame solution outperforms innerHTML on Firefox 7 and maintains the same speed on Chrome 16.