Archive for the ‘communiqué’ Category

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.

writing mvc framework in cq4 (part 1)

Sunday, February 22nd, 2009

In the next few articles I would like to give you some guidance in writing a MVC framework for Communiqué 4.2. Why 4.2 you ask - good question. With the version 5.1 finally out, I should probably be concentrating on it. The main reason is that clients still like CQ4, and most likely in 2009 there will still be a lot of new projects written on the old version of the platform, while we will be learning how to write in CQ5 and how to do it right.

Why would I want to write this framework? The default approach presented in examples provided with the default installation is lightweight, easy and quick - that’s true. In the long term, however, I’ve found it hard to scale and manage. It’s hard to force standards and QA Ecma scripts, plus, they tend to get complicated while developers hack they way through issues. Separation of concepts and putting them into layers simplifies architecture, and the cost of creating bloated codebase is compensated by the ease of supporting such a project. And the only way I know to help development team avoid messy projects is to create a framework.

Before I continue let me explain what I understand by framework. A framework is a solution to a high-level problem (here - creating web sites in CQ). This solution is provided incomplete but it can easily be extended and adapted to a given case (web site X in CQ). The spots that will be extended / overriden by the developer are clearly specified by the framework. Framework must be general enough to be reusable across the projects, while strictly enforcing solving similar problems in the same way, it must be easy to learn and hard to bypass.

Now, let’s have a look at CQ and see if we can define Model, View and Controller here.

  • Model - data displayed on the page. These data are probably persistent somewhere, have some business rules, are associated with default values  and will be displayed somewhere - but the model is unaware of all that. It just stores plain data - no logic, no formatting - it’s raw.
  • View - a JSP page generating HTML, CSS, JavaScript and so on. It is responsible for formatting data and displaying them correctly. View doesn’t care about where the data came from and has as little logic inside as possible.
  • Controller - A Java class responsible for calling the persistence layer to retrieve the model, applying business rules and default values to it and passing it to the view. It doesn’t care what the view is - it just creates the model and exposes it so that it is visible to the view.

The problems that lie ahead are:

  • How to combine controller and view? In Communiqué the page is associated with the template, and template defines one entry point - the JSP script (view). How to define a controller while keeping the logic away from the view?
  • How to pass the model to the view? How to expose Java objects to the JSP file so that it would be impossible (or at least hard) to modify them from the view?
  • How to solve persistence in an easy and effective way? Most of the data will be stored in the Content Bus. How to enforce a standard but flexible mechanism for mapping them to model objects? This operation seems easy but is very error-prone when done manually (especially when refactoring).

In the next article I will answer those questions and try to provide some examples for improved readability, so keep reading!

Cheers,
Jan

what shall we do with cq 5 early in the morning?

Sunday, June 15th, 2008

I have attended the Day’s tech summit. I have seen new, shiny and sexy stuff, heard nice words, promises and what’s the most important – the date: 15th November 2008. That’s when new and long awaited version of Day’s Content Management System (or maybe rather Content Management Platform) will become generally available.

When David Nüscheler (Day’s CTO) was talking about how great the new Communiqué is going to be, clients were overjoyed, most of the partners were watching closely with their breaths bated and we (Cognifide) were asking difficult questions. The answers we got were both humble and promising. Good thing is that we heard Day accepting that the current version (CQ 4.2) has it’s problems, is not that well documented and so on. Even better news is that they try to do something about it – e.g. they hired much more people to document and support it.

What’s worrying is the general approach to solving complex CQ 4.2 problems. “We admit it didn’t work well, that’s why we dropped that”, “It’s no longer a problem in CQ 5″ – that’s what we’ve heard for like half of our questions. It’s not like we’ve been shown a solution to our problems. It was rather a statement that the new system is completely different from the old one and a promise that it works the way we expect it to.

While I appreciate the courage to introduce deep changes when they’re needed, I will remain sceptical until I see them working in the real life. I am afraid that the marketing machine will make clients (and as a final outcome my bosses) even more enthusiastic about CQ and I will have to face an unknown enemy once again but with more pressure from their side. I am pretty sure that the new platform is not as shiny and sexy when it comes to developing it as how it is presented by it’s authors (and as people paying money might believe). With the completely new approach I expect completely new bugs. For sure, all Content Bus related problems passed on, are no more, ceased to be, expired and gone to meet their Maker. And that is not because Day nailed all of them and somehow magically fixed them, but that it just dropped the Content Bus idea altogether. I don’t know how will I replace this layer of abstraction – problematic, but still logical – in my day-to-day development. Will it be another month or two of fighting to make basic things work before I stop cursing Day’s developers every morning?

You might ask why am I so negative about it. Why can’t it be that The Basel Company has finally found the perfect design and Communiqué will just work from now on. Well, the first thing that hit me on the conference was the CQ 5 pilot project – the City of Zürich site. Once again I’ve seen HTML, CSS, JavaScript and plain Java code mixed in one file (sic!), once again I’ve seen untested (despite the new promoted testing framework) project that “will be tested in the later phase”. That’s a bad signal for me as a quality-driven developer. Haven’t they learn anything? Don’t they focus on delivery instead of just implementation?

The second thing is an increased share of a open-source software in the system. Again, while I have nothing against open source, I just can’t see Day solving my day-to-day problems that just by accident lay in the code they don’t control and probably have only a little influence on. It works very slow with Jackrabbit (that CRX – Day’s flag ship that CQ is based on) despite Day having major share in it. How will it work this time? Is the problem their or mine? I wish I knew the answer.

But still I will remain an CQ enthusiast for now. I don’t know any other platform for writing CMSs that would make developing advanced systems possible while providing consistent and not-so-bad end user (author’s) interface. Also I’ve found my way with CQ 4.2 (not to mention project I delivered in 3.5), I know how to walk on the minefield set by CQ architects and still deliver something with measurable quality. If clients want, if my company requests I will solve the CQ 5 QA puzzle and will learn (once again) how to deliver projects in it. That is what I believe and I will until I get my hands on it and find out which promises were fulfilled. Until then I can just dream about CQ 5.1 and continue to do ugly hacks in CQ 4.2.

See you at Day’s Summit this November!
Jan