wesleyhales.com

JSF Chart Creator - now with ImageMaps!

16 December 2006

Java |

I recently updated the JSF-Comp Chart Creator component to include image map support. All charts now have capabilties for custom links on each section of the chart. All customization can be handled through the tag atributes.

New attributes:

  • action
  • series
  • section

The usemap attribute must start with a # (i.e. usemap="#myMap"). For action, just input the page to link to, section and series are just parameters that are built into jfreeChart. I am currently working on drill downs, along with a few other attributes (like the abiltiy to set the range), for next release.

Usage

Besides the new attributes and an h:output tag for your imagemap string, there is nothing else you need to know apart from this documentation

Download the jar here


        <ad:chart id="chart2" 
                  datasource="#{chartCreator.cellBar}" 
                  type="bar" 
                  height="100" 

                  is3d="false" 
                  orientation="horizontal" 
                  width="300" 
                  antialias="true" 
                  title="" 

                  xlabel="" 
                  ylabel="" 
                  legend="false" 
                  usemap="#chart2_map" 
                  action="this.jsf" 

                  series="wes1" 
                  section="wes2" 
                  styleClass="wesChart"></ad:chart> 
        <h:outputText escape="false" value="#{chart1_map}"/> 



Maven 2 vs Ant - Which is better for commercial apps

10 December 2006

Java |

Currently I am working on a extreme RIA which is to use the code base of an existing project and rewrite were needed. Because of the strict time line, no one is attempting to rewrite the existing code base, and we are looking over problems that need to be fixed just to get things working.

However, we have made the appropriate steps to create a Maven archetype for the new part of the app, and to get the ball rolling away from the old ant build. What I'm wondering is:

  1. Is Maven really better suited for open source projects and not commercial?
  2. There are a ton of threads talking about how you have to be a Maven expert once the project grows past a certain point and something breaks.
  3. By googling "Maven vs. Ant" I find many threads but most are dated. I'm interested in how commercial projects are doing with the latest version of Maven today.

I came across a Selenium article on Matt Raible's blog that got the wheels turning. Since (it seems)everyone is moving towards Maven 2, will an existing ant project be better off ported to Maven?

Selenium is becoming fairly mainstream and now that Mavenium is up and coming it makes me wonder if Maven is really the way to go.

Ajax4Jsf vs AjaxAnywhere: The t:dataTable and t:dataScroller

07 December 2006

Java |

Submitting with Ajax4Jsf

On Dec 6, Ajax4Jsf released a maintenance release (ajax4jsf-1.0.4MR1.jar which fixed an IE javascript problem not in this post) - But the framework is still a little buggy dealing with the datascroller components. On a good note, Adrian Mitev gave his custom ajaxDataScroller to the A4J project and will hopefully get everything working in both browsers. ***UPDATE - Here is the latest version of the datascroller from Adrian. I had to rename the extension to .jar instead of .zip for upload reasons. If you have trouble extracting, just rename the file to .zip. Adrian says "Actually the attributes of ac:ajaxDataScroller tag differs from the attributes of t:dataScroller. You don't have paginatorMaxPages="9", the attribute is maxPages."

<a4j:form ajaxSubmit="true" reRender="carList,carIndex,scroll_1"> 
 
            <a4j:region id="stat1"> 
 
                <a4j:outputPanel id="list-body"> 
 
                    <t:dataTable id="carIndex"...> 
 
                    <t:dataTable id="carList"...> 
 
                </a4j:outputPanel> 
 
                <t:dataScroller id="scroll_1" 
                        for="carList" 
                        fastStep="10" 
                        pageCountVar="pageCount" 
                        pageIndexVar="pageIndex" 
                        styleClass="scroller" 
                        paginator="true" 
                        paginatorMaxPages="9" 
                        paginatorTableClass="paginator" 
                        paginatorActiveColumnStyle="font-weight:bold;" 
                        actionListener="#{inventoryList.scrollerAction}" 
                        > 
                </t:dataScroller> 
 
                <a4j:status for="stat1" forceId="true" id="ajaxStatus"...> 
 
             </a4j:region> 
 
 
        </a4j:form> 

The above code is functional in Firefox 1.5+ but not in IE 6+. The only bug in Firefox (that I've seen so far) is that a selected status/style on the page number link, once it has been clicked, does not appear. It looks like the component itself is not being reRendered, although it is specified in the a4j:form tag. Other than that, Sergey, Alex, and crew have been doing an awesome job answering posts and getting the maintenance releases out... keep em' coming guys!

The paging doesn't work at all in IE - it has to be something small...

Submitting with AjaxAnywhere

As much as I would love to stick with one ajax framework across the entire app, we have to have a fallback plan. AjaxAnywhere has been a life saver getting the Tomahawk components submitting. The only downfall with this framework is that you are limited no partial page updates, and nowhere near the capabilities/enhancements that A4J has...

The following code does the Ajax submit in both browser with all components working like they should. Using the A4J:status together with a custom "loading..." window with aa took some hackery, but I was able to get both working (in next post I will explain)

<h:form id="mainForm"> 
 
                <aa:zoneJSF id="dataTableZone"> 

                         
                <a4j:region id="stat1"> 
     
                <a4j:outputPanel id="list-body"> 
                <t:dataTable...> 
                </a4j:outputPanel> 

     
                        <a4j:status for="stat1" forceId="true" id="ajaxStatus"...> 
     
                 </a4j:region> 
     

                <t:dataScroller id="scroll_1"...> 
 
            </aa:zoneJSF> 
 
        </h:form> 
 

        <script type="text/JavaScript" src="/facelet-sandbox/aa.js"/> 
 
         <script type="text/JavaScript"> 
 
            ajaxAnywhere.getZonesToReload = function(url, submitButton) { 

                return 'dataTableZone'; 
            } 
 
            ajaxAnywhere.formName = 'mainForm'; 
            ajaxAnywhere.substituteFormSubmitFunction(); 
            ajaxAnywhere.substituteSubmitButtonsBehavior(true); 

           
        </script> 

One more thing, the reason I am nesting an a4j:outputPanel in the above code is for a4j:commandLinks inside the form. So far I haven't had any problems with both frameworks playing nicely together

JSF Component Library Integration

06 December 2006

JSF | Java |

Integrating multiple component libraries can provide a project many advantages but can also be a challenge to make all components live and work in harmony. This article explains how to integrate many popular component libraries into one app. Combining libraries gives developers an array of components to pick and choose from. But, knowing which components play well together and which ones don?t, will save you time and I will explain the pros and cons of each here. The following component libraries were used:


Libs

  • Myfaces 1.1.4
  • Tomahawk 1.1.4
  • Ajax4JSF 1.0.3
  • Trinidad m1 Nightly Build
  • IceFaces 1.0.1
  • Facelets 1.0.11

Environment

  • JDK 1.5 +
  • Jboss 4.0.4 (or Tomcat is better/lighter)
  • IntelliJ Idea

Software Needed

  • Subversion
  • CVS
  • Maven 2

It's worth the effort to go ahead and get yourself acquainted with downloading the source for most of your component libraries, starting with Myfaces. I use Tortoise SVN or you can download the binaries using the command line. Once you have Subversion setup, checkout Myfaces here. After that, this guide This will give you a quick how to on compiling the libraries with Maven 2. If you use IntelliJ Idea you can get a plugin that will generate your project files. This will allow you to edit the source and change things around if needed, it also helps when you are trying to follow this guide.

For the impatient, the short and sweet steps are:

  1. Download Maven 2 and add bin dir to path
  2. checkout code for project
  3. navigate to root dir (or dir with pom.xml file)
  4. run mvn install
  5. This will build the target directory for the project which will contain compiled jars, examples wars, etc.

Myfaces

Checkout: http://svn.apache.org/repos/asf/myfaces

Each servlet container has its own configuration in which details can be found here. Overall the latest version of Tomcat and Jboss had no major issues with the out-of-box Myfaces configuration. If you are integrating Myfaces with an existing JSF RI, there are steps with the ExtensionsFilter that must be taken located on the Myfaces wiki.

Viewing this up to date compatibility matrix, will ensure you are working with compatible libraries.

There are a number of performance settings you can make with Myfaces, but with integration of components being the focus for this article, performance tuning will be discussed in part 2 of this series.

Tomahawk

Checkout: Checkout: http://svn.apache.org/repos/asf/myfaces/tomahawk

Once you have the latest Tomahawk build checked out, you can find almost all of the Myfaces and Tomahawk configuration and performance settings in the sandbox/examples/src/main/webapp/WEB-INF/web.xml file. All of the settings are applicable to this article, and it is a great starting point that is well commented.

When using Facelets, each project requires its own tag library. Unfortunately Tomahawk does not include Facelet integration built into their jar(as of 1.1.4). This requires you to put together tomahawk.taglib.xml and point to it from settings in your web.xml.

<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/tomahawk.taglib.xml</param-value>
</context-param>

This provides pass-through getters and setters to the tomahawk library. You can write a *.taglib.xml for any library, but you may need to write a Facelets TagHandler.

Ajax4jsf

Checkout (use cvs): cvs -d :pserver:yourName@cvs.dev.java.net:/cvs checkout ajax4jsf

One of the largest hurdles with this library was integration with Trinidad. Trinidad and Ajax4JSF use their own ViewHandler with Facelets and both are very picky about how and where they are loaded.

Web.xml

<filter>
<display-name>Ajax4jsf Filter</display-name>
<filter-name>ajax4jsf</filter-name>
<filter-class>org.ajax4jsf.Filter</filter-class>
</filter>

<filter-mapping>
<filter-name>ajax4jsf</filter-name>
<servlet-name>FacesServlet</servlet-name>
</filter-mapping>

faces-config.xml

<application>
<default-render-kit-id>org.apache.myfaces.trinidad.core</default-render-kit-id>
<view-handler>org.ajax4jsf.framework.ajax.AjaxViewHandler</view-handler>
</application>

Initially I tried to use Neko HTML for the component XML rendering and had to abandon it because of one extra tag at the end of the response. Neko is known for not trying to "over" correct the code, but in this case it did not work. With the default Ajax4Jsf filter, you get Tidy cleaning up the response and that seemed to work just fine. Tidy is also configurable through a .properties file with various parser settings.

As of version 1.0.3, there have been many improvements and I was able to get everything working together from the settings above. This version also includes the integration jar for working with Trininad released after September 29, 2006.

One very nice debugging helper for this library is the logConsole div:

<div style="padding: 5px; overflow: auto; font-size: 9px; height: 150px; width: 100%;" id="logConsole"></div>

This allows you to see the entire Ajax request/response going and coming back from the server. One thing you may want to create is a Facelets debugging template and add this along with the facelets debugging options into it.

Trinidad

Checkout: http://svn.apache.org/repos/asf/incubator/adffaces

Here we have the basic settings for Trinidad to integrate with your application. Because we are integrating with Ajax4Jsf, Trinidad is the only ViewHandler defined in the web.xml. In the a4j example above you see how the ViewHandler for Ajax4Jsf is defined in the faces-config.xml. Again, if you are not using these two libraries together then you need to follow the documentation from the libraries corresponding websites.

Web.xml

<context-param>
<param-name>org.apache.myfaces.trinidad.ALTERNATE_VIEW_HANDLER</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>

<filter>
<filter-name>trinidad</filter-name>
<filter-class>org.apache.myfaces.trinidad.webapp.TrinidadFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>trinidad</filter-name>
<servlet-name>FacesServlet</servlet-name>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>INCLUDE</dispatcher>
</filter-mapping>

One important topic I would like to touch on is client-side state saving vs. server-side. Trinidad offers a unique strategy for JSF state saving which will allow tokens to be sent to the client allowing minimal performance drag. The default client-side state saving only saves a token to the client, and saves the real state in the HttpSession. MyFaces tells users to use server-side and Trinidad prefers client-side, but they are basically the same thing in terms of HttpSession. Also, failover is supported with the Trinidad state saving method.

As for components, Trinidad starts with more than 100 components which have already been documented and thoroughly tested. Now we have tags from 3-4 different libraries that overlap each other. We must decide which one to use where, why we are using them, and what is best for performance. Tag usage, along with state saving, will be discussed in part 2 of this series.

IceFaces

TODO - Update this section

**Note, since the writing of this article, Icefaces has been open sourced*** If you wish to make use of clustering and advanced asynchronous HTTP handling in a large-scale application, they want you to move up to the Enterprise Edition.

As of ICEfaces v1.0.1 release, they now have support for JSF integration. You can view configuration instructions here. In short, you can use the just-ice.jar, instead of the icefaces.jar, and use other JSF servlet mappings (ie. Faces Servlet) to handle non-ICEfaces pages. If you do this, you must use **only** standard JSF tags (f:) and ICEfaces tags (ice:) in you JSF pages.

ICEFaces doesn't have the same approach as ajax4jsf and DynaFaces have. You will have to follow their component-model to get the benefits of the Direct2Dom technology, so hooking up components of other libraries together with the ICEFaces components isn't possible (as of now), as they cannot re-render arbitrary components through their renderkit.

If you need to combine components from an open source library with IceFaces, one option is to use an iframe within an icefaces page. The iframe could point to the other JSF framework Servlet/ViewHandler. I haven't tried this yet myself, but according to the IceFaces support staff, it's worth a try.

For Facelets integration, along with the core jars, you will need icefaces-facelets.jar. There are minimal settings that take place for Facelet integration. The steps are located here

Facelets

The facelets ViewHandler configuration placement is critical to your application. If you are ONLY integrating Ajax4Jsf with Facelets, you should have you settings in web.xml as follows:

<context-param>
<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
<param-value>com.sun.facelets.FaceletViewHandler</param-value>
</context-param>

You need the above defined only if using Ajax4Jsf along with all other libraries besides Trinidad. If using Trinidad along with Ajax4Jsf and Facelets then follow the steps from the Trinidad section above.

One quick performance tip that will impact the foundational templating is the StreamingAddResource.

By adding:

<context-param>
<param-name>org.apache.myfaces.ADD_RESOURCE_CLASS</param-name>
<param-value>org.apache.myfaces.component.html.util.StreamingAddResource</param-value>
</context-param>

...to the web.xml and using...

  • t:document as replacement for html
  • t:documentHead as replacement for head
  • t:documentBody as replacement for body

...this will allow the pages to be streamed which will result in faster page delivery.

For debugging Facelets, add the following to your web.xml:



<context-param>
<param-name>facelets.DEVELOPMENT</param-name>
<param-value>true</param-value>
</context-param>

Setting this to true will cause the FaceletViewHandler to print out debug information in an easy to use screen when an error occurs during the rendering process. Probably one of the coolest features for debugging is the tag. Of course you can?t have ?cool? without an expense, so be careful when using this option because of overhead. You can use the UIComponent rendered property to turn debugging on or off based on some expression. In this example, debugging is backed by an entry in the web.xml.

<ui:debug hotkey="d" rendered="#{initParam.debugMode}"/>

The debug tag will capture the component tree and variables when it is encoded, storing the data for retrieval later. You may launch the debug window at any time from your browser by pressing 'CTRL' + 'SHIFT' + 'D' (by default). Like I said earlier the best place to put this tag is in your site's main template, or in some kind of debugging template, where it can be enabled/disabled across your whole application.