Wednesday, November 17, 2010

Richfaces : ReThink Before ReRender

Sometimes when you go deeper into a framework or a tool , you tend to take beginner stuff for granted. That bit me today for a while before I could get my head around it.  ;-)

When using Ajax, it's a well known fact that for you to manipulate a DOM element, that element needs to be present. Same rule applies when you are using reRender in Richfaces as well. Let's take a look at following code snippet:

<rich:panel header="Add New Application">
   <h:outputText value="App Name " />
   <h:inputText size="20" id="appNameInput" value="#{appConfigBean.currentApp.appName}" />
   <a4j:commandButton id="new_app_submit" action="#{appConfigBean.addNewApp}"     
    value="Add" reRender="appDetails" />
</rich:panel>


<h:panelGrid columns="2" id="appDetails" 
                rendered="#{appConfigBean.renderDetail}">
      <h:outputText value="Some stuff"/>
</h:panelGrid>


The addNewApp method in backing bean sets renderDetail to true which initially was false. So when you click Add button, you would expect reRender to kick in and show the panelGrid with id appDetails. Nope. It does not happen. From second paragraph you might have understood the reason already. But here is a more detailed explanation.

Since initially, renderDetail boolean is set to false, when the page is first loaded, the html for panelGrid never gets rendered hence there does not exist a DOM element with id appDetails and reRender does not know what to update.

To fix this, the easiest and probably the best solution is to surround panelGrid with a4j:outputPanel and you would put this output panel's id for reRender to do its magic.  Here is the updated code:

<a4j:commandbutton id="new_app_submit">
                      action="#{appConfigBean.addNewApp}" value="Add"
                      reRender="appDetailOutputPanel" /&gt; 

<a4j:outputpanel id="appDetailOutputPanel"> 
     <h:panelgrid columns="2" id="appDetails">
                     rendered="#{appConfigBean.renderDetail}"&gt;
          <h:outputtext value="Some stuff"></h:outputtext>
     </h:panelgrid>
</a4j:outputpanel>

Tuesday, November 2, 2010

Tips when using AWS sdk with JBoss AS + GateIn

While working on a really cool portlet for GateIn that uses Quartz scheduler and AWS sdk which I am going to unveil to the rest of the world in few days ;-), I came across a weird problem. :


Caused by: java.lang.LinkageError: loader constraint violation: when resolving interface method "javax.xml.xpath.XPath.setNamespaceContext(Ljavax/xml/namespace/NamespaceContext;)V" the class loader (instance of org/jboss/classloader/spi/base/BaseClassLoader) of the current class, org/quartz/xml/XMLSchedulingDataProcessor, and the class loader (instance of ) for resolved class, javax/xml/xpath/XPath, have different Class objects for the type javax/xml/namespace/NamespaceContext used in the signature


This kind of error obviously suggests some conflict with classloader and that was the case in this scenario too. I initially thought it must be something with quartz because I am using Quartz's XMLSchedulingDataProcessorPlugin but looks like that dependency comes from AWS sdk. To get it working, I simply removed stax-api-1.0.1.jar from WAR file and portlet deployed fine. The conflict happens because GateIn 3.0.1.GA + JBoss AS 5 combination has stax-api.jar under GateIn-3.1.0-GA/lib/endorsed which means StAX library is a system-wide library.