This is a short one since not much changed.   If you didn't have a chance to read the 3.3 version of this please review it now since I'm not going to post the entire tutorial again. We only need to change the filter and specifically how the dynamic columns are added to the form.

public class ProjectStatusFilter extends AbstractFilter<Object, NodeRef> {
@Override public void afterGenerate(Object item, List fields,
List forcedFields, Form form, Map context) {
boolean typeDefCorrect = (item instanceof TypeDefinition && ((TypeDefinition) item)
boolean nodeRefCorrect = (item instanceof NodeRef &&
.getNodeService().getType((NodeRef) item).equals(
if (typeDefCorrect || nodeRefCorrect) {
double varianceValue = 0d;
double percentComplete = 0d;
double percentExpended = 0d;
// If this is a node then do the calculations
if (nodeRefCorrect) {
NodeRef itemNode = (NodeRef) item;
/* Some calculations that aren't interesting */
/* Here are the changes for 3.4b */
/* Left the other 3 fuctions for completeness */
public void afterPersist(Object item, FormData data, NodeRef persistedObject)
public void beforeGenerate(Object item, List fields,
List forcedFields, Form form, Map context) {}
public void beforePersist(Object item, FormData data) {}