Saturday, March 24, 2007

TSSJS 2007, full time

TSSJS 2007 is over, or at least it will be in about ten minutes. I left the last session a bit early since it focused a bit too much on SOA(P) and too little on raw XML processing, which was my area of interest. It's a real shame that there's no official after-party with a chance to mingle with the Java in-crowd, everybody just seem to go home. We are staying until Sunday morning, so Friday evening and Saturday will be a mini-vacation.


The second half has been mixed, as was the first one. This morning's keynote was an endless stream of three-letter acronyms and buzzwords from a top Oracle executive, Tomas Kurian. He outlined how Oracle see the future of computing, which was quite painful to sit through. At least until an interesting announcement was made: Oracle buys Tangosol Coherence. Cameron outshone the Oracle guys with his demo, which while it wasn't very substantial, it did actually work. The Demo Devil apparently spares no one, not even senior Oracle engineers.

But the absolute highlight of the entire conference was the "Java performance myths - how do JVMs really work" session with Brian Goetz. He crammed in probably around 150% more words that the average speaker (he talks fast), and it was extremely valuable information. He went through a number of long-loived Java performance myths (object allocation is slow, garbage collection is slow, synchronizarion is slow etc) and explained why they are no longer true. His advice can be summarized into the following sentence:

The JVM is always smarter than you.

Java isn't an interpreted language, it's dynamically compiled, which enables the JVM (or the JIT compiler) to gather statistical data, at runtime, on how code is being executed to aid in optimization of the code. Also, the JVM is tuned to recognize commonly found patterns of execution and optimize them as best it can. This means that the more well-designed, clean code you write, the bigger the chance that the JVM (JIT compiler) will recognize code patterns and be able to do a good job at optimizing the code. Since the compilation into native code happens at runtime, and can even vary over time (code can be re-analyzed and re-compiled dynamically), it's very difficult to try and predict how the source code you write actually will be compiled and executed. This also has the side-effect that writing isolated benchmarks is often useless and/or misleading, since they don't properly reflect real-world usage. Just write as clean, readable and maintainable code as you can, and safely assume that the JVM will do a better job than you at optimization.

One interesting aspect of synchronization improvements in recent JVMs (Sun Java 6, I believe) is that there is no longer any performance difference between using StringBuffer (syncronized) and StringBuilder (not synchronized), since the JVM automatically detects that synchronization isn't needed, and the code executed will be equivalent. I can actually back this up with test data I gathered around the time I wrote about how the Java bytecode compiler automatically converted String concatenation using the + operator to StringBuffer/StringBuilder (depending on which version of javac used). I found no speed difference whatsoever between the two, which profiling a webapp during load-test with several hundred simultaneous threads, which at the time made me quite confused, but now I have an explanation. So the old truth "Concatenating Strings is slow, use StringBuffer" and the not so old truth "StringBuffer is slow, use StringBuilder" are now both false*, and can instead be reduced to "it doesn't matter at all". Since performance is equal, readability wins - use regular concatenation (+).

Of course, in most cases the application bottlenecks aren't in your code at all, but in I/O operations against databases etc.

I wrote a small benchmark (even though I just said that benchmarks are useless) that you can check out and play around with.


* if the JVM comes to the conclusion that StringBuffer synchronization isn't needed, which is often the case.

Thursday, March 22, 2007

TSSJS 2007, half time

I'm writing this as I'm waiting for the the presentation "Agile Development Metrics" by Neal Ford to begin. I attended a presentation on Selenium that he did yesterday, and that was one of the better ones so far. The overall quality of the sessions has been mixed, ranging from fairly shallow (Rod on "Spring 2.0 and beyond") or way too basic (Mark Richards on "Advanced (bah!) JPA", Adrian Colyer on "Simplifying Enterprise development with AOP") to very good. Hani biled the JPA session, and my feelings were exactly the same. "Hey, if you add fetch=FetchType.EAGER to your annotation, the relation is no longer lazy!". Duh. Also, showing how to make a POJO transactional using AOP isn't exactly jaw-dropping in 2007.

What is jaw-dropping however is the scale of operations run by investment banks, that John Davis talked about this morning. Java is widely used in the banking world, and outperforms C/C++ a lot of the time, but a 50 ms garbage collection run is unacceptable since it would mean missing business opportunities worth millions of dollars. The solution: hardware garbage collection. He also explained that the speed of light was a limiting factor for performance. Yes, that's right. The speed of light. A theoretical best-case roundtrip for light to travel between New York to Chicago is around 8 ms, which is enough to motivate moving the physical system from NY to Chicago if you need to talk to another system in Chicago, for example. XML isn't widely adopted either, for performance reasons. If it's used at all, you often have a situation with a single element with 4000 attributes, to minimize the number of angle brackets to parse. And when it comes to reliable messaging, no JMS vendor can match the SWIFT system, used by 8000 banks world-wide to transfer money between them. They guarantee 100% reliability, to the point where they will refund any amount submitted to the system that is lost. However, in the 30 years that they've been operating, they haven't yet lost a single message. They average around 12 million messages a day. The particular investment bank that John talked about handled around $500,000,000,000 (five hundred thousand million dollars, or half a trillion) a day, so that's why even milliseconds matter. Quite a few "whoooa!" moments during the speech :-).

The second half of TSSJS contains a few sessions that I hope will be interesting, mainly around clustering and JVM and XML performance and scalability, which will be relevant in my current work assignment right away. There's one presentation held by a Swedish developer, Jonas Bonér of Terracotta fame which I'll be watching. Terracotta has gotten quite a few mentions in other presentations, and it seems really useful in some situations.

Next up is Cameron Purdy from Tangosol. I'll be back with a review of the second half on Saturday, I think.

Monday, March 19, 2007

Viva Las Vegas

Oh how hard it is to come up with headlines for non-technical posts...anyway, I'm going to The ServerSide Java Symposium in Las Vegas tomorrow, which I'm sure will be a fantastic experience. My room at The Venetian is almost as big as my apartement, and both the weather and the schedule look very promising indeed.

So, if you're reading this and are going to TSSJS, say hi if you recognize me (I have a little bit shorter hair than on the photograph right now). My guess is, however, that the only two people in the world that fit both categories are on the same plane as I am...

Tuesday, March 06, 2007

SimpleFormController demystified - part 2

In the first part we covered the basics about the available controller approaches in Spring MVC, and the simplest possible scenario for using SimpleFormController - creating a new User.

The next step is to adapt out UserController to handle editing existing users as well, which is natural to do in the same view. What we need to do, is of course to load a specified user from our storage and prepopulate the input fields with the current values, and then hand a User object with the new/changed values back to our storage when we submit the form.

SFC uses a command object to bind parameters, just like the ActionForm in Struts. The difference is that in Spring MVC, the command object can be any class, which makes it possible to re-use the domain model classes instead of duplicating all properties in a class that extends ActionForm. As we noted in the first part, SFC places the command object in the model under the default name "command", so that you can access properties using ${command.firstName} etc in the view. If you want to use another name, call setCommandName() in the constructor or set the property in XML.

The default behaviour of SFC is to simply instantiate the command class to get the command object . What we want to do however, is to check if a certain parameter is set (such as "id"), and if it is, load the corresponding instance from storage and use as command object. The proper callback to override in this case is formBackingObject():

@Override
protected Object formBackingObject(HttpServletRequest request) throws Exception {
Long id = ServletRequestUtils.getLongParameter(request, "id");
if (id != null) {
User user = userDao.load(id);
if (user != null) {
return user;
}
}
return new User();
}

If the "id" parameter is present, and if we can find a persistent entity with that id, we use that as our command object, otherwise simply a new User. The input fields are prepopulated like this:

<input name="firstName" value="${command.firstName}"/>

As far as showing the form, it is all very straightforward. When it's time to submit the form, we need to take a step back and think about when formBackingObject() is called. It is obviously called when we first show the form, that is when we issue a GET request for /user/edit.html?id=1, when the User with id == 1 is loaded and put into to model. But once that requests ends, the User instance is lost, and we need an instance to bind the POST parameters to as well.

There are two ways to solve this: either store the command object, our loaded User, in the HttpSession, or repeat the same process as when showing the form. SimpleFormController has built-in support to store the command object in the session, just call setSessionFrom(true). Default is false, meaning we don't store the command object in the session, but instead call formBackingObject again on post. In order for that to work, you need to supply the id parameter again in the form submit, either as a hidden input:

<input type="hidden" value="${command.id}"/>

or as part of the form action url:

<form action="/user/store.html?id=${command.id}" method="POST">

Otherwise formBackingObject will instantiate a new User and bind parameters to that, most likely resulting in a new User being created by the storage instead of updating the existing one.

Note that the ServletRequestUtils.getLongParameter() method unfortunately handles "?id=" as an invalid Long value instead of null (throwing ServletBindingException), so don't build the id input at all if the User does not have id set:

#if ($command.id)
<input type="hidden" value="${command.id}"/>
#end


Storing the command object in the session has pros and cons: one benefit is that it requires one less call to the storage to fetch the command object, on the other hand putting lots of things in the session consumes memory on the server and increases the load on session replication, if you're running a cluster. As far as simultaneous editing goes, it doesn't really make much difference, since you will overwrite using your input value on submit either way (unless you put a row lock on the database and don't commit the transaction until after posting, but that's beyond the scope of this article).

I will post the source code for a very simple project implementing this article series shortly, watch this space. The next part will be about validation and more sophisticated forms.

Thursday, March 01, 2007

SimpleFormController demystified - part 1

Spring MVC is a very flexible powerful Model 2 framework, but as with all flexible frameworks, it comes with a price - confusion. In order to write a controller you have the freedom/burden to choose between implementing one of two single-method interfaces, or inherit from one of the 13 (!) skeleton implementations available. Most of the time you're probably going to want one of the extremes: as much help or as little help as possible. The former scenario is typically things like a LogoutController, where you just invalidate the session and redirect to the default start page or whatever. Good candidates for this is either to implement the Controller or the ThrowawayController interface, or inherit from AbstractController, which adds a few cache header setters and some other stuff. Using the AbstractController approach, it would look like this:

public class LogoutController extends AbstractController {

public ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) {
request.getSession().invalidate();
return new ModelAndView("redirect:/start.html");
}

}

Another candidate is when you want to delete a blog post, in which case you're only interested in a single parameter:

public class DeletePostController implements ThrowawayController {

Long id;
BlogDao blogDao;

public Long getId() { return id; }

public void setId(Long id) { this.id = id; }

public ModelAndView execute() {
blogDao.deletePost(getId());
return new ModelAndView("redirect:/posts/list.html");
}

}

The ThrowawayController is instantiated on every request, and binds parameters directly onto the controller class instead of a separate model bean, similar to the WebWork/Struts2 approach.

So in general, if you're only interested in zero or one parameter, and don't care about validation or anything, the as-simple-as-possible approach is probably right.

But this article series is supposed to be about the controller base class that gives the maximum amount of support, SimpleFormController (SFC). Some people think that's an oxymoron, but I'm going to try and show the easy ways to accomplish many common tasks using SFC.

SFC handles two actions: preparing a form view and showing it, and taking care of the submission and showing a resulting view. By default, the request method determines what kind of action to take - GET means prepare and show the form, POST means submission (it is possible to override isFormSubmission(), but it's very rarely necessary and we can disregard that for now). That is why there are two views to configure.

Suppose you have the concept of a User in your domain, and you need a way to create and edit these users in a web form. There is already a domain class named User, that's persisted in some way, and it has two properties: firstName and lastName (we'll add more later on). In order to build a controller that is capable of storing a new User, you need to do the following:

public class UserController extends SimpleFormController {

UserDao userDao;

public UserController(UserDao userDao) {
this.userDao = userDao;
setCommandClass(User.class);
}

protected void doSubmitAction(Object command) {
User user = (User) command;
userDao.store(user);
}

}

And some configuration in yourApp-servlet.xml (view parameters can be set in the constructor too, if you prefer that, and you can move the command class configuration out to XML too):

<bean name="/user/create.html" class="com.example.UserController">
<constructor-arg ref="userDao">
<property name="formView" value="user/editForm">
<property name="successViewView" value="user/created">
</bean>

This is really all there is to it. The form preparation phase is simply an instantiation of the command class, in our case a User, and rendering of the "user/editForm" view. When the form is submitted, all parameters are bound to a User instance and handed to us in the doSubmitAction() callback method where we simply store it. The superclass will then render the success view.

The default handler mapping (what controller that handles what urls) is the BeanNameUrlHandlerMapping, which uses the name attribute for registering controller beans to urls. It accepts wildcards and space-separated lists: name="/foo /bar", name="/user/*" etc.

Don't forget to set the form method to POST in the HTML page, otherwise the controller will think that you want a new form every time you submit the form. Note that the action url will be /user/create.html as well, unless you map both /user/create.html and /user/store.html to the same controller.

The input names should match the properties on the command object:

<input type="text" name="firstName"/>

The command object itself is available in the view under the default name "command", so you can access properties like this: ${command.lastName}. That will be more interesting in part 2, when we'll edit existing users.