Spring 2 MVC and ResourceBundleViewResolver problem

2008/01/24

This one took some time to figure out – it is one of those problems that are obvious after you know the solution but hard to see beforehand.

I had the ResourceBundleViewResolver configured with Tiles 2, like this:

<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="order" value="0"/>
<property name="basename" value="views"/>
<property name="defaultParentView" value="parent-view"/>
</bean>

and the view.properties was:

parent-view.(class)=org.springframework.web.servlet.view.JstlView
parent-view.(abstract)=true

about.url=/WEB-INF/jsp/about.jsp
form.url=/WEB-INF/jsp/form.jsp
list.url=/WEB-INF/jsp/list.jsp

It kept givin exception saying that /WEB-INF/jsp/list.jsp does not exist. Which it did. I tried couple of things, no result.

The problem was in trailing space AFTER list.jsp, therefore the path to JSP file searched for was “/WEB-INF/jsp/list.jsp “, not “/WEB-INF/jsp/list.jsp”.

Not sure if this is bug or feature – but removing trailing spaces should really be a sensible thing to do. As I found afterwards, the problem exists since 2005 – see this and this.


Using iBatis with Abator

2008/01/20

I am back to Java and on mission of re-discovering Spring coolness – and in awe how much was added since 1.2 to current 2.5.1. Thanks, SpringSource and hundreds of contributors.

Data layer of the current project is based on iBatis and Spring DAO. We have decided to try out the Abator tool from Apache (part of the iBatis suite) to generate initial version of data mapping (as we inherited the database schema).

Only necessary part is abator.jar (there are no other dependencies).

The abator is driven by the XML file that defines to which database to connect and which tables must be be processed.

Running abator is simple:

java -cp abator.jar org.apache.ibatis.abator.api.AbatorRunner PROJECT.xml true

Parameter ‘true’ defines whether generator will overwrite files.The generated files are stored in location from xml file (in our case ‘generated/src’). This directory MUST exist – Abator will not create it.The project file contains information about your database driver + connection the used generator, packages for generated Java and XML files. The Java5 generator is very useful, because it produces code using generics. Abator can also understand Spring based iBatis templates and produce code directly usable in Spring projects.Two “gotchas” I have encounter (so far):

If you generate maps with many tables, the Abator assumes that you will be using namespaces. The examples from Spring do not however use namespaces, so if you use the existing code as blueprint for your project, make sure you have the namespaces enabled in the sqlmap

<sqlMapConfig>
<settings useStatementNamespaces="true" />
...

Second is related to timestamp columns (e.g. CREATED_AT and similar columns).In Java, they are (most of the time) represented as java.util.Date object, which contains both date and time portion. In SQL, there are multiple data types available, depending on your database. We are using Oracle 10g and the generated map was using DATE as SQL type. This caused cutting of the time portion of the value and setting all times to 0:00:00.The solution was to use proper, explicit types for both SQL and Java. You may need to edit the map in multiple locations, replacing:

<result column="CREATE_DATE" property="createDate"
jdbcType="DATE" />

with


<result column="CREATE_DATE" property="createDate"
 jdbcType="DATETIME" javaType="java.util.Date" />

and the


CREATE_DATE = #createDate:DATE#,

with


CREATE_DATE = #createDate:DATETIME#,

After this, everything works fine.So far, the only minor unresolved annoyance is the abatorgenerated_ prefix of all SQL id’s – I cannot find the way how to switch it off.It is sometimes very useful – if you want to re-run the tool, it will not touch SQL without this prefix. In our case, where the generated code is just an initial step to speed us in getting the initial codebase out fast., we would actually prefer to avoid it and keep the SQL fragments id’s nice and tidy.


Steve’s latest …

2008/01/16

Of course, I mean the other Steve, Steve Jobs. My world is revolving around few Steves. Steve Jobs is usually Steve Nr. 2 – and no, Joel – the Steve #1 is definitely not Ballmer :-). But every year, for two brief occasions – Macworld and WWDC – Steve Jobs becomes Steve #1 for very large amount of people.

I was waiting with this post full day to allow the new-ity of the keynote sink in and reality distortion field to evaporate …. This is my take on the latest from Appleverse – and an answer to all who were asking whether I did already (pre)ordered and what :-). The answer is – nothing so far. I even have mixed feelings about the four Macworld news and here is why:

Biggest news and coolest announcement is the Macbook Air. Yes, it looks very nice indeed. Yes, the new gestures are amazing. Both pricewise and performance-wise it sits in between Macbook and Macbook Pro, beating both on coolness and portability. But I think I will skip this one.

Main reason is that number of notebooks in my house divided by number of household members is already bigger than one – even if I include the cat. Besides, I do not really need ultra portable notebook so it is hard to justify the cost. For an eBook reader it is still too big and has too short battery life. And for serious work, the screen is too small and the computing power / graphics card not a match to Macbook Pro.

If I did not already have a Macbook, that may have been very strong temptation. But – IMHO – being thinnest and best looking is maybe most important for superstars, but not the most important feature for a notebook. For $500 less you will get same size screen with same resolution, same graphic card, 20% faster CPU plus the DVD drive and Ethernet port. Is the form factor and iluminated screen worth six hundred dollars ? You decide. I am just not convinced that it is worth the asking price of $1899. And how the hell did Apple come to the conclusion that $1799 USD times 1.01 equals $1899 CAD ? What kind of math is that ?

Apple is generally not very nice to Canadians. Regardless of pretty much parity between the loonie and the greenback for many months, we are still paying 10-15% more for the same products as our friends in the USA. We have (officially) no iPhone – unlike Germany, France and UK . Selection offered on iTunes here and down there is so different that it is not even funny. No movie rentals for us for quite some time. It may or may not be in Apple’s hands and possibly caused by legal issues around our overregulated telecom sector … But back to the Macworld.

The iPhone / iTouch upgrades do not excite me at all. The iPhone upgrade is irrelevant (see above) and from the new Touch 4 apps I do not need at least three. Google Maps on iTouch cannot work anywhere as good as on iPhone. Not without phone tower triangulation capability. And density of public WiFi spots in Canada …. no comment. I guess much better will be to wait until SDK is out and third party vendors will join the market. I will happily pay for an application that will make Touch better eBook reader. But charging the $20 for the apps that otherwise identical, same retail price iPod will have for free since today, just cannot be understood otherwise than Apple likes to punish the early adopters – the most loyal fans. Second time in less that 8 months. Point taken …

If you live in the USA, new Apple TV is actually a great idea. The convenience of renting without leaving the sofa can make a huge difference. Price is the about the same or better as the OnDemand rental, you have 30 days to start watching and the same 24 hrs to finish as with cable. What is IMHO killer feature is making it computer independent, but still allow transfer purchased/rented content to your Mac or PC and iPod. An ideal way how to take few movies with you for a long flight or commute. I would buy one right away – if there was a good content.

If the Apple TV had a DVD slot, it would be completely amazing and it would be best shot to become the only box next to TV – no more need for digital terminal and DVD player … I will re-evaluate this one when it is clear what is the iTunes movie selection in Canada – and stick with cable and DVD until then.

Last but not least – Time Capsule. Nice, but I already have an external harddrive for Time Machine. Whether paying twice the price of 500 GB disk is worth the convenience of not having to attach the cable to my Macbook – I am not quite sure. I am also not sure how will the wireless backup speed do compared to FireWire. Capability of backing up both Macs would not help me either because the Macbook still runs Tiger …

So from all the shiny new offering, my most likely 2008 purchase is something that was announced before Macworld to avoid distracting the audience and stealing the thunder: the new Mac Pro server. Getting really well designed and well built 8 cores server with 16 GB RAM for a little more than $4000 is a great deal – and he best way how to run Windows: inside the safe boundaries of UNIX :-).


The best GTD tool is still a Wiki – part II

2008/01/14

Continuation of this post.

As every TiddlyWiki, the main building block of the MGTDTW (MonkeyGTD TiddlyWiki, if you are wondering what kind of monstrous acronym is that) is a tiddler. And the only one building block because everything is a tiddler. How does this map to the GTD approach ?

The GTD workflow works with projects, contexts and actions. Action (or task or todo) is smallest building stone. The actions in GTD are really small actions. Every goal that requires multiple steps is a project – thus project has multiple actions. Context is an environment for executing the actions – e.g. Office, On-Line, Errands. Action can be in of the the state: “next” – ready to be started, waiting-for (something else needs to happen before you can start), future (something you may want to do later but not really a task right now) or done. OK, this is slightly oversimplified – for real explanation check the resources in Part I.

Everything GTD related in MGTDTW is done using tags on tiddler and “special tiddlers”. Because tiddlers are all there is, all your actions are tiddlers. So are all your projects and context. What makes “action tiddler” differrent from “project tiddler” is that action tiddler has tag “Action” and tiddler representing the project has tag “Project”. The Wiki is smart enough to provide an easy UI to assign the tags and to create the tiddler. For example, inside the “project tiddler”, you have links to add new next action, new waiting action, new future action. Each of this create new tiddler, tags it with “Action” tag as well as with appropriate action status tag.

Some tags have graphical representation rather than verbal. Clicking on yellow start will assign/unassign the tiddler Starred tag. Starred items are quick reference list for wide variety of the usage.

If you read The Book, you will learn about other concepts such as reference file and ticklers. Good news is that the MGTDTW implements both. The tickler is special UI for the tiddler connected with the year-month-day – an activation date. The reference is simply a tidller tagged as Reference. Simply use subject matter tagging in addition to that to properly categorize it. But whether you tag it or not, you can always find it using fulltext search as well as see it in the timeline

The MGTDTW has also few extensions above the “canonical” Allen-ist GTD (if such thing as cannonical GTD exists at all). These extensions are Areas – something similar than projects and Realms – something even wider. By default, two realms are defined: personal and work, which pretty give an idea how they can be used: separate world or zones of responsibilities. The areas are trickier: they can be used as groups for projects (for the control freaks ;-)). The UI design of the project suggest this usage and makes it very easy. In one of the Mac programs (I believe it was Things) I have founds different explanation for area: it is kind of project that is never done – like house maintenance. MGTDTW does not directly support this semantics, because the action UI does not offer the Area, only Project. But nothing prevents you in the edit mode tag the action with the area tag. It will show properly in the Area view as the Next Action, even if it is not assigned to a project.

Many of these concepts are actually much easier to see and experience than explain. So why not donwload the MGTDTW and play with it ?


Safari Books Online and Lynda.com on iPod Touch

2008/01/11

Last few weeks I have been using one application on iTouch much more than before: YouTube. Within my how wireless network, I can have an access to the videos on YouTube without sitting behind the computer – for example while walking on treadmill (I recommend walking slowly) or on a sofa :-).

Very interesting videos and actually worth the time spent on them are Google technical talks from Google channel. Few examples of videos I watched and liked:

– Linus Torvalds talk on Git
– Brian O’Sullivan talk on Mercurial
Secret History of Silicon Valey

All these videos are available in larger format on Google Video as well.

I was trying to watch the instructional video’s from Lynda.com on iPod touch as well. Unfortunately, that does not work. I could log on to Lynda and select the section, but instead of video, only an icon of broken movie player was displayed. It seems that iTouch Safari does not support the plugin required for the Lynda videos to function.

Speaking of Safari – our company has corporate subscription of Safari Books online – a huge library of almost 4000 technical books. An excellent resource ! The website is very well readable on the Touch. Especially nice feature is that after you “pinch” web size to enlarge it (and focus on the content area), the changing to page does not resize page back to default, but keeps the resolution. This way you can easily move around and navigate with single finger …

Nicely done Apple / O’Reilly Media :-).


Sony eReader format (LRF) viewer for the Mac, Linux and Windows

2008/01/07

Thanks to Kovid Goyal, the Sony Reader’s very own terrible software (iTunes wannabe) can very soon be decommissioned from my software collection. The libprs500 project, multi-platform solution written in Python works very well and allows to move data between Sony and your Mac / Linux / Windows. The UI is actually pretty decent, considering that it is not native Cocoa app:

picture-8.png

You can also edit metadata, which is very important because of the limited screen space on PRS500. As added benefit, the application gives you a reader for LRF file format that allows reading unprotected LRF books on the Mac/Linux as well in addition to Windows. Here is a snapshot:

picture-9.png

And best for the end: the libprs500 can do format conversion from TXT, HTML, RTF and LIT (haleluja !) as well as PDF – as long as it does not contain too many images. Seems like Christmas arrived twice this winter – and we have still Macworld ahead 🙂

Huge thanks to Kovid who wrote this thing and to Peter who made aware of it …


The best GTD tool is still a Wiki – part I

2008/01/06

Did you notice that there are seasons for software as well ? Similarly as with other merchandise, there are times during the year when many more people suddenly decide they need that one application X. Luckily, this trend is not as extreme as with e.g. Santa hats or carved pumpkins, which are impossible to find in stores outside of the narrow window around Christmas and Halloween (I am grateful for that :-)). In software world, the most seasonal category is tax preparation software, for obvious reasons. Taxes, like the dentist checkup are not something you will be crazy even thinking about, unless it is that time of year ….

Less seasonal but still quite tied to the “New Year’s Resolutions’ Season” is the personal productivity software. Every year in January, big part of the population starts to work on their time management skills, weight loss, healthy eating or personal productivity in general. I personally cannot wait until this wave fades and the gyms are at normal mostly-empty state – I hate waiting in line to get to treadmill just to listen to next episode of the TWIT. But back to the software.

After reading a lot (and I mean a lot) of articles about the best way how to do GTD (if you are not familiar with the cult of the GTD, see the 43 Folders, listen to the Merlin Mann’s interview with David Allen or buy The Book – ideally all of these), I have decided to review my tool selection from about 2 months ago. I am informally following the GTD approach with mixed success – I am about 10% more productive, but at least 50% less stressed, which much more important.

The GTD tools come in three categories: online-only, desktop based and something in-between. Hardest decision was deciding between whether go online only or not. As with GMail, having all your data in the cloud is so convenient and it eliminates problems with backups and synchronization. But what makes sense for email, does not necessarily work for the task management as well: quite often you want to go offline, free from temptations of RSS newsfeeds and distraction of the Web, just to think and plan. So online-only did not work for me. I did look into and tried out some online tools – if I get to it, I may write about the experience.

Non-web based tools give the maximal user comfort, as long as you have your notebook with you. This was a problem for me before, but since I have unified all platforms on the Macbook Pro, it became so indispensable that I hardly ever part from it, so this was less an issue. Also synchronization was not too important, for the very same reason: the notebook is portable enough to be taken with me anywhere I need. The last issue was the data format: with something so important, I was careful about keeping my data in proprietary format (more so after experiencing two occasions of Outlook PST file corruption and data loss during past 10 years).

The solution I have selected was Wiki-in-File, based on idea of TiddlyWiki. First – Wiki-In-A-File is Wiki system, implemented as one large HTML file, which stores both the data that is displayed in the browser as well as the code driving Wiki – in JavaScript. Unlike in case of a server based Wiki, you need neither Web server, nor the database – just open the .html file and after editing the content, save it back to disk (most W-I-A-F will create backup of the old file first).

In traditional Wiki’s, the information is structured into pages that are interlinked. In the TiddlyWiki, the unit is a page segment, named tiddler. The actual page consists of some subset of tiddlers, that are dynamically opened, added to page or closed by JavaScript code. The result is much more dynamic and less “webbish” – very Ajaxian.

TiddlyWiki offers all features that one would expect in a Wiki – such as automatic interlinking of tiddlers (pages), difference and history of a tiddler. It also has few great features that you normally find only in better products such as automatic timeline (list of tiddlers edited on a date), full text search, tagging of tiddlers and search by tags, macros. One features that is lacking is security and access rights – being a single user personal Wiki, it is not really a problem.

There are many flavors of TiddlyWikis out there: see this, this and this – or read the comparison. What is special on the MonkeyGTD (the one I am using) is predefined set of tags and content for the GTD specific application and also possibility of saving file both locally, or uploading it to the “cloud” on the tiddlyspot. The uploaded version is protected by password and can be used as emergency copy. You can also edit the online copy and save it both to local disk to the cloud. The only issue that I have found out is that it takes some management to keep track where is the latest version and whether to start with remote or local to avoid overwriting some changes.

This post starts to get too large, so better split it in few parts. In part II I will describe how the GTD works in MonkeyGTD. Stay tuned.


JRuby – keeping your database.yml really DRY

2008/01/03

I am experimenting in JRuby and use database in virtual machine (VMWare Fusion). This is great because you can have multiple versions of multiple databases ready without polluting the notebook. One downsize though is that IP address of the database will change between the VM restarts.

First important setting in Fusion is to use the ‘NAT’ option rather than ‘Bridged’. With NAT, you database host IP address will not follow the network. It was quite annoying to change it from 192.168.X to 192.168.Y everytime I reconnected at home from work or vice versa.

But even with this setting, the IP may change as you restart the VM and you will have to modify the database.yml. To keep the amount of editing minimal, here is my database.yml for the shoplet example:


<% dbhost = 'jdbc:mysql://172.16.219.131' %>
common: &common
adapter: jdbc
driver: com.mysql.jdbc.Driver
password: shoplet

development:
<< : *common
url: <%=dbhost%>/shoplet_dev
username: shoplet_dev

test:
<< : *common
url: <%=dbhost%>/shoplet_test
username: shoplet_test

production:
<< : *common
url: <%=dbhost%>/shoplet_prod
username: shoplet_prod

It will work in Ruby as well of course – with different (non-jdbc based) adapter..


Free Microsoft Press E-Books !

2008/01/02

Microsoft Press is handing out 3 books:

– Introducing Microsoft LINQ by Paolo Pialorsi and Marco Russo

– Introducing ASP.NET Ajax by Dino Esposito

– Introducing Microsoft Silverlight 1.0 by Laurence Moroney

Silverlinght 1.0 is probably a bit outdated (with 1.1/2.0 close), but the others should be good, judging by the authors. Dino Esposito wrote couple of very good books on ASP.NET and .NET.

See this blog for more details and download links.


Face(book) time

2008/01/01

It is a tradition to do crazy and wild things on New Year’s Eve. Some people play with fireworks and other noise making devices, other tend to celebrate the end of year by partying and drinking. I am not big fan of explosives and to sacrifice too many neurons to honor randomly chosen point on Sun’s orbit sounds like a pretty silly idea. But still, I wanted to do something out-of-line on December 31st.

So I joined Facebook.

It has been nagging me for some time – the curiosity about the API’s and “Facebook applications” and “new platforms” etc. The only way how to find out more and explore was to join. You can find me at firstname dot lastname at gmail dot com – if you have an account.

The reluctance was caused by the Facebook’s demographics and motivation. Unlike some other quite geeky social networks and groups, Facebook is wide audience and general public network. It is definitely platform of the “internet generation” – I found there my son and many of his friends. This was very nice discovery because now I know somebody whom I can ask stupid questions without public embarrassment :-).

People use Facebook to get new friends and meet new people and also expose their lives for the others. I have mixed feelings about both – I see the value of networking but …. However great it is to meet new people, if you do not have enough time for those people you already know, meeting new people makes situation only worse. And frankly – most people’s life is pretty uninteresting for the others and maybe keeping private things private would be better for all.

So far, I am in discovery mode and try to find out what is that Facebook thing all about. I have added few friends – if you are one of them, you may be exposed to unexpected results of my experiments :-). You have been warned …