limitToList attribute prevents flashing

If you have some elements (or even the whole page) that flash/twinkle using RichFaces, it probably means that these elements are AJAX-rendering. The question is by whom and how to fix it?

A lot of tags in RichFaces can AJAX-render elements such as:

<a4j:form>
    <a4j:jsFunction name="updateName" reRender="showname">
        <a4j:actionparam name="param1" assignTo="#{userBean.name}"  />
    </a4j:jsFunction>
</a4j:form>

On the above example, the JavaScript function updateName will AJAX-render the element which has the ID showname.

In some cases, you would have some elements that would AJAX-render without asking them to do so!
I still didn’t figure it out why. :( (if anybody has an idea, please don’t hesitate to tell me!)

But, I found a way to prevent this!
You simply can add the following attribute to your tag:

limitToList="true"

You even can add it to the tags that don’t have a reRender attribute.
For example:

<a4j:form>
    <a4j:poll id="poll" interval="1000" limitToList="true" />
</a4j:form>

, , , ,

No Comments

Apple UK keyboard layout for Windows

Because I am now working on a .Net project and I don’t want to work on a PC ;-) , I decided to install Windows as guest on my Mac in VirtualBox.

Everything works perfectly fine except that Windows doesn’t like my Apple keyboard. What a surprise! :roll:

After a quick search on Google, I found a fix for:

But I didn’t find anything for the ‘normal’ Apple UK keyboard. Unfortunately, I can’t use the MacBook Pro UK keyboard layout because it is slightly different than the USB and Wireless Apple UK keyboards layout. :-(

So my friend Google :-P didn’t leave me any other choice than create my own keymap for this keyboard using the Microsoft Keyboard Layout Creator.

You can download it clicking on the following link: Keyboard Layout Setup Files (English UK – Apple). And here is the source KLC file if you want to make change to it: Source KLC File for English UK – Apple Keyboard Layout.

To use, simply unzip, run setup, and then in your keyboard settings (Control Panel -> Regional and Language Options) change to “United Kingdom – Custom”. You may wish to remove the default UK keyboard to avoid confusion. If it still doesn’t work, don’t hesitate to reboot Windows! ;)

This is working well on my VirtualBox but it should also work on any Windows instance (i.e. VMWare, Parallels, etc).

, , ,

1 Comment

Why GROUP_CONCAT returns BLOB?

Last week, when using the GROUP_CONCAT() function on a MySQL database, I got an unexpected result. :(

Indeed, instead of getting my result as VARCHAR types, I got it as BLOB types! For information, a BLOB is a binary large object that can hold a variable amount of data:
http://dev.mysql.com/doc/refman/5.0/en/blob.html
Because BLOB values are treated as binary strings, it is not easy to use. This is why we would prefer to have VARCHAR values.

So the question is how to get around this frustrating problem?

The answer is, for once, very simple! :D
You simply need to:

  • Open your my.ini or my.cnf file;
  • Change the value of the group_concat_max_len system variable to 512 (no ‘k’ suffix);
  • Restart the mysql service

To verify if the value has been successfully updated, execute the following command in your mysql client:

mysql> show variables like "%concat%";
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| group_concat_max_len | 512   |
+----------------------+-------+
1 row in set (0.00 sec)

Note that you cannot set the value of group_concat_max_len to less than 1Kb using the MySQL Administrator GUI. Which means that the only way to set this system variable to 512 (which is less than 1Kb) is to edit your MySQL configuration file as described above.

, , , ,

No Comments

Locale settings for your cron job

Do you get special characters problem when executing your bash script from a cron job?
And does the same script work fine when it is directly executed from the command line?
If yes, continue reading this article! ;)

The reason of this characters problem is probably because of your locale settings.
Indeed, If you try to run the command locale from the command line and from a cron job, you may get different results such as:

From the command line From a cron job
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=
LANG=
LC_CTYPE="POSIX"
LC_NUMERIC="POSIX"
LC_TIME="POSIX"
LC_COLLATE="POSIX"
LC_MONETARY="POSIX"
LC_MESSAGES="POSIX"
LC_PAPER="POSIX"
LC_NAME="POSIX"
LC_ADDRESS="POSIX"
LC_TELEPHONE="POSIX"
LC_MEASUREMENT="POSIX"
LC_IDENTIFICATION="POSIX"
LC_ALL=

As you can see, the cron job is not using UTF-8. That must be the problem! :)


So the question now is how to change the locale settings for the cron job?
Some people say that you need to add the following environment variables to the crontab entry:

SHELL=/bin/bash
LANG=en_US.UTF-8
LANGUAGE=en
LC_CTYPE=en_US.UTF-8

But this actually didn’t work for me. :(


What you can do instead is create (if not already present) the file /etc/environment and add the following line:

LANG=en_US.UTF-8

The cron process will read this file when it starts, so you need to restart it in order to apply the change:

service cron restart


Hope this will fix your characters problem. ;)

, , , , ,

No Comments

WritableFont doesn’t like to be static!

While using the tool JExcelAPI within my Java application to generate Excel spreadsheets, I got the following exception:

java.lang.ArrayIndexOutOfBoundsException: 5
	at jxl.biff.IndexMapping.getNewIndex(IndexMapping.java:68)
	at jxl.biff.FormattingRecords.rationalize(FormattingRecords.java:388)
	at jxl.write.biff.WritableWorkbookImpl.rationalize(WritableWorkbookImpl.java:988)
	at jxl.write.biff.WritableWorkbookImpl.write(WritableWorkbookImpl.java:692)
	...


It appears that this exception occurs only when you try to generate more than one Excel spreadsheet! How strange is that! 8-O
After a bit of investigation, it seems that the problem comes from the use of the static modifier with a jxl.write.WritableFont variable.

I unfortunately don’t have the time to check the JExcelAPI code source to understand the root cause.
So my advice would be: “if you get EXACTLY the same stack trace, simply delete any static modifier you used with the WritableFont variables”. :-)

, , , , ,

No Comments

Deploy your app to the root context

This is an easy trick which I am sure most of you already know.

Let’s take a Java application called MyAddressBook. Its generated war file could be called myaddressbook.war.

By default, when you deploy this web application to Tomcat, the URL to access it will be http://localhost:8080/myaddressbook/. And if you point a domain name such as ‘addressbook.com’ to this server, the URL would be http://addressbook.com/myaddressbook/.

I don’t know for you but I don’t like to systematically have the subfolder ‘myaddressbook’ after my domain. But maybe I am too picky! ;)

The idea is to deploy our application in the Tomcat root context.
You have two ways of doing this:

  • Define a ROOT.xml file in your conf/Catalina/localhost folder, or;
  • Rename your war file to ROOT.war.

Note that the case is important, it has to be ROOT in UPPERCASE! :)

Once this is done, you will be able to call your application via the URL http://localhost:8080/
or http://addressbook.com/. Way better! 8-)

, ,

No Comments

How to monitor your Java application

It is very good to have your application and your database running on a Linux or Windows server, but who will tell you if your website is down? Who said “the users”? 8-O No, you won’t look very professional if you wait for a user complaint.

What you need to do is to monitor your server. But which tools to use? There are so many on the market… :(

I tested a few of them (Hyperic, Nagios, Zenoss, Cacti, Monitis) but the one I choose is Zabbix. What I like with Zabbix is its price (free 8-) ) and the fact that it is easy to configure and very flexible. Indeed, you can monitor anything you want on the machine (CPU, network, disk space, services, etc)! :)

However, if you also want to monitor your Tomcat application server or even Hibernate Java library, you need some more work.


To monitor Tomcat, you first need to enable JMX Remote. To do so, you can have a look at the official documentation or simply add the following parameters to your Tomcat startup script:

export CATALINA_OPTS='-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=8999 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false'


Then, I will recommend you to deploy Zapcat JMX Zabbix Bridge in your Tomcat web server. This tool has been developed to simplify the communication between the JMX management API inside Java applications and the Zabbix monitoring tool.

To read the installation instructions for Tomcat, please click on the following link:
http://www.kjkoster.org/zapcat/Tomcat_How_To.html


Finally, if you are using Hibernate in your Java application and would like to monitor it, you have to instantiate and configure a Hibernate MBean (org.jboss.hibernate.jmx.Hibernate) that will be responsible for constructing a Hibernate SessionFactory and exposing it to your application through JNDI.

Here are the lines you need to add to your context XML file:

<bean id="mbeanExporter" class="org.springframework.jmx.export.MBeanExporter" lazy-init="false">
    <property name="server" ref="mbeanServerFactory"/>
    <property name="beans">
        <map>
            <entry key="org.hibernate:type=statistics"  value-ref="hibernateMBean"/>
        </map>
    </property>
</bean>

<bean id="mbeanServerFactory" class="org.springframework.jmx.support.MBeanServerFactoryBean">
    <property name="locateExistingServerIfPossible" value="true"/>
</bean>

<bean id="hibernateMBean" class="org.hibernate.jmx.StatisticsService">
    <property name="sessionFactory" ref="sessionFactory"/>
    <property name="statisticsEnabled" value="true"/>
</bean>

, , , , , , ,

No Comments

Onclick event is not fired on IE

I am pretty sure everybody knows that Internet Explorer has “a few” bugs… :roll:
You didn’t? 8-O Alright, better to stay on your little cloud and leave this blog right away!

For the others, I will talk about the JavaScript event onclick which is not fired when the following requirements are matched:

  • In a form;
  • There is only ONE input text element;
  • There is one button which has an onclick event assigned;
  • You press the ‘Enter’ button inside the input text element.

For a better understanding, let’s now take the following example:

<html>
    <head><title>Test</title><head>
    <body>
        <form>
            <input type="text" id="t1"/>
            <input type="submit" onclick="alert('onclick fired!'); return true;"/>
        </form>
    </body>
</html>

As you can see, there is nothing difficult in this code.
Well, that doesn’t mean Internet Explorer can handle it… :lol:

The bug occurs if you press the ‘Enter’ button inside the input text element using Internet Explorer. Indeed, the onclick event is not fired and the text ‘onclick fired!’ is not display to the user! However, it works perfectly fine on Firefox and Safari.

The funny thing is this code works on Internet Explorer if you add another input text, even if it is hidden!
Why? Don’t ask me! :-|

Anyway, the following example works on IE:

<html>
    <head><title>Test</title><head>
    <body>
        <form>
            <input type="text" id="t1"/>
            <input type="text" style="display:none"/>
            <input type="submit" onclick="alert('onclick fired!'); return true;"/>
        </form>
    </body>
</html>


Why are we assigning an onclick event to the submit button?
It could be for a lot of reasons, but the main one is probably to validate the form before submitting the data.

By the way, RichFaces is very often using this event on the submit buttons.
So remember to add a hidden input text to your form if you want to allow users to use the ‘Return’ key. :)

, , , , , ,

No Comments

Be careful of SKIP_COMMENTS

In the early days, we used to hide JavaScript code from old browsers that do not support JavaScript.
The way of doing this was to put a one-line HTML-style comment without the closing characters immediately after the opening <script> tag and put //--> at the end of the script.

For example:

<script type="text/javascript">
<!--
alert('Test');
//-->
</script>

However if you are using this trick with the initialization parameter facelets.SKIP_COMMENTS set to true, the code between <!-- and //--> won’t even be sent to the client!
It simply means that the code above won’t open an alert window because it has been skipped during the page rendering.

Here is what the client will receive:

<script type="text/javascript">
<!--
//-->
</script>


You have two solutions to avoid this situation:

  1. Set the SKIP_COMMENTS parameter to false (the default is true). This can’t really hurt, your page will just be heavier depending on how much HTML comments you put on your page;
  2. No need to hide the JavaScript code as all browsers are now supporting it and over 99.9% of users have it enabled – this is the solution I chose.

For information, below is the code to put in your web.xml file to set the SKIP_COMMENTS parameter to false:

<context-param>
    <param-name>facelets.SKIP_COMMENTS</param-name>
    <param-value>false</param-value>
</context-param>

, , ,

No Comments

No saved view state

How many of you did already get the following error when working with JSF?
I would be surprised if none of you got it at least once! ;)

HTTP ERROR: 500

/web/home.htmlNo saved view state could be found for the view identifier: /web/home.html

RequestURI=/web/home.html

Caused by:

javax.faces.application.ViewExpiredException: /web/home.htmlNo saved view state could be found for the view identifier: /web/home.html
	at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(RestoreViewExecutor.java:88)
	at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:103)
	at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:76)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:151)
	at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)
	at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:341)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:83)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178)
	at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
	at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:368)
	at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:495)
	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)
	...

This very common error happens because your session has timed out. As you probably already know, JSF is storing the view state of your page in session. Obviously, when the session has timed out, it can’t restore the view state and so throws a ViewExpiredException.

The solution for this problem is to add the following lines in your web.xml file:

<context-param>
    <param-name>facelets.BUILD_BEFORE_RESTORE</param-name>
    <param-value>true</param-value>
</context-param>

When this initialization parameter is turned on, it changes ViewHandler.restoreView() to build the view before asking the StateManager for help.

However, if you are using RichFaces, for some reason this is breaking a few Ajax components! :(
To be honest with you, I didn’t investigate in depth why these components don’t work with this parameter set to true.

What I did instead is to make sure the session actually never times out! ;)
To do that, I am polling the server every 29 minutes (as my session time out is set to 30 minutes). Obviously, you can poll the server only every 59 minutes if you set your session time out to 60 minutes.

Here is the code I used to poll the server every 29 minutes:

<h:form>
    <a4j:poll id="poll" interval="1740000" limitToList="true" />
</h:form>

Note that the interval attribute is in milliseconds (29 minutes x 60 x 1000 = 1,740,000 milliseconds).

This solution is far from being perfect! Indeed, if, for example, a user doesn’t close his browser during the night, it means that we will have to keep the session opened during hours! :|
But, as far as I am concerned, it is still better than to throw an exception at the user face. ;)

, , , , , , ,

1 Comment