Archive for the 'JSF' Category

July 25th, 2011
11:35 am
Using the Primefaces p:panel component

Posted under JSF
Tags , , , ,

This post details some tips discovered whilst experimenting with p:panel.

1/ The toggle button on the right hand side of the panel is rendered with ui-state-default. This does not look attractive with some themes – it often looks like a bit of a zit due to the background on the thick plus sign icon. I noticed that the dialog component p:dialog does not render its close icon in the header with ui-state-default,  and this looks much more attractive as the surrounding highlight on the icon only shows on hover.

This can be applied to p:panel by removing the ui-state-default class from the anchor tags around the icons on the panel header. The following example jQuery performs this (in my case, the panelDivId argument is the ID of an h:paneGroup/div surrounding the panel:-

function ss_PanelFixIcons(panelDivId) {
    var escapedPanelDivId = panelDivId.replace(/:/g, ‘\\3A ‘);
    var panelIcons = jQuery(‘div#’ + escapedPanelDivId + ‘ div.ui-panel-titlebar > a.ui-panel-titlebar-icon’);
    panelIcons.removeClass(‘ui-state-default’);
}

 

2/ It would be nice to be able to explicitly expand and collapse the panel as well as to just toggle it. In fact the panel widget does expose its current state via its cfg property, although this is not publicly documented. The following example functions use this to provide explict expand, collapse, and set to passed boolean state functions. In addition a function is provided to get the current panel state:-

function ss_PanelExpand(widgetVar) {
    if (widgetVar.cfg.collapsed) {
        widgetVar.toggle();
    }
}

function ss_PanelCollapse(widgetVar) {
    if (!widgetVar.cfg.collapsed) {
        widgetVar.toggle();
    }
}

function ss_PanelSetCollapsed(widgetVar, state) {
    if (!widgetVar.cfg.collapsed == state) {
        widgetVar.toggle();
    }   
}

function ss_PanelGetCollapsed(widgetVar) {
    return widgetVar.cfg.collapsed;
}

 

3/ A query came up on the Primefaces forum on how to lazy load the panel, as it eagerly loads and the expand/collapse is all done client side. The post is available here. the solution is straightforward:-

  • Use a toggleListener to update a renderPanel property to true if the panel state from the event was visible, and false if it was hidden.
  • Then conditionally render a content h:panelGroup inside the panel, using the above property as the rendered property.
  • One issue with this is that the actual panel toggle occurs before the ajax update of the panel not after, so with the slide toggle effect on (say with toggleSpeed=”1000”), you see an empty sliding toggle first, then a non sliding ajax update. In this case it is best to turn off the slide effect with toggleSpeed=”0”. If you use another button to toggle the panel you can get around this, as the onComplete event for the button can toggle the panel (via its widget/ as per the above JavaScript), and this happens after the Ajax to render the panel. In practice you would have to somehow overlay the standard toggle button with another one of your own, or manually disable the standard one via CSS, as if you set toggleable=”false” for the panel this completely disables toggling via the widget as well as removing the toggle button.
  • It is probably not worth the trouble of trying to get sliding to work if you are lazy loading. Note that when I tried some older/slow machines the slide effect rendered poorly anyway, so this should also be born in mind.

No Comments »

July 19th, 2011
10:14 pm
Accessing JSF Resource Bundles from Java Code

Posted under JSF
Tags , , ,

This is useful to be able to do. Typically you will want to declare a resource bundle in faces-config.xml to load it once for the application. You then refer to it from any JSF page that needs it.

However, you often want to also load messages from code. An example might be the generation of custom faces messages or other error messages generated by the code.

It is clearly therefore desirable to access the same message bundle that JSF has loaded, so that it is specified centrally, loaded once for the application, and reused by both JSF and Java.

This post here by Andy Gibson details how to do this. The code fragments are shown below, in case the link ever becomes broken:-

 

Resource File

firstName=First Name
lastName=Last Name
forgotPassword=Forgot Password?
usernameTaken={0} is already taken

 

faces-config.xml

<application>
    <resource-bundle>
        <base-name>org.fluttercode.resourcedemo.MessageResources</base-name>
        <var>msgs</var>
    </resource-bundle>
</application>

 

Class MessageProvider

public class MessageProvider {

    private ResourceBundle bundle;

    public ResourceBundle getBundle() {
        if (bundle == null) {
            FacesContext context = FacesContext.getCurrentInstance();
            bundle = context.getApplication().getResourceBundle(context, “msgs”);
        }
        return bundle;
    }

    public String getValue(String key) {

        String result = null;
        try {
            result = getBundle().getString(key);
        } catch (MissingResourceException e) {
            result = “???” + key + “??? not found”;
        }
        return result;
    }

}

Backing Bean

@Named
@RequestScoped
public class SomeBean {

    public String getMessage() {
        String msg = new MessageProvider().getValue(“someMessage”);
        return MessageFormat.format(msg, “SomeValue”);
    }
}

Example Code to generate a custom FacesMessage (from CoreJSF Edition 3, Page 332)

public void validateDate(ComponentSystemEvent event) {
    UIComponent source = event.getComponent();
    UIInput dayInput = (UIInput) source.findComponent(“day”);
    UIInput monthInput = (UIInput) source.findComponent(“month”);
    UIInput yearInput = (UIInput) source.findComponent(“year”);
    int d = ((Integer) dayInput.getLocalValue()).intValue();
    int m = ((Integer) monthInput.getLocalValue()).intValue();
    int y = ((Integer) yearInput.getLocalValue()).intValue();

    if (!isValidDate(d, m, y)) {
       FacesMessage message = com.corejsf.util.Messages.getMessage(
            “com.corejsf.messages”, “invalidDate”, null);
        message.setSeverity(FacesMessage.SEVERITY_ERROR);
        FacesContext context = FacesContext.getCurrentInstance();
        context.addMessage(source.getClientId(), message);
       context.renderResponse();
    }

}

No Comments »

July 7th, 2011
9:52 am
A ui:param/attribute value is passed on invisibly to a called custom tag with attribute of the same name

Posted under JSF
Tags , , , ,

I passed a styleClass attribute to a facelets decorator using <ui:param>. The decorator in turn used a custom tag which had a styleClass attribute.
I discovered whilst looking in Firebug that the styleClass attribute passed to the decorator was being passed on to the custom tag, even though I had not specified a styleClass attribute on the custom tag. The CSS class name was clearly visible in Firebug.

I’ve investigated this with a test application and have confirmed the following points. I have also logged these points under a Mantis issue here.

Note that this was running on Mojarra 2.0.4 FCS, and I am not clear whether all of these issues are by design or would be considered a bug, and how consistent they are across other versions/JSF implementations:-

  1. A ui:param passed say to a decorator is indeed visible via EL in a custom tag called from the decorator. If the custom tag has an attribute of the same name, this will be passed to the tag in preference, but crucially, if the attribute is omitted/defaulted on the tag, the tag will then see the ui:param from the calling decorator.
  2. The above issue in 1/ even occurs if the above decorator is changed to be itself a custom tag, and the ui:param instead becomes an attribute of the parent/calling custom tag. In this case, the nested custom tag sees attributes passed to its parent if the same attribute is not explicitly passed to it.
  3. Fortunately, if a child custom tag is called with an explicit attribute with the same name as an attribute or ui:param passed to its calling tag or decorator, the value in the calling tag/decorator is not modified. This means that you can call child tags without corrupting state in the calling environment.
  4. Point 3/ is also true when a decorator is called with ui:param. If the ui:param has the same name as one used in the caller (either defined there or passed to it), changing the value of the ui:param within the ui:decorate tag to pass it to the decorator does not change the value of the same named parameter outside of the ui:decorate tag.
  5. If a child decorator modifies a ui:param passed by its caller, the modified value is visible only within the child decorator. On return to the calling environment, the ui:param value reverts to what was passed to the child by the caller. This indicates that there is scoping going on.

 

The lessons from this are therefore as follows:-

  1. The prime gotcha here is that if you omit an attribute on a custom tag call or a ui:param on a decorator call, a ui:param or attribute value in the caller’s environment will be visible to the called environment exactly as if it was passed in explicitly! You must therefore take great care to ensure that child calls have explicit empty/null attributes or ui:params specified where there is a name clash with one in the calling environment.
  2. Attribute values and ui:param values are scoped, and you can safely pass the same named ones with different values to child decorators or custom tags without affecting the values in the calling environment. This is even true when defining a ui:param within a ui:decorate tag – it does not affect the value of a similarly named ui:param outside the ui:decorate tag.
  3. Changing the value of a ui:param in a child decorator/tag does not change the value of the same named one in the calling environment. It does however cause the value to change after the point of change in the child environment.

No Comments »

July 6th, 2011
5:27 pm
Facelets – using <f:subview> to create a naming container

Posted under JSF
Tags , , ,

<f:subview> creates a naming container and so may be used to avoid ID collisions on a facelets page. It says in CoreJSF, 3rd edition, that this is not needed for facelets, but as it turns out, I have found a significant use for this.

One of my custom tags is a complex multi table tree browser component, which has lots of optionally included/defined markup. It therefore needs to be a custom tag rather than a composite component, as the latter would not give the required flexibility.

The issue I hit with this is that I use multiple variants of this tree browser on the same page, to browser different tree structured data within my application. The trees are all polymorphic, and indeed share and subclass the same base JSF controller class, as well as re-using the same base custom tag. As there is more than one on a page, I have potential ID collisions, and so to avoid this, using <f:subview> to define a naming container in the custom tag is ideal in this case.

This is helped by the fact that in JSF 2 you can actually pass an ID to a custom tag and define it in the tag in <f:subview> using an EL expression. Whilst this is normally unorthodox and not encouraged, in this case it makes perfect sense – the value does not come from a bean, but is a constant string passed via the attribute.

No Comments »

July 6th, 2011
5:16 pm
Facelets–using a custom tag interchangeably instead of a Decorator

Posted under JSF
Tags , , ,

Update 26/7/2011

Some more points that were omitted or incorrect in the first posting:-

  • A handy feature with templates/custom tags is that you can render children of the template/tag at the call site simply by using a <ui:insert> without a name. You therefore do not need to use a <ui:define> tag in this case, and all children which are not contained in other <ui:define> or <ui:param> tags will be rendered as part of this default <ui:insert>
  • The statement below that it is not possibly to insert a number of different markup variants in a composite component is incorrect. A composite component can have a number of named facets just like a ‘real’ JSF component, and these allow markup to be inserted in the same way as <ui:insert>/<ui:define> does for a template or custom tag.

Original Post

I had a complex decorator which was used for tree browsing. It had a number of ui:inserts for custom markup, plus also a large number of <ui:params> to define EL parameters used within it.

This all worked fine, and even looked quite tidy as all the <ui:params> were listed one per line below each other. However, it was all rather verbose compared to using a custom tag where you would use attributes instead to pass the EL parameters.

It turns out that you can convert a decorator to be a custom tag with no effort as they operate similarly. You merely need to register the xhtml file in a taglib as with any custom tag, and you can then call exactly the same code as a custom tag instead of a decorator.

The neat tricks here are that:-

  • <ui:params> become attributes which are less verbose, but the tag itself does not know any difference and needs no changes.
  • <ui:insert>/<ui:define> work perfectly with a custom tag exactly as they do with a decorator.

 

Another nice point on this is you can develop custom tags that include pseudo ‘child markup’ in similar fashion to composite components, by using the <ui:define>s. Providing you do not need the other features of composite components such as retargeting, Ajax etc., custom tags can be very useful where you have a need to insert a number of different markup variants for different flavours of the tag, as you cannot do this so flexibly with a composite component.

The technique of using <ui:inserts> in a custom tag is hinted at somewhat obliquely in Core Javaserver Faces, 3rd Edition, on P196 in the listing of the planet custom tag, which contains a <ui:insert> called content1.

No Comments »

July 6th, 2011
5:01 pm
Facelets–using <ui:param> for temporary in-page variables

Posted under JSF
Tags , , ,

I have sometimes had a need to define temporary variables for use on a facelets page.

When I tried using <c:set> for this it failed to work when used within a decorator.

However, <ui:param> fulfills the need admirably. Whilst it is normally used to pass EL parameters to a template from its client, it can also be used to hold data for use elsewhere in the same decorator for example. Bear in mind that there are scoping issues which as yet I have not fully bottomed out – the variable is probably visible anywhere else in other templates/xhtml files on the same page and so care is needed with naming.

A good example of this was when I wanted to define a couple of size parameters (which could not be done with CSS) at the top of a decorator/custom tag where they were clearly visible, and then re-use them multiple times further down in tag attribtutes to called tags.

No Comments »

July 6th, 2011
4:28 pm
Issues when using EL expressions in nested Composite Component children

Posted under JSF
Tags , , , ,

There appears to be an issue when using EL in child components included in a composite component using <composite:insertChildren>

I am already using this technique for the tableCC component, to insert the columns as children, and the child columns have plenty of EL in them which is not passed to tableCC, as well as having custom tags as columns. However, there appears to be an issue when this technique is used in nested composite components.

When I tried this, I found that any EL expressions in the child components is evaluated as late as possible in the context of the called composite component, not the caller!

This means that if you need to refer to an attribute passed in to the caller of the CC, you must pass that attribute on to the CC as well as referring to it in the child components, as their EL will be evaluated in the CC not the caller.

Providing you do this, it all works fine. However, the issue with this is that it will tend to break encapsulation of the interface to the child nested CC – you have to change its interface depending on what EL you want to use in the child components passed to it.

This was unacceptable to me, so I switched to a different technique. Instead, my base component (actually a flexible icon/base button using p:commandLink) became a custom tag, and I used facelets <ui:inserts> to handle the insertion of custom markup. I then wrapped composite components around this to provide the necessary custom markup.

The reason for going down this route was that I have had issues with glitchy ajax updates on standard Primefaces buttons at small sizes (see this Mantis issue). Also I was crafting icon buttons with multiple jQuery icons on them, using CSS to position them accurately. This was tricky with a p:commandButton and involved introducing CSS that I was concerned may need change in future releases, so I went my own way when using highly custom buttons and buttons at small sizes.

No Comments »

July 6th, 2011
3:47 pm
Optionally including Primefaces <p:dataTable> Columns

Posted under JSF
Tags , , ,

This can be done e.g. by a Facelets Decorator using <ui:insert> and I have used this in a number of places.

However, in one case, I wanted to make a complex treeBrowser custom tag switchable between editable mode and readonly using just a single flag passed as an attribute. Note that I did not want to switch it dynamically at run time – I just re-used the tag in a number of places and some were editable and some were not. As this switch involved a number of changes in the tag, it was convenient to drive them all from a single flag.

In addition, whilst I could have used a decorator for this, I already had 2 versions of the tag each decorating a base version, where each version was used to browse completely different tree structured data in the application which was all handled polymorphically.  Using decorators for readonly/editable as well would have multiplied up the variants to 4, which was undesirable. By using a single EL flag, I was able to make all the switching entirely in the base custom tag which was a real help here.

Anyway – to discuss the real point of the post – to achieve my goal I needed to conditionally include columns for a <p:dataTable>. Using <ui:fragment> to do this does not work as <ui:fragment> creates a new component in the JSF tree which is not a column, and <p:dataTable> ignores any children that are not columns. Whilst there are ways using composite components to indicate with interface properties the precise Class type that the component appears to be, fooling <p:dataTable> by making it look like a column does not work – I tried this and it failed, and there are posts on the Primefaces forum citing the same issue.

The simple solution was to use <c:if> to conditionally include columns. This eventually worked correctly, once I had fixed a particularly nasty incorrect JSTL namespace issue which is fully described in this post here.

No Comments »

June 14th, 2011
6:28 pm
Passing an enum as an argument to a JSF 2 EL method expression

Posted under JSF
Tags ,

It is useful to be able to pass an enum rather than a string value as this introduces additional error checking by JSF.

JSF has a built in enum converter, so that all you need to do is pass a literal string which must then be one of the enum fields. JSF detects that the method argument is an enum and does the appropriate conversion and error checking. This will not occur until run time, but you will at the very least get a JSF error on your browser page and in the log, for example:-

javax.faces.el.EvaluationException: java.lang.IllegalArgumentException:
  
No enum const class uk.co.salientsoft.view.Workspace$PageType.LOGOUT

See here for the StackOverflow post detailing this issue  – BalusC to the rescue again!

No Comments »

June 7th, 2011
12:58 pm
Theme Manager and Theme switcher

Posted under JSF
Tags ,

Primefaces uses the theming capability of jQuery, including the ability to create your own themes using ThemeRoller. This powerful facility separates theme specific CSS from structural CSS which defines the layout of UI components such as tables. At the time of writing, Primefaces has 32 different themes. It does also have a themeSwitcher component, but this has some issues which make it less than ideal for many environments. In addition, the structure of the themes has changed as of version 2.2 – they are now deployed in jars rather than as bare resource files. The following lists the salient issues and desirable features regarding the theme switcher:-

  • When switching themes, rather than using a theme deployed with the application, the Primefaces themeSwitcher downloads the new theme from the internet and installs it directly, which is undesirable in many environments.
  • Ideally, as well as using the themes deployed with the application, the themeSwitcher should be configurable dynamically to allow new themes to be easily added.
  • The theme switcher should also, as far as possible, derive its theme list presented to the user dynamically from the themes that have actually been deployed. Failing this, it should be possible to configure this list as a deployment configuration option, i.e. in web.xml
  • It would be desirable to isolate the theme Switcher from any further changes to the Primefaces theming structure. For example, if a plug-in architecture is used, a new theming interface can be incorporated simply by adding a new plug-in.

 

The Theme Manager attempts to address all of the above issues to provide a flexible and upgradeable solution to Primefaces theming. The Theme Manager including PDF documentation will be found  in the repository here.

No Comments »