My blog has moved!

You should automatically be redirected in 6 seconds. If not, visit
http://blogs.i2m.dk/allan
and update your bookmarks.

Monday, 16 March 2009

Sending files through action listeners

For this weeks JSF tip, I’ll show you how to send binary data (such as a file) to the user by way of an action handler or listener.

Say, you want to generate a custom PDF and send it to the user as he clicks a link. You need a JSF page, and a backing bean.

Your JSF page may look like this:


<h:form>
<h:commandLink id="lnkDownload"
actionListener="#{myBean.onDownload}"
target="_blank"
value="Download PDF" />
</h:form>



Your JSF backing bean may look like this:

public MyBean {

public void onDownload(ActionEvent event) {
try {
// here you need to get the byte[] representation of
// the file you want to send
byte[] binary_data = ;
String filename = "generated_file.pdf”;
FacesContext fctx = FacesContext.getCurrentInstance();
ExternalContext ectx = fctx.getExternalContext();

HttpServletResponse response = (HttpServletResponse) ectx.getResponse();
response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
response.setHeader("Content-Transfer-Encoding", "Binary");
response.setHeader("Pragma", "private");
response.setHeader("cache-control", "private, must-revalidate");

ServletOutputStream outs = response.getOutputStream();
outs.write(binary_data);
outs.flush();
outs.close();
response.flushBuffer();

fctx.responseComplete();
} catch (IOException ex) {
ex.printStackTrace();
}
}


That’s it for today.

P.S. alternatively you can use this component which is less code intensive: http://kenai.com/projects/scales/pages/Download

Monday, 9 March 2009

JSF and I18N

It has been a busy year so far. Every year I start out thinking that I really need to relax because the previous year was too hectic, but every year it ends up being much more hectic. Anyway, I thought I’d post a JSF quick time that might shave some headache for people developing internationalised applications.

Most JSF developers are aware of the resource-bundle tag in faces-config. Using this tag you can specify a resource bundle that should be available to all your pages using a given variable. For example, the code below will make a variable, msgs, available in all your pages without having to use the loadBundle tag.


<faces-config version="1.2">
...
<application>
<resource-bundle>
<base-name>my.class.path.Messages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
...
</faces-config>


So, say that Messages.properties contains the following:


HELLO_WHAT_IS_YOUR_NAME=Hello, what’s your name?


you can from any page reference this text by writing:


<h:outputText value=”#{mgs.HELLO_WHAT_IS_YOUR_NAME}” />

or

<h:outputText value=”#{mgs[‘HELLO_WHAT_IS_YOUR_NAME’]}” />


I prefer the former as my favourite IDE (NetBeans) support code completion for all the messages in a managed resource bundle.

So far so good. But what if you want to do something a bit more advanced, such as outputting “Hello Allan, welcome to my site. Your last visit was 7. February 2009 at 10:45”. You are not limited to static text in your resource bundle. You can provide placeholders for content that will be replaced at run-time. Let’s have a look at the Message.properties:


WELCOME_MESSAGE=Hello {0}, welcome to my site. Your last visit was {1,date,long} at {1,time,short}


You’ll notice that the message is parameterised using two parameters. The first parameter we are expecting a string containing the name of the user, the second parameter is a java.util.Date containing both the date and time when user last visited the site. Notice that I’ve reused the second paramenter ({1}), one time for the date and the other for the time. On your JSF page you would use the message as follows (imaging that you have a bean called welcome containing a property for getting the name of the user and last visit):


<h:outputFormat value=”#{msgs.WELCOME_MESSAGE}”>
<f:param value=”#{welcome.userName}” />
<f:param value=”#{welcome.lastVisit}” />
</h:outputFormat>


Pretty neat, eh?

What about the classical case of singular and plural messages? Imagine that you want to display the number of records in a table “There are 10 records in the table”. If the Message.properties contained:


RECORDS_IN_TABLE=There are {0} records in the table


You’d end up an embarrassing problem if there was only one record in the table:

“There are 1 records in the table” (This sentence is grammatical incorrect)

Instead you would want it to output:

“There is 1 record in the table”

To do this, you have to use the choice pattern:


RECORDS_IN_TABLE=There {0, choice, 0#are|1#is|2#are} {0} {0, choice, 0#records|1#record|2#records}


The format might look a bit awkward, but once you have understood the pattern it is simple:


{0,choicemeans, taking the first parameter and base the output on a choice of formats
0#areif the first parameter contains 0 (or below), then it should print “are”
|1#isor, if the first parameter contain 1, then it should print “is”
|2#are}or, if the first parameter contains 2 (or above), then it should print “are”


Now, that is nice! So let’s examine the output of these examples:


<h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”>
<f:param value=”#{0}” />
</h:outputFormat>
There are 0 records in the table

<h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”>
<f:param value=”#{1}” />
</h:outputFormat>
There is 1 record in the table

<h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”>
<f:param value=”#{2}” />
</h:outputFormat>
There are 2 records in the table

<h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”>
<f:param value=”#{10}” />
</h:outputFormat>
There are 10 records in the table


Enjoy!