<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6133363959081933104</id><updated>2011-11-28T00:21:06.935+01:00</updated><category term='Mobile'/><category term='Enterprise'/><category term='JPA'/><category term='Software Engineering'/><category term='Certification'/><category term='Travel'/><category term='Linux'/><category term='Conference'/><category term='Review'/><category term='Solaris'/><category term='Quick tip'/><category term='JSF'/><category term='Book'/><category term='Java'/><category term='NetBeans'/><category term='Useless drivel'/><title type='text'>Big Al's Blog</title><subtitle type='html'>The blog has moved to http://blogs.i2m.dk/allan</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>35</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-6652555645565024154</id><published>2009-03-16T14:44:00.004+01:00</published><updated>2009-03-16T14:51:23.499+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Quick tip'/><title type='text'>Sending files through action listeners</title><content type='html'>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. &lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;Your JSF page may look like this:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;h:form&amp;gt;&lt;br /&gt;    &amp;lt;h:commandLink id="lnkDownload"&lt;br /&gt;                   actionListener="#{myBean.onDownload}"&lt;br /&gt;                   target="_blank"&lt;br /&gt;                   value="Download PDF"  /&amp;gt;&lt;br /&gt;&amp;lt;/h:form&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Your JSF backing bean may look like this:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public MyBean {&lt;br /&gt;&lt;br /&gt;    public void onDownload(ActionEvent event) {&lt;br /&gt;         try {&lt;br /&gt;            // here you need to get the byte[] representation of &lt;br /&gt;            // the file you want to send&lt;br /&gt;            byte[] binary_data = ;&lt;br /&gt;            String filename = "generated_file.pdf”;&lt;br /&gt;            FacesContext fctx = FacesContext.getCurrentInstance();   &lt;br /&gt;            ExternalContext ectx = fctx.getExternalContext();&lt;br /&gt;            &lt;br /&gt;            HttpServletResponse response = (HttpServletResponse) ectx.getResponse();&lt;br /&gt;            response.setHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");&lt;br /&gt;            response.setHeader("Content-Transfer-Encoding", "Binary");&lt;br /&gt;            response.setHeader("Pragma", "private");&lt;br /&gt;            response.setHeader("cache-control", "private, must-revalidate");&lt;br /&gt;        &lt;br /&gt;            ServletOutputStream outs = response.getOutputStream();&lt;br /&gt;            outs.write(binary_data);&lt;br /&gt;            outs.flush();&lt;br /&gt;            outs.close();&lt;br /&gt;            response.flushBuffer();&lt;br /&gt;            &lt;br /&gt;            fctx.responseComplete();&lt;br /&gt;        } catch (IOException ex) {&lt;br /&gt;            ex.printStackTrace();&lt;br /&gt;        }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That’s it for today.&lt;br /&gt;&lt;br /&gt;P.S. alternatively you can use this component which is less code intensive: &lt;a target="_blank" href="http://kenai.com/projects/scales/pages/Download"&gt;http://kenai.com/projects/scales/pages/Download&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-6652555645565024154?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/6652555645565024154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=6652555645565024154' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/6652555645565024154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/6652555645565024154'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2009/03/sending-files-through-action-listeners.html' title='Sending files through action listeners'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-5073175996568706445</id><published>2009-03-09T21:35:00.003+01:00</published><updated>2009-03-09T22:40:40.611+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Quick tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Useless drivel'/><title type='text'>JSF and I18N</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;faces-config version="1.2"&amp;gt;&lt;br /&gt;...&lt;br /&gt;    &amp;lt;application&amp;gt;&lt;br /&gt;        &amp;lt;resource-bundle&amp;gt;&lt;br /&gt;            &amp;lt;base-name&amp;gt;my.class.path.Messages&amp;lt;/base-name&amp;gt;&lt;br /&gt;            &amp;lt;var&amp;gt;msgs&amp;lt;/var&amp;gt;&lt;br /&gt;        &amp;lt;/resource-bundle&amp;gt;&lt;br /&gt;    &amp;lt;/application&amp;gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;/faces-config&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, say that Messages.properties contains the following:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;HELLO_WHAT_IS_YOUR_NAME=Hello, what’s your name?&lt;br /&gt; &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;you can from any page reference this text by writing:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;h:outputText value=”#{mgs.HELLO_WHAT_IS_YOUR_NAME}” /&amp;gt; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;or&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;h:outputText value=”#{mgs[‘HELLO_WHAT_IS_YOUR_NAME’]}” /&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I prefer the former as my favourite IDE (NetBeans) support code completion for all the messages in a managed resource bundle.&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;WELCOME_MESSAGE=Hello {0}, welcome to my site. Your last visit was {1,date,long} at {1,time,short}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;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):&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;h:outputFormat value=”#{msgs.WELCOME_MESSAGE}”&amp;gt;&lt;br /&gt;    &amp;lt;f:param value=”#{welcome.userName}” /&amp;gt;&lt;br /&gt;    &amp;lt;f:param value=”#{welcome.lastVisit}” /&amp;gt;&lt;br /&gt;&amp;lt;/h:outputFormat&amp;gt;    &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Pretty neat, eh?&lt;br /&gt;&lt;br /&gt;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:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;RECORDS_IN_TABLE=There are {0} records in the table&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;You’d end up an embarrassing problem if there was only one record in the table:&lt;br /&gt;&lt;br /&gt;“There are 1 records in the table” (This sentence is grammatical incorrect)&lt;br /&gt;&lt;br /&gt;Instead you would want it to output:&lt;br /&gt;&lt;br /&gt;“There is 1 record in the table”&lt;br /&gt;&lt;br /&gt;To do this, you have to use the choice pattern:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;RECORDS_IN_TABLE=There {0, choice, 0#are|1#is|2#are} {0} {0, choice, 0#records|1#record|2#records}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The format might look a bit awkward, but once you have understood the pattern it is simple:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;{0,choice&lt;/td&gt;&lt;td&gt;means, taking the first parameter and base the output on a choice of formats&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;0#are&lt;/td&gt;&lt;td&gt;if the first parameter contains 0 (or below), then it should print “are”&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;|1#is&lt;/td&gt;&lt;td&gt;or, if the first parameter contain 1, then it should print “is”&lt;/td&gt;&lt;/tr&gt;&lt;br /&gt;&lt;tr&gt;&lt;td&gt;|2#are}&lt;/td&gt;&lt;td&gt;or, if the first parameter contains 2 (or above), then it should print “are”&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Now, that is nice! So let’s examine the output of these examples:&lt;br /&gt;&lt;br /&gt;&lt;table&gt;&lt;tr&gt;&lt;td&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”&amp;gt;&lt;br /&gt;    &amp;lt;f:param value=”#{0}” /&amp;gt;&lt;br /&gt;&amp;lt;/h:outputFormat&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;There are 0 records in the table&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”&amp;gt;&lt;br /&gt;    &amp;lt;f:param value=”#{1}” /&amp;gt;&lt;br /&gt;&amp;lt;/h:outputFormat&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;There is 1 record in the table&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”&amp;gt;&lt;br /&gt;    &amp;lt;f:param value=”#{2}” /&amp;gt;&lt;br /&gt;&amp;lt;/h:outputFormat&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;There are 2 records in the table&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;h:outputFormat value=”#{msgs.RECORDS_IN_TABLE}”&amp;gt;&lt;br /&gt;    &amp;lt;f:param value=”#{10}” /&amp;gt;&lt;br /&gt;&amp;lt;/h:outputFormat&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td&gt;There are 10 records in the table&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-5073175996568706445?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/5073175996568706445/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=5073175996568706445' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/5073175996568706445'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/5073175996568706445'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2009/03/jsf-and-i18n.html' title='JSF and I18N'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-1458792445163341446</id><published>2009-02-02T10:45:00.003+01:00</published><updated>2009-02-02T11:15:38.781+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Review'/><category scheme='http://www.blogger.com/atom/ns#' term='Book'/><title type='text'>Review: Getting Real -- The smarter, faster, easier way to build a successful web application</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__SeQT33Fv3E/SYbHugbBtPI/AAAAAAAADJ8/ktfGh6B9ILE/s1600-h/320_383343.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;width: 215px; height: 322px;" src="http://4.bp.blogspot.com/__SeQT33Fv3E/SYbHugbBtPI/AAAAAAAADJ8/ktfGh6B9ILE/s400/320_383343.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5298141613439169778" /&gt;&lt;/a&gt;&lt;br /&gt;Since mid last week I've been down with a terrible flu. It has been so bad that I haven't been able to look at the computer screen (imagine that!!). To pass time I picked up a &lt;a href="http://www.lulu.com/content/383343" target="_blank"&gt;book that I picked up from Lulu.com&lt;/a&gt; a few months ago called "&lt;a target="_blank" href="http://gettingreal.37signals.com/"&gt;Getting Real -- The smarter, faster, easier way to build a successful web application&lt;/a&gt;". The authors behind the book are the developers behind 37signals (probably most known for developing the Ruby on Rails framework). The contents of the book is actually freely available from their website, but since I'm spending more and more time away from the computer these days I decided to buy a paper copy.&lt;br /&gt;&lt;br /&gt;I absolutely loved the book. I knew that I would love the book when I read part of the disclaimer: "&lt;em&gt;If our tone seems too known-it-allish, bear with us. We think it's better to present ideas in bold strokes than to be wishy-washy about it. If that comes off as cocky or arrogant, so be it. We'd rather be provocative than water every down with "it depends..."&lt;/em&gt;". It is so refreshing to read something that is written with confidence and not some generic advice that can mean everything and nothing.&lt;br /&gt;&lt;br /&gt;The book takes you through the stages of launching a web application from staffing, to interface design, to pricing and post-launch activities. Each chapter deals with a specific stage of the launch and provide easy-to-read, snappy, no bull advices on how to go about the given stage.  Although I don't agree with everything in the book it is very enlighting, refreshing and entertaining.  It reminds me a lot about the book &lt;a target="_blank" href="http://www.amazon.com/How-Become-CEO-Rising-Organization/dp/0786864370"&gt;"How to become a CEO- The Rules for Rising to the Top of Any Organization" by Jeffrey J Fox&lt;/a&gt;, which I can recommend for a quick entertaining read.&lt;br /&gt;&lt;br /&gt;It's a must read for everything developing web applications. I'll give this book &lt;b&gt;five stars out of five&lt;/b&gt;!!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-1458792445163341446?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/1458792445163341446/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=1458792445163341446' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/1458792445163341446'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/1458792445163341446'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2009/02/review-getting-real-smarter-faster.html' title='Review: Getting Real -- The smarter, faster, easier way to build a successful web application'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/__SeQT33Fv3E/SYbHugbBtPI/AAAAAAAADJ8/ktfGh6B9ILE/s72-c/320_383343.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-8246874256822126365</id><published>2009-01-08T17:25:00.003+01:00</published><updated>2009-01-08T17:40:27.596+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Useless drivel'/><title type='text'>Another big shot goes bust</title><content type='html'>Another big shot goes bust! This time it's the Indian IT "giant" Satyam (&lt;a href="http://www.computing.co.uk/vnunet/news/2233443/satyam-chairman-admits-seven"&gt;http://www.computing.co.uk/vnunet/news/2233443/satyam-chairman-admits-seven&lt;/a&gt;). This is not long after the Danish company; IT Factory, pulled a similar stunt (&lt;a href="http://politiken.dk/newsinenglish/article605506.ece"&gt;http://politiken.dk/newsinenglish/article605506.ece&lt;/a&gt;). I'm starting to think that when all things are going well, it's just an illusion with a few puppet masters pulling all the strings.  However, I just can't believe that in both cases it is claimed that the auditors and board didn't have any knowledge of the wrong doings. If this is true then we must be talking about the dumbest people in the world.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-8246874256822126365?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/8246874256822126365/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=8246874256822126365' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/8246874256822126365'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/8246874256822126365'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2009/01/another-big-shot-goes-bust.html' title='Another big shot goes bust'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-3619789836537071519</id><published>2009-01-02T01:50:00.004+01:00</published><updated>2009-01-02T02:08:50.926+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Certification'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Christmas present from Sun</title><content type='html'>Just as the year was ended I got a great Christmas present from Sun Microsystems.&lt;br /&gt;&lt;br /&gt;1) A cool NetBeans 10 year anniversary T-shirt for participating in the community acceptance test programme for NetBeans 6.5 (NetCAT)&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__SeQT33Fv3E/SV1mp3aDBII/AAAAAAAAC9E/o40HtfR2ii8/s1600-h/nb_65_tshirt.gif"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 188px;" src="http://2.bp.blogspot.com/__SeQT33Fv3E/SV1mp3aDBII/AAAAAAAAC9E/o40HtfR2ii8/s400/nb_65_tshirt.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5286494407036699778" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2) A pass on my exam to become Sun Certified Specialist for NetBeans IDE&lt;br /&gt;&lt;br /&gt;The exam was special to me as it was my first ever certification exam. My score was 82%, with the least score in questions about building Java SE applications. I guess it shows that I've never build Java SE applications on NetBeans. Otherwise I think the exam was great. Studying for the exam revealed a lot of useful features that I had never used before, but now wondering how I could ever live without. I can highly recommend doing the exam!&lt;br /&gt;&lt;br /&gt;Thanks Sun!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-3619789836537071519?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/3619789836537071519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=3619789836537071519' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3619789836537071519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3619789836537071519'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2009/01/christmas-present-from-sun.html' title='Christmas present from Sun'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/__SeQT33Fv3E/SV1mp3aDBII/AAAAAAAAC9E/o40HtfR2ii8/s72-c/nb_65_tshirt.gif' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-880287370991710804</id><published>2008-12-31T02:16:00.005+01:00</published><updated>2008-12-31T02:26:58.259+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Linux'/><category scheme='http://www.blogger.com/atom/ns#' term='Quick tip'/><title type='text'>Setting JAVA_HOME on Ubuntu</title><content type='html'>A thing that always annoys me about installing Java is that it doesn't automatically set up the JAVA_HOME environment variable after installation. I guess this is to avoid having problems when you have multiple virtual machines installed. Anyway, I use Ubuntu Linux to host the majority of my Java Application Server. It is easy install Java (&lt;code&gt;sudo apt-get install sun-java6-jdk&lt;/code&gt;) but there always seems to be a debate about where to set the &lt;code&gt;JAVA_HOME&lt;/code&gt; environment variable. Some instructions say you should add it to your personal profile (e.g. &lt;code&gt;~/.bashrc&lt;/code&gt;) others suggest adding it to the global profile (i.e. &lt;code&gt;/etc/profile&lt;/code&gt;), some people even suggest adding it directly in the init script for the services that need the variable. My suggest is to add an executable shell script to &lt;code&gt;/etc/profile.d/&lt;/code&gt; called &lt;code&gt;javahome.sh&lt;/code&gt;. The content of the file would be:  &lt;code&gt;export JAVA_HOME=/usr/lib/jvm/java-6-sun&lt;/code&gt;. All shell scripts (i.e. executable files with the extension &lt;code&gt;.sh&lt;/code&gt;) located in the &lt;code&gt;/etc/profile.d/&lt;/code&gt; directory are loaded upon login and would therefore work for all users without having to change system files that may change upon the next O/S upgrade. To test the script simply type  &lt;code&gt;source /etc/profile&lt;/code&gt;  This will reload the profile for the current user. To verify that the environment variable has been initialised type &lt;code&gt;export|grep JAVA_HOME&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-880287370991710804?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/880287370991710804/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=880287370991710804' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/880287370991710804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/880287370991710804'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/12/setting-javahome-on-ubuntu.html' title='Setting JAVA_HOME on Ubuntu'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-7115337005086811904</id><published>2008-11-24T00:31:00.004+01:00</published><updated>2009-01-02T14:20:14.105+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Quick tip'/><title type='text'>Getting value expressions from f:attributes</title><content type='html'>If you have a custom converter or validator you may provide these with the option of letting developers specify attributes. For example, let's say that we are creating a converter that will allow the formatting of a &lt;code&gt;Calendar&lt;/code&gt; object. Note, that the &lt;code&gt;&amp;lt;f:convertDateTime /&amp;gt; &lt;/code&gt; is for &lt;code&gt;Date&lt;/code&gt; objects (which can be easily retrieved from a &lt;code&gt;Calendar&lt;/code&gt;, but that is beside the point). So the custom converter I'll create here is for converting/formatting &lt;code&gt;Calendar&lt;/code&gt; objects.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package com.blogspot.bigallan.converters;&lt;br /&gt;&lt;br /&gt;import java.text.*;&lt;br /&gt;import java.util.*;&lt;br /&gt;import javax.el.ValueExpression;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;import javax.faces.convert.Converter;&lt;br /&gt;&lt;br /&gt;public class CalendarConverter implements Converter {&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Not implemented as the converter is one-way only.&lt;br /&gt;     */&lt;br /&gt;    public Object getAsObject(FacesContext ctx, UIComponent component, String value) {&lt;br /&gt;        return null;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String getAsString(FacesContext ctx, UIComponent component, Object value) {&lt;br /&gt;        &lt;br /&gt;        // Get the Calendar to convert&lt;br /&gt;        Calendar calendar = (Calendar) value;&lt;br /&gt;&lt;br /&gt;        String pattern = "";&lt;br /&gt;&lt;br /&gt;        // Obtain attributes specified along with the converter&lt;br /&gt;        Map&amp;lt;String, Object&amp;gt; attributes = component.getAttributes();&lt;br /&gt;&lt;br /&gt;        // Check if the pattern attribute was specified&lt;br /&gt;        if (!attributes.containsKey("pattern")) {&lt;br /&gt;            System.out.println("pattern was not specified");&lt;br /&gt;            return "";&lt;br /&gt;        } else {&lt;br /&gt;            pattern = (String)attributes.get("pattern");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Create a DateFormatter for the pattern&lt;br /&gt;        DateFormat outputFormat = new SimpleDateFormat(pattern);&lt;br /&gt;&lt;br /&gt;        // Format the calendar&lt;br /&gt;        try {&lt;br /&gt;            Date date = originalFormat.parse(calendar.getTime());&lt;br /&gt;            return outputFormat.format(originalDate));&lt;br /&gt;        } catch (ParseException ex) {&lt;br /&gt;            ex.printStackTrace()&lt;br /&gt;     return "";&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In &lt;code&gt;faces-config.xml&lt;/code&gt; you would declare the converter like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;    &amp;lt;converter&amp;gt;&lt;br /&gt;        &amp;lt;converter-id&amp;gt;calendarConverter&amp;lt;/converter-id&amp;gt;&lt;br /&gt;        &amp;lt;converter-class&amp;gt;com.blogspot.bigallan.converters.CalendarConverter&amp;lt;/converter-class&amp;gt;&lt;br /&gt;    &amp;lt;/converter&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can now use the converter in a view:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;   &amp;lt;h:outputText value="#{myBean.calendarObject}"&amp;gt;&lt;br /&gt;       &amp;lt;f:converter converterId="calendarConverter" /&amp;gt;&lt;br /&gt;       &amp;lt;f:attribute name="pattern" value="d. MMMM yyyy" /&amp;gt;&lt;br /&gt;   &amp;lt;/h:outputText&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When the code is rendered in the browser you'll get the calendar converter to something like this &lt;em&gt;24. November 2008&lt;/em&gt;. So far so good. However, what if we didn't specify the date pattern as static text, but rather bind it to a value. This technique is efficient when you reuse the pattern in many places and want to keep the pattern in a central place. So say that we had a managed-bean called &lt;code&gt;common&lt;/code&gt; with a method &lt;code&gt;getDateFormat() : String&lt;/code&gt; that would provide the pattern. The code would look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;   &amp;lt;h:outputText value="#{myBean.calendarObject}"&amp;gt;&lt;br /&gt;       &amp;lt;f:converter converterId="calendarConverter" /&amp;gt;&lt;br /&gt;       &amp;lt;f:attribute name="pattern" value="#{common.dateFormat}" /&amp;gt;&lt;br /&gt;   &amp;lt;/h:outputText&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When the code is rendered in the browser you'll get a blank response and see the following in the log, "&lt;code&gt;pattern was not specified&lt;/code&gt;". The log statement is generated from out code above where we check for the attribute named "pattern". This is because of a requirement in the JSF 1.2 specification (JSR-252) that states (Section 9.4.2) that literal (static) text should be stored in the attribute map of the component and non-literal texts should be stored in the value expression map of the component. So to get the pattern from the value expression map we modify the &lt;code&gt;getAsString&lt;/code&gt; method as follows:  &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;    public String getAsString(FacesContext ctx, UIComponent component, Object value) {&lt;br /&gt;        &lt;br /&gt;        // Get the Calendar to convert&lt;br /&gt;        Calendar calendar = (Calendar) value;&lt;br /&gt;&lt;br /&gt;        String pattern = "";&lt;br /&gt;&lt;br /&gt;        // Obtain attributes specified along with the converter&lt;br /&gt;        Map&amp;lt;String, Object&amp;gt; attributes = component.getAttributes();&lt;br /&gt;        &lt;br /&gt;        // Check if the pattern attribute was specified&lt;br /&gt;        if (!attributes.containsKey("pattern")) {&lt;br /&gt;&lt;br /&gt;            ValueExpression ve = component.getValueExpression("pattern");&lt;br /&gt;            if (ve == null) {&lt;br /&gt;                System.out.println("pattern was not specified");&lt;br /&gt;                return "";&lt;br /&gt;            } else {&lt;br /&gt;                pattern = (String) ve.getValue(ctx.getELContext());&lt;br /&gt;            }&lt;br /&gt;        } else {&lt;br /&gt;            pattern = attributes.get("pattern");&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Create a DateFormatter for the pattern&lt;br /&gt;        DateFormat outputFormat = new SimpleDateFormat(pattern);&lt;br /&gt;&lt;br /&gt;        // Format the calendar&lt;br /&gt;        try {&lt;br /&gt;            Date date = originalFormat.parse(calendar.getTime());&lt;br /&gt;            return outputFormat.format(originalDate));&lt;br /&gt;        } catch (ParseException ex) {&lt;br /&gt;            ex.printStackTrace()&lt;br /&gt;     return "";&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The difference is that we now first check to see if there is a literal value specified. If not, we check if there is a value expression, and if there is no value expression either we will fail. If there is a value express we evaluate it and use it as our pattern.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-7115337005086811904?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/7115337005086811904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=7115337005086811904' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7115337005086811904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7115337005086811904'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/11/getting-value-expressions-in.html' title='Getting value expressions from f:attributes'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-3894725999655970568</id><published>2008-10-28T21:21:00.004+01:00</published><updated>2008-10-28T21:24:10.891+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Open Source vs. Commercial Software</title><content type='html'>Today I stumbled upon the following article about Open Source vs Commercial Software. It's quite entertaining and shows may of the pros and cons for both open source and commercial software licensing.&lt;br /&gt;&lt;br /&gt;&lt;a target="_blank" href="http://www.isitedesign.com/insight/08_07/open-source-versus-commercial-web-software.cfm"&gt;http://www.isitedesign.com/insight/08_07/open-source-versus-commercial-web-software.cfm&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-3894725999655970568?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/3894725999655970568/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=3894725999655970568' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3894725999655970568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3894725999655970568'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/10/open-source-vs-commercial-software.html' title='Open Source vs. Commercial Software'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-640220367323205468</id><published>2008-10-24T23:12:00.003+02:00</published><updated>2008-10-24T23:53:48.673+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Enterprise'/><category scheme='http://www.blogger.com/atom/ns#' term='JPA'/><title type='text'>Replacing TopLink Essentials with OpenJPA as my persistence provider</title><content type='html'>During the development of my latest pet project I decided to go head-on with many of the latest Java Enterprise APIs. One of these was the Java Persistence API (JPA), which I had already used in a handful of projects before. On previous projects the persistence requirements were very simple. I could use JPA out-of-the-box with TopLink Essentials which is the standard set-up for a JPA project in NetBeans/GlassFish. However, for this new pet project of mine I was in need of storing large binary objects (BLOBs). I was shocked to discover that TopLink Essentials doesn't support the Fetching configuration for relationships and properties. Instead it will &lt;code&gt;Fetch.EAGER&lt;/code&gt; everything in a relationship and property. This made my application crash hard (&lt;code&gt;OutOfMemoryException&lt;/code&gt;) when ever I would query for all entities containing the BLOB. So, I set out to replace the persistence provider. First I looked at Hibernate. I used Hibernate before JPA was released and never had much trouble with it. Unfortunately I found that Hibernate also doesn't support the fetching configuration (in JPA mode). That lead me to OpenJPA which really surprised me. It is well documented, clean, easy to use, and support the fetch configuration. I've now replaced the persistence provider on two projects with OpenJPA and the performance has increased significantly. However, here are a few gotchas that you have to look out for:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Auto-generated identity fields must not have a preset value in your JavaBean (hence, this would give you problems:  &lt;br /&gt;&lt;code&gt;&lt;br /&gt;@Id&lt;br /&gt;@GeneratedValue(strategy = GenerationType.IDENTITY)&lt;br /&gt;private Long id = 0L&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Instead you should write&lt;br /&gt;&lt;code&gt;&lt;br /&gt;@Id&lt;br /&gt;@GeneratedValue(strategy = GenerationType.IDENTITY)&lt;br /&gt;private Long id;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Collections are &lt;code&gt;Fetch.LAZY&lt;/code&gt; by default, so if you got an existing using TopLink Essentials, you have to double check that your relations are not throwing &lt;code&gt;LazyInitializationException&lt;/code&gt; upon fetching outside the transation.&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Remember to specify the Fetch depth (&lt;code&gt;openjpa.MaxFetchDepth&lt;/code&gt;) in &lt;code&gt;persistence.xml&lt;/code&gt; for using the &lt;code&gt;Fetch.EAGER&lt;/code&gt; configuration&lt;/li&gt;&lt;br /&gt;&lt;li&gt;TopLink Essentials compiles named queries when your application is deploy on the application server, OpenJPA on the other hand compiles the named queries upon first usage.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;When enabling SQL DDL on OpenJPA it doesn't generate foreign key constraints, unlike TopLink Essentials&lt;/li&gt; &lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;That's all for now. I'd love to hear about your experiences with OpenJPA or any other persistence provide you find suitable for your need.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-640220367323205468?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/640220367323205468/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=640220367323205468' title='14 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/640220367323205468'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/640220367323205468'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/10/replacing-toplink-essentials-with.html' title='Replacing TopLink Essentials with OpenJPA as my persistence provider'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>14</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-188787190119604953</id><published>2008-10-10T22:07:00.003+02:00</published><updated>2008-10-10T22:19:15.513+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Useless drivel'/><title type='text'>Cycling</title><content type='html'>For the past week I've been cycling to and from work. That might not sound like a big deal to you, but it has certainly been a challenge for me. In the past it has been all to easy to jump into the car and head off for work. No more, I've decided. The distance to work is very do-able, 5.5 KM each way. It's better for me and it's better for the environment. The biggest problem so far has been the uphill route on my way back. Nevertheless, I've made great progress already. The first day was absolutely hell! When I got to work I could barely breathe and I had to spend several minutes in the bike shed to compose myself. On the third day I managed to cut off 5 minutes from the ride, and today I was only plagued by fatigue in my joints. I'm looking forward to seeing how I'll be feeling on Monday and if I can take another week.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-188787190119604953?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/188787190119604953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=188787190119604953' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/188787190119604953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/188787190119604953'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/10/cycling.html' title='Cycling'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-356090438041777260</id><published>2008-10-09T20:10:00.004+02:00</published><updated>2008-10-09T20:34:30.323+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>MyFaces and Facelets - The Definitive Guide</title><content type='html'>For the past five months or so, I've had the pleasure of participating as a contributing author and editor of the recently released Apress publication, "MyFaces and Facelets - The Definitive Guide".&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.amazon.com/Definitive-Guide-Apache-MyFaces-Facelets/dp/1590597370/ref=sr_1_1?ie=UTF8&amp;s=books&amp;qid=1223575969&amp;sr=8-1"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/__SeQT33Fv3E/SO5LB9kMV4I/AAAAAAAACYE/csZkVnIQwww/s400/51SuoTS1F5L._SS500_.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5255220312266266498" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It was a great experience that I hope that I'll be able to relive in the near future on other book writing projects. What I liked about the book was the focus on the array of JSF components under the MyFaces Apache project. Most people seem to think that MyFaces is simply an implementation of the JavaServer Faces specification. &lt;a href="http://myfaces.apache.org"&gt;MyFaces&lt;/a&gt; is an umbrella project for JavaServer Faces related technologies. The most famous of the sub-projects is the &lt;a href="http://myfaces.apache.org/tomahawk/index.html"&gt;Tomahawk components&lt;/a&gt; project which provides a lot of useful JSF component that I certainly couldn't live without.&lt;br /&gt;&lt;br /&gt;The focus of the book is on technologies under the Apache MyFaces project as well as the Facelets technology. Facelets is another very important JSF technology that deserves more attention from the community. There are lots of people using Facelets, but little development is going on to make it truly professional.&lt;br /&gt;&lt;br /&gt;The book is not for newcomers to JSF, but for programmers already familiar with the basics of JSF. If you are looking to get familiar with JSF I can highly recommend &lt;a href="http://www.manning.com/mann/"&gt;JSF In Action by Kito D. Mann published by Manning&lt;/a&gt;.  &lt;br /&gt;&lt;br /&gt;Thanks to &lt;a href="http://zwadia.com/"&gt;Zubin Wadia&lt;/a&gt; and &lt;a href="http://www.jroller.com/HazemBlog/"&gt;Hazem Saleh&lt;/a&gt; for making the project a great experience!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-356090438041777260?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/356090438041777260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=356090438041777260' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/356090438041777260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/356090438041777260'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/10/myfaces-and-facelets-definitive-guide.html' title='MyFaces and Facelets - The Definitive Guide'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/__SeQT33Fv3E/SO5LB9kMV4I/AAAAAAAACYE/csZkVnIQwww/s72-c/51SuoTS1F5L._SS500_.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-208513924134922346</id><published>2008-09-01T08:01:00.004+02:00</published><updated>2008-09-01T08:23:33.041+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Travel'/><title type='text'>On the road again... (Uganda)</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__SeQT33Fv3E/SLuHr5gfXzI/AAAAAAAACX8/lAW9Jak-SYw/s1600-h/uganda.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/__SeQT33Fv3E/SLuHr5gfXzI/AAAAAAAACX8/lAW9Jak-SYw/s400/uganda.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5240931779616923442" /&gt;&lt;/a&gt; I'm on the road again again. This time I'm in Uganda. Uganda has to be one of my absolute favorite countries. I've be dropping in and out of Uganda the past nine years and even lived here for a few years. What I like about Uganda is the friendliness of the people. Ugandans have to be the friendliest people in the world! That is not to say that there are no dodgy Ugandans, but overall they are very easy people to get along with.&lt;br /&gt;&lt;br /&gt;This time I'm not travelling for the company. Instead I'm here to assess some business opportunities for the near future. You would be surprised how many IT-related business opportunities you will find in a developing economy.&lt;br /&gt;&lt;br /&gt;Anyways, just wanted to drop a post on the blog to show that I'm still alive and well. More about my trip later.&lt;br /&gt;&lt;br /&gt;By the way, if you are ever in Uganda there are two things you must try; 1) A whole deep fried tilapia from the Lake Victoria  2) Roasted pork.  Both usually come with a range of accessories such as avocado, cassava, and matoke.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-208513924134922346?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/208513924134922346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=208513924134922346' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/208513924134922346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/208513924134922346'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/09/on-road-again-uganda.html' title='On the road again... (Uganda)'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/__SeQT33Fv3E/SLuHr5gfXzI/AAAAAAAACX8/lAW9Jak-SYw/s72-c/uganda.gif' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-7529026775307601989</id><published>2008-08-06T13:39:00.003+02:00</published><updated>2008-08-06T13:42:05.048+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Project-based formatting in NetBeans 6.5</title><content type='html'>Being part of the NetBeans Community Acceptance Testing (NetCAT) Programme has definate advantages. For one, you get to try out all the new features planned and influence how they will work before being released to the general public (that is not quite true....anyone can download the daily development builds).&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__SeQT33Fv3E/SJmN5ceLJLI/AAAAAAAACOs/hKQWaiBjoNY/s1600-h/netbeans_project-based_formatting.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://4.bp.blogspot.com/__SeQT33Fv3E/SJmN5ceLJLI/AAAAAAAACOs/hKQWaiBjoNY/s400/netbeans_project-based_formatting.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5231368460202353842" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;One of the features in the upcoming NetBeans 6.5 that I'm particularly happy about is Formatting by project. In NetBeans it has always been one configuration for all projects. This is slowly changing. During NetCAT for 6.1 the "Shared Library" feature was implemented to detach library management from NetBeans and thereby making projects more portable. So, this time the brilliant guys on the NetBeans development team implemented a feature making it possible to do project-based formatting. This is a great feature when you work on many different projects with different formatting requirements. Way to go! My hope is that for the next version of NetBeans they will also have made template management project-based.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-7529026775307601989?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/7529026775307601989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=7529026775307601989' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7529026775307601989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7529026775307601989'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/08/project-based-formatting-in-netbeans-65.html' title='Project-based formatting in NetBeans 6.5'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/__SeQT33Fv3E/SJmN5ceLJLI/AAAAAAAACOs/hKQWaiBjoNY/s72-c/netbeans_project-based_formatting.png' height='72' width='72'/><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-6256482796904062915</id><published>2008-06-25T08:25:00.005+02:00</published><updated>2008-06-25T08:36:53.748+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Travel'/><title type='text'>On the road again...</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/__SeQT33Fv3E/SGHnVvdT_NI/AAAAAAAAB5w/U6lolXlVSzw/s1600-h/zambia.gif"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/__SeQT33Fv3E/SGHnVvdT_NI/AAAAAAAAB5w/U6lolXlVSzw/s400/zambia.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5215704204174425298" /&gt;&lt;/a&gt; After a lovely week back home in Denmark with my family, I am once again on the road. This time I'm in Zambia to conduct training and hand-over a system we have built for COMESA. I've been to Zambia twice before and always enjoy coming here as it is clean and people are friendly. Anyways, I still hope this will be must last trip this year as I really need to spend some time at home with my family.&lt;br /&gt;&lt;br /&gt;Note: If you are planning on going to Zambia I can highly recommend staying at the Intercontinental. At my first visit I was staying at Holiday-Inn. The food and service was excellent but the rooms were terrible!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-6256482796904062915?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/6256482796904062915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=6256482796904062915' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/6256482796904062915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/6256482796904062915'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/06/on-road-again.html' title='On the road again...'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/__SeQT33Fv3E/SGHnVvdT_NI/AAAAAAAAB5w/U6lolXlVSzw/s72-c/zambia.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-3123245753667155353</id><published>2008-06-12T20:31:00.001+02:00</published><updated>2008-06-19T20:33:53.474+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Travel'/><title type='text'>Finalised my mission in Djibouti and Kenya</title><content type='html'>Today, I finalised my mission to Djibouti and Kenya. I've still got another three days until I'm back home, but at least my work is done. While in Djibouti I carried out four days of System Administration training for the Web Portal I'm putting into place. That was followed by a one day steering committee meeting and four days workshop on Portal Management in Nairobi. It has been a very exhausting trip as I caught a food poisoning in Djibouti two days after having arrived. The food poisoning persisted until yesterday (almost a week) after which I had to go see a doctor. Fortunately, Nairobi Hospital is located just opposite the venue where I was conducting the workshop. So after having consulted a doctor and taken a few samples, I was given some medicine that would hope initially until they had time to examine my samples. So, today I got a call from the doctor explaining that I had a fungus growing in my stomach that was developing into a yest infection. I was then given some antibiotica and now feeling very fine. However, the last week was hell. Imagine having to do presentation from morning till afternoon with a constant stomach ache and having to run off to the wash room after every meal. Anyways, it is now being treated and I'm feeling much better.&lt;br /&gt;&lt;br /&gt;Besides my illness I got to talk and meet some wonderful people from around Eastern Africa. Tomorrow morning I'm off to Dubai where I'll spend one day before heading home to the family! Traveling can be very tiring and stressful when you'd rather spend time with your wife and baby.&lt;br /&gt;&lt;br /&gt;That's all for now folks.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-3123245753667155353?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/3123245753667155353/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=3123245753667155353' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3123245753667155353'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3123245753667155353'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/06/finalised-my-mission-in-djibouti-and.html' title='Finalised my mission in Djibouti and Kenya'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-6932054840533131154</id><published>2008-06-01T14:54:00.002+02:00</published><updated>2008-06-01T15:05:01.323+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Travel'/><title type='text'>Dubai is hot!!</title><content type='html'>Dubai is hot, in more than one sense. I'm currently on my way to Djibouti to finalise some work on a project. On my way I stopped in Dubai for two days as I've always been curious about the place. I was very pleasantly surprised as people were nice, the place was clean, and the city was beautiful!&lt;br /&gt;&lt;br /&gt;The real hotness though is the weather. I couldn't help laughing when I saw the sticker on the window in my hotel room.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp2.blogger.com/__SeQT33Fv3E/SEKeWY8RwAI/AAAAAAAAB5g/P_GKjkcusOs/s1600-h/31052008(020).jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/__SeQT33Fv3E/SEKeWY8RwAI/AAAAAAAAB5g/P_GKjkcusOs/s320/31052008(020).jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5206898226683297794" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;It says "WARNING - Humidity from outside may activate the fire alarm". I can testify to the hotness (between 40 and 50 degrees celcius) as I spent a whole day on the top deck of a Big Bus tour around Dubai (if you only got a day in Dubai I would strongly suggest the Big Bus Tour - it' is excellent!).&lt;br /&gt;&lt;br /&gt;Of all the places I've been I'd give it a 9 out of 10.&lt;br /&gt;&lt;br /&gt;That's all for now - I'm off to Djibouti in a few minutes.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-6932054840533131154?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/6932054840533131154/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=6932054840533131154' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/6932054840533131154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/6932054840533131154'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/06/dubai-is-hot.html' title='Dubai is hot!!'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/__SeQT33Fv3E/SEKeWY8RwAI/AAAAAAAAB5g/P_GKjkcusOs/s72-c/31052008(020).jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-4710603925937774074</id><published>2008-05-08T19:40:00.012+02:00</published><updated>2008-05-27T15:24:13.856+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Using Facelets with NetBeans 6.1 (without nbfaceletssupport)</title><content type='html'>--&lt;br /&gt;&lt;em&gt;Update 27. May 2008: You can download the Facelets NetBeans plug-in for 6.1 from: &lt;a target="_blank" href="http://project-template.googlecode.com/files/nbfaceletssupport-6.1.zip"&gt;http://project-template.googlecode.com/files/nbfaceletssupport-6.1.zip&lt;/a&gt;&lt;/em&gt;&lt;br /&gt;--&lt;br /&gt;&lt;br /&gt;I'm a fan of Facelets when it comes to templating for JSF applications. Prior to version 6.1 of NetBeans I was using the &lt;a href="https://nbfaceletssupport.dev.java.net/" target="_blank"&gt;nbfaceletssupport&lt;/a&gt; plug-in. Sure, it had its quirks, but overall it was a good plug-in. After installing NetBeans 6.1 and really got into using all the new cool features (shared libraries being the most significant) I realised that the nbfaceletssupport plug-in for NetBeans 6.0 didn't work and a fix had not yet been released at the &lt;a href="https://nbfaceletssupport.dev.java.net/" target="_blank"&gt;nbfaceletssupport project site&lt;/a&gt; (&lt;em&gt;note: Po-Ting Wu of Sun Microsystems has provided &lt;a href="  http://blogs.sun.com/poting/entry/build_and_install_facelets_support" target="_blank"&gt;instructions on how to re-compile the plug-in for NetBeans 6.1&lt;/a&gt;&lt;/em&gt;). This also happened when I switched from NetBeans 5.5.1 to 6.0, so I anticipate that this will also happen in the future. So, I thought to myself, why not use the powerful XML support already built-in NetBeans to give me what I need. What I really needed the plug-in for is code completion. So, here goes.  First I decided to drop JSP pages (&lt;code&gt;.jsp&lt;/code&gt;) for JSP documents (&lt;code&gt;.jspx&lt;/code&gt;). The difference being that &lt;code&gt;.jspx&lt;/code&gt; is pure XML and &lt;code&gt;.jsp&lt;/code&gt; is HTML.  &lt;br /&gt;&lt;br /&gt;&lt;u&gt;Facelets file as a JSP page (.xhtml)&lt;/u&gt;:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;        &amp;lt;title&gt;JSP facelets file&amp;lt;/title&amp;gt;&lt;br /&gt;    &amp;lt;/head&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;&lt;br /&gt;        &amp;lt;ui:composition template="/resources/templates/page.xhtml"&amp;gt;&lt;br /&gt;            &amp;lt;ui:define name="pageTitle"&amp;gt;This is a page title&amp;lt;/ui:define&amp;gt;&lt;br /&gt;            &amp;lt;ui:define name="pageContent"&amp;gt;This is the page content&amp;lt;/ui:define&amp;gt;&lt;br /&gt;        &amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;&lt;u&gt;Facelets file as a JSP document (.jspx)&lt;/u&gt;:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;jsp:root version="2.0" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:t="http://myfaces.apache.org/tomahawk" xmlns:c="http://java.sun.com/jstl/core" xmlns:jsfExt="http://java.sun.com/jsf/extensions/dynafaces"&amp;gt;&lt;br /&gt;    &amp;lt;ui:composition template="templates/page.xhtml"&amp;gt;&lt;br /&gt;        &amp;lt;ui:define name="pageTitle"&amp;gt;This is a page title&amp;lt;/ui:define&amp;gt;&lt;br /&gt;        &amp;lt;ui:define name="pageContent"&amp;gt;This is the page content&amp;lt;/ui:define&amp;gt;&lt;br /&gt;    &amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&amp;lt;/jsp:root&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When creating facelets file as JSP document in NetBeans you will automatically get code completion (without any third-party plug-ins).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp1.blogger.com/__SeQT33Fv3E/SDl1Qi84jYI/AAAAAAAAB5Y/YZ9Ei_sjM54/s1600-h/facelets-codecompletion.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/__SeQT33Fv3E/SDl1Qi84jYI/AAAAAAAAB5Y/YZ9Ei_sjM54/s320/facelets-codecompletion.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5204319771523845506" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;For this to work, ensure that the following configuration is set it web.xml:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;javax.faces.DEFAULT_SUFFIX&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;.jspx&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;and that the &lt;a href="http://allan.lykke.christensen.googlepages.com/facelets.tld" target="_blank"&gt;faclets tag library descriptor (TLD)&lt;/a&gt; is accessible in the classpath (eg. &lt;code&gt;/WEB-INF/tlds&lt;/code&gt;).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br/&gt;&lt;br /&gt;References:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="https://nbfaceletssupport.dev.java.net/"&gt;nbfaceletssupport Project Site&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a hreF="http://blogs.sun.com/poting/entry/build_and_install_facelets_support"&gt;Po-Ting Wu's Weblog: Build and Install Facelets Support Modules on NetBeans 6.1&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-4710603925937774074?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/4710603925937774074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=4710603925937774074' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/4710603925937774074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/4710603925937774074'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/05/using-facelets-with-netbeans-61-without.html' title='Using Facelets with NetBeans 6.1 (without nbfaceletssupport)'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/__SeQT33Fv3E/SDl1Qi84jYI/AAAAAAAAB5Y/YZ9Ei_sjM54/s72-c/facelets-codecompletion.png' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-3543864374495188295</id><published>2008-05-06T20:41:00.005+02:00</published><updated>2008-05-06T21:12:00.148+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Conference'/><category scheme='http://www.blogger.com/atom/ns#' term='Enterprise'/><title type='text'>Yearly conference at the local Danish IT Society branch</title><content type='html'>Last week I went to the yearly conference for my local &lt;a href="http://www.danskit.dk" target="_blank"&gt;Danish IT Society&lt;/a&gt; branch. The topic of the conference was Enterprise Architecture. I was a bit unsure about attending as I was expecting some obscure high-level talks that has never seen the light of day. I was pleasantly surprised! All the speakers did a great job and managed to cover the various facets (from theory, to best practice, to practice) of Enterprise Architecture. What especially caught my attention was the excellent governance and organisational re-structuring implemented at NyKredit headed by their CIO (and president of Danish IT Society) Lars Mathiesen (You can read &lt;a href="http://www.computerworld.dk/tag/Lars_Mathiesen?art" target="_blank"&gt;articles about Mathiesen on Computerworld.dk&lt;/a&gt;). From a vendor point-of-view the Vice President SOA Strategy, Ivo Totev of Software AG flew in from Germany. Last year I went for another meeting arranged by Danish IT Society with Scrum founder Jeff Sutherland. I wasn't too impressed as there was too much "going-around-the-bush" and not a clear business case for Scrum. Anyways, I didn't know what to expect from Ivo Totev's presesentation. However, I was very impressed with his presentation about the best practices of Enterprise Architecture coupled with anecdotes about what was working and not working with their clients. If you've got interest in Enterprise Architecture, Service-oriented Architecture (SOA), and Business Process Management, I suggest visiting Software AG's customer community at &lt;a href="http://communities.softwareag.com/" target="_blank"&gt;http://communities.softwareag.com/&lt;/a&gt; where you'll interesting resources such as podcasts, blogs, discussion groups and even a freely downloadable PDF version of the book "BPM Basics for Dummies".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-3543864374495188295?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/3543864374495188295/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=3543864374495188295' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3543864374495188295'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3543864374495188295'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/05/yearly-conference-at-local-danish-it.html' title='Yearly conference at the local Danish IT Society branch'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-3634484753359011674</id><published>2008-04-18T16:21:00.003+02:00</published><updated>2009-05-29T09:24:41.714+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Creating a generic error page for JSF</title><content type='html'>Sometimes using &lt;code&gt;FacesMessage&lt;/code&gt;s is not sufficient for reporting errors. For example, if you have a runtime error (invalid JSF mark-up or NullPointerExceptions) it is difficult to report them using &lt;code&gt;FacesMessage&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Creating a generic error page for JSF is similar to creating a generic error page for plain JSP applications. You'll need a configuration in web.xml to tell the servlet container to redirect errors to a given page. Then you'll need to create that page as well as a backing bean that can show you the stacktrace or error message.&lt;br /&gt;&lt;br /&gt;web.xml&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"&amp;gt;&lt;br /&gt;&lt;br /&gt;    ... markup for your web app ...&lt;br /&gt;    &lt;br /&gt;    &amp;lt;error-page&amp;gt;&lt;br /&gt;        &amp;lt;error-code&amp;gt;500&amp;lt;/error-code&amp;gt;&lt;br /&gt;        &amp;lt;location&amp;gt;/Error.jsp&amp;lt;/location&amp;gt;&lt;br /&gt;    &amp;lt;/error-page&amp;gt;&lt;br /&gt;    &lt;br /&gt;&amp;lt;/web-app&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;With that we will get the servlet container to forward any Internal Server Errors (HTTP 500) to the page Error.jsp.&lt;br /&gt;&lt;br /&gt;Okay, now we need to create a bean that will prepare the error message based on the exception that was thrown:&lt;br /&gt;&lt;br /&gt;Error.java&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package bigallan.beans;&lt;br /&gt;&lt;br /&gt;import java.io.PrintWriter;&lt;br /&gt;import java.io.StringWriter;&lt;br /&gt;import java.util.Map;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;import javax.servlet.ServletException;&lt;br /&gt;&lt;br /&gt;public class Error {&lt;br /&gt;    &lt;br /&gt;    public Error() {}&lt;br /&gt;        &lt;br /&gt;    public String getStackTrace() {&lt;br /&gt;&lt;br /&gt;        // Get the current JSF context&lt;br /&gt;        FacesContext context = FacesContext.getCurrentInstance();&lt;br /&gt;        Map requestMap = context.getExternalContext().getRequestMap();&lt;br /&gt;&lt;br /&gt;        // Fetch the exception&lt;br /&gt;        Throwable ex = (Throwable) requestMap.get("javax.servlet.error.exception");&lt;br /&gt;        &lt;br /&gt;        // Create a writer for keeping the stacktrace of the exception&lt;br /&gt;        StringWriter writer = new StringWriter();&lt;br /&gt;        PrintWriter pw = new PrintWriter(writer);&lt;br /&gt;&lt;br /&gt;        // Fill the stack trace into the write &lt;br /&gt;        fillStackTrace(ex, pw);&lt;br /&gt;        &lt;br /&gt;        return writer.toString();&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    /**&lt;br /&gt;     * Write the stack trace from an exception into a writer.&lt;br /&gt;     *&lt;br /&gt;     * @param ex&lt;br /&gt;     *         Exception for which to get the stack trace&lt;br /&gt;     * @param pw&lt;br /&gt;     *         PrintWriter to write the stack trace&lt;br /&gt;     */&lt;br /&gt;    private void fillStackTrace(Throwable ex, PrintWriter pw) {&lt;br /&gt;        if (null == ex) {&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;        &lt;br /&gt;        ex.printStackTrace(pw);&lt;br /&gt;       &lt;br /&gt;        // The first time fillStackTrace is called it will always be a ServletException&lt;br /&gt;        if (ex instanceof ServletException) {&lt;br /&gt;            Throwable cause = ((ServletException) ex).getRootCause();&lt;br /&gt;            &lt;br /&gt;            if (null != cause) {&lt;br /&gt;                pw.println("Root Cause:");&lt;br /&gt;                fillStackTrace(cause, pw);&lt;br /&gt;            }&lt;br /&gt;        } else {&lt;br /&gt;            // Embedded cause inside the ServletException&lt;br /&gt;            Throwable cause = ex.getCause();&lt;br /&gt;            &lt;br /&gt;            if (null != cause) {&lt;br /&gt;                pw.println("Cause:");&lt;br /&gt;                fillStackTrace(cause, pw);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now that we have the Backing Bean we need to register it in faces-config.xml:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;.. usual faces-config stuff ..&lt;br /&gt;&lt;br /&gt;    &amp;lt;managed-bean&amp;gt;&lt;br /&gt;        &amp;lt;managed-bean-name&gt;Error&amp;lt;/managed-bean-name&amp;gt;&lt;br /&gt;        &amp;lt;managed-bean-class&gt;bigallan.beans.Error&amp;lt;/managed-bean-class&amp;gt;&lt;br /&gt;        &amp;lt;managed-bean-scope&gt;request&amp;lt;/managed-bean-scope&amp;gt;&lt;br /&gt;    &amp;lt;/managed-bean&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And lastly the JSP page (Error.jsp) displaying the error:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;.. usual JSP header stuff ..&lt;br /&gt;&lt;br /&gt;&amp;lt;h:panelGrid&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText value="The follow error occured:" /&gt;&lt;br /&gt;    &amp;lt;h:inputTextarea style="width: 100%;" rows="20" readonly="true" value="#{Error.stackTrace}" /&amp;gt;&lt;br /&gt;&amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's all!&lt;br /&gt;&lt;br /&gt;Enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-3634484753359011674?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/3634484753359011674/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=3634484753359011674' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3634484753359011674'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3634484753359011674'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/04/creating-generic-error-page-for-jsf.html' title='Creating a generic error page for JSF'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-2979762938245524213</id><published>2008-04-02T11:46:00.004+02:00</published><updated>2008-04-13T23:53:18.023+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Useless drivel'/><title type='text'>Tomato juice on airplanes</title><content type='html'>I've just returned from a two week business trip and there is something that just keeps puzzling me when I fly. The amount of people that drink tomato juice on airplanes just amazes me. I have never dined with anyone who ordered tomato juice neither I have ever tasted it. However, on airplanes it seems like people have the urge to drink tomato juice. Flying back from Uganda (via Nairobi) to Amsterdam, an 8+ hours journey my co-passenger only had tomato juice! Tomorrow I've got to go buy myself some tomato juice to see what the craze is all about.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-2979762938245524213?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/2979762938245524213/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=2979762938245524213' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/2979762938245524213'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/2979762938245524213'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/04/tomato-juice-on-airplanes.html' title='Tomato juice on airplanes'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-1989093985879820953</id><published>2008-03-29T21:34:00.003+01:00</published><updated>2008-03-29T22:01:51.231+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Mobile'/><title type='text'>Using my Nokia 6120 for presentations</title><content type='html'>&lt;a href="http://bp1.blogger.com/__SeQT33Fv3E/R-6qCvwTupI/AAAAAAAABw0/klBjRifv5CE/s1600-h/nokiawirelesspresenter1.jpg"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/__SeQT33Fv3E/R-6qCvwTupI/AAAAAAAABw0/klBjRifv5CE/s400/nokiawirelesspresenter1.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5183267185305565842" /&gt;&lt;/a&gt; Today I noticed a cool feature of my new Nokia 6120 mobile phone. From it's download menu I was able to download a presentation tool from Nokia that turns the phone into a remote control for my PC. I've been thinking about getting a separate presentation device as I do a fair share of presentations and hate having to walk back to my PC everytime I want to move to the next slide. So, the way it works is by having a java application on the phone that emulates the mouse and an application on the PC that turns the keypresses on the phone into mouse movesments on the PC. I've tried it out with PowerPoint and works great. The tool also supports other applications out of the box such as Winamp and Media Player. The desktop tool can futhermore configure the remote control for other programs as well by specifying what should happen when each individual key on the phone is pressed.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp1.blogger.com/__SeQT33Fv3E/R-6t1vwTuqI/AAAAAAAABw8/nqG3OwdDt7k/s1600-h/nokiawirelesspresenter2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/__SeQT33Fv3E/R-6t1vwTuqI/AAAAAAAABw8/nqG3OwdDt7k/s320/nokiawirelesspresenter2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5183271360013777570" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The application (containing both the desktop application and the Java ME application) can be downloaded from the Nokia Community Portal: Mosh.&lt;br /&gt;&lt;br /&gt;Links:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Nokia Wireless Presenter&lt;br/&gt;&lt;a href="http://mosh.nokia.com/content/379183464B5803F5E040050AEE044DC0" target="_blank"&gt;http://mosh.nokia.com/content/379183464B5803F5E040050AEE044DC0&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Nokia MOSH&lt;br/&gt;&lt;a href="http://mosh.nokia.com/" target="_blank"&gt;http://mosh.nokia.com/&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-1989093985879820953?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/1989093985879820953/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=1989093985879820953' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/1989093985879820953'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/1989093985879820953'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/03/using-my-nokia-6120-for-presentations.html' title='Using my Nokia 6120 for presentations'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/__SeQT33Fv3E/R-6qCvwTupI/AAAAAAAABw0/klBjRifv5CE/s72-c/nokiawirelesspresenter1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-8694710046326137083</id><published>2008-03-19T01:18:00.003+01:00</published><updated>2008-03-19T02:14:28.583+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Shared libraries finally made it to NetBeans</title><content type='html'>Today I installed NetBeans 6.1 beta. I've always been a great fan of NetBeans and participated in the Community Acceptance Testing programme (NetCAT) for version 4.0 and 6.0.&lt;br /&gt;&lt;br /&gt;I haven't had time to go through all the changes yet, but one thing caught my attention immediately, the "Shared Library" functionality. It has always amazed me that this feature was not implemented way sooner. I have never used the built-in library manager for third-party libraries as the information about the libraries were not included with the projects, i.e. when I create a third-party library in the Library manager for say Apache Commons Configuration and use that in my project, it will break the built for not only other developers by also my continuous integration server. The alternative is to simply add the third-party library directly to the project as jars. The downside about that is that you can't attach the source and JavaDocs, so the inline code completion becomes almost useless. A third alternative is to manage dependencies completely outside of the IDE using Ant and Maven build scripts. I use to do this when using Eclipse, however then you have to update the dependencies in both the IDE and the build script = twice the work.&lt;br /&gt;&lt;br /&gt;Back to NetBeans 6.1. When creating a project you now get the offer to enable "sharable libraries". When enabling this feature you are asked to specify the location where the libraries should be saved. By default it will suggest &lt;code&gt;..\libraries&lt;/code&gt;, which is a bit strange considering that it is outside the project folder. I guess it depends on the configuration management practices used on the project. Personally I always check in third-party libraries (as long as there are no licensing issues preventing it). In that way I alaways know that I can build the software anywhere on any machine (that includes my CI box).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp3.blogger.com/__SeQT33Fv3E/R-BoH1huhEI/AAAAAAAABws/-s2X_0mO8L0/s1600-h/Screen+2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/__SeQT33Fv3E/R-BoH1huhEI/AAAAAAAABws/-s2X_0mO8L0/s400/Screen+2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5179254055312983106" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;After having enabled sharable libraries, NetBeans will automatically copy library to the specified folder when you add dependencies to your project. Furthermore, if you find out that you'd rather have your sharable libraries in a different location, you can simply change the location click "Save" and it will re-create the sharable libraries. Very neat!&lt;br /&gt;&lt;br /&gt;I can imagine that they will continue working on the feature at NetBeans and this feature will become even better before the next release.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-8694710046326137083?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/8694710046326137083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=8694710046326137083' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/8694710046326137083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/8694710046326137083'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/03/shared-libraries-finally-made-it-to.html' title='Shared libraries finally made it to NetBeans'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp3.blogger.com/__SeQT33Fv3E/R-BoH1huhEI/AAAAAAAABws/-s2X_0mO8L0/s72-c/Screen+2.png' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-8502629907781655235</id><published>2008-03-18T12:15:00.003+01:00</published><updated>2008-03-18T12:18:23.767+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><title type='text'>Example of using custom facelet tags</title><content type='html'>Rather than using includes when creating templates you can create your own custom facelet tags without the husle of creating a JSF component from scratch. As an example, I'll create a menu tag that can be used to switch a selected menu item on and off.&lt;br /&gt;&lt;br /&gt;Here is the menu (save it as &lt;code&gt;/WEB-INF/facelets/tags/menu.xhtml&lt;/code&gt;):&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;ui:composition xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"&amp;gt;&lt;br /&gt;&amp;lt;h:panelGrid columns="10"&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText styleClass="menuItem" value="Home" /&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText styleClass="menuItem" value="Some page" /&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText styleClass="menuItem" value="Another page" /&amp;gt;&lt;br /&gt;    &amp;lt;h:outputText styleClass="menuItem" value="Third page" /&amp;gt;&lt;br /&gt;&amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here is the cascanding style sheet:&lt;br /&gt;&lt;pre name="code" class="css"&gt;&lt;br /&gt;.menuItem {&lt;br /&gt;    border: 1px solid black;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;.menuItemSelected {&lt;br /&gt;    background: red;&lt;br /&gt;    color: white;&lt;br /&gt;    font-weight: bold;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To make the menu into a tag you create a facelets tag library. I'll call it &lt;code&gt;mytags.taglib.xml&lt;/code&gt; and place it in &lt;code&gt;/WEB-INF/facelets/&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&gt;&lt;br /&gt;&amp;lt;!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd"&gt;&lt;br /&gt;&amp;lt;facelet-taglib&amp;gt;&lt;br /&gt;    &amp;lt;namespace&gt;http://bigallan.blogspot.com/mytags&lt;/namespace&gt;&lt;br /&gt;    &amp;lt;tag&gt;&lt;br /&gt;        &amp;lt;tag-name&amp;gt;menu&amp;lt;/tag-name&amp;gt;&lt;br /&gt;        &amp;lt;source&amp;gt;tags/menu.xhtml&amp;lt;/source&amp;gt;&lt;br /&gt;    &amp;lt;/tag&amp;gt;&lt;br /&gt;&amp;lt;/facelet-taglib&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To make the web application recognise your tag library you need to update add the following context parameter to &lt;code&gt;web.xml&lt;/code&gt;:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;facelets.LIBRARIES&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;/WEB-INF/facelets/mytags.taglib.xml&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;If you have more than one custom tag library you can separate them with semicolons (;)&lt;br /&gt;&lt;br /&gt;On your pages you can now include the menu tag:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version='1.0' encoding='UTF-8' ?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:mytags="http://bigallan.blogspot.com/mytags"&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;    &amp;lt;title&amp;gt;My page&amp;lt;/title&amp;gt;&lt;br /&gt;    &amp;lt;link href="css/styles.css" rel="stylesheet" type="text/css" /&amp;gt;&lt;br /&gt;    &amp;lt;/head&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;        &amp;lt;mytags:menu home="true" /&amp;gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;All we need to do now is to look out for the attributes of the custom tag. Attributes are automatically turned into variables on the tag pages, so we simply make the following changes to &lt;code&gt;/WEB-INF/facelets/tags/menu.xhtml&lt;/code&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;ui:composition xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"&amp;gt;&lt;br /&gt;    &amp;lt;h:panelGrid columns="10"&amp;gt;&lt;br /&gt;        &amp;lt;h:outputText styleClass="menuItem #{home == 'true' ? 'menuItemSelected' : ''}" value="Home" /&amp;gt;&lt;br /&gt;        &amp;lt;h:outputText styleClass="menuItem #{somePage == 'true' ? 'menuItemSelected' : ''}" value="Some page" /&amp;gt;&lt;br /&gt;        &amp;lt;h:outputText styleClass="menuItem #{anotherPage == 'true' ? 'menuItemSelected' : ''}" value="Another page" /&amp;gt;&lt;br /&gt;        &amp;lt;h:outputText styleClass="menuItem #{thirdPage == 'true' ? 'menuItemSelected' : ''}" value="Third page" /&amp;gt;&lt;br /&gt;    &amp;lt;/h:panelGrid&amp;gt;&lt;br /&gt;&amp;lt;/ui:composition&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;To turn all menu items on you code do the following:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version='1.0' encoding='UTF-8' ?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:mytags="http://bigallan.blogspot.com/mytags"&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;    &amp;lt;title&amp;gt;My page&amp;lt;/title&amp;gt;&lt;br /&gt;    &amp;lt;link href="css/styles.css" rel="stylesheet" type="text/css" /&amp;gt;&lt;br /&gt;    &amp;lt;/head&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;        &amp;lt;mytags:menu home="true" somePage="true" anotherPage="true" thirdPage="true" /&amp;gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;Suggested reading on the subject: &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.ibm.com/developerworks/java/library/j-facelets/" target="_new"&gt;Facelets fits JSF like a glove&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="https://facelets.dev.java.net/nonav/docs/dev/docbook.html" target="_new"&gt;Facelets Developer Documentation&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-8502629907781655235?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/8502629907781655235/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=8502629907781655235' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/8502629907781655235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/8502629907781655235'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/03/example-of-using-custom-facelet-tags.html' title='Example of using custom facelet tags'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-7672170583075369434</id><published>2008-03-17T23:21:00.003+01:00</published><updated>2008-05-06T20:20:47.194+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Enterprise'/><title type='text'>Creating timers in EJB3</title><content type='html'>While the EJB 3.1 expert group is working on the improved timer service using annotations (See &lt;a href="http://www.theserverside.com/tt/articles/article.tss?l=NewFeaturesEJB31" target="_new"&gt;New Features in EJB 3.1&lt;/a&gt;) I thought that I'd just bring a small entry on using the timer service in EJB 3.&lt;br /&gt;&lt;br /&gt;The timer service works by telling the service when it should timeout (i.e. when shall the "alarm" go off). You can add to this by telling it when it should timeout the first time, and how often (in ms) it should timeout after that.  You define which methods on the bean that should be invoked upon timeout by annotating them &lt;code&gt;@Timeout&lt;/code&gt;. The timer service is initialised by annotating a &lt;code&gt;TimerService&lt;/code&gt; object as a &lt;code&gt;@Resource&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Okay, before I show the code, these are the methods that we need:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;A method for starting the timer&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A method for stopping the timer&lt;/li&gt;&lt;br /&gt;&lt;li&gt;One or more listener methods that will be invoked when the timer has timed-out&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;@Stateless&lt;br /&gt;public class MyTimerBean implements MyTimerLocal {&lt;br /&gt;&lt;br /&gt;    /** Service used for scheduling tasks. */&lt;br /&gt;    @Resource private TimerService timerService;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Starts the scheduler.&lt;br /&gt;     * &lt;br /&gt;     * @param startDate&lt;br /&gt;     *          Start date&lt;br /&gt;     * @param interval&lt;br /&gt;     *          Interval at which the timeout shall repeat&lt;br /&gt;     * @param timerName&lt;br /&gt;     *          Timer to start&lt;br /&gt;     */&lt;br /&gt;    public void startTimer(Date startDate, Long interval, String timerName) {&lt;br /&gt;        this.timerService.createTimer(startDate, interval, timerName);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Stops a given scheduler.&lt;br /&gt;     * &lt;br /&gt;     * @param timerName&lt;br /&gt;     *          Timer to stop&lt;br /&gt;     */&lt;br /&gt;    public void stopTimer(String timerName) {&lt;br /&gt;         for (Timer timer : (Collection&lt;Timer&gt;) this.timerService.getTimers()) {&lt;br /&gt;            if (timer.getInfo() instanceof String) {&lt;br /&gt;                if (((String) timer.getInfo()).equals(timerName)) {&lt;br /&gt;                    timer.cancel();&lt;br /&gt;                    return;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * {@link Timeout} event handler for generating a report.&lt;br /&gt;     * &lt;br /&gt;     * @param timer&lt;br /&gt;     *          Timer that timed out&lt;br /&gt;     */&lt;br /&gt;    @Timeout&lt;br /&gt;    public void generateReport(Timer timer) {&lt;br /&gt;        if (timer.getInfo() instanceof String) {&lt;br /&gt;            if (((String) timer.getInfo()).equals("Generate Report")) {&lt;br /&gt;                ... do some processing ...&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * {@link Timeout} event handler for cleaning the cache.&lt;br /&gt;     * &lt;br /&gt;     * @param timer&lt;br /&gt;     *          Timer that timed out&lt;br /&gt;     */&lt;br /&gt;    @Timeout&lt;br /&gt;    public void cleanCache(Timer timer) {&lt;br /&gt;        if (timer.getInfo() instanceof String) {&lt;br /&gt;            if (((String) timer.getInfo()).equals("Clean Cache")) {&lt;br /&gt;                ... do some processing ...&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Right, so we have a method for starting a timer (&lt;code&gt;startTimer&lt;/code&gt;). This method needs to be invoked in order to start the timer. This is one of the drawbacks of the &lt;code&gt;TimerService&lt;/code&gt;, you cannot tell it to just start when the application is deployed (will be there in EJB3.1). Instead I use a Servlet Context Listener to invoke the &lt;code&gt;startTimer&lt;/code&gt; method when the accompaying webapplication is deployed:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;public class TimerInitialisationListener implements ServletContextListener {&lt;br /&gt;&lt;br /&gt;    /** Local interface for {@link MyTimerBean}. */&lt;br /&gt;    @EJB private MyTimerLocal myTimer;&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Initialises the timer service.&lt;br /&gt;     * &lt;br /&gt;     * @param event&lt;br /&gt;     *          Event that invoked the listener&lt;br /&gt;     */&lt;br /&gt;    public void contextInitialized(ServletContextEvent event) {&lt;br /&gt;        Calendar now = Calendar.getInstance();&lt;br /&gt;        now.set(Calendar.HOUR_OF_DAY, 0);&lt;br /&gt;        now.set(Calendar.MINUTE, 0);&lt;br /&gt;        now.set(Calendar.SECOND, 0);&lt;br /&gt;        int year = now.get(Calendar.YEAR);&lt;br /&gt;        int month = now.get(Calendar.MONTH);&lt;br /&gt;        int dayOfMonth = now.get(Calendar.DAY_OF_MONTH);&lt;br /&gt;        int hourOfDay = now.get(Calendar.HOUR_OF_DAY);&lt;br /&gt;        int minute = now.get(Calendar.MINUTE);&lt;br /&gt;        Long repeat = 60000L * 60L * 24L;&lt;br /&gt;        LogFactory.getLog(TimerInitialisationListener.class).info("Start time: " + now.getTime());&lt;br /&gt;        LogFactory.getLog(TimerInitialisationListener.class).info("Repeat every: " + repeat + " ms (" + (repeat / 3600000L) + " hrs)");&lt;br /&gt;&lt;br /&gt;        myTimer.startTimer(new GregorianCalendar(year, month, dayOfMonth, hourOfDay, minute).getTime(), 60000L * 60L * 24L, "Generate Report");&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    /**&lt;br /&gt;     * Context is uninstalled from the servlet container.&lt;br /&gt;     * &lt;br /&gt;     * @param event&lt;br /&gt;     *          Event that invoked the listener&lt;br /&gt;     */&lt;br /&gt;    public void contextDestroyed(ServletContextEvent event) {&lt;br /&gt;        LogFactory.getLog(TimerInitialisationListener.class).info("Stopping timer");&lt;br /&gt;        myTimer.stopTimer("Generate Report");&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;When you deploy the enterprise application you will see that the timer is set to start at midnight and execute every 86400000 ms (i.e. every 24 hours). What you will notice is that it is only the &lt;code&gt;generateReport&lt;/code&gt; method that is executed fully at every timeout as I've put in a check to ensure that it is the correct action being executed. Instead of using a String as the identifier of the &lt;code&gt;Timer&lt;/code&gt; you can create create your own custom objects as pass them instead (just remember to make it serializable).&lt;br /&gt;&lt;br /&gt;That's all for now. I'll bring another entry when EJB3.1 has been released and the new timer service annotations have been implemented.&lt;br /&gt;&lt;br /&gt;On a side note, I've used Quartz before and it's great - I just like to stick to the standards if it can do the job.&lt;br /&gt;&lt;br /&gt;Checkout the &lt;a href="http://java.sun.com/javaee/5/docs/api/javax/ejb/TimerService.html"&gt;JavaDocs for the TimerService&lt;/a&gt; for more information.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;UPDATE: 6. May 2008&lt;/strong&gt;: Yesterday I was preparing some code using the timer service and I noticed that only the first method annotated with &lt;code&gt;@TimeOut&lt;/code&gt; is executed upon timeout. Therefore, use only one &lt;code&gt;@TimeOut&lt;/code&gt; method per SessionBean.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-7672170583075369434?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/7672170583075369434/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=7672170583075369434' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7672170583075369434'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7672170583075369434'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/03/creating-timers-in-ejb3.html' title='Creating timers in EJB3'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-613110596719216729</id><published>2008-03-15T00:25:00.005+01:00</published><updated>2008-03-15T18:41:01.149+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Mobile'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Yippiee my new phone arrived</title><content type='html'>For a long time my old phone has been way past retirement. It was a Qtec 2020 (I believe). I've always loved smartphones and hated the glorified music players (e.g. Sony Ericsson). I don't see the point in the fancy music player phones, but that is probably because I'm perfectly happy with my iPod and have no plans of replacing it for something less cool.&lt;br /&gt;&lt;br /&gt;Anyways, the Qtec acted up a long time ago. I used it as my organiser, phone and GPS for the car. When it suddenly started losing all its memory and at the same time I misplaced my stylus, I thought that it was high time to get a new phone. So this time I decided not to get a smartphone (mostly because the complete lack of market for smartphones in Denmark - this makes it very expensive!). Instead I got myself a &lt;a href="http://europe.nokia.com/A4399010" target="_new"&gt;Nokia 6120&lt;/a&gt; with all the latest services provided on the 3G network (Skype, MSN, MobileTV, etc).&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.netbeans.org/kb/60/mobility/mobile-dilbert.html"&gt;&lt;img src="http://www.netbeans.org/images/mobility/dilbert/end-result.png" align="left" border="0" style="padding-right: 10px;" alt="From the End-to-End Web Service Tutorial on NetBeans.org" title="From the End-to-End Web Service Tutorial on NetBeans.org" /&gt;&lt;/a&gt; So far I'm loving the phone! It is fully compatible with Java MIDP 2.0 - so I'll have to get cracking with Java ME to make some applications soon. Can anybody recommend a good starting point for Java ME programming? My background in Java is purely enterprise and web. NetBeans got some cool mobile development aids that I'll be trying out - but I'd really like to know the basics before I start all the dragging and dropping. In anycase I think this is a good place to start: &lt;a target="_new" href="http://www.netbeans.org/kb/60/mobility/index.html"&gt;NetBeans 6.0 Mobility Documentation&lt;/a&gt;. It's got a pretty good tutorial for creating a mobile Dilbert browser.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-613110596719216729?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/613110596719216729/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=613110596719216729' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/613110596719216729'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/613110596719216729'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/03/yippiee-my-new-phone-arrived.html' title='Yippiee my new phone arrived'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-7685646300421773710</id><published>2008-03-15T00:17:00.003+01:00</published><updated>2008-03-15T00:24:19.561+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><category scheme='http://www.blogger.com/atom/ns#' term='Certification'/><title type='text'>Ordered the certification books</title><content type='html'>I've finally ordered the certification books that I mentioned in a previous post (SCJP Sun Certified Programmer for Java 5 Study Guide (Exam 310-055): Study Guide Exam 310-055 and Sun Certified Enterprise Architect for Java EE Study Guide (Exam 310-051): Study Guide Exam 310-051).&lt;br /&gt;&lt;br /&gt;It is my personal goal to have taken both certifications before the end of April. I was tempted to also get the Certification Press book about Sun Certified Business Components Developer, but it got such bad reviews on Amazon that I didn't dare to get it. Unfortunately it seem to be the only study guide for Business Components Development.&lt;br /&gt;&lt;br /&gt;Anyways, I'm looking forward to the books getting here so that I can get started!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-7685646300421773710?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/7685646300421773710/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=7685646300421773710' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7685646300421773710'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7685646300421773710'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/03/ordered-certification-books.html' title='Ordered the certification books'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-1178599906308412423</id><published>2008-02-15T23:58:00.003+01:00</published><updated>2008-03-12T23:48:48.509+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Useless drivel'/><title type='text'>Riots in Gellerup</title><content type='html'>&lt;A HREF='http://bp1.blogger.com/__SeQT33Fv3E/R7YZDpxLdII/AAAAAAAABtE/wqNjk27OXe0/s1600-h/MOV01015.jpg'&gt;&lt;IMG SRC='http://bp1.blogger.com/__SeQT33Fv3E/R7YZDpxLdII/AAAAAAAABtE/wqNjk27OXe0/s320/MOV01015.jpg' border=0 alt='' id='BLOGGER_PHOTO_ID_' style='clear:both;float:left; margin:0px 10px 10px 0;'&gt;&lt;/A&gt;This is a photo from a fire started just outside my appartment. The fire was dangerously close to my car but luckily the skilled firemen got the fire under control very quickly. The reason for the riot is apparently because of the re-publication of the famous Muhammad drawings in the Danish newspapers. I really think that "Respect" should be a mandatory course taught in primary school. To me it seems like respect for one another has simply disappear from this world. Everyday I see the lack of respect between people, whether it's between men and women, christians and muslims, employers and employees, buyers and sellers, children and adults. Oh dear oh dear, what has this place come to. Please, if you read this, respect the people and things around you!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-1178599906308412423?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/1178599906308412423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=1178599906308412423' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/1178599906308412423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/1178599906308412423'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/02/riots-in-gellerup.html' title='Riots in Gellerup'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp1.blogger.com/__SeQT33Fv3E/R7YZDpxLdII/AAAAAAAABtE/wqNjk27OXe0/s72-c/MOV01015.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-2736780892974348926</id><published>2008-02-12T19:52:00.003+01:00</published><updated>2008-07-30T01:11:21.357+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Creating a custom JSF message component</title><content type='html'>The other day I was tasked with creating feedback messages for a JSF-based application as JavaScript alert dialogues. JSF already got a tag for displaying messages attached to components (&lt;code&gt;&amp;lt;h:message /&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;h:messages /&amp;gt;&lt;/code&gt;), however they are limited to render the text using a given cascading style sheet class for each level of severity.&lt;br /&gt;&lt;br /&gt;This entry will show how to build a custom JSF message tag for rendering the messages as a JavaScript alert.&lt;br /&gt;&lt;br /&gt;There are many excellent tutorials and blog entries out there describing JSF component development much better than I am capable of. So, I'll just focus on what is needed to create this specific component. My instructions are based on NetBeans 6.0, but they don't including anything that is not possible to do in other IDEs, so you should be able to translate the instructions into your own IDE.&lt;br /&gt;&lt;br /&gt;We will keep the tag simple with one attribute, &lt;code&gt;for&lt;/code&gt;, which will specify for which component the messages should be displayed. The signature of the tag will therefore be: &lt;code&gt;&amp;lt;jc:alertMessage for="myForm" /&amp;gt;&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;1. Fire up NetBeans&lt;br /&gt;&lt;br /&gt;2. Create a new Java Class Library Project (I've called mine jsf-components)&lt;br /&gt;&lt;br /&gt;Before we continue let me briefly explain what we need:&lt;br /&gt;&lt;dl&gt;&lt;br /&gt;   &lt;dt&gt;&lt;code&gt;META-INF/jsf-components.tld&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;   &lt;dd&gt;Tag library descriptor declaring your tag and defining its attributes&lt;/dd&gt;&lt;br /&gt;   &lt;dt&gt;&lt;code&gt;META-INF/faces-config.xml&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;   &lt;dd&gt;Declares the tag in the faces application&lt;/dd&gt;&lt;br /&gt;   &lt;dt&gt;&lt;code&gt;components/AlertMessage.java&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;   &lt;dd&gt;Class representing the user interface component with properties for each attribute supported by the tag. It's recommended to sub-class one of the existing components to avoid doing all the work yourself.&lt;/dd&gt;&lt;br /&gt;   &lt;dt&gt;&lt;code&gt;components/AlertMessageRenderer.java&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;   &lt;dd&gt;Class for rendering the content of the tag. This is the class where we will actual construct the HTML/Javascript code that is outputted to the browser.&lt;/dd&gt;&lt;br /&gt;   &lt;dt&gt;&lt;code&gt;components/AlertMessageTag.java&lt;/code&gt;&lt;/dt&gt;&lt;br /&gt;   &lt;dd&gt;Class representing the actual tag.&lt;/dd&gt;&lt;br /&gt;&lt;/dl&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/__SeQT33Fv3E/R7ISp5xLchI/AAAAAAAABnY/qLlwUgfEp_U/s1600-h/scrsht3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/__SeQT33Fv3E/R7ISp5xLchI/AAAAAAAABnY/qLlwUgfEp_U/s400/scrsht3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5166212233638408722" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now that we know what to do - lets get on with it.&lt;br /&gt;&lt;br /&gt;3. Create the &lt;code&gt;components&lt;/code&gt; package in the Source Packages&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/__SeQT33Fv3E/R7H29JxLcgI/AAAAAAAABnQ/09cBVB3caSU/s1600-h/scrsht1.png"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/__SeQT33Fv3E/R7H29JxLcgI/AAAAAAAABnQ/09cBVB3caSU/s400/scrsht1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5166181778025312770" /&gt;&lt;/a&gt;&lt;br /&gt;3a) Right click Source Packages&lt;br /&gt;3b) Select 'New'&lt;br /&gt;3c) Select 'Other'&lt;br /&gt;3d) Select 'Java'&lt;br /&gt;3e) Select 'Java Package'&lt;br /&gt;3f) Click 'Next'&lt;br /&gt;3g) Enter &lt;code&gt;components&lt;/code&gt; as the package name&lt;br /&gt;3h) Click 'Finish'&lt;br /&gt;&lt;br /&gt;4. Create the tag library descriptor&lt;br /&gt;4a) Right click Source Packages&lt;br /&gt;4b) Select 'New'&lt;br /&gt;4c) Select 'Other'&lt;br /&gt;4d) Select 'Web'&lt;br /&gt;4e) Select 'Tag Library Descriptor'&lt;br /&gt;4f) Click 'Next'&lt;br /&gt;4g) Enter the following information:&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/__SeQT33Fv3E/R7ITQZxLciI/AAAAAAAABng/MAZLovycbK4/s1600-h/scrsht4.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/__SeQT33Fv3E/R7ITQZxLciI/AAAAAAAABng/MAZLovycbK4/s400/scrsht4.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5166212895063372322" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;TLD name: &lt;code&gt;jsf-components&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;URI: &lt;code&gt;http://jsf-components&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Prefix: &lt;code&gt;jc&lt;/code&gt;&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;4h) Click 'Finish'&lt;br /&gt;&lt;br /&gt;5. Add the javaee.jar from the GlassFish project (&lt;code&gt;%GLASSFISH%/lib&lt;/code&gt;) to the library dependencies of the project.&lt;br /&gt;&lt;br /&gt;6. Create the Java class for the UI component, AlertMessage subclassing the &lt;code&gt;UIMessage&lt;/code&gt; component.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package components;&lt;br /&gt;&lt;br /&gt;import javax.faces.component.UIMessage;&lt;br /&gt;&lt;br /&gt;public class AlertMessage extends UIMessage {&lt;br /&gt;&lt;br /&gt;    private static final String MSG_COMPONENT_TYPE = "components.alertmessage";&lt;br /&gt;    private static final String MSG_COMPONENT_FAMILY = "javax.faces.Message";&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public String getFamily() {&lt;br /&gt;        return MSG_COMPONENT_FAMILY;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public String getRendererType() {&lt;br /&gt;        return MSG_COMPONENT_TYPE;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public String getFor() {&lt;br /&gt;        return super.getFor();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void setFor(String forParam) {&lt;br /&gt;        super.setFor(forParam);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;7. Create the Java class for the tag, AlertMessageTag subclassing the &lt;code&gt;UIComponentELTag&lt;/code&gt; tag.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package components;&lt;br /&gt;&lt;br /&gt;import javax.el.ValueExpression;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.webapp.UIComponentELTag;&lt;br /&gt;import javax.servlet.jsp.JspException;&lt;br /&gt;import javax.servlet.jsp.PageContext;&lt;br /&gt;import javax.servlet.jsp.tagext.Tag;&lt;br /&gt;&lt;br /&gt;public class AlertMessageTag extends UIComponentELTag {&lt;br /&gt;&lt;br /&gt;    private ValueExpression forParam;&lt;br /&gt;&lt;br /&gt;    private static final String MSG_COMPONENT_TYPE = "components.alertmessage";&lt;br /&gt;&lt;br /&gt;    private static final String MSG_RENDERER_TYPE = "components.alertmessage";&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public String getComponentType() {&lt;br /&gt;        return MSG_COMPONENT_TYPE;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public String getRendererType() {&lt;br /&gt;        return MSG_RENDERER_TYPE;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    protected void setProperties(UIComponent component) {&lt;br /&gt;        super.setProperties(component);&lt;br /&gt;        AlertMessage em = (AlertMessage) component;&lt;br /&gt;        em.setValueExpression("for", forParam);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public int doEndTag() throws JspException {&lt;br /&gt;        return super.doEndTag();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public int doStartTag() throws JspException {&lt;br /&gt;        return super.doStartTag();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void setPageContext(PageContext ctx) {&lt;br /&gt;        super.setPageContext(ctx);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void setParent(Tag tag) {&lt;br /&gt;        super.setParent(tag);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setFor(ValueExpression forParam) {&lt;br /&gt;        this.forParam = forParam;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;9. Create the Java class for rendering the tag, AlertMessageRenderer subclassing the JSF &lt;code&gt;Renderer&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package components;&lt;br /&gt;&lt;br /&gt;import java.io.IOException;&lt;br /&gt;import java.util.Iterator;&lt;br /&gt;import javax.faces.application.FacesMessage;&lt;br /&gt;import javax.faces.component.UIComponent;&lt;br /&gt;import javax.faces.context.FacesContext;&lt;br /&gt;import javax.faces.context.ResponseWriter;&lt;br /&gt;import javax.faces.render.Renderer;&lt;br /&gt;import org.apache.commons.lang.StringEscapeUtils;&lt;br /&gt;&lt;br /&gt;public class AlertMessageRenderer extends Renderer {&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {&lt;br /&gt;        AlertMessage alertMessage = (AlertMessage) component;&lt;br /&gt;&lt;br /&gt;        // Locate the component for which to display messages&lt;br /&gt;        UIComponent forComponent = alertMessage.findComponent(alertMessage.getFor());&lt;br /&gt;&lt;br /&gt;        // If the component could not be found end processing&lt;br /&gt;        if (forComponent == null) {&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        // Iterate through messages for the component&lt;br /&gt;        Iterator iter = context.getMessages(forComponent.getClientId(context));&lt;br /&gt;        if (iter.hasNext()) {&lt;br /&gt;            ResponseWriter writer = context.getResponseWriter();&lt;br /&gt;&lt;br /&gt;            // Start the script tag&lt;br /&gt;            writer.startElement("script", alertMessage);&lt;br /&gt;            writer.writeAttribute("type", "text/javascript", null);&lt;br /&gt;&lt;br /&gt;            // Construct one big string of all messages&lt;br /&gt;            StringBuffer message = new StringBuffer();&lt;br /&gt;            while (iter.hasNext()) {&lt;br /&gt;                FacesMessage msg = (FacesMessage) iter.next();&lt;br /&gt;                if (message.length() &gt; 0) {&lt;br /&gt;                    // Separate each message with the JavaScript escape code&lt;br /&gt;                    // for newline&lt;br /&gt;                    message.append("\n");&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                message.append(msg.getSummary());&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // Escape the constructed string to be outputable as a JavaScript&lt;br /&gt;            String displayMessage = StringEscapeUtils.escapeJavaScript(message.toString());&lt;br /&gt;&lt;br /&gt;            // Output the javascript code for displaying the alert dialogue&lt;br /&gt;            String jsAlert = "alert('" + displayMessage + "');";&lt;br /&gt;            writer.writeText(jsAlert.toCharArray(), 0, jsAlert.length());&lt;br /&gt;&lt;br /&gt;            // End the script tag&lt;br /&gt;            writer.endElement("script");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void decode(FacesContext ctx, UIComponent component) {&lt;br /&gt;        if (ctx == null || component == null) {&lt;br /&gt;            throw new NullPointerException();&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Notice that I'm using &lt;code&gt;StringEscapeUtils.escapeJavaScript(String)&lt;/code&gt; from the &lt;a href="http://commons.apache.org/lang/" target="_blank"&gt;Apache Commons Lang&lt;/a&gt; library to ensure the correct output of the JavaScript code.&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;10. Update the tag library descriptor to reflect the created component:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br /&gt;&amp;lt;taglib version="2.0" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"&amp;gt;&lt;br /&gt;    &amp;lt;tlib-version&gt;1.0&amp;lt;/tlib-version&amp;gt;&lt;br /&gt;    &amp;lt;short-name&gt;jc&amp;lt;/short-name&amp;gt;&lt;br /&gt;    &amp;lt;uri&amp;gt;http://jsf-components&amp;lt;/uri&amp;gt;&lt;br /&gt;    &amp;lt;tag&amp;gt;&lt;br /&gt;        &amp;lt;name&gt;AlertMessage&amp;lt;/name&amp;gt;&lt;br /&gt;        &amp;lt;tag-class&gt;components.AlertMessageTag&amp;lt;/tag-class&amp;gt;&lt;br /&gt;        &amp;lt;body-content&gt;JSP&amp;lt;/body-content&amp;gt;&lt;br /&gt;        &amp;lt;attribute&amp;gt;&lt;br /&gt;            &amp;lt;description&amp;gt;&lt;br /&gt;                The ID of the component whose attached FacesMessage object &lt;br /&gt;                (if present) should be diplayed by this component.&lt;br /&gt;            &amp;lt;/description&amp;gt;&lt;br /&gt;            &amp;lt;name&gt;for&amp;lt;/name&amp;gt;&lt;br /&gt;            &amp;lt;required&gt;true&amp;lt;/required&amp;gt;&lt;br /&gt;            &amp;lt;deferred-value/&amp;gt;&lt;br /&gt;        &amp;lt;/attribute&amp;gt;&lt;br /&gt;    &amp;lt;/tag&amp;gt;&lt;br /&gt;&amp;lt;/taglib&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;11. Create the faces configuration (&lt;code&gt;META-INF/faces-config.xml&lt;/code&gt;) for the component:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version='1.0' encoding='UTF-8'?&amp;gt;&lt;br /&gt;&amp;lt;faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"&amp;gt;&lt;br /&gt;    &amp;lt;component&amp;gt;&lt;br /&gt;        &amp;lt;component-type&amp;gt;components.alertmessage&amp;lt;/component-type&amp;gt;&lt;br /&gt;        &amp;lt;component-class&amp;gt;components.AlertMessage&amp;lt;/component-class&amp;gt;&lt;br /&gt;    &amp;lt;/component&amp;gt;&lt;br /&gt;    &lt;br /&gt;    &amp;lt;render-kit&amp;gt;&lt;br /&gt;        &amp;lt;renderer&amp;gt;&lt;br /&gt;            &amp;lt;description&amp;gt;Renderer for the alert message component.&amp;lt;/description&amp;gt;&lt;br /&gt;            &amp;lt;component-family&amp;gt;javax.faces.Message&amp;lt;/component-family&amp;gt;&lt;br /&gt;            &amp;lt;renderer-type&amp;gt;components.alertmessage&amp;lt;/renderer-type&amp;gt;&lt;br /&gt;            &amp;lt;renderer-class&amp;gt;components.AlertMessageRenderer&amp;lt;/renderer-class&amp;gt;&lt;br /&gt;        &amp;lt;/renderer&amp;gt;&lt;br /&gt;    &amp;lt;/render-kit&amp;gt;&lt;br /&gt;&amp;lt;/faces-config&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;12. Build the class library&lt;br /&gt;&lt;br /&gt;All you need to do now is to place the jsf-components.jar into your web application, declare the tag library (&lt;code&gt;&amp;lt;%@taglib prefix="jc" uri="http://jsf-components" %&amp;gt;&lt;/code&gt;) on the pages where you want to use the tag (&lt;code&gt;&amp;lt;jc:alertMessage for="componentId" /&amp;gt;&lt;/code&gt;). Example:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;%@page contentType="text/html"%&amp;gt;&lt;br /&gt;&amp;lt;%@page pageEncoding="UTF-8"%&amp;gt;&lt;br /&gt;&amp;lt;%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%&amp;gt;&lt;br /&gt;&amp;lt;%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%&amp;gt;&lt;br /&gt;&amp;lt;%@taglib prefix="jc" uri="http://jsf-components" %&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;    &amp;lt;head&amp;gt;&lt;br /&gt;        &amp;lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8"&amp;gt;&lt;br /&gt;        &amp;lt;title&amp;gt;Example of AlertMessage component&amp;lt;/title&amp;gt;&lt;br /&gt;    &amp;lt;/head&amp;gt;&lt;br /&gt;    &amp;lt;body&amp;gt;&lt;br /&gt;        &amp;lt;f:view&amp;gt;&lt;br /&gt;            &amp;lt;h:form&amp;gt;&lt;br /&gt;                &amp;lt;jc:AlertMessage for="numberField" /&amp;gt;&lt;br /&gt;                &amp;lt;h:inputText id="numberField"&amp;gt;&lt;br /&gt;                    &amp;lt;f:validateLength minimum="5" maximum="10" /&amp;gt;&lt;br /&gt;                    &amp;lt;f:validateLongRange minimum="10000" maximum="222222" /&amp;gt;&lt;br /&gt;                &amp;lt;/h:inputText&amp;gt;&lt;br /&gt;                &amp;lt;h:commandButton value="Submit" action="reload" /&amp;gt;&lt;br /&gt;            &amp;lt;/h:form&amp;gt;&lt;br /&gt;        &amp;lt;/f:view&amp;gt;&lt;br /&gt;    &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/__SeQT33Fv3E/R7IUgpxLcjI/AAAAAAAABno/1W8KK7_p8cc/s1600-h/scrsht5.png"&gt;&lt;img style="cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/__SeQT33Fv3E/R7IUgpxLcjI/AAAAAAAABno/1W8KK7_p8cc/s400/scrsht5.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5166214273747874354" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;UPDATE (30. July 2008)&lt;/b&gt;: Facelets Support&lt;br /&gt;&lt;br /&gt;You can use the component with Facelets by providing a Facelets Tag Library descriptor. In this example I name the tag library descriptor  &lt;code&gt;mycomponents.taglib.xml&lt;/code&gt; and place in the &lt;code&gt;WEB-INF/&lt;/code&gt; directory.&lt;br /&gt;&lt;br /&gt;The contents of the descriptor is:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;?xml version="1.0"?&amp;gt;&lt;br /&gt;&amp;lt;!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/facelet-taglib_1_0.dtd"&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;facelet-taglib&amp;gt;&lt;br /&gt;    &amp;lt;namespace&amp;gt;http://jsf-components&amp;lt;/namespace&amp;gt;&lt;br /&gt;    &amp;lt;tag&amp;gt;&lt;br /&gt;        &amp;lt;tag-name&amp;gt;alertMessage&amp;lt;/tag-name&amp;gt;&lt;br /&gt;        &amp;lt;component&amp;gt;&lt;br /&gt;            &amp;lt;component-type&amp;gt;components.alertmessage&amp;lt;/component-type&amp;gt;&lt;br /&gt;            &amp;lt;renderer-type&amp;gt;components.alertmessage&amp;lt;/renderer-type&amp;gt;&lt;br /&gt;        &amp;lt;/component&amp;lt;&lt;br /&gt;    &amp;lt;/tag&amp;lt;  &lt;br /&gt;&amp;lt;/facelet-taglib&amp;lt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Next you need to reference the descriptor in &lt;code&gt;web.xml&lt;/code&gt; using the &lt;code&gt;facelets.LIBRARIES&lt;/code&gt; context parameter:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;&amp;lt;context-param&amp;gt;&lt;br /&gt;    &amp;lt;param-name&amp;gt;facelets.LIBRARIES&amp;lt;/param-name&amp;gt;&lt;br /&gt;    &amp;lt;param-value&amp;gt;/WEB-INF/mycomponents.taglib.xml&amp;lt;/param-value&amp;gt;&lt;br /&gt;&amp;lt;/context-param&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Remember that if you have more than one Facelets Tag Library Descriptor, to separate them using semicolons (;)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-2736780892974348926?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/2736780892974348926/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=2736780892974348926' title='24 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/2736780892974348926'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/2736780892974348926'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/02/creating-custom-jsf-message-component.html' title='Creating a custom JSF message component'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp2.blogger.com/__SeQT33Fv3E/R7ISp5xLchI/AAAAAAAABnY/qLlwUgfEp_U/s72-c/scrsht3.png' height='72' width='72'/><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-741810260166351915</id><published>2008-02-06T22:43:00.000+01:00</published><updated>2008-02-06T23:15:52.630+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Solaris'/><title type='text'>Getting to know Solaris</title><content type='html'>The past ten years I've been working comfortably with various distributions of Linux (Ubuntu, Kubuntu, Gentoo, Mandrake, RedHat, Debian, Suse) and I have really enjoyed what they have to offer. During the four years where I was self-employed all my machines were running one or the other distribution of Linux (My favourite to this day is Ubuntu closely followed by Gentoo).&lt;br /&gt;&lt;br /&gt;Anyways, lately I've become curious about Solaris and would like to use it for a Java build server that I'm setting up. The server will host a versioning system (&lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt;), a continuous integration system (&lt;a href="http://cruisecontrol.sourceforge.net/"&gt;CruiseControl&lt;/a&gt; most likely) and an issue tracking system (&lt;a href="http://www.mantisbt.org/"&gt;Mantis&lt;/a&gt; most likely).&lt;br /&gt;&lt;br /&gt;Last weekend I started my project to set-up Solaris. It's been quite a struggle as I thought that I could just transfer all my Linux skills to Solaris - but little did I know at that time.&lt;br /&gt;&lt;br /&gt;Status as of now is that I've &lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sun.com/software/solaris/get.jsp"&gt;downloaded the DVD image of Solaris 10&lt;/a&gt; onto my Windows workstation&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.sun.com/software/solaris/download_instruction.xml"&gt;Merged the two ISO files&lt;/a&gt; (this took me time to figure out as I'm not exactly known for reading the instructions before starting work!)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Created a Virtual Machine in the &lt;a href="http://www.vmware.com/download/server/"&gt;free version of VMWare 1.0.4&lt;/a&gt; with 15 GB Hard disk space&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Installed Solaris with the minimum required software (the first few times I installed it I didn't select the custom installation and ended up installing both Java Desktop System and CDE - all I really wanted was just a text console).&lt;/li&gt;&lt;br /&gt;&lt;li&gt;&lt;a href="http://www.bolthole.com/solaris/pkg-get.html"&gt;Installed pkg-get for package management&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Installed a few packages like SSH, Subversion, Apache, PHP, MySQL&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;One thing that has thoroughly annoyed me is package management. When you're use to apt-get (Debian) its &lt;u&gt;hard&lt;/u&gt; getting use to tinker around so much to get packages to compile and configure properly.&lt;br /&gt;&lt;br /&gt;So here I am... I've been contemplating how to continue from here, and that is when I saw &lt;a href="http://www.sun.com/training/sweepstakes_solaris.html"&gt;an announcement about free Solaris training&lt;/a&gt; in Sun Learning Centre with the added bonus of being part of a $50,000 sweepstake! &lt;br /&gt;&lt;br /&gt;For any other people considering Solaris I'd recommend signing up for the free training while it lasts as it will give you a head start on the nitty gritty of Solaris.&lt;br /&gt;&lt;br /&gt;More about my adventures into Solaris later.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-741810260166351915?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/741810260166351915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=741810260166351915' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/741810260166351915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/741810260166351915'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/02/getting-to-know-solaris.html' title='Getting to know Solaris'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-5832593792880755379</id><published>2008-02-06T19:23:00.000+01:00</published><updated>2008-02-06T19:45:19.339+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Quick tip'/><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Custom code folding in NetBeans</title><content type='html'>When you got large source files it can sometimes be helpful to create foldings for certain sections of your code. NetBeans got a nifty functionality for this using non-intrusive XML code (similar to Visual Studio).&lt;br /&gt;&lt;br /&gt;To create a custom code folding section simply insert the following before the content to fold:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;    //&amp;lt;editor-fold defaultstate="collapsed" desc="My custom code folding"&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;and the following after the content to fold:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;    //&amp;lt;/editor-fold&amp;gt;&lt;br /&gt;&lt;/pre&gt;.&lt;br /&gt;&lt;br /&gt;So for example, if you had a JSF backing bean where you want to create a custom code folding for your properties, action listeners, and action handlers you could do as follows:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package backingbeans;&lt;br /&gt;&lt;br /&gt;import javax.faces.model.*;&lt;br /&gt;import javax.faces.event.*;&lt;br /&gt;&lt;br /&gt;public class MyBackingBean {&lt;br /&gt;&lt;br /&gt;    private String prop1 = "";&lt;br /&gt;&lt;br /&gt;    public MyBackingBean() {&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    //&amp;lt;editor-fold defaultstate="collapsed" desc="Properties"&amp;gt;&lt;br /&gt;    public String getProp1() {&lt;br /&gt;        return this.prop1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void setProp1(String prop1) {&lt;br /&gt;        this.prop1 = prop1;&lt;br /&gt;    }&lt;br /&gt;    //&amp;lt;/editor-fold&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    //&amp;lt;editor-fold defaultstate="collapsed" desc="Action listeners"&amp;gt;&lt;br /&gt;    public void myFirstListener(ActionEvent event) {&lt;br /&gt;        ... do something ...&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void mySecondListener(ActionEvent event) {&lt;br /&gt;        ... do something else ...&lt;br /&gt;    }&lt;br /&gt;    //&amp;lt;/editor-fold&amp;gt;&lt;br /&gt;&lt;br /&gt;    //&amp;lt;editor-fold defaultstate="collapsed" desc="Action handlers"&amp;gt;&lt;br /&gt;    public String myFirstActionHandler() {&lt;br /&gt;        ... do something ...&lt;br /&gt;        return "OUTCOME1";&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public String mySecondActionHandler() {&lt;br /&gt;        ... do something else ...&lt;br /&gt;        return "OUTCOME2";&lt;br /&gt;    }&lt;br /&gt;    //&amp;lt;/editor-fold&amp;gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This will create three custom folders that are collapsed by default when the file is opened.&lt;br /&gt;&lt;br /&gt;If you like this, I'd suggest setting up a coding template for inserting the XML code as it can otherwise be tricky to remember. This is done by following these steps:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Click Tools -&gt; Options&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Select "Editor" from the top options&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Select the "Code Templates" tab&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Select "Java" in the &lt;em&gt;Language&lt;/em&gt; dropdown&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click the "New" button&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Enter the shorthand for inserting the template, for example I use 'efold'&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Click the "OK" button&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The template has been created, now enter the following code into the &lt;em&gt;Expanded Text&lt;/em&gt; textbox:&lt;br /&gt;&lt;pre name="code" class="xml"&gt;&lt;br /&gt;    //&amp;lt;editor-fold defaultstate="collapsed" desc="${cursor}"&amp;gt;&lt;br /&gt;&lt;br /&gt;    //&amp;lt;/editor-fold&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;li&gt;Click the "OK" button.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;You can try out the template by opening a Java source file, place the cursor where you want to insert the folding and type &lt;code&gt;efold&lt;/code&gt; followed by the tab key. It will now have inserted the complete editor-fold and place the cursor ready for you to enter a description for the folding.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-5832593792880755379?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/5832593792880755379/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=5832593792880755379' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/5832593792880755379'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/5832593792880755379'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/02/custom-code-folding-in-netbeans.html' title='Custom code folding in NetBeans'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-3458448311904524817</id><published>2008-02-04T22:37:00.000+01:00</published><updated>2008-02-04T23:08:35.511+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NetBeans'/><title type='text'>Using the "License" functionality in NetBeans 6</title><content type='html'>NetBeans 6 comes with a brand new functionality for including project-based licenses in source files. This enables you to easily use different licenses in the headers depending on the project you are working on.&lt;br /&gt;&lt;br /&gt;Using the functionality is simple, here are the steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Add your licenses to the NetBeans templates&lt;/li&gt;&lt;li&gt;Update the &lt;code&gt;project.properties&lt;/code&gt; to specify the desired license&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Simple, eh?&lt;br /&gt;&lt;br /&gt;Okay, first we add a license to the NetBeans template. For the sake of this example I'll add the GPL license:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Click Tools -&gt; Templates&lt;/li&gt;&lt;li&gt;Expand the "Licenses" folder&lt;/li&gt;&lt;li&gt;Select  "Default License"&lt;/li&gt;&lt;li&gt;Click the "Duplicate" button (a new template is created called license-default_1.txt)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Select &lt;span style="font-weight: bold;"&gt;license-default_1.txt&lt;/span&gt;&lt;/li&gt;&lt;li&gt;Click the "Rename" button&lt;/li&gt;&lt;li&gt;Name the new license license-gpl.txt (notice, the name should follow the format:  license-&lt;license_identifier&gt;.txt)&lt;/li&gt;&lt;li&gt;Select license-gpl.txt&lt;/li&gt;&lt;li&gt;Click "Open in Editor"&lt;/li&gt;&lt;li&gt;Enter the following text (GPL license) into the editor:&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;&amp;lt;#if licenseFirst??&gt;&lt;br /&gt;${licenseFirst}&lt;br /&gt;&amp;lt;/#if&gt;&lt;br /&gt;${licensePrefix}${name}.java&lt;br /&gt;${licensePrefix}&lt;br /&gt;${licensePrefix}Copyright (C) ${date?date?string("yyyy")} Allan Lykke Christensen&lt;br /&gt;${licensePrefix}&lt;br /&gt;${licensePrefix}This program is distributed in the hope that it will be useful,&lt;br /&gt;${licensePrefix}but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt;${licensePrefix}MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt;${licensePrefix}GNU General Public License for more details.&lt;br /&gt;${licensePrefix}&lt;br /&gt;${licensePrefix}You should have received a copy of the GNU General Public License&lt;br /&gt;${licensePrefix}along with this program.  If not, see &amp;lt;http://www.gnu.org/licenses/&amp;gt;.&lt;br /&gt;&amp;lt;#if licenseLast??&amp;gt;&lt;br /&gt;${licenseLast}&lt;br /&gt;&amp;lt;/#if&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Replace the author name&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Save and close the template (CTRL+S followed by CTRL+W)&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;You have successfully added the template to NetBeans for use in future projects.&lt;br /&gt;&lt;br /&gt;To use the license in a project do the following:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Open the "Files" view (CTRL+2)&lt;/li&gt;&lt;li&gt;Expand the &lt;code&gt;nbproject&lt;/code&gt; folder of your project&lt;/li&gt;&lt;li&gt;Open the &lt;code&gt;project.properties&lt;/code&gt; file&lt;/li&gt;&lt;li&gt;Add &lt;code&gt;project.license=gpl&lt;/code&gt; in the end of the file, or if you already have a line starting &lt;code&gt;project.license&lt;/code&gt; replace it.&lt;/li&gt;&lt;li&gt;Save and close the file&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Alright, you are ready to try out the license. Create a new Java class in your Source Packages and viola, the source file is using the newly created license.&lt;br /&gt;&lt;br /&gt;In a future version of NetBeans I expect that it will be possible to select the license from the project properties page rather than you having to tinker around with &lt;code&gt;project.properties&lt;/code&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-3458448311904524817?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/3458448311904524817/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=3458448311904524817' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3458448311904524817'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3458448311904524817'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/02/using-license-functionality-in-netbeans.html' title='Using the &quot;License&quot; functionality in NetBeans 6'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-3755795237777100461</id><published>2008-02-04T21:35:00.000+01:00</published><updated>2008-02-04T21:43:42.274+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Certification'/><title type='text'>Considering Java certification</title><content type='html'>As one of my new year resolutions I promised myself that I'd get some sort of technical certification this year. Basically what I'm interested in is the Java Programmer Certification, Web Component Developer Certification and Enterprise Architect Certification. For the three certifications I've found the following prep literature:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;SCJP Sun Certified Programmer for Java 5 Study Guide (Exam 310-055): Study Guide Exam 310-055 (Certification Press) - &lt;a href="http://www.amazon.co.uk/Certified-Programmer-Study-Guide-310-055/dp/0072253606"&gt;Link&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Sun Certified Web Component Developer Study Guide (Exam 310-081) - &lt;a href="http://www.amazon.co.uk/Certified-Component-Developer-Study-310-081/dp/0072258810"&gt;Link&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;Sun Certified Enterprise Architect for Java EE Study Guide (Exam 310-051): Study Guide Exam 310-051 (Certification Press) - &lt;a href="http://www.amazon.co.uk/Certified-Enterprise-Architect-Study-310-051/dp/0071488618"&gt;Link&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;On the project management side I'm considering the Scrum Master Certification or Prince 2 Certification.&lt;br /&gt;&lt;br /&gt;Any recommendation?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-3755795237777100461?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/3755795237777100461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=3755795237777100461' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3755795237777100461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/3755795237777100461'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/02/considering-java-certification.html' title='Considering Java certification'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-5227962843772445606</id><published>2008-02-04T20:32:00.000+01:00</published><updated>2008-02-04T21:27:59.548+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='JSF'/><category scheme='http://www.blogger.com/atom/ns#' term='Quick tip'/><title type='text'>Concatenating strings in JSF</title><content type='html'>To start the day off I though I'd share a quick tip using JSF. Say you have a list of messages:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;quicktip.Messages&lt;/b&gt;:&lt;br /&gt;&lt;pre name="code" class="html"&gt;&lt;br /&gt;ITEM_1=First item&lt;br /&gt;ITEM_2=Second item&lt;br /&gt;ITEM_3=Third item&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now, on your JSF page you would like to show one of these messages depending on the ID of the item to display. For example, you might have an list of beans containing items you'd like to display:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;quicktip.Item&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;package quicktip;&lt;br /&gt;&lt;br /&gt;public class Item {&lt;br /&gt;&lt;br /&gt;     /** Unique ID of the item. */&lt;br /&gt;     private int id;&lt;br /&gt;&lt;br /&gt;     /** Number of items. */&lt;br /&gt;     private int count;&lt;br /&gt;&lt;br /&gt;    public Item() {}&lt;br /&gt;&lt;br /&gt;    ...usual getters and setters...&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;So, in your backing bean to the JSF page you have a method that constructs a DataModel containing items (I won't go into those details as it's not very exciting). For the sake of this example the signature of the method is   &lt;code&gt;public DataModel getItems();&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Finally we get to the interesting bit, the actual JSF page.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="html"&gt;... usual jsf stuff ...&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;&amp;lt;f:loadbundle basename="quicktip.Messages" var="msgs" /&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;h:datatable value="#{backingBean.items}" var="item"&amp;gt;&lt;br /&gt;        &amp;lt;h:column&amp;gt;&lt;br /&gt;            &amp;lt;c:set var="key" value="ITEM_#{item.id}" /&amp;gt;&lt;br /&gt;            &amp;lt;h:outputtext value="#{msgs[key]}" /&amp;gt;&lt;br /&gt;        &amp;lt;/h:column&amp;gt;&lt;br /&gt;        &amp;lt;h:column&amp;gt;&lt;br /&gt;            &amp;lt;h:outputtext value="#{item.count}" /&amp;gt;&lt;br /&gt;        &amp;lt;/h:column&amp;gt;&lt;br /&gt;    &amp;lt;/h:dataTable&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;That's it. So, the real gist of the tip is that you can use the jstl &lt;c:set&gt; tag to concatenating a string that you can re-use to fetch values from maps.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-5227962843772445606?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/5227962843772445606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=5227962843772445606' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/5227962843772445606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/5227962843772445606'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/02/concatenating-strings-in-jsf.html' title='Concatenating strings in JSF'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-7277243317790057399</id><published>2008-02-04T19:58:00.000+01:00</published><updated>2008-02-04T21:00:42.809+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Useless drivel'/><title type='text'>He's back!</title><content type='html'>Hello people!&lt;br /&gt;&lt;br /&gt;I'm back after a long hiatus! This time I intend to keep up the blogging and keep it at the same domain.&lt;br /&gt;&lt;br /&gt;Watch this space!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-7277243317790057399?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/7277243317790057399/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=7277243317790057399' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7277243317790057399'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7277243317790057399'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2008/02/hes-back.html' title='He&apos;s back!'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6133363959081933104.post-7230513855638219622</id><published>2006-06-16T23:41:00.003+02:00</published><updated>2008-06-19T20:12:14.369+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Software Engineering'/><title type='text'>Requirement Points in Software Engineering</title><content type='html'>This post describes how I use requirement points (or story points as they are called in eXtreme Programming) to manage the time aspect of software projects.&lt;br /&gt;&lt;br /&gt;My use of requirement points are very similar, if not identical, to the way they are used in eXtreme Programming. The reason why I have decided to write about requirement points aside from eXtreme Programming is because I find them useful no matter what process/methodology/framework is used for developing software.&lt;br /&gt;&lt;br /&gt;To enhance the explanation of requirement points I will use a recent project I worked on as a case study. However, I’ll start by defining the theory and then apply it to the case study in a later post.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Theory&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;What is a requirement point?&lt;/strong&gt;&lt;br /&gt;A requirement point is an arbitrary number that signifies a certain amount of work needed to satisfy a requirement.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;The Process&lt;/strong&gt;&lt;br /&gt;Below is a simplified process outlining the phases where the requirement points come to play&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/6143/2955/1600/simplified-process.3.jpg"&gt;&lt;img border="0" src="http://photos1.blogger.com/blogger/6143/2955/200/simplified-process.2.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;1.0 Initial Estimation&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;u&gt;Step 1.1) Baseline&lt;/u&gt;&lt;/em&gt;&lt;br /&gt;&lt;em&gt;&lt;u&gt;&lt;/u&gt;&lt;/em&gt;&lt;br /&gt;We need to baseline the requirement point to some initial value. There are a number of techniques for doing this. Here are a few techniques that I find useful:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt; &lt;li&gt;Time-based&lt;br /&gt;Assume that a single point is equivalent to given time span, e.g. 1 hour, 1 day, 1 week, or 1 month.&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Scope-based&lt;br /&gt;Assume that a single point is equivalent to a certain amount of work, e.g. 1 point equal to a basic C/R/U/D implementation for an entity).&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;The technique used depends on your personal preference. Many professionals refrain from using the time-based technique as its meaning keeps changing throughout the project as you will see later. However if you work with a customer that requires immediate time estimates the time-based technique can provide you with an initial estimate.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 1.2) Estimate Requirements&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;Using requirement points estimate all known requirements.&lt;br /&gt;&lt;br /&gt;A rule of thumb in project management is to always breakdown work into smaller chunks that are easier to estimate. Each requirement may therefore have to be broken down into smaller tasks.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;&lt;u&gt;Step 1.3) Determine initial project velocity&lt;/u&gt;&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;The project velocity is the number of requirement points that can be implemented in one customer iteration. If you use the time-based technique to baseline the requirements point then the initial project velocity could be the number of hours or days that make up the duration of a customer iteration. The duration of a customer iteration is often recommended to be no longer than three weeks.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 1.4) Determine the velocity of each project member&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;Determine how many requirements points each project member is expected to complete each customer iteration. To avoid causing problems among the project members you may want to start all project members at the same level.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;2. Iteration Planning&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 2.1) Determine project velocity&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;Once again the project velocity is determined, but this time the focus is on the duration of the current iteration. If some members are not available full time, or public holidays are coming up, this will reduce the project velocity. You can reduce the project velocity using basic maths, e.g. if a project member is only available for half the iteration, you would remove half the velocity of the member.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 2.2) Requirements Selection&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;It is the customer or business representative’s responsibility to select estimated requirements worth the current project velocity. This will make up the iteration plan.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 2.3) Requirements Acceptance&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;I could also have called this step “Requirements Delegation”, but there is a theory that says that for project members to be truly effective they have to select their own work, so rather than implying that the project manager delegates the requirements selected from Step 2.1, it is instead implied that project members pick and accept the requirements they would like to implement. Project members pick requirements worth their personal velocity.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;3. Implementation&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 3.1) Tracking&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;While the project members are implementing the selected requirements they keep track of how many requirement points they complete. If a project member completes all the requirements he has accepted he will be able to pick more requirements from the pool of requirements (preferably the ones of high customer importance).&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;4. Evaluation&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 4.1) Re-calculate project member velocity&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;The project member velocity is re-calculated by adding up all the requirement points he has managed to complete. In that way his personal velocity will go up if he has managed to complete more than he accepted, or down if he fell behind. This new velocity is important in that it will constitute the amount of requirements the project member is allowed to accept in the next iteration.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 4.2) Re-calculate project velocity&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;The velocity of all project members is summed up and determines how much progress was made in that iteration and how much effort is required to finish the remaining requirements. When the project velocity has been calculated the burn down chart is updated.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://photos1.blogger.com/blogger/6143/2955/1600/burn_down_chart.3.jpg"&gt;&lt;img border="0" src="http://photos1.blogger.com/blogger/6143/2955/200/burn_down_chart.0.jpg" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Note: The burn down chart is a graphical representation of the history of the project velocity. The chart can also be made for each individual project member.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;&lt;em&gt;Step 4.3) Customer Evaluation&lt;/em&gt;&lt;/u&gt;&lt;br /&gt;&lt;br /&gt;The customer evaluates the system and decides if the development should go on or halt. If the customer decides to continue with the development the process jumps back to Iteration planning.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Using requirement points is simply and does not require you to follow eXtreme programming or any other specific methodology. It will require you to estimate requirements and keep track of how many points you complete, the benefits however are enormous as you will always be able to get a clear view of how much effort are remaining and how well you are performing. Furthermore it allows for auto-correction of project members with inaccurate estimation skills by providing them with a personal velocity based on their previous performance.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Fowler 2000&lt;/strong&gt;, &lt;em&gt;Planning Extreme Programming&lt;/em&gt;, 1st Edition, Addison Wesley&lt;br /&gt;&lt;strong&gt;Beck 2005&lt;/strong&gt;, &lt;em&gt;Extreme Programming Explained&lt;/em&gt;, 2nd Edition, Addison Wesley&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6133363959081933104-7230513855638219622?l=bigallan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bigallan.blogspot.com/feeds/7230513855638219622/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6133363959081933104&amp;postID=7230513855638219622' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7230513855638219622'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6133363959081933104/posts/default/7230513855638219622'/><link rel='alternate' type='text/html' href='http://bigallan.blogspot.com/2006/06/requirement-points-in-software.html' title='Requirement Points in Software Engineering'/><author><name>Allan Lykke Christensen</name><uri>http://www.blogger.com/profile/00646797647221121520</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='22' height='32' src='http://bp0.blogger.com/__SeQT33Fv3E/R6djGG-3IqI/AAAAAAAABZ8/W_9ELjjh_lQ/S220/small_DSC00143.JPG'/></author><thr:total>1</thr:total></entry></feed>
