Archive for March, 2009

communiqué as a windows service

Sunday, March 22nd, 2009

When running CQ on Windows there is a common issue everyone runs into: how to install it as a Windows service? There are basically two ways: the built-in (automatic) and the manual.

built-in way

This one is available for CQ 4 only - one has to open Communiqué Manager and click File -> Register Service. The Service will appear in Window’s administrative tools -> services

register service

Ta-da-da, but… we’ve encountered multiple issues with this approach. The most serious is that all instances are starting up / stopping with the service - one can no choose to start/stop single instance. If you need this functionality: you have to do it manually.

installing service manually

First thing you need is a cqsvc.exe tool located in CQ 4 installation directory under opt\helpers\cqsvc.exe. To install a service, you execute it with the following arguments:

  • -i
  • -n <service name>
  • -e <full path to java.exe>
  • -w <workdir>
  • -a <arguments>
  • -o <outfile (log)>
  • -t <timeout>

example:
cqsvc -i -n “communique4401″
-e “C:\Program Files\Java\jdk1.5.0_16\bin\java.exe”
-w “D:\Day\CQ-4.2.1\server”
-a “-Xrs -Xms512m -Xmx768m -XX:PermSize=256m
-XX:MaxPermSize=256m -jar bin/bootstrap.jar”
-o “D:\Day\CQ-4.2.1\server\outfile.log”
-t 180

Ta-da-da - your service appeared under the name you selected. Now you can install instances as a separate services - each one with a different name. Note that this tool can be used for CQ 5 as well.

writing mvc framework in cq4 (part 3)

Sunday, March 15th, 2009

In the first part of this little tutorial I’ve shown three major problems I encountered when building a CQ 4 framework. Two of them were solved in the previous post, leaving the persistence one for today. Once again, what it’s about: let’s assume you’ve got your shiny new project with Java controller and JSP view, the data you’re about to use to create your model are stored in pages as a set of atoms, containers and container lists. The simplest way of accessing them is by using e.g.:

Container pageContent = page.getContent();
ContainerList list = pageContent.getContainerList("myData");
Container content = list.getContainer("Single");
Atom atom = content.getAtom("myAtom");
String data = atom.getString();

Though it’s scary, it works just fine. Though it works, it’s too damn easy to hide an error here. For pages storing multiple containers with many atoms inside, managing such a mapping has proven to be really tricky.

We at Cognifide have been struggling with this one for quite a while. The credit for the solution I am about to present goes mainly to Albert Cenkier who invented an automated mapper from a CQ container to a Java object. In order to build it we did the following assumptions:

  • one CQ container is mapped to one java object (DTO),
  • an atom is mapped to the object field of the same name as atom’s label (case insensitive),
  • the above requires that all labels used are valid Java identifiers - we use camel case names.

The mechanism we came up with uses reflection mechanism to find all the properties of a DTO class. It then tries to fetch atoms with the same labels as the fields from the given container. This approach is called “standard over configuration” - instead of the excessive layer enabling the most flexible and elaborate mapping (that you’re not ever going to use anyway) it introduces a standard solution at the cost of a few restrictions (that you most often abide to already).

Time for more implementation details. Here are some example code listings - not a complete solution, but should be enough to get you started. First - get all setters of a given class:

private static Collection/* <Method> */getSetters(Class clazz) {
  Method[] methods = clazz.getMethods();
  Pattern pattern = Pattern.compile("(set)([A-Z_]\\w+)");
  Collection/* <Method> */setters = new ArrayList/* <Method> */();
 
  for (int i = 0; i < methods.length; i++) {
    String methodName = methods[i].getName();
    if (matcher.matches()) {
      setters.add(methods[i]);
    }
  }
}

Now, to get those from a container and execute the setter:

public static Object mapContainerToObject(Container content, Collection/* <Method> */setters)
    throws Exception {
  Pattern pattern = Pattern.compile("(get|set)([A-Z_]\\w+)");
  Object result = clazz.newInstance();
 
  for (int i = 0; i < setters.size(); i++) {
    Method setter = (Method) setters.get(i);
    Matcher matcher = pattern.matcher(method.getName());
    String propertyName = matcher.group(2);
    propertyName = propertyName.substring(0, 1).toLowerCase()
        + propertyName.substring(1);
 
    if (content.hasElement(propertyName)) {
      String value = content.getAtom(propertyName).getString();
      setter.invoke(result, new Object[] { value });
    }
  }
}

Note - the above doesn’t implement case insensitivity and assumes that every value is a string. The implementation of those complicates the code significantly and I wanted to show the basic idea here. From this point however, it shouldn’t be much of a challenge to implement the following:

  • mapping to any basic data type (string, integer, boolean, floating-point, date, etc.) based on Java field type and pre-defined parsing rules,
  • mapping container label to one specific field (essential for list’s parNum),
  • mapping a container list to a list of objects.

In fact, it is possible to implement a complete hibernate-like solution for Communiqué. Just remember - do not over-complicate. This piece of code lies at the very basis of all your projects. If it’s clean and simple, anything built on it will be so as well.

writing mvc framework in cq4 (part 2)

Sunday, March 1st, 2009

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.