Pragmatic J2EE Architecture

Saturday, March 18, 2006

MVC is not Templates

After studying the general misconception of "no logic in JSPs" in a previous post, I now deal with what I consider the most harmful misconception in the J2EE world: the general confusion with the MVC pattern and Template View Pattern, that drives architects and frameworks to introduce the template view concept as an evident and inevitable consequence of the MVC overall implementation.

Let's take a look at a typical Struts-based application:


public class CreateCustomer extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

try{
// .. Create the actual customer

}catch(Exception e){
// Some kind of error
return(mapping.findForward("createCustomer.jsp"));
}

// .. Prepare the data for the jsp
return(mapping.findForward("customersList.jsp"));
}
}

public class DeleteCustomer extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

try{
// .. Delete the actual customer

}catch(Exception e){
// Some kind of error
return(mapping.findForward("deleteCustomer.jsp"));
}

// .. Prepare the data for the jsp
return(mapping.findForward("customersList.jsp"));
}
}

public class ListCustomers extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

// .. Prepare the data for the jsp
return(mapping.findForward("customersList.jsp"));
}
}

We have three Struts actions. The first and the second do some business logic, and then redirect to the jsp that shows the list of all customers in the system. The third action does no business logic at all, but redirects to the customersList.jsp as well.

A seasoned architect can quickly detect a problem here. We have the same code repeated in all three actions. The three actions share the same jsp to redirect, which is a reasonable architecture strategy, but they all have to prepare exactly the same data for the jsp. The jsp can change its data requirements, which is a very usual thing, by presenting more objects, or presenting less, or presenting different objects. And every action calling the jsp must be aware of the changes. This is a clear example of duplication of code. All actions are sharing the code:

// .. Prepare the data for the jsp
return(mapping.findForward("customersList.jsp"));

What is wrong here? The key is that the data preparation and the jsp itself are very coupled issues. If the jsp will present the current date, the date must be prepared for the jsp. If the jsp will present the customer's name, age, and address, all this information must be prepared. The jsp is who better knows what to present, because it's all about view logic, as long as no model changes are performed in between. Every attempt to remove this logic from the jsp doesn't respond to a genuine architecture philosophy, but to the mistaken concept "No logic in JSPs".

If you are trying to remove all code from your jsp in such a way, you are in fact implementing a Template View pattern. In such a pattern the same data is prepared by a view delegate that then chooses a way to present this data by executing a different template depending on the case. Consider you have an application that serves HTML pages, as well as WML pages. A template view pattern is a sound pattern to be implemented here, as long as you have the same data to be visualized in different ways. Other reasons for adopting this pattern are "HTML Design and Application Programming are different skills", and "Development Tool Support". Template View Pattern has pros and cons, but it has definitely nothing to do with the MVC goal.

Remember: MVC is not Templates
  • MVC: Separation of model logic, view logic, and action logic (for user interaction with the model).
  • Templates: Isolating the HTML from the programming language code.


These patterns are orthogonal, and you could use them independently, by adopting one of them, both or none. So, if you really need to adopt the Template View Pattern, Struts is a very poor tool to do it. You better use XSLT, or Velocity. But not Struts.

Moreove the example above is not only bad because of mistaking the Template View Pattern, but it also fails in accomplishing one of the purposes of the MVC pattern itself!

public class CreateCustomer extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

try{
// .. Create the actual customer

}catch(Exception e){
// Some kind of error
return(mapping.findForward("createCustomer.jsp"));
}

// .. Prepare the data for the jsp
return(mapping.findForward("customersList.jsp"));
}
}

Can be interpreted as:

public class CreateCustomer extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

// ... Action logic

// ... View logic
return(mapping.findForward("customersList.jsp"));
}
}

The same action has Action logic as well as View logic in it, and it isn't separating both logics after all. This pattern implementation is useless. But if we keep the real MVC principles the code becomes clear and straight-forward.

public class CreateCustomer extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

try{
// .. Create the actual customer

}catch(Exception e){
// Some kind of error
return(mapping.findForward("createCustomer.jsp"));
}

return(mapping.findForward("customersList.jsp"));
}
}

public class DeleteCustomer extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {

try{
// .. Delete the actual customer

}catch(Exception e){
// Some kind of error
return(mapping.findForward("deleteCustomer.jsp"));
}

return(mapping.findForward("customersList.jsp"));
}
}

The data preparation has been moved to the customerList.jsp itself, which is now requesting information directly from the model. As an additional benefit, the ListCustomers action disappears because it's no longer needed, since other jsps can directly call to the customersList.jsp. The complexity has been reduced.

According to SmallTalk MVC definition: "[...] the model manages the behavior and data of the application domain, responds to requests for information about its state (usually from the view), and responds to instructions to change state (usually from the controller)". In MVC, The controller is NOT a Mediator between the view and the model. The controller does not sit in between the model and the view. Both the controller and the view have equal opportunity to access the model. Although we removed the Template View pattern from this implementation, notice that MVC pattern remains and is more useful than ever.

In future posts we will see a clean, easy-to-learn, easy-to-maintain, configuration-free MVC implementation based on jsps: POJM (Plain Old Jsp MVC).

Saturday, March 04, 2006

Null variables invocations

While reading the post Fundamentals of data presentation I remembered how annoying it is to check that an object is not null before invoking any method on it. It happens everytime.

I'm not only talking about some kind of assistance to your code in order to discern whether your variables are null or not. I'm talking about the problem of writing two blocks of code: one for the case that your variable is null, and one for the normal case. Consider the code:

final Customer customer= ...; // Retrieve customer
if(customer==null) out.println(" -- No customer --");
else out.println(customer.display());

This code is ugly, because of the need of an if statement where you would just want to write one simple invocation. But this is a small problem compared with the duplication of code you have to face up if you try to display a customer variable in many places in your code. You would have to write the annoying if statement everywhere. This definitely moves away from good coding principles.

The -- No customer -- string is somehow related to the Customer class itself. It's the class that best knows what to display when the variable is null. Good OO principles advise us for inserting this logic inside the Customer class.

And in fact, there is a good pattern that solve this problem: the NullObject pattern. This pattern prescribes to always manage an object, even if you are trying to express the null value. Instead of the null value, use an object with no local variables, or a special subclass NullCustomer conveniently rewriting the methods. I recommend to read about this pattern. The NullObject pattern, however, doesn't completely satisfy me, because it makes you write an additional class for almost every class in your project, and because it doesn't definitely prevent the problem of an inadvertent null variable, after all.

A different, simpler approach is to replace the object method invocation with a static method invocation:

final Customer customer= ...; // Retrieve customer
out.println(Customer.display(customer));

class Customer{
// ...
public static String display(Customer customer){
if(customer==null) return " -- No customer --";
else return customer.display();
}
// ...
}


This static method invocation is NullPointerException safe, but it gives you the feeling that you are using OO no more. Can't Java or any of the OO languages respond with a better sollution to this problem?

In fact, this is well-known problem for a long time. You can read discussions about it in the SmallTalk community, and the "message consuming nil". I think the Java language could provide an idiom similar to the "message consuming nil", but a little smarter. Consider that the JVM could check whether the invoked object is null, and conveniently forward to the corresponding static method in the class. So you could write code like this:

final Customer customer= ...; // Retrieve customer
out.println(customer.display());

class Customer{
// ...
public static String display(){
return " -- No customer --";
}

public String display(){
// ...
}

// ...
}


It is now clear, but powerful! Although this approach is elegant, I envision two troubles:
  • Interfaces cannot declare methods with code in them. If your variable is an instance of such interface, would Sun allow to write some kind of code inside interfaces?

  • Sun cannot rewrite core objects to comply with this change, since existing code is already written expecting NullPointerException instead of silent returns.

What do you think?

Sunday, February 26, 2006

DO logic in JSPs!

One of the most overused and mistaken concepts in J2EE is "No Logic in JSPs", meaning that you should separate business logic from data presentation, and that data presentation is the JSP's responsibility. This concept frequently arises in connection with MVC pattern.

This is a misconception, because in real applications some kind of logic is always needed in the presentation. Conditional presentation on different chunks of data, iteration over multiple elements: this is logic that cannot be removed from the presentation, no matter whether you code it with java, Velocity of taglibs. The real point is that you have two different types of logic: business logic, and view logic. How to determine what logic is the actual view logic intended to be located in the JSP?

A good architect can draw a neat analogy with the process of refactoring a complex method inside any class of your project. Imagine one of these methods, with too many lines of code, with complex loops, temporal variables, and so on. The very purpose of the method is obscured by the complex code, which makes it difficult to maintain. You should move part of the code to another methods, or even better, to the class that best whose responsibilities best fit the task. You should replace temporal variables with queries. And the final goal of the refactoring is to clean the code to the point that any developer in your team can take a quick look to it and figure out the task of the method, how it achieves its client's requests, with which dependencies. The code of the method must be its logic, no more nor less.

We can apply the same rule to the JSP: the code must be its logic, no more nor less. That means that JSPs have to obeys the user's mandate: "Present me the data related to the parameters I provide to you". So, the JSPs must read the parameters, retrieve the data to be presented, and present it accordingly, with the necessary iterations and conditional blocks. With HTML code and Java in the same file, the code is very difficult to read and maintain. For that reason a correct refactoring is even more important in a JSP. It would be a mess to code these tasks line by line. Retrieving the data is behind business logic, so you must refactor that code by moving it to business delegates in the business layer. The presentation can be sometimes really complex. For instance date format, or polymorphical presentation as a result of polymophical hierarchy data. In such cases you can benefit of moving part of the code to presentation delegates in a presentation layer. And the request parameters parsing is seldom non-trivial. For such cases, you can sometimes move that code to presentation layer as well. Voilà. The logic in the JSP is reduced to simple lines invoking the business and presentation layers, and some iterations and conditions.

But many projects, misguided by the "No logic in JSPs" rule, implement unnecessary complex frameworks, actually trying to achieve "No java in JSPs". It's easy to find the intrinsic contradiction of trying to remove Java from JavaServer Pages. That should make us wonder about the soundness of this principle. If you replace your Java code with another type of code, then you have to think in two languages instead of one. I definitely torn apart from those architectures that make "No java in JSPs" one of their guiding rules. I found two actual ways projects are currently implementing that philosophy:
  • Custom tags: At first an interesting way to simplify your JSP code. But you shouldn't go too far by trying to replace every java code in your JSP with custom tags. For every tag you have to maintain not only the code, but also its tag definition. If the code you are trying to replace is one single line, it's definitely not worth the effort of writing more lines than you are trying to remove. And you can always consider the alternative of writing the java invocation directly in the JSP removing the need of any man-in-the-middle, and keeping simplicity by only thinking in one single language, instead of two.
  • Struts actions: This is even worse. In common Struts MVC pattern, the action takes the control of the task of accomplishing the user's mandate, reducing the JSP role to a mere Template. In future posts I will explain why this conception perverts the original SmallTalk MVC pattern and how it creates more harm than good.

Conclusion: JSPs task is to accomplish simple user's mandates with complex business rules and presentation logic. Therefore the JSP code must be refactored to the more straight code as possible. Since JSP standard is simple but powerful, this is feasible with conventional, well-known refactoring rules, and there is little or none need to replace java code with other types of code. Other patterns, such as Templates, make things worse.

Friday, February 17, 2006

Fundamentals of Data Presentation

Though it's useful to know and learn different complex frameworks that arise and promise to make your life easier (Struts, Hibernate, JSF, etc), for an architect to become strong it's much more important to master the fundamentals.

Jakarta Commons boosts your java-coding potential by providing a huge collection of small functionalities for very different purposes. It works as a natural extension of the Java libraries including I/O, XML, databases, and even core concerns such as language, and Collection utils.

One of the functionalities that makes me very happy is as simple as providing default behaviour when null values are found. It's a very common mistake to design a poor data presentation and eventually display a "null" as the value for a field in the HTML page when the field is not populated. It must be managed. Consider the following code:

final String givenName=customer.getGivenName();
if(givenName==null) out.println("(not provided)");
else out.print(givenName);

The conditional is mandatory in order to provide a custom message instead of a "null" message, but with Jakarta Commons Lang all the task becomes easy and natural:

final String givenName=customer.getGivenName();
out.println( ObjectUtils.defaultIfNull(givenName, "(not provided)"));

Moreover, the whole Commons Lang package is designed taking care of this issue. Another very useful functionality for JSP developers is the ability to escape special characters when generating HTML code. This is mandatory in order to avoid HTML Injection, and make your application secure.

final String givenName=customer.getGivenName();
StringEscapeUtils.escapeHtml(givenName);

And it correctly displays an empty string when the givenName is null! With these small helpers, proper data presentation will never be painful nor easy to forget.

Thursday, January 05, 2006

JavaServer Pages over Servlets

It is often stated that JSPs and Servlets, though similar in functions and potential, have different natural responsibilities, and that you should use one or another depending on the different parts of your projects. So, JSPs should be the correct choice when generating final HTML and presenting the data to the user, while the task of controlling the flow and performing actions and modifications in the model should be accomplished by Servlets.

But pragmatic use of J2EE architecture tells us that almost in every case JSPs are more useful and easy to use that servlets, and therefore JavaServer Pages are the best choice for every task in your J2EE project.

The most obvious advantage of JSPs is instant compiling, that makes the programming-deploying-testing cycle faster. When you are coding a servlet and want to put it to run you must first tell your IDE to compile the Java code, and deploy the resulting classes in the J2EE container, usually Tomcat o JBoss. Moreover the container normally has to detect the changes and reload the servlet class. The reloading also triggers a total restarting of the application, adding more time to wait. Not to mention the problems of losing some temporal variables in the restarting and having to perform the same sequence of user actions up to the exact point you are testing. Of course, many of these problems can be minimized by using automated Ant deploying and correctly configuring the J2EE container to serialize session variables. But even with these provisions in effect, you will have to wait for compilation plus some additional time for the container to detect the changes and restart the application. Compare this to the testing cycle of a JSP: just copy the JSP, and the container automatically compiles the JSP when invoked with no side effects.

Another advantage of JSPs is the inline constructs and taglibs automatically provided by JSP standard, whith difficult replication in servlets. Just think the complex and difficult-to-read code you should write to emulate the following JSP constructs:

session
<jsp:useBean id="name" scope="session" />
<jsp:setProperty name="myName" property="*" />
<jsp:forward page="/utils/errorReporter.jsp" />
<%@ include file="sessionCheck.jsp" %>

Those contructs are very useful even if your JSP has no HTML generation responsibilities.

And an very important advantage of the JSPs is that, unlike servlets, they don't create an unneeded double indirection. For the servlets to be callable as an URL, they must be declared in the web.xml. The user doesn't call the servlet by its name but by the name configured in the web.xml. Double indirections have several uses, but they create very painful problems. An architect must be very sure before adopting such a costly pattern. Not only does this pattern burden the programmers with additional work when creating new servlets, but also puts on the architect the additional task of:
  • controlling that every servlet has its corresponding configuration
  • controlling that when a servlet changes its name, the web.xml changes accordingly
  • controlling that when a servlet changes its URL, the web.xml changes accordingly
  • controlling that when a servlet is removed, the corresponding configuration is changed, in order to maintain the web.xml clean
But it also makes it difficult for developers and IDEs to easily traverse between JSPs invocations. Consider the scenario when a newly arrived developer takes a look at a JSP, sees a link to a URL, has to search in the web.xml for this URL, and then finds the servlet. For big aplications this is too much. Compare with the alternative of using JSPs for every responsibility. JSPs automatically have a URL with the same name that the jsp file with no further registration, are cleany removed from the project by only deleting the file, and are easily found when you look for the JSP that is called from any URL.

Ruby on Rails people were aware of this problem when they stated one of their famous guiding principles: "convention over configuration".

For Struts enthusiasts, the same advantages depicted here are applicable when comparing to coding actions with Struts. Actually all of my projects are primarily developed with plain JSPs and rarely use servlets, with the result of a very clean and easy to manage architecture.