Archive for category Java

Too many open files on Tomcat

The other day, one of my websites was not available anymore. Looking at the log files, I found the following exception:

Dec 7, 2011 1:22:39 AM org.apache.jk.common.ChannelSocket acceptConnections
WARNING: Exception executing accept
java.net.SocketException: Too many open files
	at java.net.PlainSocketImpl.socketAccept(Native Method)
	at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:384)
	at java.net.ServerSocket.implAccept(ServerSocket.java:450)
	at java.net.ServerSocket.accept(ServerSocket.java:421)
	at org.apache.jk.common.ChannelSocket.accept(ChannelSocket.java:307)
	at org.apache.jk.common.ChannelSocket.acceptConnections(ChannelSocket.java:661)
	at org.apache.jk.common.ChannelSocket$SocketAcceptor.runIt(ChannelSocket.java:872)
	at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
	at java.lang.Thread.run(Thread.java:595)


This was the first time I was getting this exception. What is even stranger is that I didn’t change anything on this application for quite a while!
Anyway, I first did what I usually do with Tomcat: restart it! This fixed the issue but only for a few hours before it crashed again.

After some investigation, it seems that Tomcat was reaching the limit of open file descriptors allowed in this machine (1024 in my case).
To get the maximum number of open file descriptors, simply type the following command:

ulimit -n

It is possible to increase this value by editing the file /etc/security/limits.conf and adding the new limit for the user running Tomcat. However, this is not recommended as 1024 should be sufficient.

The second thing I did was to check the list of open files used by the Tomcat process:

lsof -p

What I found by running this command was a bit odd. It seems that Tomcat was having a multitude of opened connections to one of the web services used by the application. So it looks like the connections between my website and the web service were never closed!  :-|
Because I didn’t change the code on my side, I asked the third party who owns the web service to check their code. I don’t know what was the root cause of the problem but they fixed it on their side and it is now working fine.

In conclusion, if you get the same exception, try to find where the problem is coming from before increasing the maximum number of open file descriptors. ;)

, , , , , ,

No Comments

Make image backgrounds transparent with tolerance

In one of the projects I am working on at the moment, I needed to convert the background colour of an image to be transparent so the image looks better on a non-white background.

Looking on the Web, I found the following article from Dustin Marx:
Making White Image Backgrounds Transparent with Java 2D/Groovy
If the link is broken, please download his code from the following link: ImageTransparency.java

The method which makes the background colour transparent is called makeColorTransparent. This method works pretty well, except in some cases as shown in the example below:

Original image Converted image
using Dustin’s method

This is actually quite normal. Indeed, his code is converting a specific colour (#FFFFFF in our case) to be transparent. But what if the background is not homogeneous?

This is the reason why I had to modify his method to add a new parameter called tolerance:

private Image makeColorTransparent(final BufferedImage im, final Color color, int tolerance) {
    int temp = 0;
    if (tolerance < 0 || tolerance > 100) {
        System.err.println("The tolerance is a percentage, so the value has to be between 0 and 100.");
        temp = 0;
    } else {
        temp = tolerance * (0xFF000000 | 0xFF000000) /100;
    }
    final int toleranceRGB = Math.abs(temp);

    final ImageFilter filter = new RGBImageFilter() {
        // The color we are looking for (white)... Alpha bits are set to opaque
        public int markerRGB = color.getRGB() | 0xFF000000;

        public final int filterRGB(final int x, final int y, final int rgb) {
            if ((rgb | 0xFF000000) == markerRGB) {
                // Mark the alpha bits as zero - transparent
                return 0x00FFFFFF & rgb;
            } else {
                // Nothing to do
                return rgb;
            }
        }
    };

    final ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
    return Toolkit.getDefaultToolkit().createImage(ip);
}

Such as Photoshop, the tolerance is a percentage value between 0 and 100. The higher the tolerance is, the bigger the range of colours will be.

Let’s take our previous example and apply a 50% tolerance:

That looks much better, isn’t it? :)

, , ,

No Comments

Delete the components holding unwanted state

This is a small addition to a problem discussed on the MyFaces Wiki: http://wiki.apache.org/myfaces/ClearInputComponents

Just in case the page is removed from the Wiki, please see below a copy of the problem description:

Sometimes you want to provide a command component (eg a link or button) that performs some server action, and renders the same page but with completely “fresh” values for all components.

When using command components with the normal immediate setting (false), achieving this is just a matter of clearing the beans that the JSF component value attributes access. Any values entered by the user will have been pushed into these beans as part of the Update Model phase, so the components themselves will not be holding any information about submitted data. The action method associated with the command is then run which resets the model, and when the components render themselves they will draw fresh data from the (reset) beans.

Note that because data is being pushed into the model, the validation phase must run, and therefore any invalid data in the page will cause the action to be skipped, and the page is redisplayed with the validation errors displayed. This is not generally the desired behaviour for a “clear” type operation! The solution is to set attribute immediate=true on the command so that its associated action is invoked before validation is applied to the input components in the same view (see How_The_Immediate_Attribute_Works).

However when using command components with immediate=true, things become more complex. All components will retrieve the raw submitted values submitted by the user, but the immediate command will then run before they can be pushed into the backing beans; the components therefore remember this data. When the (immediate) action causes navigation to another view then this is no problem; these components will be discarded anyway. However if the action method causes JSF to go directly to the render phase ‘of the same view’ [by calling facesContext.renderResponse()], then the components will behave as they do for a validation failure – by displaying the value cached in the component rather than fetching data from the backing bean.

MyFaces gave four solutions to this problem, but the one I used is the following:

Find the parent component of the problem inputs, and call
parentComponent.getChildren().clear();

During the render phase, new instances of these child components will then be created, while other components will not be affected.

This is effectively the same as the above solution, but discards a selected subset of components rather than the UI!ViewRoot.

Obtaining the parent component to discard can be done via binding. Alternatively, the “action listener” form of callback can be used for the command; this is passed an ActionEvent from which the command component that was clicked can be found. A call to “findComponent” can be made on this to locate the desired parent component by id, or other similar solutions.

All of this is good and well but what if you don’t have the component object but only the name of the form? How would you call the clear method then?

This is the reason why I wrote the code below:

/**
 * Return the UIComponent that represents the root of the UIComponent tree.
 * @return the UIComponent that represents the root of the UIComponent tree
 */
public static UIViewRoot getUIViewRoot() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    return facesContext != null ? facesContext.getViewRoot() : null;
}

/**
 * Search for a component in the UIComponent tree
 * @param parentComponent the parent component
 * @param componentId the component identifier we look for
 * @return the component found
 */
private static UIComponent findComponent(UIComponent parentComponent, String componentId) {
    if (parentComponent != null) {
        if (componentId.equals(parentComponent.getId())) {
            return parentComponent;
        }
        for (UIComponent child : parentComponent.getChildren()) {
            UIComponent component = findComponent(child, componentId);
            if (component != null) {
                return component;
            }
        }
    }
    return null;
}

/**
 * Deletes components holding unwanted state
 * @param componentId the component identifier
 */
public static void deleteComponentsHoldingUnwantedState(UIComponent parentComponent) {
    if (parentComponent != null) {
        parentComponent.getChildren().clear();
    }
}

/**
 * Deletes components holding unwanted state
 * @param componentId the component identifier
 */
public static void deleteComponentsHoldingUnwantedState(String componentId) {
    deleteComponentsHoldingUnwantedState(findComponent(getUIViewRoot(), componentId));
}

The last method of the code above will allow you to delete all the components holding unwanted state of a form simply by passing its name.
For example:

deleteComponentsHoldingUnwantedState("myform");

, , ,

No Comments

Close ModalPanel if no error

It has been a very long time I wrote this code, but I thought I would share it with you as it is quite useful.

If like me, you are an adept of RichFaces, you might have already seen and used the modal panel functionality. By default, a modal panel is used to display a message, but what if you actually want to display a form within it? How nice would it be if, for example, you could put your login form in a modal panel instead of opening a new page?

With the following steps, you will be able to achieve this:

  • First, get the maximum severity in the message queue:
    <a4j:outputPanel ajaxRendered="true">
        <h:form style="display:none" id="maximumSeverityForm">
            <h:inputHidden id="maximumSeverity"
                value="#{facesContext.maximumSeverity.ordinal}"/>
        </h:form>
    </a4j:outputPanel>
    

    This form has to be placed on all your pages using an include for example. This form will basically get refreshed on every postback and will contain the maximum severity in the message queue or null if the queue is empty.

  • Create a JavaScript method which reads the maximumSeverity hidden field:
    function ajaxRequestContainsErrors() {
        return document.getElementById("maximumSeverityForm:maximumSeverity").value > 0;
    }
    

    This method has to also be included in all the pages.

  • Finally, use the following code for the “Submit” button in your form:
    <a4j:commandButton action="#{userBean.loginAction}" value="Submit" oncomplete="if (!ajaxRequestContainsErrors()) {Richfaces.hideModalPanel('loginModalPanel');}"/>
    

    This button is actually checking if there is no error before closing the modal panel.

, , ,

No Comments

JDBC and the “zero” date

A few weeks ago, I was in the process of writing a little script in Java to extract data from a MySQL database. Because this is what we can call a micro project, I decided to simply use JDBC to talk to the database.

But when I tried to run my script, I got the following exception:

java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Date
	at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:910)
	at com.mysql.jdbc.ResultSet.getDateFromString(ResultSet.java:2032)
	at com.mysql.jdbc.ResultSet.getDate(ResultSet.java:1956)
	at com.mysql.jdbc.ResultSet.getDate(ResultSet.java:1924)
	at com.mysql.jdbc.ResultSet.getDate(ResultSet.java:1972)
	...

After looking at the database, it seems that this exception has been thrown because the fields of type datetime contain the value ’0000-00-00 00:00:00′. Don’t ask me why I have this kind of value in the database! Obviously, we would prefer to have a NULL value instead of a “zero” date.

There are two solutions to fix this problem:

  1. Replace all the “zero” dates by NULL using the following SQL query:

    UPDATE table SET datefield = NULL WHERE datefield = '0000-00-00 00:00:00';
    
  2. Add the parameter zeroDateTimeBehavior=convertToNull to the connection url which will automatically convert the “zero” date to NULL. Please find below an example of connection url with this parameter:

    jdbc:mysql://localhost:3306/dbname?zeroDateTimeBehavior=convertToNull
    

Personally, I choose the second solution as I didn’t want to change the original data of the database.

, , , ,

No Comments

Update your Twitter status with Java

Some time ago, Twitter stopped supporting “Basic Authentication” in the Twitter API, in favour of a new, more secure system, OAuth.
Please read this article for more information about OAuth: http://en.wikipedia.org/wiki/OAuth

The basic authentication was straightforward, you only needed to provide the Twitter username and password in order to authenticate and send tweets from an application. That was it!
But things get more complicated with the new authentication. :(
You now need FOUR credentials:

  • A consumer key;
  • A consumer secret;
  • An access token;
  • An access token secret.

Please follow the instructions below to get these credentials for your application:

  1. Register the site as an application on http://dev.twitter.com/apps/new
    • If you’re not currently logged in, use the Twitter username and password which you want associated with this site
    • Your Application’s Name will be what shows up after “via” in your twitter stream. Your application name cannot include the word “Twitter.” I suggest using the name of your web site.
    • Your Application Description can be whatever you want
    • Application Type should be set on Browser
    • The Callback URL should be the URL of your web application
    • Default Access type must be set to Read & Write (this is NOT the default)

    Once you have registered your site as an application, you will be provided with a consumer key and a consumer secret.

  2. Get the access token executing the following code:
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    
    import twitter4j.Twitter;
    import twitter4j.TwitterException;
    import twitter4j.TwitterFactory;
    import twitter4j.http.AccessToken;
    import twitter4j.http.RequestToken;
    
    public class TwitterAccessToken {
    	private static final String CONSUMER_KEY = "[your consumer key]";
    	private static final String CONSUMER_SECRET = "[you consumer secret]";
    
    	public static void main(String[] args) throws Exception {
     		Twitter twitter = new TwitterFactory().getInstance();
    		twitter.setOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
    		RequestToken requestToken = twitter.getOAuthRequestToken();
    		AccessToken accessToken = null;
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    		while (null == accessToken) {
    			System.out.println("Open the following URL and grant access to your account:");
    			System.out.println(requestToken.getAuthorizationURL());
    			System.out.print("Enter the PIN (if available) or just hit enter.[PIN]:");
    			String pin = br.readLine();
     			try {
    				if (pin.length() > 0) {
    					accessToken = twitter.getOAuthAccessToken(requestToken, pin);
    				} else {
    					accessToken = twitter.getOAuthAccessToken();
    				}
    			} catch (TwitterException e) {
    				if (401 == e.getStatusCode()) {
    					System.err.println("Unable to get the access token.");
    				} else {
    					e.printStackTrace();
    				}
    			}
    		}
    
    		System.out.println("Access Token: " + accessToken.getToken());
    		System.out.println("Access Token Secret: " + accessToken.getTokenSecret());
    	}
    }
    

    Once you have executed this script and followed the instructions, you will be provided with an access token and an access token secret.


Finally, here is the code to update your Twitter status using the new credentials:

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationContext;
import twitter4j.http.AccessToken;
import twitter4j.http.OAuthAuthorization;

public class TwitterTest {
	private static final String ACCESS_TOKEN = "[your access token]";
	private static final String ACCESS_TOKEN_SECRET = "[your access token secret]";
	private static final String CONSUMER_KEY = "[your consumer key]";
	private static final String CONSUMER_SECRET = "[you consumer secret]";

    public static void main(String[] args) {
    	AccessToken accessToken = new AccessToken(ACCESS_TOKEN, ACCESS_TOKEN_SECRET);
    	OAuthAuthorization authorization = new OAuthAuthorization(ConfigurationContext.getInstance(), CONSUMER_KEY, CONSUMER_SECRET, accessToken);
    	Twitter twitter = new TwitterFactory().getInstance(authorization);
		try {
			twitter.updateStatus("Hello World!");
		} catch (TwitterException e) {
			System.err.println("Error occurred while updating the status!");
			return;
		}
        System.out.println("Successfully updated the status.");
    }
}

Please note that this code is using the Java library Twitter4J which helps to integrate a Java application with the Twitter service.

, , , , ,

6 Comments

Illegal Key Size

About a week ago, I wrote an article on how to encrypt with PHP and decrypt with Java. The funny thing is I got an error when I deployed the Java code into the live server! :-|

As a reminder, this is the code I am talking about:

SecretKeySpec skeySpec = new SecretKeySpec("SECRET KEY".getBytes(), "AES");
IvParameterSpec initalVector = new IvParameterSpec("iv_example".getBytes());
Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, initalVector);

This code was working perfectly fine on my local machine but here is the exception I got when I ran it on a Linux server:

java.security.InvalidKeyException: Illegal key size
        at javax.crypto.Cipher.a(DashoA12275)
        at javax.crypto.Cipher.a(DashoA12275)
        at javax.crypto.Cipher.a(DashoA12275)
        at javax.crypto.Cipher.init(DashoA12275)
        at javax.crypto.Cipher.init(DashoA12275)
        ...


Looking on internet for an explanation, I found the following answer on Charitha Kankanamge’s blog (which I slightly updated):

“java.security.InvalidKeyException: Illegal key size” error is a common issue which occurs when you try to invoke a secured web service in an environment where the provision for java unlimited security jurisdiction is not done.
This can be avoided by installing Java Cryptography Extension (JCE) unlimited strength jurisdiction policy files.

1. Go to http://www.oracle.com/technetwork/java/javase/downloads/index.html

2. Go to the Additional Resources section and click on the download button next to “Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files X”

3. Download jce_policy-X.zip and extract it into a directory

4. You will find local_policy.jar and US_export_policy.jar files there in the extracted directory. Copy these two files to $JAVA_HOME/jre/lib/security directory (These files might already be there, replace them in this case)

5. Restart the web server and invoke your secured service again. You will not encounter the “invalidkeyException” any more

Please click on the link below to see the original article:
http://charithaka.blogspot.com/2008/08/how-to-avoid-javasecurityinvalidkeyexce.html

, , , ,

No Comments

Encrypt with PHP – Decrypt with Java

For security reason, I wanted to encrypt the data transferred between PHP web services and a Java application. But the problem was to encrypt the data with PHP in a way that it is possible to decrypt it using Java.

It obviously exists a lot of ways of doing this. But here is the way I choose:

  • Use a secret key and an initialisation vector for the encryption and decryption
  • Use the mcrypt PHP module for the encryption
  • Use the javax.crypto Java package for the decryption

Please find below the PHP code for the encryption:

function encrypt($message, $initialVector, $secretKey) {
    return base64_encode(
        mcrypt_encrypt(
            MCRYPT_RIJNDAEL_128,
            md5($secretKey),
            $message,
            MCRYPT_MODE_CFB,
            $initialVector
        )
    );
}

And please see below the Java code for the decryption:

public static String md5(String input) throws NoSuchAlgorithmException {
    MessageDigest md = MessageDigest.getInstance("MD5");
    byte[] messageDigest = md.digest(input.getBytes());
    BigInteger number = new BigInteger(1, messageDigest);
    return number.toString(16);
}

public String decrypt(String encryptedData, String initialVectorString, String secretKey) {
    String decryptedData = null;
    try {
        SecretKeySpec skeySpec = new SecretKeySpec(md5(secretKey).getBytes(), "AES");
        IvParameterSpec initialVector = new IvParameterSpec(initialVectorString.getBytes());
        Cipher cipher = Cipher.getInstance("AES/CFB8/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec, initialVector);
        byte[] encryptedByteArray = (new org.apache.commons.codec.binary.Base64()).decode(encryptedData.getBytes());
        byte[] decryptedByteArray = cipher.doFinal(encryptedByteArray);
        decryptedData = new String(decryptedByteArray, "UTF8");
    } catch (Exception e) {
        LOGGER.debug("Problem decrypting the data", e);
    }
    return decryptedData;
}

, , , , ,

25 Comments

Upgrade to RichFaces 3.3.3.Final

From time to time, it is good to upgrade the application libraries to the latest stable version. Especially the frontend libraries as the browsers are constantly involving and new ones are coming on the market.

This is why I wanted to upgrade the RichFaces library on one of my web application which was still using the version 3.3.0.GA with JSF/MyFaces 1.2.5.
The RichFaces dependency was looking like the following in my pom.xml file:

<dependency>
    <groupId>org.richfaces.ui</groupId>
    <artifactId>richfaces-ui</artifactId>
    <version>3.3.0.GA</version>
    <scope>compile</scope>
</dependency>

The upgrade should be straightforward.
But when changing to the version 3.3.3.Final, I got the following error:

2010-10-13 15:56:14.959::WARN:  Error starting handlers
java.lang.NoClassDefFoundError: org/ajax4jsf/component/SequenceDataAdaptor
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366)
	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366)
	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
	at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:366)
	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
	at java.lang.Class.forName0(Native Method)
	at java.lang.Class.forName(Class.java:247)
	at org.apache.myfaces.shared_impl.util.ClassUtils.classForName(ClassUtils.java:132)
	at org.apache.myfaces.shared_impl.util.ClassUtils.simpleClassForName(ClassUtils.java:158)
	at org.apache.myfaces.application.ApplicationImpl.addComponent(ApplicationImpl.java:564)
	at org.apache.myfaces.config.FacesConfigurator.configureApplication(FacesConfigurator.java:650)
	at org.apache.myfaces.config.FacesConfigurator.configure(FacesConfigurator.java:277)
	at org.apache.myfaces.webapp.AbstractFacesInitializer.buildConfiguration(AbstractFacesInitializer.java:131)
	at org.apache.myfaces.webapp.Jsp21FacesInitializer.initContainerIntegration(Jsp21FacesInitializer.java:64)
	at org.apache.myfaces.webapp.AbstractFacesInitializer.initFaces(AbstractFacesInitializer.java:83)
	at org.apache.myfaces.webapp.StartupServletContextListener.contextInitialized(StartupServletContextListener.java:72)
	at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:540)
	at org.mortbay.jetty.servlet.Context.startContext(Context.java:135)
	at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
	at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:510)
	at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
	at org.mortbay.jetty.plugin.Jetty6PluginWebAppContext.doStart(Jetty6PluginWebAppContext.java:110)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
	at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:152)
	at org.mortbay.jetty.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:156)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
	at org.mortbay.jetty.handler.HandlerCollection.doStart(HandlerCollection.java:152)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
	at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:117)
	at org.mortbay.jetty.Server.doStart(Server.java:222)
	at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)
	at org.mortbay.jetty.plugin.Jetty6PluginServer.start(Jetty6PluginServer.java:132)
	at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:357)
	at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:293)
	at org.mortbay.jetty.plugin.AbstractJettyRunMojo.execute(AbstractJettyRunMojo.java:203)
	at org.mortbay.jetty.plugin.Jetty6RunMojo.execute(Jetty6RunMojo.java:182)
	at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:451)
	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:558)
	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:512)
	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:482)
	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:330)
	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:291)
	at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:142)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:336)
	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:129)
	at org.apache.maven.cli.MavenCli.main(MavenCli.java:287)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
	at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
	at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
	at org.codehaus.classworlds.Launcher.main(Launcher.java:375)
Caused by: java.lang.ClassNotFoundException: org.ajax4jsf.component.SequenceDataAdaptor
	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
	at org.codehaus.classworlds.RealmClassLoader.loadClassDirect(RealmClassLoader.java:195)
	at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:255)
	at org.codehaus.classworlds.DefaultClassRealm.loadClass(DefaultClassRealm.java:274)
	at org.codehaus.classworlds.RealmClassLoader.loadClass(RealmClassLoader.java:214)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:375)
	at org.mortbay.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:337)
	... 82 more


What happened here? I simply changed the version number and it now does NOT work! :(
Looking at the exception, it seems that it cannot find the class org.ajax4jsf.component.SequenceDataAdaptor which is part of the richfaces-impl library. Why not?

Well, in fact, it is quite simple! It appears that from the version 3.3.3 of RichFaces, you now have to specifically add the richfaces-impl dependency to your pom.xml file such as:

<dependency>
    <groupId>org.richfaces.ui</groupId>
    <artifactId>richfaces-ui</artifactId>
    <version>3.3.3.Final</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>org.richfaces.framework</groupId>
    <artifactId>richfaces-impl</artifactId>
    <version>3.3.3.Final</version>
    <scope>compile</scope>
</dependency>

Why do we have to manually add this dependency? This is because the new version of RichFaces allows you to use JSF 2.0 instead of JSF 1.2. To do that, simply add the library richfaces-impl-jsf2 instead of richfaces-impl in your pom.xml file.

Please click on the following link for the JBoss manual about this configuration:
http://community.jboss.org/wiki/HowtoaddRichFaces33xtomavenbasedproject

, , , , ,

No Comments

The selfRendered attribute

This is an interesting problem related to the RichFaces rich:suggestionbox tag.

Let’s take the following code:

<rich:suggestionbox for="q" minChars="1"
    suggestionAction="#{myBean.mySuggestionAction}" var="result"
    limitToList="true">
    <h:column>
        <h:outputText value="#{result}" />
    </h:column>
</rich:suggestionbox>

If you use the code above as it is, the whole page is going to be processed each time the suggestionAction is called. And because the minChars attribute is set to 1, the action is going to be called each time the user enters a character! :-o
For obvious reason, such as performance issue, this is not ideal.

To avoid this behaviour, you simply need to set the attribute selfRendered to true as shown below:

<rich:suggestionbox for="q" minChars="1"
    suggestionAction="#{myBean.mySuggestionAction}" var="result"
    limitToList="true" selfRendered="true">
    <h:column>
        <h:outputText value="#{result}" />
    </h:column>
</rich:suggestionbox>

Here is the description of the selfRendered attribute from RichFaces documentation:

If “true”, forces active Ajax region render response directly from stored components tree, bypasses page processing. Can be used for increase performance. Also, must be set to ‘true’ inside iteration components, such as dataTable.

Don’t hesitate to add this attribute to increase the performance of your website. ;)

, , ,

No Comments