JSF Backing Beans are Just Controllers

Writing some initial code for a JSF TDD seminar I’m putting together for our developers I had an early test method:

public void testUserCanLogin() throws Exception {
  User fred = new User();
  fred.setName("fred");
  fred.setPassword("password");
UserBean userBean = new UserBean(); userBean.setUser(fred);
assertTrue(userBean.login()); }

After realizing the JSF backing bean, UserBean, is actually just a page controller and all I want it to do at this point is allow a user to login I refactored the name:

public void testUserCanLogin() throws Exception {
  User fred = new User();
  fred.setName("fred");
  fred.setPassword("password");
LoginController controller = new LoginController(); controller.setUser(fred);
assertTrue(controller.login()); }

Part of this may be inspired by Ruby on Rails, but I get tired of using Bean in so many java classes, and really this bean was not just a traditional DTO style bean with no behavior. So Controller just feels a lot more explanatory. As an extra bit of semantic cleanup I renamed the default package for the backing bean. By default when you use RAD 6.0 to setup a new JSF page it dumps your backing beans into a

1
pagecode.pages

package which bugs the crap out of me. So since I’m starting from scratch and working in IDEA I just put it in a

1
controller

package which describes its function better.

PeepCode and Screencasts

Last week, I finally got around to checking out Geoffrey Grosenbach’s PeepCode screencasts. Not much risk at nine bucks, I went ahead and sampled the Test First Development episode, because I’m a test first convert.

I learned a lot of small points:

  • How to easily run Rails edge for a single Rails project.
  • Other people, or at least Geoffery Grosenbach deal with BDD utilizing well named test methods including things like <div class="codecolorer-container text vibrant overflow-off" style="overflow:auto;white-space:nowrap;">
    1
    test_should_guess_date

    </div>

    , so I’m not alone.</li>

    • Learned about the nice natural language date/time parser, chronic.
    • Move to <div class="codecolorer-container text vibrant overflow-off" style="overflow:auto;white-space:nowrap;">
      1
      assert_select

      </div>

      replacing the

      1
      assert_tag

      in Rails 1.2.</li> </ul>

      The format works really well for tutorials as you can follow along by simple pausing every 30 seconds or so and typing in the examples as you can go. Many technical trainers will tell you group demos are really great, but difficult to pull off. The problem is people don’t keep up at the same pace or they miss something typed in and start seeing exceptions instead of moving forward with the rest of the class. This really lets you follow along at your own pace. The other nice thing was that all of the code typed in actually worked.

      I’ll probably try out the TextMate screencast next since I don’t feel like I’ve yet scratched the full power of the editor.

Bug in Java 1.5 Timestamp.compareTo()

About two months ago we caught a nasty issue with getting some

1
ClassCastExceptions

when comparing two

1
Dates

. The code that failed the unit tests looked something like:

if (startDate.compareTo(endDate) < 0) {

The strange part was the developers running IBM’s RAD 6.0 never had failing tests and

1
ClassCastExceptions

. The tests failed on the build box. When I tried the tests in IntelliJ they failed as well. After some investigation it was apparent it some of the

1
Dates

were coming from a Hibernate mapping class and so they were dates, but in actuality they were

1
java.sql.Timestamps

. Since

1
TimeStamp

extends

1
java.util.Date

this wouldn’t appear to be much of an issue. The fix was simple enough:

startDate is actually a java.sql.Timestamp
endDate is actually just a java.util.Date

So just switching the order and utilizing

1
java.util.Date's
1
compareTo()

makes the problem go away.

if (endDate.compareTo(startDate) > 0) {

Seemed like a crappy overriding of the

1
compareTo()

method by

1
java.sql.Timestamp

, but it did fix the problem. Some more digging turned up the real story. A bug, #6304469, was actually introduced in Java 1.5 and has now been fixed in 1.6. Since RAD 6.0 was running in 1.4 and it only supports 1.4 this explained why we didn’t see the bug in RAD.

The explanation in the Java 1.6 release notes is:

A regression introduced in J2SE 5.0 created a binary compatibility problem with java.sql.Timestamp.compareTo which was only detectable at run-time.

This bug is fixed in Java SE 6, Beta2 and in J2SE 5.0, Update 7 (5.0u7).

Encrapted Passwords

Learned a new term today going through 19 Deadly Sins of Software Security. They give an example of a URL containing a strange looking id parameter:

1
www.xyzzy.com?id=TXkkZWNyZStwQSQkdzByRA==

Turns out a simple run through a base64 decoder for gives you:

1
My$ecre+pA$$w0rD

The authors then refer to this as an “encrapted” password.

Excessive Setup Anti-Pattern

James Carr has come up with a basic list of TDD anti-patterns and while I’ve seen many of them, one currently still plagues many of our tests:

Excessive Setup

A test that requires a lot of work setting up in order to even begin testing. Sometimes several hundred lines of code is used to setup the environment for one test, with several objects involved, which can make it difficult to really ascertain what is tested due to the “noise” of all of the setup going on.

The core issue comes down to having to use JSF for the GUI layer and dealing with its’ many mock objects using Shale’s mocking package for JSF. Thus many tests cannot simply test a single method without making sure FacesContext and many other stubs are setup. This tends to make the tests harder and more tedious to write especially for developers who haven’t quite caught the whole TDD bug anyway. The setup might not be hundreds of lines, but it is far more than you’d want for simple unit testing.

We’re still looking at ways to improve this from refactoring out even more code out of JSF backing beans to bringing in some TDD heavyweights to mentor the team through the best way to deal with it.