Oct 08

Use HSQLDB Functions with Hibernate Mapping Files

Let’s say you need to do a “local integration” test, where you code does not depend on external systems (queues/external servers/DB/etc..). Creating unit tests, mocking/stubbing everything out is all good, but sometimes you need to be able to run tests that are as close as possible to the “real world” deal, while you are in “local mode” – e.g. plane, subway, basically somewhere without access to the real external systems.

One of ways you can approach it with databases is to load schemas you need in memory, and work (test) against those schemas. This is relatively easy to do with HSQLDB, and there are many “googlable” guides on how to do it. However in this little howto, I want to show you how you can define your own HSQLDB functions, and use them as either “stubs” (or even “real deal”).

Here is an example on why you may need it. Consider this Hibernate mapping file that is used in your application:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	<class name="CustomerCreditCardSearchResultDto" table="CR_CREDIT_CARD">
		<id name="id" column="CR_CREDIT_CARD_ID">
			<generator class="native">
                                 <param name="sequence">SQ_CR_CREDIT_CARD</param>
                <property name="accountNumber" formula="some_pkg.decode( ACCOUNT_NUMBER )" />
                <property name="secretNumber" formula="some_pkg.decode( SECRET_NUMBER )" />
                <property name="expirationDate" column="EXPIRATION_DATE" type="date" />
                <property name="zipCode" column="ZIP_CODE" />

Let’s say you created a CR_CREDIT_CARD table in in-memory DB, populated it, started your test. Now when you try to read a “CustomerCreditCardSearchResultDto” object somewhere in your test, Hibernate will construct an SQL query from the mapping file above, and execute it on the in-memory DB.

However there is a problem – it is going to fail with a similar Exception:

Caused by: java.sql.SQLException: Unexpected token: DECODE in statement [select <query here> .... ]
	at org.hsqldb.jdbc.Util.throwError(Unknown Source)
	at org.hsqldb.jdbc.jdbcPreparedStatement.<init>(Unknown Source)
	at org.hsqldb.jdbc.jdbcConnection.prepareStatement(Unknown Source)
	at org.apache.commons.dbcp.DelegatingConnection.prepareStatement(
	at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(
	at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(
	at org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(
	at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(
	at org.hibernate.loader.Loader.prepareQueryStatement(
	at org.hibernate.loader.Loader.doQuery(
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(
	at org.hibernate.loader.Loader.loadEntity(
	... 60 more

If there is an Exception – there is a Reason for it :) Notice these two mappings in the Hibernate mapping file above:

<property name="accountNumber" formula="some_pkg.decode( ACCOUNT_NUMBER )" />
<property name="secretNumber" formula="some_pkg.decode( SECRET_NUMBER )" />

That says Hibernate to construct SQL that uses this “some_pkg.decode()” custom function/store procedure after (in case of SELECT) reading these values from a database. However, in you local testing environment, you do not have this function defined. It is probably defined in the DB (like Oracle/DB2/etc) itself.

But for most, if not for all, technical problems there is a solution, so don’t worry – you can define this function(s) yourself. Since it is a test, the most logical thing, since you want to abstract the code out from the external systems (and their functions) would be to define stubs to these functions.

Let’s create a utility “HsqlFunctions” Java class with static methods to be used by HSQLDB (it can only use static Java methods in its SQL, btw):

package org.project.test.util;
 * HSQL functions to be aliased.
 *    DDL example:
 *    CREATE ALIAS DECODE FOR "org.project.test.util.HsqlFunctions.decodeString"
 * @author
public final class HsqlFunctions
   private HsqlFunctions()
     // static utility class - does not need to be constructed.
     * Stub for the decode function.
     * Usually used to "please" Hibernate Mapping Files.
     * @param value - String value for the column
     * @return - returns the same String value
    public static String decodeString( String value )
        return value;

Now, when creating a test schema, you can ALIAS this static method as HSQLDB function like this:

     CREATE ALIAS DECODE FOR "org.project.test.util.HsqlFunctions.decodeString"

This will tell HSQLDB to call “decodeString” static Java method on the column value, every time it sees “decode( COLUMN )” in SQL.

One thing to notice, though – make sure the type that the Java methods take are exactly the same as defined by DDL (Database Schema). For example, if you pass in column value as an Object:

    public static String decodeString( Object value )
        return String.valueOf (value );

And the column is defined as VARCHAR in schema, HSQLDB will try to pack that String into an Object, and it will fail with a similar exception:

Caused by: java.sql.SQLException: Wrong data type: hexadecimal string with odd number of characters in statement [select ... <query here>]
	at org.hsqldb.jdbc.Util.throwError(Unknown Source)
	at org.hsqldb.jdbc.jdbcPreparedStatement.executeQuery(Unknown Source)
	at org.apache.commons.dbcp.DelegatingPreparedStatement.executeQuery(
	at org.hibernate.jdbc.AbstractBatcher.getResultSet(
	at org.hibernate.loader.Loader.getResultSet(
	at org.hibernate.loader.Loader.doQuery(
	at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(
	at org.hibernate.loader.Loader.loadEntity(
	... 60 more

Below is just an excerpt on how you would set up the schema to use it with HSQLDB in your test:

    private static final String CREATE_ALIASES =
        "FOR \"org.project.test.util.HsqlFunctions.decodeString\"";
    private static final String CREATE_SEQUENCES =
    private static final String CREATE_TABLES =
        "DROP TABLE cr_credit_card IF EXISTS;" +
        "CREATE TABLE cr_credit_card (" +
            "cr_credit_id NUMERIC(15), " +
            "account_number VARCHAR(48)," +
        //  Creating the schema
        m_jdbcTemplate.execute( CREATE_ALIASES );
        m_jdbcTemplate.execute( CREATE_SEQUENCES );
        m_jdbcTemplate.execute( CREATE_TABLES );
        //  HSQLDB is ready to be populated with data at this point.

You can use DBUnit to create the schema above and populate it with the data. The above is just a straight forward hardcoded example.
Notice how it also creates a sequence “SQ_CR_CREDIT_CARD” to please the Hibernate, and others who might use it in the application.

Happy “local integration” testing!

Feel free to post questions/comments/suggestions, I’ll try to respond when have a free second or two :)

Sep 08

Reset Lost Password in Sun Application Server

Sun Application Server Password ResetHappens to the best of us, less with system admins more with developers. But we are all human, and believe it or not we DO forget and loose passwords at least once every so often. Some time ago I wrote a tutorial on how to reset lost root password in mysql, and here is another similar tutorial on how to reset the lost domain password but this time for Sun Application Server.

Before going any further with this article, please first check “.asadminprefs” file:

cat /home/toly/.asadminprefs

the admin password could be there

If it is not there, there are two ways to reset it:

  • Reinstall or recreate the affected domain.
  • Create a new dummy domain and copy its security key file over to the real domain to substitute the password.

Below is an explanation for the second approach (in case when “reinstall or recreate affected domain” is not an option):


 >   Sun App server is installed in                 "/opt/SUNWappserver"
 >   Domain to which the password is lost:   "domain1"

Step 1. Creating a new dummy domain

/opt/SUNWappserver/bin/asadmin create-domain --adminport 7070 --adminuser admin --instanceport 7071 dummy-domain
Please enter the admin password>password
Please enter the admin password again>password
Please enter the master password>password
Please enter the master password again>password
Domain dummy-domain created.

Step 2. Copy dummy-domain’s “admin-keyfile” to domain1’s “admin-keyfile”

cp /opt/SUNWappserver/domains/dummy-domain/config/admin-keyfile  /opt/SUNWappserver/domains/domain1/config/admin-keyfile

now the password for domain1 is “password” – DONE :)

Step 3. Deleting the dummy domain

/opt/SUNWappserver/bin/asadmin delete-domain dummy-domain
Domain dummy-domain deleted.


The above is true for Sun’s Application Server 8.x and later.

For Sun’s Application Server 9.x check out “change-admin-password

Sep 08

Install Sun Application Server on Ubuntu

Sun Microsystems

On the client site when working on Java (or should I say JEE) projects, the application servers are most of the time “rotate” between these four: JBoss, Websphere, Weblogic, and someties Geronimo. However there are some clients who have pretty tight contracts with Sun, and in these cases the Sun Application Server is used.

I think now days in development world in general, well except maybe .NET part of it, Ubuntu and/or Mac OS slowly become OSs of choice for developers. Sun app server however is not the most used app server out there, and since its installation could be a bit non-straightforward, here are four simple steps on how to install it on Ubuntu box:

Step 1. Download the “.bin” form sun:

“Sun Java System Application Server” (I needed 8.2, but there are more recent ones)

Step 2. Change permissions, to make it runnable:

chmod 744 sjsas_pe-8_2-linux.bin

Step 3. If you just run it:


It is going to complaint that it is missing a standard c++ library:

./sjsas_pe-8_2-linux.bin: error while loading shared libraries: cannot open shared object file: No such file or directory

Having done some “apt-cache” searches ( apt-cache search libstdc++ ), found that Ubuntu has “″ in /usr/lib.
From /usr/lib run:

 sudo ln -s

Step 4. Run it now, it will install Sun App Server successfully! * **

* Do not run installation as root – it will fail (for most sun app servers versions)

** If you use any form of Beryl (or some Compiz’es), disable it, or reload window manager as a “Gnome Manager”. This is due to the fact the the installer is written in Swing, and Swing does not get along too well with some display managers.

Jul 08

Spring Web Application Context Visibility

spring framework logoWhile developing a Web App using Spring little things can take a lot of time to resolve. At the end they may appear to be very simple, and you may ask your self “how could I not think of it before – it is so obvious!”. Well, yea, it is obvious, but you just have to know it! One of the places that helps you to solve the “obvious” (and not so obvious), so you do not have to spin your wheels is, with no doubts, the spring forum. However you need to know the right search criteria to find what you need.

Here I just want to share something small but important about the visibility of Spring Contexts in a Web App.

Looking at org.springframework.web.servlet.DispatcherServlet API notice this:

“A web application can define any number of DispatcherServlets. Each servlet will operate in its own namespace, loading its own application context with mappings, handlers, etc. Only the root application context as loaded by ContextLoaderListener, if any, will be shared.”

This brings an interesting point – in a Spring Web App you have one root application context which is private, and many dispatcher servlet application contexts which are children of the root application context:


In the above, everything that is defined in “contextConfigLocation” is your root application context. Every “dispatcher-servlet-number-x” (“dispatcher-servlet-number-1″, “dispatcher-servlet-number-2″, etc..) would represent a child application context which will see (have the visibility to) all the beans from the parent (root) context, but will not see any of the beans defined by its siblings – another dispatcher servlet contexts.

The only gotcha in the above visibility is BeanFactoryPostProcessor / BeanPostProcessor (s) – like “PropertyPlaceholderConfigurer” for example. These guys apply ONLY to beans in its own context. For example, if you have PropertyPlaceholderConfigurer defined in the root application context, none of root’s children will be able to use it (see) the ${properties}.

Here is the semi-official version “why” from Juergen (Spring Lead Developer):

“PropertyPlaceholderConfigurer is an implementation of the BeanFactoryPostProcessor interface: This interface and its sibling BeanPostProcessor just apply to the BeanFactory that defines them, that is, to the application context that defines them.

If you combine multiple config files into a single contextConfigLocation, a PropertyPlaceholderConfigurer defined in any of the files will apply to all of the files, because they are loaded into a single application context.

However, a DispatcherServlet has its own application context, just using the root web application context as parent. Therefore, it needs to define its own BeanFactoryPostProcessors and/or BeanPostProcessors, in this case its own PropertyPlaceholderConfigurer.”

Happy Springing!

May 08

Generate XSD from XML

There are several tools out there to create (or to infer) an XSD schema from XML document. I liked trang command line tool the most. Found it first when reading about Spring web services in Spring in Action book (very good book btw).

Here are four simple steps how to create XSD from XML* using trang:

Step 1. Get trang

Download from here (at the moment of writing “”)

Step 2. Extract it

Use “unzip”, or just winzip/winrar/7z etc.. if on windows

Step 3. Make an alias

This step is optional, but makes it extremely easy to run the tool with a single command. Make an alias to the “trang.jar” by (in my case Ubuntu/Linux) editing “~/.bashrc” and adding the following:

# execute trang.jar (create XSD from XMLs)
alias xml2xsd='java -jar ~/soft/utils/trang/trang-20030619/trang.jar'

above “~/soft/utils/trang” is the directory where “trang” was unzipped to.

Step 4. Create XSD from XML

Let’s look at the XML file we need an XSD for:

$ ls -l
total 4
-rw-r--r-- 1 user group 357 2008-05-28 15:38 holiday-request.xml
$ cat holiday-request.xml
<?xml version="1.0" encoding="UTF-8"?>
<holidayRequest xmlns="">

now run the tool against it:

$ xml2xsd holiday-request.xml hr.xsd
$ cat hr.xsd
<?xml version=”1.0″ encoding=”UTF-8″?>
<xs:schema xmlns:xs=”” elementFormDefault=”qualified” targetNamespace=”” xmlns:schemas=””>
  <xs:element name=”HolidayRequest”>
        <xs:element ref=”schemas:Holiday”/>
        <xs:element ref=”schemas:Employee”/>
  <xs:element name=”Holiday”>
        <xs:element ref=”schemas:StartDate”/>
        <xs:element ref=”schemas:EndDate”/>
  <xs:element name=”StartDate” type=”xs:NMTOKEN”/>
  <xs:element name=”EndDate” type=”xs:NMTOKEN”/>
  <xs:element name=”Employee”>
        <xs:element ref=”schemas:Number”/>
        <xs:element ref=”schemas:FirstName”/>
        <xs:element ref=”schemas:LastName”/>
  <xs:element name=”Number” type=”xs:integer”/>
  <xs:element name=”FirstName” type=”xs:NCName”/>
  <xs:element name=”LastName” type=”xs:NCName”/>



* – NOTE: “trang” can create an XSD from multiple XML documents, not just one.

List of other tools to use as an alternative to trang:

XSD away, Good Luck!

Apr 08

Creating Public and Private Certificates/Keys

Public and Private Key PairHave you ever tried to communicate with somebody/something through any kind of technology? Most of the time “those” people/systems like privacy, in a way that they like their communication with everybody including you to be private. Hence once you want to communicate with them they give you something called a “public key” ( or “public-key certificate” ) and ask you to give them yours. Usually when you talk to different sources, nobody would guide you through on how to create that “public key” of yours, “they” would just want it, but you would be left alone to figure out how you should generate it.

Hence this little guide will show you one of many ways on how to generate a pair of X.509 public/private keys, and how to access this magic pair to get that “public key”, so it can be given to anyone who needs it.

First, let us throw a couple of sentences on how these keys are used. It is actually very simple – there is “YOU” and “THEY”:

  • YOU: generate a pair of public/private keys (where whatever is encrypted with your public key can only be decrypted with your private key)
  • YOU: hide your private key from everybody
  • YOU: give your public key to anybody who wants to communicate with you
  • THEY: generate a pair of public/private keys
  • THEY: hide their private key from everybody including YOU
  • THEY: give their public key to anybody who wants to communicate with them

Now when YOU and THEY have each others public keys and their own private keys communication may begin:

  • YOU: write your secret message, encrypt it with THEIR public key and send to them
  • THEY: receive your top secret message and using THEIR private key decrypt it
  • THEY: write you an answer, encrypt it with YOUR public key, and send to you
  • YOU: receive their top secret response and using YOUR private key decrypt it

Told you it is very simple!

Now let’s see how to do the magic – how to generate a pair of YOUR public and private keys.

There are number of ways – tools/libraries/code snippets/etc.. I would show you one of the simplest ways how this can be archived using a tool called… any guess? Yes – a “keytool” – make sense, right?

“keytool” is a java tool that has a great manual, and since its java – it’ll work on any OS that has JVM. In order to get/download a keytool, you just have to install Java (JRE) on your system (95% that you already have it installed, hence you can go ahead and use “keytool” without needing to install/download anything else).

Examples here are run on Linux (Ubuntu), but as long as you have Java installed, it does not really matter what OS you have to get the job done.

So, fire up the terminal (Windows’ “cmd”) and let’s generate a pair of public/private keys now:

$ keytool -genkey -alias otherguy -keypass p@ssw0rd -keystore our.keystore
Enter key store password: ksp@ssw0rd
You are about to enter information that will be incorporated into
your certificate request.  This information is what is called a
Distinguished Name or DN.  There are quite a few fields but you
can use supplied default values, displayed between brackets, by just
hitting &lt;Enter&gt;, or blank the field by entering the &lt;.&gt; character
before hitting &lt;Enter&gt;.
Common Name (hostname, IP, or your name): myname
Organization Name (company) [The Sample Company]: my company
Organizational Unit Name (department, division): department of departments
Locality Name (city, district) [Sydney]: gorodok
State or Province Name (full name) [NSW]: state of new noisy
Country Name (2 letter code) [AU]: zz

As you might figured already, a keystore is a small database, that we just created, that would hold all the keys (private/public) for many systems – right now we only have one pair, but later we can add more keys to the keystore. So let’s look at this keystore that we just generated:

$ ls -l
total 4
-rw-r--r-- 1 user group 1641 2008-04-22 20:46 our.keystore

But now you need to be able to access this “database” to get a public key, so you can share it with others. It is done by exporting this public key – again, very simple:

$ keytool -export -rfc -alias otherguy -file us-to-otherguy.cer -keystore our.keystore
Enter key store password: ksp@ssw0rd

let’s see what files we have now:

$ ls -l
total 8
-rw-r--r-- 1 user group 1641 2008-04-22 20:46 our.keystore
-rw-r--r-- 1 user group 1189 2008-04-22 20:48 us-to-otherguy.cer

And here it is (!) your public key certificate – “us-to-otherguy.cer”. Let’s see what’s inside:

$ cat us-to-otherguy.cer

that is exactly what you send to everybody else to encrypt their secret messages!

The last thing that I want to show you is how to see what’s inside the keytore database:

$ keytool -list -v -keystore our.keystore
Enter key store password: ksp@ssw0rd
Key store type: gkr
Key store provider: GNU-CRYPTO
Key store contains 1 entry(ies)
Alias name: otherguy
Creation timestamp: Tuesday April 22, 2008 AD - 8:46:38;616 o`clock PM EDT
Entry type: key-entry
Certificate chain length: 1
Owner: CN=myname,O=my company,OU=department of departments,L=gorodok,ST=state of new noisy,C=zz
Issuer: CN=myname,O=my company,OU=department of departments,L=gorodok,ST=state of new noisy,C=zz
Serial number: 1
Valid from: Wednesday April 23, 2008 AD - 1:46:59;989 o`clock AM EDT
until: Tuesday July 22, 2008 AD - 1:46:59;990 o`clock AM EDT
Certificate fingerprints
MD5: BB:35:C0:6B:D0:B2:67:26:BF:AB:AD:5A:87:51:AA:32
SHA-160: 19:67:F9:8B:DF:52:24:4A:61:4D:76:1C:79:2E:4B:5B:8E:A8:AA:E1

Here you can see that a public certificate that we exported is ” Valid from: Wednesday April 23, 2008 until: Tuesday July 22, 2008″, hence 90 days. That means it will need to be changed in 90 days, which would also, of course mean you would have to issue a new certificate to all your contacts in 90 days. In order to change this time frame, when generating a keystore, just add a “-validity <number of days>”when generating keys:

$ keytool -genkey -alias otherguy -keypass p@ssw0rd -keystore our.keystore -validity 3600

that would create a pair valid for 3600 days from the current date.

What if somebody wants to share secret with you? Well, now you are ready! :)

Feb 08

Install Maven Plugin for Eclipse

Installing a Maven Plugin for Eclipse can be a bit tricky if you want to get the whole spectrum of features. By default you would go to “Eclipse -> Help -> Software Updates -> Find and Install”, then “Search for new features to install”, then click on “New Remote Site”, and enter the Maven Projects name (e.g. Maven2Plugin) and its home URL there ““.

Once you install it at first everything would seem quite right. However, if you try “Import” a Maven Project, you will not see such an option in under the “General” menu, since it would be missing.

The reason for that is that “” brings in an old version of the plugin. (At the moment of writing) It brings in “Maven 2 Plugin 0.0.9″, whereas what you need is 0.0.12.

Hence you read the “Maven Integration for Eclipse” installation guide and point your “New Remote Site” to “” instead of ““. The one thing to be cautious about is an “update” link will try to also bring “subclipse” and “mylin” projects, hence you will need to “uncheck” them if you do not want to bring them:

Choosing only Maven dependency while installing Maven Plugin for Eclipse

Happy Maving everybody! :)

Jun 07

Haptic Clock Beats The Time Into You

Haptic Java Mobile ClockHave a mobile phone that you do not want to look at? Is it that bad, or maybe it is awesome, but you are just annoyed to look at it to find out something as simple as current time? Then here is a very interesting Java Mobile application that is written by Che-Wei Wang and makes your phone to literally beat the time into you.

The Haptic Clock is a small clock program for Java powered mobile phones.  The clock conveys time through  a sequence of vibrations so you never have to pull the phone out of your pocket to tell time.


Haptic Java Mobile Clock

Long vibrations are the number of hours of the current time on a 12 hour clock, so 6pm and 6am are both 6 vibrations.  The shorter vibrations are the number of minutes divided by 5. So 4 vibrations is 20 minutes and 7 vibrations is 35 minutes.  Example: (3) long vibrations and (6) short vibrations means it’s 3:30.  Just in case you do want to see the time, the screen displays the time with tick marks for hours, minutes and seconds.

Instructions: Press ‘5′ to vibrate the current time. Press ‘0′ to exit program. UP and DOWN to control the speed of vibrations. Time alerts (vibrations) will occur automatically every 15 minutes on the hour.

Version:         0.06
Released:      5.24.2007
Creator:         Che-Wei Wang
License:         GNU Public License (source coming soon)

Download  (includes JAR and JAD)
                                    Beta means it may not work on your phone or worse, may break your phone. Install and use at your own risk.

Tested on:            Nokia E70
Issues:                  J2ME drains the batteries. Looking for ways around it, or a more efficient platform.

Jun 07

Convert Date to String in Java

Just an example on how “java.text.SimpleDateFormat” can be used to convert a java date object (java.util.Date) to a string (String, StringBuffer, StringBuilder, etc..).
The whole magic is done by SimpleDateFormat, the child of “java.text.DateFormat”, which, as its name suggests, formats the date by a provided template.

This template is very flexible and provided to the formatter as a string. Here are the values which are used by SimpleDateFormat’s template:


Date or Time Component




Era designator






1996; 96


Month in year


July; Jul; 07


Week in year




Week in month




Day in year




Day in month




Day of week in month




Day in week


Tuesday; Tue


Am/pm marker




Hour in day (0-23)




Hour in day (1-24)




Hour in am/pm (0-11)




Hour in am/pm (1-12)




Minute in hour




Second in minute








Time zone

General time zone

Pacific Standard Time; PST; GMT-08:00


Time zone

RFC 822 time zone


Below, I wrote an example on how to implement the conversion. Here I used two different templates: “yyyyMMdd” and “MMddyyyy” to show that several letters from the table above can be used in different sequence for the desired format:

import java.util.Date;
import java.text.SimpleDateFormat;
... ... ... ...
    public void testConvertDateToString()    {
        //   Allocates a Date object and initializes it so that it represents the time
        // at which it was allocated, measured to the nearest millisecond.
        Date dateNow = new Date ();
        SimpleDateFormat dateformatYYYYMMDD = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat dateformatMMDDYYYY = new SimpleDateFormat("MMddyyyy");
        StringBuilder nowYYYYMMDD = new StringBuilder( dateformatYYYYMMDD.format( dateNow ) );
        StringBuilder nowMMDDYYYY = new StringBuilder( dateformatMMDDYYYY.format( dateNow ) );
        System.out.println( "DEBUG: Today in YYYYMMDD: '" + nowYYYYMMDD + "'");
        System.out.println( "DEBUG: Today in MMDDYYYY: '" + nowMMDDYYYY + "'");


DEBUG: Today in YYYYMMDD: ‘20070609’
DEBUG: Today in MMDDYYYY: ‘06092007’

You may also notice that in the example I used StringBuilder, and not String or StringBuffer. The reason is simple – “best practice – use the right tool for the right task”.

“String” is immutable, meaning it cannot be changed, every time you try to change it, new String object is created and the old one is released for garbage collection, therefore String can be perfect for something like constants e.g. { private static final String FORTY_TWO = “42”; }.

StringBuilder and StringBuffer can be changed (modified), and, in fact, they have exactly the same functionality with one distinct difference – StringBuffer is synchronized and StringBuilder is not. Therefore if the segment of code we are working on is not designed to be multi threaded (used by different threads in a same time), it is better to use StringBuilder, since it will work faster.

StringBuilder is available in Java 1.5.0 (Java 2 SE 5.0) and up.

KISS – Keep It Simple Stupid 😉