February 21st, 2012
3:57 pm
CDI Interceptors not called on local call to service layer EJB method

Posted under CDI
Tags , ,

When a service layer EJB method is called locally from within the same class, any CDI interceptors on the method are not invoked. This is standard CDI behaviour, as interceptors are only designed to be called when a method is called from an external client.

I hit this issue when my OptimisticLockInterceptor (which converts OptimisticLockException to ChangeCollisionException) was not being called, and OptimisticLockExceptions where being propagated all the way up to the view layer -  Mantis issue 120 details this.

The solution to this is to ensure that any required interceptors are annotated on methods at the point of call from an external client. If they then call another EJB method locally, any interceptors on the second method will not be called, but this is not a problem if the first method is correctly annotated. If the second method is also used externally, then its interceptors will be correctly invoked.

No Comments »

February 13th, 2012
2:42 pm
CDI/Weld fails to inject a reference with nested parameterised types

Posted under CDI
Tags , , , ,

Weld 1.0 was failing with “WELD-001408 Injection point has unsatisfied dependencies” when nested parameterised types were present.

The referenced bean was correctly present and annotated.

I found that I could work around the problem by simplifying/removing some of the generics. This allowed the beans to inject, but also gave warnings about the use of raw types. For example:-

//Original code
    private @Inject TableCtrl<TreeNodePath<TaxonomyNode>, RowMetadata> selectionTable;

//was replaced with the following
    private @Inject TableCtrl<TreeNodePath, RowMetadata> selectionTable;

Attempts to use a CDI extension to find out more about what was happening did not reveal any more insight. This post discusses Weld performance and debugging and refers to a Stack Overflow post on the subject.

My solution to the problem (which I have also logged on Mantis) is  as follows :-

  1. Injecting the bean into a raw type does not suffer from the problem.
  2. I therefore inject into a temporary raw type, and cast that to the correct type.
  3. Wrapping this in a method annotated with @Inject neatly solves the problem, as the method can take the raw types as arguments, and cast to the correctly parameterised fields in the method.
  4. As all this is done in a method, warnings can be suppressed for the method. This is a tidy solution, as the method only has this specific purpose, and no other warnings in the class are incorrectly suppressed.
  5. This is far better than the original workaround which involved hacking the generics back to non nested parameterised types throughout – this meant hacking a number of classes. The current solution entirely isolates the issue and allows the desired generics to be correctly used everywhere.

An example of the correct generic declarations and the method used follows :-

public abstract class TreeBrowser<N extends TreeNode<T>, T extends Tree<N>, P extends TreeNodePath<N>>
                            implements Serializable, BreadcrumbCtrlEvent<N> {

    private CrumbComparator<N> crumbComparator;
    private BreadcrumbCtrl<N> breadcrumb;   
    private TableCtrl<N, RowMetadata> treeNodeTable;
    private TableCtrl<P, RowMetadataStatusMap> trayTable;

    @Inject
    @SuppressWarnings({"rawtypes", "unchecked"})
    void injectWeldUnsatisfiedGenericBeans(CrumbComparator crumbComparator, BreadcrumbCtrl breadcrumb,
                           TableCtrl treeNodeTable, TableCtrl trayTable) {
        this.crumbComparator = crumbComparator;
        this.breadcrumb = breadcrumb;
        this.treeNodeTable = treeNodeTable;
        this.trayTable = trayTable;
    }

 

This solved the problem.

No Comments »

January 27th, 2012
11:30 am
Controlling CDI conversation propagation

Posted under JSF
Tags , , , , ,

This is a tricky issue to control correctly. The following points have been found during testing (Mojarra 2.0.4 FCS / Primefaces 2.2.1 / Glassfish 3.0.1)

  1. One key issue is that to start a new conversation on a page, the navigation to that page must not propagate any previously active conversation. This will then start a new transient (i.e. not long-running/not started) conversation on the new page, and conversation.begin() can be used to make it long-running (i.e. start it).
  2. When doing a standard JSF Ajax postback, the current conversation is always propagated, and it does not appear to be possible to prevent this/start a new conversation from a postback. JSF always adds the current CID as a querystring parameter
  3. To prevent propagation and to allow a new page to start a new conversation, GET navigation needs to be performed. This fits in well with my main toolbar options – I use pre-emptive GET navigation for the main pages with full page refreshes.
  4. Primefaces p:button allows the new JSF 2 outcome style GET navigation but cannot be stopped from propagating a conversation – it always adds a CID parameter. If you add one with an empty or null value, you still get a “cid=” attribute which CDI then spits out as an invalid conversation on the new page.
  5. h:link can be stopped from propagating by using an explicit f:param for the cid, providing the param has no value or an explicit null value (an empty string will not work).
  6. Trying to refer to another inactive conversation, e.g. by storing conversation scoped bean references in a session level map and looking them up, seriously screws up CDI with an extremely long/possibly recursive stack trace. (See Mantis issue xxx for the stack dump). This is likely to be due to the proxying mechanism used for conversations.
  7. Therefore, it is not possible to invent say a ‘onPageLeave’ event for a previous page and call it after a new page has started and had its conversation activated.
  8. If therefore I need to refresh all pages for the application, for example if an OptimisticLockException occurred, I use a central workspace session bean to manage all the pages. I set a refresh pending flag in a map for each page, and then when the page is next visited, the workspace bean calls a refresh event of my own for the page, and then clears the pending flag. When processing the current page after an OptimisticLockException, I can refresh directly if the user requests it from a lock dialog.
  9. My workspace bean holds the CID for each page against the page name in a map, and uses this when rendering the Toolbar, adding the appropriate cid= parameter for each toolbar option. In fact I use an outer map keyed on page group name (where the page group corresponds to a top level toolbar option), with an inner map containing all the cids and refresh pending flags for the individual pages in that group. This allows for example a report toolbar option to be a menu of currently active reports, and allows new reports to be created dynamically as new conversations and added to the list under the report menu on the toolbar.
  10. Conversations are started and ended via calls to the workspace bean, which can then add/remove entries from the maps to keep track of what pages/cids are currently active.
  11. Regarding navigation and cid propagation, another option is to call JSF directly to obtain the navigation case for an outcome. ConfigurableNavigationHandler allows you to pass an outcome and get the actual navigation case, from which you can then get the URL. This should allow full control of the cid= propagation parameter on the querystring, and allow control for components which do not support JSF 2.0 style GET pre-emptive navigation directly from an outcome. The url can be passed to any component which accepts a url, and should then still perform the correct navigation and conversation control. See CoreJSF 3 page 333 for a code example on this. This method could prove useful for example with a Primefaces MenuItem, which does either JSF postback style navigation, or URL navigation, but does not directly do pre-emptive GET navigation by giving it an outcome.

No Comments »

June 2nd, 2011
3:30 pm
JSF 2–Objects as selectOneMenu items–Custom Converter/CDI issues

Posted under JSF
Tags , , ,

With JSF 2.0, it is now possible to use any class as an item in a selectOneMenu combo and related components. This is described in  “Core JavaserverFaces” p157ff. However, the book does not mention that you also need a custom JSF converter to convert between object and string.

If you then implement a custom converter as in the book on p279, e.g. with:-

<h:selectOneMenu styleClass="ss-tsw-select" id="cmbTheme"
      value="#{themeSwitcherBean.theme}" disabled="#{themeSwitcherBean.selectDisabled}"
      converter="uk.co.salientsoft.thememanager.ThemeConverter"
      immediate="true" onchange="submit()">

CDI fails to inject any references used in the converter class, as JSF 2 does not allow CDI in converters, as detailed in this Stack Overflow Post.

It does work however if you use an EL reference in the converter attribute as mentioned in this post here.

Note that the post indicates that it may require it to be an application scoped bean. In my case, it worked fine as both a request scoped and application scoped bean with no trouble. I also removed the @FacesConverter("uk.co.salientsoft.thememanager.Theme") annotation as this was no longer required due to the EL reference. The post indicates that this is perceived to be more untidy due to the use of EL and a managed bean, but I cannot see an issue with this. I cannot see why converters cannot be application scoped CDI beans, it all fits in fine. Here is the code fragment above, modified to use an EL reference instead:-

<h:selectOneMenu styleClass="ss-tsw-select" id="cmbTheme"
      value="#{themeSwitcherBean.theme}" disabled="#{themeSwitcherBean.selectDisabled}"
      converter="#{themeConverter}"
      immediate="true" onchange="submit()">

No Comments »

May 31st, 2011
6:42 pm
Iterating CDI Bean Types

Posted under CDI
Tags , , ,

When developing plugin architectures with IOC, it is useful to be able to iterate over the available beans of a given type which are known to the IO container.

In CDI, this is easy to do, but it is not obvious how from the Weld documentation unless you do a bit of digging and searching.

This post here gives a sample application which does it. The crucial code snippet which does the business is here:-

private @Named @Produces ArrayList<String> wilsons = new ArrayList<String>();
@Inject
void initWilsonRacquets(@Any Instance<WilsonType> racquets) {
    for (WilsonType racquet : racquets) {
        wilsons.add(racquet.getWilsonRacquetType());
    }
}

The intance keyword (used with @Any) exposes an iterator which lets you iterate the available beans. In the above sample they are added to a collection, but you could equally call methods on them as you iterate if you don’t need to keep them.

The Weld documentation describes this on page 25, with the following sample fragment:-

@Inject
void initServices(@Any Instance<Service> services) {
    for (Service service: services) {
        service.init();
    }
}

No Comments »

May 31st, 2011
4:13 pm
Using CDI Conversation Scope

Posted under CDI
Tags , ,

This is an interesting  2 part article by Andy Gibson on how to use CDI conversations. Part 1 is here and Part 2 is here. Of particular interest is his discussion in part 2 about how to manage a collection of conversations and index them/return to them etc.

Another post here discusses the use of conversations and some custom reflection trickery to implement a generic CRUD application that only uses JSF view coding to implement a particular application.

No Comments »

May 24th, 2011
8:05 am
Weld Debugging and performance issues

Posted under CDI
Tags ,

It seems to be that Weld:-

  • has error/log messages which are not as good as Spring
  • has a lot of magic going on compared with, say, Guice, and so more info is needed about what is going on under the hood.
  • Turning logging up to full is obviously a starter. I haven’t done this yet – need to look at weld log messages to see what to turn up. Note that Weld uses sls4J NOT java.util.logging, and the levels are therefore different – need to look at how they are mapped/how to turn it up.

You can find out more about Weld’s decision making when injecting beans by writing some code to listen to various weld events. You have to use Weld’s extension mechanism to do this but it is apparently very easy. Details of it in this post here on stackoverflow.

There are also some comments around about slow weld performance and memory usage, during startup. Performance is being improved and Weld 1.1 has these fixes in, but you need Glassfish 3.1 to use it which also opens up all the issues of Mojarra client state saving problems etc. which have prevented me moving to it.

There is some negative CDI/Weld comment about on the net, but as with any toolset there is no silver bullet. Any choice will have some downsides and our priorities should and will determine the best choice. Even with these issues, I cannot see a justification to move to Spring as whilst it is mature and very popular, it is a closed standard which is very XML heavy and does not do typesafe injection. Guice is closer in style to CDI, but both Guice and Spring are JSR330 implementations and so are not portable. Weld uses JSR299/CDI and is therefore an open portable (and the most recent) standard, and is built on input from both the Spring and Guice teams. If we can suffer some early adopter pain, I feel Weld will end up being the best choice.

By the time performance becomes a serious issue for this project, Weld will have moved on and these issues should have improved. Note also that there is already (at least) one alternative JSR299 implementation – Apache OpenWebBeans. This means that we can move to another CDI implementation if we have to, with minimum pain, in the same way that if Mojarra screws us we still have Apache Myfaces as a choice.

No Comments »

April 12th, 2011
2:21 pm
Composite Components–Best Practice

Posted under JSF
Tags , , , ,

Update

The original post below mentioned at the beginning #{cc.attrs.clientId}. Whilst this does work and is mentioned on the net, the correct form is #{cc.clientId}. I have amended accordingly.

Original Post

This post here is an IBM Developerworks post on CC best practice. Some comments/observations follow:-

  1. Wrap a cc in a div (NOT a panelgroup) and give it id=“#{cc.attrs.clientId }” “#{cc.clientId }” to give it the ID given to the actual composite. Note that if you use a div, it will NOT be given the CC’s Nameingcontainer prefix (and hence will not have the “double ID” issue whereby it prefixes the ID you specify with the naming container prefix again).
  2. You cannot specify an h:panelGroup inside a CC without an ID, or the resulting div is not rendered on the page at all.
  3. The id= and rendered= are both ‘standard’ attributes of a CC that you can use by virtue of the fact that a CC is a jsf component – you don’t need to roll your own ‘display=’ attribute for example. This is helpful, as otherwise you would need to wrap a CC in a div in order to give it the CC naming container ID as in 1/, but you would also need to wrap it additionally in an actual h:panelGroup in order to roll your own display= ‘rendered’ style attribute. This may very well be the reason why you get an illegal argument exception if you try to specify your own rendered= attribute on a CC (as per this Mantis issue).
  4. cc.id is a built in reference for the CC’s declared ID without any naming container prefixes. cc.clientId is the full monty with all the prefixes. These are analagous to component.id and component.clientId which can be used for any JSF component. Sadly I have not seen any full documentation for the cc or component built in objects.

The second part of the IBM Developerworks article is here. It details how to add Ajax behaviour to a CC, and in particular how to add Ajax behaviour to a component inside a CC from outside. This is useful for less complex CCs, and partners with the other features like retargeting which allows you to pass a listener to a CC which is attached to a component inside the CC.

For more complex CCs, I tend to take a different approach, as follows:-

  • I code a controller class in Java for use with the CC, and pass it in as an attribute of the CC (typically controller=). Any behaviour of components inside the CC such as Ajax and listeners are all handled by this controller bean.
  • The controller bean is injected by CDI as an @dependent bean, and is typically injected into the page bean which acts as controller for the page. In this way, the lifecycle of the controller is tied to that of its containing bean, which is clear and exactly as it should be.
  • As the controller is a dependent bean, CDI allows it to be generic and to use parameterised types (you can only do this for a dependent bean). For example, I have my own breadcrumb control CC (see here) which has its own controller class. This accepts a list of crumbs, where a crumb is a parameterised type for the class.
  • A page may have multiple instances of such a CC, in which case it just injects multiple controllers, one per CC that it manages.
  • In order to provide event handling, I take a simple approach. A controller just has an event interface which it calls out to in order to pass on any relevant events such as listener or action events. Typically, these will mimic the interface for a listener or action and just pass it on. I generally add an additional argument to the start of all such calls, containing a reference to the controller itself (i.e. the controller passes this in the argument). This is useful in cases where for example the containing page bean itself implements the event interface and handles the events, as where there are multiple components/controllers on a page this argument can be used to determine which one the event was for.
  • A key concept with this technique, which works better for more complex cases, is that I am not just exposing internal component behaviour of components in the CC to the outside as you might using JSF retargeting for example. Rather, I am using the controller to provide its own abstraction of the internal behaviour and to provide an external interface which reflects its overall function. In other words, I can map the internal behaviour to the external interface in any way I choose, which gives me much greater control and design flexibility.
  • Another approach would be to use a JSF CC Backing Component, as detailed in Core Javaserver Faces on p373. This allows Java behaviour to be added to a CC transparently to the CC’s clients. However, it does involve using some of the JSF internal interfaces that would also be used to develop full blown custom components. In that sense it provides a halfway house to a full custom component implementation. I have deliberately not used this approach in my use cases – the ‘controller’ approach I have outlined is simple and clear, and easy to develop. The controller is not hidden, being declared as a dependent by a calling backing bean, and being passed in to the CC on the facelet page. I feel that in my use cases the visibility, clear lifecycle control, and use of a separate controller instance per component on the page are a benefit and keep things clear and simple.  In design pattern terms, JSF uses the MVC pattern. The JSF components form the view, and my controllers and page beans form the controller. It could be said that a backing component for a CC is part of the view rather than part of the controller, as it uses internal JSF interfaces used by JSF components to implement the view part of the pattern.

No Comments »

March 4th, 2011
5:48 pm
Breadcrumb Composite Component using ui:repeat

Posted under JSF
Tags , , , , , , ,

Update 16/1/2012

A bug was found in the crumb styling. max-width was correctly set on the crumbs to truncate them, but when white space is present in a crumb, the default is to wrap at the max-width. This causes the breadcrumb to increase in height and add a second line. The fix was to turn off the wrapping by setting “white-space:nowrap” in the css for the crumb anchor tags (see Mantis issue 99 for details) :-

.ss-breadcrumb ul li,
.ss-breadcrumb ul li a {
    overflow:hidden!important;
    display:inline-block;
    white-space:nowrap;
    text-decoration: none;
}

 

Original Post

This follows on from my previous posts on the Primefaces breadcrumb here  and here.

I found a couple of further important issues I hit when using the standard breadcrumb:-

  1. In order to add and remove crumbs dynamically, it uses the Primefaces MenuModel. Methods of the MenuItem class are used to add actions and listeners.
  2. The mechanism seems somewhat cumbersome. In particular, it does not appear to be easy to pass a particular target object as an argument to an action or listener method, as the binding appears to be created as a string. Ideally what I would want is for the breadcrumb entries to be created by iterating a list using a var attribute like a table, and then to pass the var object containing the current crumb in the list as an argument in a method call to an action when that crumb was clicked.
  3. The only way I could see to do it involved passing an identifier for an object (such as the primary key for an entity). Whilst I certainly did not bottom it out completely, the mechanism seemed somewhat complex to use and lacking in flexibility.

Adding these issues to the ones already highlighted in the other posts (in particular the slowness of the jQuery operations when initially collapsing a breadcrumb in preview mode), I decided to take the step of rolling my own custom breadcrumb. The following approach was taken:-

  1. I decided to use a composite component rather than create a full blown custom component in code, as this looked more straightforward, and I had experience of composite component creation.
  2. The key factor which made this possible was that I could use ui:repeat to build the breadcrumbs dynamically from a list.
  3. Conditionally rendered xhtml tags could be handled using ui:fragment within the ui:repeat loop. This allowed the use of the rendered attribute on ui:fragment to optionally render sections even when standard non-jsf html tags such as <li> were used. For example, the root crumb of the component is rendered differently to the others, using an icon only. Also, full width crumbs are rendered differently to truncated crumbs (when truncating the component to fit a target width)

The following are the key features and design points for the breadcrumb:-

  1. The component is designed specifically for dynamic use, being driven from a list much like a table. It is not possible to build it statically on the facelets page (static use is covered by the standard control so this was specifically a non-goal/non-requirement).
  2. It is rendered entirely statically, so there is no (potentially slow) javascript/jQuery stuff going on at render time or during use.
  3. Compression to fit a target width is done by passing the desired target width in to the control. This is then used to set max-width css properties on the crumbs. This allows the crumbs to take the width they need and to only be truncated when they hit the max value. The max value is calculated on the server at render time by dividing the max target width by the number of crumbs to be rendered (allowing for the root crumb as a special case).
  4. The full text for a crumb can be viewed at any time by hovering over the crumb – it is displayed using the HTML title attribute. This is one annoyance with the standard Primefaces control – it does not allow use of the title attribute. Using the title  attribute allows the control to be static on the page for speed but still allows truncated crumbs to be easily read.
  5. The component supports the concept of stale crumbs. The idea is that when moving back up the crumb path (leftwards, or navigating up a tree path), the crumbs to the right which were previously visited are not immediately removed. They are highlighted differently as non bold and italic to make them less important compared to the ‘fresh’ crumbs on the path. In addition, the current crumb is underlined in order to make it completely clear where the current position is. Without stale crumbs present, this would normally be the rightmost crumb, but this will now no longer be the case if stale crumbs are present.
  6. Stale crumbs are only removed if the user navigates down a different tree path which invalidates them, in which case they disappear. Provided the user remains on the same tree path, the crumbs will be left in place.
  7. The stale crumbs may be clicked for navigation just like the fresh ones, to allow the user to revisit old ‘stale’ locations. When a stale crumb is revisited, it changes back to a fresh crumb again (as do all other stale crumbs to its left) and it becomes the current crumb – it is therefore rendered in bold, non-italic, and is underlined. The crumbs to the right of it if any still remain stale as they were before.
  8. To assist navigation up a tree structured hierarchy, it is common to include an ‘up’ button somewhere. This is taken a step further by including both up (= left pointing) and down (=right pointing)buttons on the left hand side of the breadcrumb component. When combined with stale crumb support, this feature allows easy navigation both up and down a given tree path. The right button is only enabled when stale crumbs are present, and clicking it moves down the stale crumb list just as if the next stale crumb was clicked. Navigating to the root of the tree (leftmost crumb) disables the left button.
  9. The component is styled in a similar way to the standard Primefaces component, and uses the same CSS classes for the styling.
  10. Styling may be modified, and features such as up/down support turned on or off.
  11. The component is styled using an inner div which holds the component itself – this can be floating if desired in which case it resizes the width to hold its contents. The inner div is contained in an outer div which is typically fixed in size to suit the page, allowing the inner div to scale up to that size. The width used for crumb truncation calculation is passed separately into the control – this will normally be slightly less than the max width set for the divs.
  12. The component is backed by a controller backing bean, BreadcrumbCtrl/BreadcrumbCtrlImpl, which may be subclassed to allow further customisation. The crumbs are passed into the bean as a simple generic list, and a property name used for the crumb text display is passed as a string attribute to the composite component. The controller fields action and listener events from the component, and passes them on using a BreadcrumbEvent interface – an object implementing this interface is passed into the controller bean at init time. When the user clicks on a crumb, the actual crumb in the list plus its list index are simply passed to its action method. When multiple components are used on a page, each will have their own controller object. These will typically be injected into the page backing bean e.g. by CDI as dependent beans. When the action and listener events are called, the actual controller object is also passed. This would allow for example the page backing bean to implement BreadcrumbEvent and manage actions for a number of dependent breadcrumb controllers, using the passed controller object to determine which one was clicked.

The following are some of the key technical issues which arose during development of the component:-

  • ui:repeat is used for iterative xhtml generation of the crumbs. This uses a var attribute like a table to represent the current object (crumb) in the list. It also supports a varstatus attribute which allows access to various loop properties within the loop, such as the current loop index, first and last boolean properties and others. The index property in particular is used to determine styling for the current crumb and stale crumbs etc.
  • In addition, the varstatus object (com.sun.faces.facelets.tag.jstl.core.IterationStatus) can be accessed from the controller bean using code similar to the following, where varStatusKey is the name given in the varstatus attribute to ui:repeat:-

Map<String, Object> requestMap = FacesContext.getCurrentInstance().getExternalContext().getRequestMap();
IterationStatus varStatus = IterationStatus) requestMap.get(varStatusKey);

  • It is important to note that whilst it is tempting to cache the varstatus object in the controller bean, this does not work – a new object must be obtained each time using the above code.
  • ui:fragment can be used directly in the ui:repeat loop within the composite component implementation – it is not immediately obvious from the documentation that this is the case.
  • When declaring the attributes for the composite component using <composite:attribute>, note that the type attribute allows specification of a particular object type, the required attribute makes an attribute mandatory, and the default attribute sets a default.

The source code and a usage example of the breadcrumb control may be found in the repository here.

No Comments »

February 2nd, 2011
7:56 pm
Primefaces Table Sorting–Common Gotchas

Posted under JSF
Tags , , , , , , , ,

Update 2/2/2011

According to this post here by Cagatay Civici, the Primefaces Project Leader, as at Primefaces 2.2M1, client side datatable is not supported and the dynamic attribute is deprecated from then on.
Seemingly it was becoming too hard to support all the table features on both client and server sides.
It is a shame that this was not documented better and more widely – the user manual still documents the dynamic attribute, and there are a number of posts about client side sorting (though in fairness they probably predate 2.2M1).

This behaviour exactly ties up with what I am seeing in my testing – the dynamic attribute does nothing, sortFunction is ignored, and all sorting is done via Ajax server side.

Original Post 2/2/2011

Having successfully got sorting working I was frustrated to find that a new simple example failed to work. Primefaces table sorting is pretty much transparent, requiring minimal effort and working out of the box. The lessons learned on this one are instructive so I summarise them below.

Details of Example and Problem

  1. The example fetched a list using JPA, stored the list in a view backing bean, then displayed it in a table with a sortable header.
  2. When the header was clicked, the up/down arrows were correctly displayed, but the data was not sorted – it was as if the request was ignored.
  3. It was not immediately obvious how the header click was handled – there was no obvious click event on the HTML element, and I could not see any Javascript running after a quick test with Firefox/Firebug. I gave up this line of attack but may look into it later as to how it all works. Some dynamic CSS pseudo classes/jQuery trickery may be involved.
  4. I was not certain as to whether the table was client side or server side/Ajax, even though it should have been client side by default. To diagnose the problem, I changed the value of the sortBy attribute in the column header to be an invalid bean property. The symptoms did not change, but an errors were logged in the Glassfish server log for each header click – “[#|2011-02-02T18:22:14.557+0000|SEVERE|glassfish3.0.1|org.primefaces.model.BeanPropertyComparator|_ThreadID=24;_ThreadName=Thread-1;|Error in sorting|#]”.
  5. This showed that the sort was being attempted but was failing due to the invalid property, which indicates that the sort was attempted server side. According to the Primefaces forum, for client side sorting, the sortBy property is not used as the displayed data is sorted.
  6. Interestingly, I would have expected Primefaces to use a client side table by default, but clearly it was not. Changing the dynamic property on the table tag to false explicitly had no effect and the behaviour was unchanged, so I will need to investigate client side tables further as for small data sets they are faster – I will update this post when I have done this.
  7. I turned on FINEST logging with Eclipselink in persistence.xml. Use <property name="eclipselink.logging.level" value="FINEST" /> to do this, and note that you need to bounce Glassfish to for a logging level change to be picked up. I noticed after this that the JPA query seemed to be rerunning very often, perhaps for every click of the sort header. This lead me to wonder if the backing bean was being recreated each time.

 

Cause and Solution

In the end, it was simply that I had not annotated the JSF backing bean as @SessionScoped (the example used CDI throughout, and did not use JSF managed beans). This meant the bean was request scoped by default, and was indeed being recreated – the sort was trying to do the correct thing, but the data was getting reloaded from the database in the original sort order each time!

Adding the correct annotation as above (and making a couple of the beans correctly implement serialisable to satisfy CDI/Weld) solved the problem.

This is a good example of where a problem cause is not immediately apparent from the symptoms.

Sample JSF page fragment showing the form containing the table

<h:form id="frmTest">   
    <util:themeSwitcher form="frmTest" outerStyle="clear: both; float: left; margin-bottom:20px;" innerStyleClass="ui-widget"/>
    <h:panelGroup layout="block" style="width:300px;">   
        <p:dataTable var="taxonomyNodes" value="#{taxonomyBrowser.taxonomyNodes}" scrollable="true"
             styleClass="clear #{fn:length(taxonomyBrowser.taxonomyNodes) lt 20 ? ‘ss-tableheader-scrolladjust-nobars’ : ‘ss-tableheader-scrolladjust-bars’}"
             height="460" > 
             <f:facet name="header">
                Client Side Sorting
             </f:facet>
             <p:column headerText="Category List"  sortBy="#{taxonomyNodes.text}">
                 <h:outputText value="#{taxonomyNodes.text}" />
             </p:column>           
        </p:dataTable>
    </h:panelGroup>
</h:form>

No Comments »