Blog Archives

December 3rd, 2010
12:17 pm
Using the Primefaces Breadcrumb Component

Posted under JSF
Tags , , , ,

I did some experimentation on the best look and feel (in my humble opinion!) for this component, and found the following points along the way:-

  • By default the component was underlining all the entries. This was because all anchor tags were being underlined. The Primefaces showcase has specific rules in default.css to turn this off, so I added them too. (You might have expected this to all be done by the themes or breadcrumb css, but not the case). I just added “a {text-decoration: none;}” and “a:hover {text-decoration: underline;}” rules, but obviously there are other ways if you want other links to be underlined.
  • I then tried to place a breadcrumb in a scrolling div, to ensure that it would still work if the content overflowed. I knew that horizontal scroll bars on a breadcrumb would not look at all sexy, but wanted at least some solution for edge cases with extreme amounts of content, as by default the component truncates to the right and content is lost/not accessible. I was unable to solve this issue – the component would not play ball. I wanted to leave an inner div containing the component at a floating size, so that the control sized itself for the content, and then add a scrollable outer div with overflow:auto so that it would scroll if needed. However, the component appears to use some jQuery magic to detect the size of any fixed ancestor outer level div of the component, and then fix the control width to that size using inline styling added to one of its own inner divs by jQuery/Javascript. The only partial solution was to have a large fixed size component in a smaller outer scrolling div, but this was not good as the scrollbars were present even if not needed as the control had a fixed size.
  • The problem could probably be solved using jQuery, perhaps by modifying the jBreadcrumb jQuery component which Primefaces uses, but I did not investigate this further.
  • In the end, I reconciled myself with the default way the component works. It does have a good solution to this issue by (optionally) dynamically collapsing the entries to a designated preview width, and then expanding an entry on mouse hover (so-called preview mode). This does save a lot of space, and I decided that I could easily have more than enough entries for my needs in say an 800 pixel wide breadcrumb. Alternatively the component can be left to float entirely and rely on the browser for scrolling, but in practice there will generally be an outer container of some kind which will set a limit and trigger the above issue. In my case, this would likely be an outer level tab for a form.
  • I also decided that in practice it would be helpful to turn the preview mode on dynamically, perhaps say when the number of entries exceeded a certain number, or better still when the total character count in the breadcrumb exceeds a certain figure, as this would give good results on average and still be easy to calculate. For normal use, when there is plenty of room left in the breadcrumb, preview mode is a nuisance, but it is obviously essential when the component fills up. Ideally, this would be done when the component is filled rather than based on an entry count, but this would be tricky to calculate. Ideally this would be done dynamically by the component itself. Best of all might be a dynamic preview mode which shrinks the entries only when required and only enough to fit everything in the component.
  • Rendering the component in preview mode takes significant time when there are a lot of entries (even on my Core I7 920). This might be an issue when partially updating a page (and the component) during navigation. This is even more reason not to use preview mode unless it is really essential, as with it turned off the breadcrumb renders very quickly. On some occasions it would be possible to update the control client side, for example when just changing the underline/italic decoration on the text (see below re traversing a hierarchy) and no entries are added or removed. In this case the necessary classes could just be added and removed from the breadcrumb entries dynamically with jQuery. I have also not tried any Ajax/partial form updates with it, for example just adding or removing a single entry, but I expect the whole component will be re-rendered each time as the manual makes no mention of partial updating.
  • I experimented a bit with the expand and contract timings in preview mode. These interact with the time taken by the JavaScript to dynamically collapse the entries when the component is first rendered, so if you try to make them too fast it looks clunky. Also if the expand is too fast it can confuse you as to which entry you are hovering on, especially when there is a lot of preview compression, as you can end up highlighting the next entry along without realising it, just due to the expand/collapse effect.
  • One common use case for me is to use the component to hold the navigation path when traversing a hierarchical data set. A desirable feature would be that when you traverse back up the tree say by clicking on one of the higher levels in the breadcrumb, you do not immediately lose all the lower levels you visited. They would only be removed if you visited a higher level and then traversed down a different lower level path at some point, in which case the lower levels visited previously beyond that point would then be removed and a new path built.
  • The nice thing about the above concept is that you can repeatedly wander freely up and down a given tree path via the breadcrumb without losing any of the context, which is handy in my case as the UI deliberately only shows the current level of the tree in a table – no tree or treetable components are used in order to keep things intuitive and simple for novice users.
  • When applying this concept, it is necessary to highlight the current location in the breadcrumb, as this will no longer always be the rightmost entry. The most logical way to do this seemed to apply the same highlight as the mouse hover, which is to underline an entry. Therefore, the current entry will always be underlined, as will any other entry that is hovered over.
  • In addition, it is desirable to distinguish between the breadcrumb levels between the root and the current point from those previously visited below the current point, as the breadcrumb is no longer only showing the path to where you currently are. I tried various kinds of dimmed, disable style highlighting, but whilst it is important to make these previously visited lower level entries look different, it must also be clear that you can still click on them. In the end, my preferred solution which looks good in all the top 5 browsers and with all the Primefaces themes was to italicise the previously visited lower level entries. You therefore end up with ‘normal’ styling up to the current level. The current level itself is then shown underlined so it is clear where you are. All the entries to the right (if any) are then italicised.

The following example shows my preferred component, which is somewhat thinner than the default due to the removed padding. Examples of the different highlighting discussed above are all just coded directly into the menu options. The example also uses my theme switcher component which is not listed.

 

index.xhtml

<!DOCTYPE HTML>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"   
xmlns:util="http://java.sun.com/jsf/composite/uk.co.salientsoft/util">
<f:view contentType="text/html">
<h:head>
    <util:themeSwitcher    outputStyle="true"
                        themeBase="/resources/themes"
                        defaultTheme="redmond"/>
<style>
    .ui-widget {
        font-size: 75% !important;
    }
    h1.header {
        font-size: 1.2em !important;
        padding: 5px;
        margin: 0px 0px 20px 0px;
        float: left;
    }
    .themeswitcher {
        float: left;
        clear: both;
        margin-bottom: 20px;
    }   
    .ss-breadcrumb {
        clear:both;
        margin: 0 0 10px 0;
        padding: 0;
        width:800;
    }   
    a {text-decoration: none;}
    a:hover {text-decoration: underline;}
    .ss-currentlevel {text-decoration:underline;}
    .ss-lowerlevel {font-style: italic;}
</style>

</h:head>
<h:body>
<h1 class="header ui-widget ui-widget-header ui-corner-all" style="">Breadcrumb</h1>

<h:form id="frmTest">
<util:themeSwitcher form="frmTest" outerStyleClass="themeswitcher"/>
<br/><br/>
    <p:breadCrumb styleClass="ss-breadcrumb" preview="false">
        <p:menuitem value="Categories" url="#" />
        <p:menuitem value="Sports" url="#" />
        <p:menuitem value="Football" url="#" />
        <p:menuitem value="Countries" url="#" styleClass="ss-currentlevel"/>
        <p:menuitem value="Spain" url="#"  styleClass="ss-lowerlevel"/>
        <p:menuitem value="F.C. Barcelona" url="#" styleClass="ss-lowerlevel"/>
        <p:menuitem value="Squad" url="#" styleClass="ss-lowerlevel"/>
        <p:menuitem value="Lionel Messi" url="#" styleClass="ss-lowerlevel"/>
        <p:menuitem value="Squad" url="#" styleClass="ss-lowerlevel"/>
        <p:menuitem value="Lionel Messi" url="#" styleClass="ss-lowerlevel" />
    </p:breadCrumb>
    <p:breadCrumb styleClass="ss-breadcrumb" preview="true" previewWidth="24"
        expandEffectDuration="400" initialCollapseEffectDuration="100"
        expandedBeginningItems="1" expandedEndItems="1">
        <p:menuitem value="Categories" url="#" />
        <p:menuitem value="Sports" url="#" />
        <p:menuitem value="Football" url="#" />
        <p:menuitem value="Countries" url="#" />
        <p:menuitem value="Spain" url="#" />
        <p:menuitem value="F.C. Barcelona" url="#"  styleClass="ss-currentlevel"/>
        <p:menuitem value="Squad" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Lionel Messi" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Categories" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Sports" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Football" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Countries" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Spain" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="F.C. Barcelona" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Squad" url="#" styleClass="ss-lowerlevel" />
        <p:menuitem value="Lionel Messi" url="#"  styleClass="ss-lowerlevel" />
    </p:breadCrumb>
</h:form>
</h:body>
</f:view>
</html>

No Comments »

December 3rd, 2010
9:42 am
JPA error “Class is mapped, but is not included in any persistence unit”

Posted under JPA
Tags , , , ,

I received this compile time error from Eclipse with one of my test projects which was previously fine, using Eclipse Helios with Eclipselink 2.1.0 (and container managed JPA in EJBs). The error occurred when I was autodiscovering the entities rather than listing them in persistence.xml explicitly, even when <exclude-unlisted-classes>false</exclude-unlisted-classes> was explicitly present.

Supposedly, as the annotated entity sources for the classes are in a subfolder of the parent of the META-INF folder containing persistence.xml, they should be discovered automatically. Listing the fully qualified classes explicitly in persistence.xml solved the problem, however this is not ideal as it would mean having an alternative version of persistence.xml for testing.

I googled for the problem but could not find a solution listed anywhere. For now this is just one to be aware of – I’ll stick with listing the classes explicitly and look further for a solution later on as and when it becomes a nuisance!

No Comments »

November 30th, 2010
4:37 pm
Tailoring a Primefaces TreeTable with JavaScript/jQuery/JSF 2.0

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

This example came about from the desire to hightlight a Primefaces TreeTable row when a checkbox in the row is ticked. I wanted to do this because a ticked checkbox is not as visible as I would like when a lot of data is present. I was not keen on adding DataTable style dynamic selection by hovering and clicking anywhere in a row, as this conflicts somewhat with the paradigm of clicking on the expander to expand/collapse the tree, and you would have to special case hovering/clicking on the expander somehow to prevent row selection.

Ideally you would use CSS for this, but this would involve tagging a component in a TreeTable cell (<td> element) with a class (as in the TreeTable component we cannot directly add row styling), and then using some kind of ancestor selector to traverse the DOM tree upwards to get the row. The simple answer to this is that whilst CSS can do some clever things, it does not have any kind of ancestor selector, so it is not possible to do it just with CSS.

An attractive alternative for this kind of thing in Primefaces is to use jQuery – a very powerful JavaScript based UI library upon which Primefaces is based. As it is already present in a Primefaces environment, it is trivial to call and ideal for this kind of thing. In particular, it has powerful mechanisms for traversing and searching the DOM tree and selecting elements etc. If you combine this with its features for dynamically adding and removing classes from elements, it can do exactly the kind of thing that we cannot do in CSS. The jQuery website is here, and the API documentation for it may be found here.

The sample code fragments below demonstrate the idea. The sample is based on a hacked version of the the Primefaces showcase TreeTable demo. Note the following points:-

  • It is perfectly possible to add both Javascript and JSF EL inline inside a JSF component, such that the JavaScript runs at that point when the page is rendered. This example adds some JavaScript inside the JSF tags for a checkbox.
  • As the example uses JavaScript, the hightlight is added/removed both client side from a click event on the check box, and when the page is rendered based on the current check box value in the TreeTableDocument object from the server.
  • The sample uses the JSF 2.0 EL implicit object reference component.clientId to get the client ID of the component where the EL reference is used. This is new for JSF 2.0 (previously additional code would be needed for this) and like the cc implicit object used with composite components, is not at all well documented. I was unable to find reference documentation for it anywhere in the JSF 2.0 specs, but found details of it here (at the end of the post). Note that the reference needs to be placed with care – it sometimes appears to come up with ‘ghost’ client IDs which may have been allocated by JSF but do not actually appear anywhere as IDs in the HTML. When using it, check that it returns the correct ID, for example by just placing a bare #{component.clientId} on the page directly adjacent to where you are using it, and view the source of the generated page in the browser to check that the client ID it returns matches the id of the component it is used for.
  • Be careful to consider any ordering issues – the inline JavaScript call I am using must be placed on the page after the component it refers to has been rendered. By default, using component.clientId  inside a script block which is in turn inside the checkbox component tags causes the script block to be output immediately prior to the html for the checkbox. Therefore, I use two script blocks – one inside the checkbox to save the component ID in a temporary JavaScript variable, which guarantees that I obtain the correct component ID and not an incorrect or ‘ghost’ one, and then another script block immediately after the closing tag for the checkbox component which passes the form ID and saved component ID to a JavaScript function which calls jQuery to do the highlighting after the html element has been rendered on the page. Note that the client side onClick() event on the checkbox will always run after  the full page has been rendered, when the user clicks the box, so ordering is not an issue for this.
  • The call to jQuery passes in the checkbox DOM element, which jQuery wraps with a jQuery object and returns. The parent() method is then used twice to traverse the DOM tree up from the check box to the table cell <td>, and thence to the table row <tr>. The addClass() and removeClass() methods are then used to dynamically add/remove the required CSS classes to the table row depending on the passed check box state. Adding and removing classes with jQuery is useful as it does all the string bashing for you to check if the class being added/removed is already present, handles spaces correctly, and leaves all other classes on the element intact.
  • Note that in an earlier version I had tricky issues with nested quotes in JSF EL. I initially used outer double quotes, with inner single quotes on the JavaScript calls. The EL through this out however. I ended up using double quotes throughout, and escaped the inner ones with backslashes (\). This worked fine. The version shown here does not need this as it is a later modification.
  • The example extends the Primefaces Document class used in the showcase, adding a boolean property for the check box value.
  • My example uses CDI, whereas the original showcase uses JSF managed beans.

Sample Code Fragments

Index.xhtml

<!DOCTYPE HTML>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:c="http://java.sun.com/jsp/jstl/core"   
xmlns:util="http://java.sun.com/jsf/composite/uk.co.salientsoft/util">
<f:view contentType="text/html">
<h:head>
    <util:themeSwitcher    outputStyle="true"
                        themeBase="/resources/themes"
                        defaultTheme="redmond"/>
<style>
    .ui-widget {
        font-size: 75% !important;
    }
    h1.header {
        font-size: 1.2em !important;
        padding: 5px;
        margin: 0px 0px 20px 0px;
    }
    h2.subheader {
        font-size: 0.9em !important;
        padding: 2px;
        margin: 0px 0px 10px 0px;
    }
    .float {
        float: left;
    }
   
    .clear {
        clear: both;
    }
    .themeswitcher {
        float: left;
        clear: both;
        margin-bottom: 10px;
    }   
    .ss-selectcolumn {
        width:30px !important;
        padding:0px !important;
        text-align:center;
    }
    .ss-checkbox {
        color:red!important;
    }
/* treetable arrow light/dark switch
    .ui-treetable tr.collapsed td .expander {
        background-image:url("/TreeTable1/javax.faces.resource/treetable/images/toggle-expand-light.png.jsf?ln=primefaces&amp;v=2.2.RC2");
    }
    .ui-treetable tr.expanded td .expander {
        background-image:url("/TreeTable1/javax.faces.resource/treetable/images/toggle-collapse-dark.png.jsf?ln=primefaces&amp;v=2.2.RC2");
    }   
*/
/* Styling nicked from default.css in the Primefaces Showcase */
    a {text-decoration: none;}
    a:hover {text-decoration: underline;}
    a img {border: none;}   
</style>

<script type="text/javascript">
//<![CDATA[
    function highlightTreeTableRow(formId, checkBoxId) {
        var checkBox = document.forms[formId][checkBoxId];
        if (checkBox.checked)
            jQuery(checkBox).parent().parent().addClass(‘ui-state-highlight ui-selected’);
        else
            jQuery(checkBox).parent().parent().removeClass(‘ui-state-highlight ui-selected’);
    }
//]]>
</script>
</h:head>
<h:body>
<h1 class="float header ui-widget ui-widget-header ui-corner-all" style="">Theme Switcher</h1>
<h:form prependId="false" id="frmTest">
<util:themeSwitcher form="frmTest" outerStyleClass="themeswitcher" style="margin-bottom:20px;"/>
<br/><br/>

<div style="width:600px;clear:both;">
    <p:treeTable value="#{documentsController.root}" var="document"
       styleClass="#{(document.name==’logo.png’)? ‘ui-state-highlight ui-selected’:’fred’}"
        expanded="true">
        <p:column>
            <f:facet name="header">
                Name
            </f:facet>
            <h:outputText value="#{document.name}" />
        </p:column>
       
        <p:column>
            <f:facet name="header">
                Size
            </f:facet>
            <h:outputText value="#{document.size}" />
        </p:column>
       
        <p:column>
            <f:facet name="header">
                Type
            </f:facet>
            <h:outputText value="#{document.type}" />
        </p:column>
       
        <p:column>
            <f:facet name="header">
                Options
            </f:facet>
            <p:commandLink update="documentPanel" oncomplete="documentDialog.show()" title="View Detail">
                <p:graphicImage value="/images/search.png"/>
                <f:setPropertyActionListener value="#{document}" target="#{documentsController.selectedDocument}" />
            </p:commandLink>
        </p:column>
       
        <p:column styleClass="ss-selectcolumn">
            <f:facet name="header">
            <h:selectBooleanCheckbox disabled="true" label="box header"/>
            </f:facet>
            <h:selectBooleanCheckbox value="#{document.selected}"
                 
onclick="highlightTreeTableRow(‘frmTest’, this.id);" styleClass="ss-checkbox" id="selector" >                
                 <script>selectId = ‘#{component.clientId}’;</script>
            </h:selectBooleanCheckbox>
            <script>highlightTreeTableRow("frmTest", selectId);</script>
        </p:column>
    </p:treeTable>
    <p:commandButton type="submit" value="Submit" onclick="submit();" style="margin-top:10px;"/>
   
    <p:dialog header="Document Detail" fixedCenter="true" effect="FADE" effectDuration="0.3"
        widgetVar="documentDialog" modal="true">
   
        <p:outputPanel id="documentPanel">
            <h:panelGrid  columns="2" cellpadding="5">
                <h:outputLabel for="name" value="Name: " />
                <h:outputText id="name" value="#{documentsController.selectedDocument.name}" style="font-weight:bold" />
               
                <h:outputLabel for="size" value="Size: " />
                <h:outputText id="size" value="#{documentsController.selectedDocument.size}" style="font-weight:bold" />
               
                <h:outputLabel for="type" value="Type " />
                <h:outputText id="type" value="#{documentsController.selectedDocument.type}" style="font-weight:bold" />
            </h:panelGrid>
        </p:outputPanel>
    </p:dialog>
    </div>
</h:form>
</h:body>
</f:view>
</html>

DocumentsController.java (modified from Showcase)

package org.primefaces.examples.view;
import java.io.Serializable;
import java.util.logging.Logger;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import uk.co.salientsoft.treetable.view.TreeTableDocument;

@Named
@SessionScoped
public class DocumentsController implements Serializable {
   
    private static final long serialVersionUID = -3593168523028092346L;
    private static final Logger logger = Logger.getLogger(DocumentsController.class.getName());
    private TreeNode root;
    private TreeTableDocument selectedDocument;
    public DocumentsController() {
        root = new DefaultTreeNode("root", null);
       
        TreeNode documents = new DefaultTreeNode(new TreeTableDocument("Documents", "-", "Folder"), root);
        TreeNode pictures = new DefaultTreeNode(new TreeTableDocument("Pictures", "-", "Folder"), root);
        TreeNode music = new DefaultTreeNode(new TreeTableDocument("Music", "-", "Folder"), root);
       
        TreeNode work = new DefaultTreeNode(new TreeTableDocument("Work", "-", "Folder"), documents);
        TreeNode primefaces = new DefaultTreeNode(new TreeTableDocument("PrimeFaces", "-", "Folder"), documents);
       
        //Documents
        TreeNode expenses = new DefaultTreeNode("document", new TreeTableDocument("Expenses.doc", "30 KB", "Word Document"), work);
        TreeNode resume = new DefaultTreeNode("document", new TreeTableDocument("Resume.doc", "10 KB", "Word Document"), work);
        TreeNode refdoc = new DefaultTreeNode("document", new TreeTableDocument("RefDoc.pages", "40 KB", "Pages Document"), primefaces);
       
        //Pictures
        TreeNode barca = new DefaultTreeNode("picture", new TreeTableDocument("barcelona.jpg", "30 KB", "JPEG Image"), pictures);
        TreeNode primelogo = new DefaultTreeNode("picture", new TreeTableDocument("logo.jpg", "45 KB", "JPEG Image"), pictures);
        TreeNode optimus = new DefaultTreeNode("picture", new TreeTableDocument("optimusprime.png", "96 KB", "PNG Image"), pictures);
       
        //Music
        TreeNode turkish = new DefaultTreeNode(new TreeTableDocument("Turkish", "-", "Folder"), music);
       
        TreeNode cemKaraca = new DefaultTreeNode(new TreeTableDocument("Cem Karaca", "-", "Folder"), turkish);
        TreeNode erkinKoray = new DefaultTreeNode(new TreeTableDocument("Erkin Koray", "-", "Folder"), turkish);
        TreeNode mogollar = new DefaultTreeNode(new TreeTableDocument("Mogollar", "-", "Folder"), turkish);
       
        TreeNode nemalacak = new DefaultTreeNode("mp3", new TreeTableDocument("Nem Alacak Felek Benim", "1500 KB", "Audio File"), cemKaraca);
        TreeNode resimdeki = new DefaultTreeNode("mp3", new TreeTableDocument("Resimdeki Gozyaslari", "2400 KB", "Audio File"), cemKaraca);
       
        TreeNode copculer = new DefaultTreeNode("mp3", new TreeTableDocument("Copculer", "2351 KB", "Audio File"), erkinKoray);
        TreeNode oylebirgecer = new DefaultTreeNode("mp3", new TreeTableDocument("Oyle bir Gecer", "1794 KB", "Audio File"), erkinKoray);
       
        TreeNode toprakana = new DefaultTreeNode("mp3", new TreeTableDocument("Toprak Ana", "1536 KB", "Audio File"), mogollar);
        TreeNode bisiyapmali = new DefaultTreeNode("mp3", new TreeTableDocument("Bisi Yapmali", "2730 KB", "Audio File"), mogollar);
    }
    public TreeNode getRoot() {return root;}
    public void setRoot(TreeNode root) {this.root = root;}
    public TreeTableDocument getSelectedDocument() {return selectedDocument;}
    public void setSelectedDocument(TreeTableDocument selectedDocument) {
        this.selectedDocument = selectedDocument;
    }
}

TreeTableDocument.java

package uk.co.salientsoft.treetable.view;
import org.primefaces.examples.domain.Document;

public class TreeTableDocument extends Document {
    private static final long serialVersionUID = 7339615098050125785L;
    public TreeTableDocument(String name, String size, String type) {
        super(name, size, type);
    }   
    private boolean;
    public boolean isSelected() {return this.selected;}
    public void setSelected(boolean selected) {this.selected = selected;}
}

No Comments »

November 26th, 2010
8:25 pm
Using container managed JPA 2.0 with CDI/EJB 3.1/Glassfish 3

Posted under JPA
Tags , , , , , ,

Update

  • One issue to be aware of, which is not immediately obvious, is when populating a database from scripts. If the version column is left null (Eclipselink leaves it as nullable by default), then the null value causes an immediate OptimisticLockException to be thrown. This is because EclipseLink expects and checks for a zero as the initial value for a new record. If EclipseLink itself persists the record, then it writes a zero.
  • One good idea to resolve this would be to enforce version columns to be non null with a zero default – although it must be said that it would be helpful if EclipsLink did this automatically in response to the @Version annotation.
  • Population scripts should therefore set version to zero, unless it is set non null with a default of zero in JPA – this latter solution is cleaner and would be automatic for me because I create version columns in a mapped superclass used by all Entities. I have yet to test this out however.

 

Original Post

This follows on from a previous post relating to JPA 1.0/Glassfish 2.1, and contains a few notes and pointers relating to JPA 2.0 under Glassfish 3 with CDI/Weld.

Firstly, when using an EJB from a client, use CDI injection (@Inject) rather than the @EJB annotation, as CDI gives many additional benefits such as type safety.

In an EJB:-

  • You are using container managed transactions, and so simply have to inject an entity manager rather than create one from an entity manager factory.
  • The container managed entity manager can be injected with a simple @PersistenceContext annotation – the persistence unit name may be defaulted and is discovered automatically.
  • The container is responsible for entity manager lifetime/closing. Calling e.g. em.close at the end of a bean method is illegal and will make Glassfish angry. You do not want to make Glassfish angry – you end up with many long stack traces in the log which on the surface do not appear to relate to this trivial problem!

A major issue with container managed transactions is how to use optimistic locking and detect and handle optimistic lock exceptions correctly. This is detailed in Pro JPA 2, pages 355-357 (you can preview this in Google Books). The main problem is that in a server environment, the OptimisticLockException will simply be logged by the container which then throws an EJBException. Trying to catch an OptimisticLockException in the calling client is therefore doomed to failure – it will probably never be caught!

The solution is to call flush() on the entity manger (e.g. em.flush()) just before you are ready to complete the method. This forces a write to the database, locking resources at the end of the method so that the effects on concurrency are minimised. This allows us to handle an optimistic failure while we are still in control, without the container swallowing the exception. The ChangeCollisionException might contain the object which caused the exception, but it is not guarranteed to. If there were multiple objects in the transaction, we could have invoked getEntity() on the caught exception to see whether the offending object was included.

If we do get an exception from the flush() call, we can throw a domain specific application exception which the caller can recognise, i.e. convert an OptimisticLockException to our own ChangeCollisionException, avoiding coupling the caller to the internal semantics of JPA transactions. It is also desirable to factor out the code which calls flush() into our own method, e.g. flushChanges() to avoid the need for every method which needs to flush having to catch the optimistic lock exception and then throw our domain specific one – we can centralise the exception conversion in our own single method.

We must annotate the ChangeCollisionException class with @ApplicationException, which is an EJB container annotation, to indicate to the container that the exception is not really a system level one but should be thrown back to the client as-is. Normally defining an application exception will cause the container not to roll back the transaction, but this is an EJB 3 container notion. The persistence provider that threw the OptimisticLockException  (in this case Eclipselink) does not know about the special semantics of designated application exceptions and, seeing a runtime exception, will go ahead and mark the transaction for rollback. The client can now receive and handle the ChangeCollisionException and do something about it.

Here is an example of our exception class with the required annotation:-

@ApplicationException
public class ChangeCollisionException extends RunTimeException {
   public ChangeCollisionException() {super(); }
}

Here are code fragment examples from a stateless session bean showing the entity manager injection, and a client JSF model bean showing the CDI injection of the stateless session bean. Note that with EJB 3.1 it is not necessary to declare local or remote interfaces for an EJB as business interfaces are not a requirement. However, I always use an interface as it allows for example a mock version of a service layer to be easily swapped in for testing. CDI supports this conveniently via alternatives, whereby a mock version of a bean can be switched in via a setting in beans.xml for testing.

@Stateless
public class SentryServiceImpl implements SentryServiceLocal {

    @PersistenceContext
    private EntityManager em;

}

@Named
@Dependent
public class ModelBeanImpl implements ModelBean, Serializable {
    private static final long serialVersionUID = -366401344661990776L;
    private @Inject SentryServiceLocal sentryService;
… 
}

With container managed JPA and/or Glassfish your persistence.xml  can also be simplified, as you can define your data source in Glassfish rather than explicitly in persistence.xml, as described here.

Note that when defining a data source directly in persistence.xml,  some property names have been standardized for JPA 2.0, so have changed from e.g. eclipselink.jdbc.user to javax.persistence.jdbcuser. The following properties in persistence.xml are now standard:-

<property name="javax.persistence.jdbc.url" value="jdbc:oracle:thin:@localhost:1521:xe"/>
<property name="javax.persistence.jdbc.user" value="sentry"/>
<property name="javax.persistence.jdbc.password" value="sentry"/>
<property name="javax.persistence.jdbc.driver" value="oracle.jdbc.OracleDriver"/>

An example persistence.xml used under JPA 2.0 follows:-

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

    <persistence-unit name="SentryPrototype" transaction-type="JTA">
      <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
      <jta-data-source>jdbc/SentryPool</jta-data-source>
      <properties>
       <property name="eclipselink.logging.level" value="INFO" />
       <property name="eclipselink.target-database" value="Oracle" />      
       <property name="eclipselink.ddl-generation.output-mode" value="database" />      
      </properties>
     </persistence-unit>
</persistence>

No Comments »

November 15th, 2010
11:56 am
Namespace error when using JSTL in Facelets with JSF 2.0

Posted under JSF
Tags , , , , ,

Update 6/7/2011

I hit this problem again when accidentally ignoring the Eclipse warning.
This time, the problem prevented <c:if> tags from working correctly – the tags always tested as true. This was especially nasty as the cause did not appear related to the problem I was having. See this issue in Mantis about the problem.

Original Post

I was using the following namespace declaration in order to use JSTL (c:if etc.) on a Facelets/JSF 2.0 page, as I had done successfully previously under JSF 1.2:-

xmlns:c=”http://java.sun.com/jstl/core

This gave rise to the following warning in Eclipse:-

NLS missing message: CANNOT_FIND_FACELET_TAGLIB in: org.eclipse.jst.jsf.core.validation.internal.facelet.messages

The namespace is incorrect, and as pointed out here (in Ryan Lubke’s comment on the post) should now be:-

xmlns:c=”http://java.sun.com/jsp/jstl/core

This fixed the problem. A complete listing of the namespaces for the tag libraries is also available in edition 3 of Core JavaServer Faces, at the start of Chapter 4, page 101 – (edition 2 did not have this table; it is a useful addition).

No Comments »

November 11th, 2010
11:35 am
Fonts reduce in size when Primefaces table moved inside a panel

Posted under CSS
Tags , , , ,

Update 22/09/2011

The following selector (as documented below) did not work when used for a particular table. CSS ignored the rule presumably for reasons of specificity:-

.ss-nested-widget, .ss-nested-widget .ui-datatable {
     font-size: 100% !important;
}

However, the following selector did work (and was also modified to include a dialog as well as a table). This has the advantage of not relying on having ss-nested-widget as a class on the table in order to work.
This has now been adopted as standard as the solution for this issue :-

.ss-nested-widget,
.ui-widget .ui-datatable,
.ui-widget .ui-dialog { 
     font-size:100% !important;   
}

Original Post

This issue is due to font size inheritance.

My default font for all Primefaces components was specified globally as follows:-

.ui-widget {

font-size: 75% !important;

}

The reason for this is that in general it is considered more flexible to go for percentage sizes as these can then be scaled automatically when viewed on smaller devices.

Unfortunately, it appears that when for example a table is nested inside a panel, the font size appears to be 75% of 75% as the rule is inherited and applied twice, as 75% is a relative measurement, The table ends up rendered as a 9px font which is too small. The situation is further complicated by the fact that in the Primefaces skinning, there is a mixture of fonts specified in ems, percentages and pixel sizes, which means that not everything is specified in relative sizing anyway.

There are 2 solutions to the issue, both are straightforward, 1/ is the simplest although arguably not the best due to absolute sizing:-

1/ Change the global ui-widget rule above to use a fixed font size (12px works as a replacement for the above 75%)

.ui-widget {

font-size: 12px !important;

}

2/ Keep the  75%  for ui-widget and introduce a new rule to specify a 100% size for nested elements:-

.ss-nested-widget {

font-size:100% !important;

}

This rule needs to be introduced inside the panel. If it is placed on the panel itself, which is the parent element, then the font size just ‘goes large’ to 100%, i.e. larger than the desired default font. To obtain the correct behaviour, the sub-elements inside the panel must be tagged with the style class. It is possible to tag an enclosing <div> just inside the panel, so that the sub-elements inherit it. However, whilst this worked for input selectors and buttons in the panel, tables refused to play ball, and the following rule was needed to ensure that a table in the panel inherited the correct size:-

.ss-nested-widget, .ss-nested-widget .ui-datatable {

font-size: 100% !important;

}

The same kind of trick can be used to target other nested elements which do not inherit the correct size.

An alternative method would be just to add the class to sub-elements individually where required.

No Comments »

November 9th, 2010
6:54 pm
Fetching the old value in a JSF input validator

Posted under JSF
Tags , ,

In my case, I did this when checking string uniqueness in a table – if the value entered was unchanged, this would give a duplicate. Whilst I could in theory detect when I was comparing with the old value, this was hard in practice as I did not know which row I was on.

This trick is a good way of not bothering with validation if the field is unchanged. Note the need to cast the UIComponent passed in the event to a UIInput in order to expose the getValue method. Sample code is as follows :-

String oldValue = ((UIInput)component).getValue().toString().trim();

No Comments »

November 8th, 2010
1:18 pm
Header width incorrect on Primefaces scrollable table

Posted under JSF
Tags , , , , ,

If a header facet is used on a Primefaces table, the header does not allow for the scrollbars if present. the column headers do adjust for the scrollbars (although there are issues with column alignment between the headers and the data – a number of such errors have been posted to the Primefaces forum).

One workaround for this is to selectively include a CSS selector to adjust the header <div> width when the scrollbars are present.
The following selector achieves this:-

<style type=”text/css”>       

    .ss-tableheader-scrolladjust > div.ui-datatable-header {
        width:495px;
    }
</style>

The following table definition selectively includes this when enough rows are present to require scroll bars (this must be derived empirically as it depends on the height of the table, font size used etc. :-

     <h:panelGroup layout=”block” style=”width:500px;”>    
     <p:dataTable var=”car” value=”#{tableBean.carsSmall}” scrollable=”true” 
         styleClass=”#{fn:length(tableBean.carsSmall) lt 8 ? ” : ‘ss-tableheader-scrolladjust’}” height=”200″ > 
         <f:facet name=”header”>
            Ajax Sorting        
         </f:facet>
         <p:column headerText=”Model”  sortBy=”#{car.model}”>
             <h:outputText value=”#{car.model}” />
         </p:column>

         <p:column headerText=”Year”  sortBy=”#{car.year}”>
             <h:outputText value=”#{car.year}” />
         </p:column>

         <p:column headerText=”Manufacturer”  sortBy=”#{car.manufacturer}”>
             <h:outputText value=”#{car.manufacturer}” />
         </p:column>

         <p:column headerText=”Color” sortBy=”#{car.color}”>
             <h:outputText value=”#{car.color}” />
         </p:column>
     </p:dataTable>
    </h:panelGroup>

No Comments »

November 8th, 2010
12:51 pm
Setting Column Headers on a Primefaces Table

Posted under JSF
Tags , , ,

The normal way to add JSF table headers is to use a header facet :-

<p:column sortBy=”#{car.model}” >
    <f:facet name=”header”>
        <h:outputText value=”Model” />
    </f:facet>
    <h:outputText value=”#{car.model}” />
</p:column>

In Primefaces tables, this can give column width and alignment issues in some cases, so the headerText attribute of the column should be used instead :-

<p:column headerText=”Model”  sortBy=”#{car.model}”>
    <h:outputText value=”#{car.model}” />
</p:column>

No Comments »

November 8th, 2010
12:26 pm
Using JSTL Functions in JSF EL e.g. to return list size

Posted under JSF
Tags , , ,

Unfortunately some methods of backing beans, such as size() to return the number of entries in a list in a bean, are not directly callable from an EL expression as they are not exposed as standard getters. Whilst expressions on a facelets page should be used with care so as not to include business logic on the page, they are sometimes useful. One of my use cases has been to optionally add a css class into a stylclass attribute to correct the width of a table header when scrollbars are present (when enough rows are present to cause scrolling).

You can add additional properties to the beans to do this, but an easier way is often to use JSTL functions on the page. The following declaration includes the namespace for them, using prefix fn:-

<!DOCTYPE HTML>
<html xmlns=”http://www.w3c.org/1999/xhtml”
xmlns:f=”http://java.sun.com/jsf/core”
xmlns:h=”http://java.sun.com/jsf/html”
xmlns:fn=”http://java.sun.com/jsp/jstl/functions”
xmlns:p=”http://primefaces.prime.com.tr/ui”>

 

The following code fragment calls the length function to return the size of a list :-

<p:dataTable var=”car” value=”#{tableBean.carsSmall}” scrollable=”true” 
         styleClass=”#{fn:length(tableBean.carsSmall) lt 8 ? ” : ‘ss-tableheader-scrolladjust’}” height=”200″ >

 The javadoc for the complete set of jstl functions may be found here.

No Comments »