Saturday, February 11, 2012

OMG you put Java code in the view!!

One of the unique joys of developing anything with Java Server Pages is encountering the Scriptlet Police.

Scriptlets, as you probably know, are little bits of Java code embedded into the JSP. I think of JSPs as being servlets turned inside out. In a servlet, everything is Java by default, but you can throw in some HTML in the form of strings. In a JSP, on the other hand, everything is HTML by default, but you can throw in some Java in the form of scriptlets, like this:

  <% for (Foo foo: listOfFoos) { %>
    <li><%= foo.getName() %></li>
  <% } %>

But God forbid you do this and then admit it on a mail group or message board. Any hint that you're actually putting Java code in your JSP will attract a lecture from the Scriptlet Police, for example:

Question: "I am a complete JSP beginner. I am trying to use a java.util.List in a JSP page. What do I need to do to use classes other than ones in java.lang?"

Helpful answer 1: "Not to mention that this is not the best practice ;)"

Helpful answer 2: "FYI - if you are importing a List into a JSP, chances are pretty good that you are violating MVC principles."


Question: "I wish to access [a model attribute] in a scriptlet (within a JSP)."

Helpful answer: "It's stored as a request attribute. ... Unrelated to the concrete problem, I suggest to ask a new question wherein you ask how to achieve the functional requirement without the need to fall back to legacy practices."

The irony of course is that when the members of the Scriptlet Police write their own JSPs, they write something like this:

  <c:forEach items="${listOfFoos}" var="foo">

Which of course is the exact same thing, just written in a slightly different "language" consisting of JSTL tags and JSP expression language (EL) expressions. So why is it verboten to write a loop as a scriptlet but not using JSTL?

If you're using Groovy and Grails, it becomes even more ironic. The code looks about the same, although the tag is called <g:each> instead of <c:forEach>. But the big difference is that the code inside the ${} is Groovy code, not some language that's been deliberately watered-down so as to make it difficult to implement "business logic" in the view.

The members of the Scriptlet Police think that they're enlightened. But in fact, they are confused. Someone told them a long time ago that they shouldn't put any "business logic" in the view, and somehow that got associated with "no Java in the view," because obviously Java is what you use to implement business logic, right? So in their minds, they are keeping business logic out of the view by only using JSP tags and Expression Language in their JSPs. In fact, instead of keeping business logic out of the view, they're only keeping Java out of the view, which isn't the same thing at all. But it's a simple criterion to apply (Expression Language good, Java bad) and enables them to avoid actually thinking about the difference between the view and... well, what?

What, because it's inevitable that there is going to business logic in the view. Applications exist in order to implement business logic. If you format one number as a currency and another as a percent, you're implementing business logic. If you only display the "Delete" button when the user is an administrator, you're implementing business logic. If you have hundreds of lines of JavaScript on your page, it's all but guaranteed that you have some business logic in there. If you have an N-tier application, you're going to have business logic in every single tier. So what's the point of all this worry about business logic in the view? What are we really trying to accomplish?

What's important isn't keeping business logic out of the view, but rather establishing some useful separation of responsibility among components. JSP is a view technology, so ideally we should limit its use to the view, and implement non-view-related logic elsewhere. For example, entitlement checks and form-saving logic are probably best implemented in a controller written in Java. If we tried to implement form-saving in JSP, we'd wind up with a JSP that had lots of logic paths and performed different functions depending on whether it was being called with GET or POST. It would no longer be a view and would be harder to understand and maintain than a simple view with two different Java controllers.

But as long as we limit ourselves to implementing view-related logic in the view, it doesn't really matter what language we use. Go ahead and write some scriptlets. Normal programming best practices still apply, of course; don't go cutting and pasting the same scriptlet into a dozen different JSPs. But don't worry that the scriptlets will pollute your view with "business logic." If a scriptlet is the best solution to your view problem, just do it.

Alex Papadimoulis also wrote about embracing business logic on his web site The Daily WTF.


Post a Comment

<< Home