writing mvc framework in cq4 (part 2)

Recently we discussed the Communiqué framework concept in general. Today let’s focus on those little details that will allow us to create such a framework.

First issue I encountered is: how to remove logic from the view? In the simplest cases one could use the <cfc:atom> tag to simply output a stored value. Once the value has to be transformed, or fetched from other page, it gets complicated, and more and more logic tends to be introduced in the view. What we need here is a way for Controller to output his data on the page.

Let’s assume we’ve got this controller already as a Java class that hides all the business logic and persistence from us. We could output data from it using <%= controller.getValue() %> but that still won’t deliver us from putting logic in there:
<%= controller.getValue().replaceAll("foo", "bar") %>
.

Fortunatelly, there is salvation - provided by Day in the JSTL integration package.  Using JSTL c:out tag one can output any value that was previously set as a request attribute.

example

Now, exactly what does it mean for us? Let’s assume we’ve got the simplest controller:


package pl.kuzniak.jan.myapp.controller;

import java.util.HashMap;
import java.util.Map;

import pl.kuzniak.jan.myapp.model.MyData;

import com.day.cq.delivery.DeliveryHttpServletRequest;

public class MyController {
public MyController(DeliveryHttpServletRequest cqRequest) {
protected final Map/* <String, Object> */model;
model = new HashMap/* <String, Object> */();
MyData data = new MyData();
data.setIndex("1");
model.put("myData", data);
cqRequest.setAttribute("model", model);
}
}

We can now use it in the JSP file just like that:


<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"

%><%@taglib uri="/cfc" prefix="cfc"
%><%@taglib uri="http://java.sun.com/jstl/core" prefix="c"

%><%@page import="pl.kuzniak.jan.myapp.controller.MyController"

%><cfc:defineObjects/><%
new MyController(cqRequest);
%>

<p><c:out value="${model.myData.index}" /></p>

As you can see - we’ve got a read-only way of accessing values here. Except for the line with controller’s constructor, there is no business logic here. The only part of Java code is in fact a mapping between the view and the controller - something you could find as obfuscated XMLs in some popular Java frameworks.

conclusion

So, here we’ve got solution to the first problem:

  • use cqRequest.setAttribute to pass a value to the view
  • use JSTL to output the value in a read-only manner

Pros:

  • it’s easy this way - developers will like it and won’t be searching ways around,
  • it’s clean - keeps Java code away from the markup,
  • it’s standard - utilises well known JSTL and Expression Language,
  • it’s easy to extend - it’s easy to write custom tags that support EL and can e.g. externalise links or format values while outputting them.

Cons:

  • often requires extra effort to write a proper taglib instead of creating HTML markup from the controller itself.
  • reduced plain code readability (it’s slightly better with syntax highlighting, but still…); example:
    <body class="<c:out value="${model.body.htmlClass}"; />">

If something is unclear - please comment. Next time I will talk about data persistence in CQ 4.

Leave a Reply