Friday, 13 January 2012

PrimeFaces 3 on non CSS3 compliant browsers

PrimeFaces 3

PrimeFaces 3, final release at the beginning of this year, is using CSS3 features to have some nice features and functionality.  And although there is a fair amount of CSS3 in the latest versions of the browser, also in IE9, their are a lot of people that uses a browser which isn’t capable of handling these nice things like rounded corners.
And for most of the widgets, like input field, it is no problem for the end user that he doesn’t have a rounded corner.  But for some, like a radio button, it is confusing that the user sees a rectangular shape instead of the, for him familiar, circle.
As an example, go to the showcase of PrimeFaces and look how the radio buttons are displayed.  Do you see a circle, then you have a CSS3 compliant (at least for the rounded corners feature) browser.  For those that have Internet Explorer 9, they can see how it is displayed for users having IE7 or IE8.  Go to the developers tools (or press F12) and select there the option ‘Browser mode: IE7’. The radio buttons become squared and I can understand the reaction of the end user that filed an issue on my last project.

Find a solution

On the internet, there are plenty solutions that provide you the possibility to have something like rounded corners in Internet Explorer 8 or older. You can split them up in 2 groups.

JavaScript

Here you have to include a JavaScript on your page and in the windows.onload function you have to pass the id’s of the elements that you like to decorate with a rounded corner. The problem with this approach, in combination with PrimeFaces, is that the DOM elements that are responsible for the presentation don’t contain an id attribute.  (Yes, there isn’t any input tag for the radio button so that it can be made styleable)

<div class="ui-radiobutton-box ui-widget ui-corner-all ui-radiobutton-relative ui-state-default">
   <span class="ui-radiobutton-icon"></span>
</div>

VML


The other solution is based on Vector Markup Language (or VML in short), a specification of Microsoft and others that lost the battle against SVG.  However, it was integrated in some of Microsoft products, like the browser.  With VML, it is possible to have rounded corners and a good site where everything is explained, with the inevitable pitfalls, is here.

So I added the script and updated the css file of the project to include the property behaviour in the style classes .ui-radiobutton .ui-radiobutton-box.  It worked like a charm on my computer (emulating IE7 with the help of the developer tools) and on a lot of the computers of other testers. But on another machine it crashed IE completely. Since it isn’t a reliable solution for a public website, I had to find something else.

Adapt skinning


Since PrimeFaces is using themes, there had to be a solution to fix the problem that way.  If I can just place the image of radio button on the area where the user expects it, there couldn’t be any problem like the VML not supported or browser incompatibilities.

And after trying a few scenarios, I’m not a css expert you know, I came to a solution which is quit simple.  I even didn’t need two images, one for the selected and one for the deselected situation.  This is what I added to the css file of the project.

.ui-radiobutton-box {
    background: url("../javax.faces.resource/radio_button.png.jsf?ln=images") no-repeat !important;
    border-style: none !important;
}

.ui-radiobutton .ui-radiobutton-box {
    width: 18px !important;
    height: 18px !important;
}

Some words of explanation:
  • All the properties need the !important marker to overrule the values that comes from the theme css file.

  • The background property defines the image that needs to be displayed.  I’m using the JSF resource notation to reference the image.

  • The border style is there to remove the square of the div element.

  • The size is maybe strange at first glance. The original size of the div element is 16 and then you have to add the border size (1 pixel) to it.  The image contains the complete radio button and needs to be 18 pixels wide.

And to my surprise, the default behaviour of PrimeFaces was providing me a dot in the center of the circle when the radio button is selected.

The easiest way to create the image is to take a snapshot of the screen area in a browser that is capable of rendering CSS3 rounded corners.

Disadvantage


The solution described above has a one major disadvantage, it isn’t compatible with the theme support.  To formulate it maybe a bit more correct, whenever you change the theme, you have to change the image that is used for the radio button whenever you want the background colour to match with the rest of the colours in the PrimeFaces theme.

Conclusion


Since the PrimeFaces 3 JSF component library uses CSS3 features, the representation on browsers that doesn’t support it, like IE7 and IE8, can be a little bit awkward.  A solution for the squared representation of radio buttons can be found in this text.  I uploaded also a test project on Google code for those that want to play with it.

Friday, 6 January 2012

CODI on Oracle WebLogic server 12c

Introduction

Oracle released recently their EE6 compliant version of the WebLogic server. It is a full EE6 profile, so everything you need is at your disposal.  Adam Bien did a smoke test and I made a small demo application where some CDI beans are defined inside a jar file placed in the WEB-INF\lib directory of the war file.
All these tests passed so we are ready to test some real world like application.  Just as JSF is an open system (it is build with extensibility in mind), CDI (Contexts and dependency injection, JSR-299) adhere to the same philosophy. And thus any real world application should use one of the extensions that make the life of the developer easy.
One of the popular CDI extensions is Apache MyFaces CODI, which brings you some goodies that you can use in your project.  You can read about the project on the wiki page.

 

Testing CODI

Testing CODI was done with the scope testing program that you can find here. I made the required adjustments in dependency scopes so that it works on any EE6 server. After deploying it on the Oracle WebLogic Server, I received the following error:
java.lang.IllegalStateException: No bean found for type:
org.apache.myfaces.extensions.cdi.core.api.config.CodiCoreConfig at
org.apache.myfaces.extensions.cdi.core.impl.util.CodiUtils.getOrCreateBeanByClass(CodiUtils.java:198)
Apparently this kind of error occurred also on older Glassfish v3 versions. So someone posting this issue on the mailing list received a solution very rapidly.

 

How to package a CODI application for WebLogic 12c?

So I tried the suggestions in the mailing list and the scope testing program works, except for one small issue. And it is not related to WebLogic only, in fact all containers running on Weld have the same problem. A method annotated with @PostConstruct isn’t executed when it is defined on a method in a super class of a bean with a custom scope.
This is the contents of the pom.xml file:
<dependency>
    <groupId>org.apache.myfaces.extensions.cdi.bundles</groupId>
    <artifactId>myfaces-extcdi-bundle-jsf20</artifactId>
    <version>${myfaces_codi.version}</version>
    <scope>provided</scope>
</dependency>
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>2.2</version>
    <executions>
        <execution>
            <id>unpack-codi</id>
            <phase>process-test-resources</phase>
            <goals>
                <goal>unpack-dependencies</goal>
            </goals>
            <configuration>
               <includeGroupIds>org.apache.myfaces.extensions.cdi.bundles</includeGroupIds>
                <includeArtifactIds>myfaces-extcdi-bundle-jsf20</includeArtifactIds>
                <outputDirectory>
                    ${project.build.directory}/classes
                </outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>
Some words of explanation:

Defining the CODI dependency as provided, means that it isn’t included in the packaged war, but you can use the classes in you code.

The maven-dependency-plugin is used to unpack the contents of the CODI jar into the classes directory so that the required classes are available in the war file.

The last thing that needs to be done is to copy the contents of the beans.xml found in the CODI jar file, into the beans.xml file of your web application.

This way, you can use CODI, on the Oracle WebLogic Server 12c.

UPDATE: Seems that there is also a problem when the 'autodeploy' directory is used.  So for the moment only regular deployed WAR files can be used as described above.