Posted on Oct 20th 2010

If you haven't already heard, the latest release of MyEclipse for Spring includes a new code generation customization feature that makes it easy to customize the templates that are used for code generation.  We've published a tutorial that walks you through the entire process of using the new feature, and in this post, I’m going to demonstrate another use case of this feature.  In particular, I'm going to demonstrate how to enhance the templates that generate the annotation-based Spring Controllers and Services to include application logging.  Initially, the templates will be customized to automatically generate a logging implementation using Simple Logging Facade for Java or (SLF4J), but then I'm going to modify the templates to apply a logging implementation using just LOG4J.

Let's review the general steps for adding logging to a controller or service:

  1. import statements for logging framework
  2. instance variables for logger
  3. getter method for logger

While manually adding logging to a single class isn't difficult or especially time-consuming, it becomes a real drag on speed and productivity when you need to do it over and over again. Given how quickly services and controllers can be generated using MyEclipse for Spring, you want to avoid having to apply manual updates to each generated class one-by-one after scaffolding.  Therefore, it makes a lot of sense to generate as much of the logging logic as possible.

Note: This blog post isn't going to provide step-by-step instructions because the process is nearly identical to the Customize Code Generation Tutorial.  If you aren't familiar with the customization process, then I would recommend that you first try the tutorial.

When a MyEclipse Customization Project is created, the project will be seeded with all the JET templates used by MyEclipse for Spring code generation.  JET templates resemble JSP in many ways, making it very easy to follow the implementation of the templates.  JET supports the concept of tags and tag libraries (just like JSP), and the templates use many of the standard JET tags.  The JET tag library is very rich in generation functionality, but you can also use custom tag libraries.  MyEclipse for Spring contributes the Skyway JET tag library for simplifying many of the recurring generation requirements of Spring applications.

The following JET templates are relevant to Controllers and Services, and they will be enhanced to include application logging.

  • Controller - WebController.jet
  • Service - Service.jet

To add logging, we're going to leverage two JET templates that already exist in the templates/common/logging folder

  • DeclareLogger.jet
  • GetLoggerMethod.jet

Open these two templates in an editor.  The templates are very brief.  DeclareLogger.jet generates the declaration for the SLF4J logger, and GetLoggerMethod.jet generates the getter method for the logger.  In order to have these generated into a controller or service, these two templates need to be added to the respective Controller and Service templates.  This is accomplished by using the JET include tag.  Refer to the following listings to see where the include tags for the DeclareLogger.jet and GetLoggerMethod.jet templates are added.

WebController.jet

// The full template is omitted for brevity
public class <sw:javaType select="$model" /> <sw:extends select="$model"/>
<c:if test="$interfacesSize > 0" > implements <c:iterate select="$interfaces" var="interface" delimiter="," >
<java:import><c:get select="$interface" /></java:import>
</c:iterate></c:if> {

<c:include template="templates/common/logging/DeclareLogger.jet" />
<c:iterate select="$model/variables" var="variable">
<c:include template="templates/variables/VariableDeclaration.jet" />
</c:iterate>

<sw:anchorSegment anchorId="actionVariables" />

<c:iterate select="$model/operations" var="currentOperation">
<c:include template="templates/operation/Operation.jet" />
</c:iterate>

<c:include template="templates/common/logging/GetLoggerMethod.jet" />

}

Service.jet


public class <sw:javaType select="$model" /> <sw:extends select="$model"/> implements
<java:import><sw:javaType alias="interface" select="$model" package="true"/></java:import>
<c:iterate select="$interfaces" var="interface">
, <java:import><c:get select="$interface" /></java:import>
</c:iterate>
<c:if test="$webService">
, <java:import><jaxws:serviceEndPointName select="$model" package="true"/></java:import>
</c:if> {
<c:include template="templates/common/logging/DeclareLogger.jet" />
<c:iterate select="$model/variables" var="variable">
<c:include template="templates/variables/VariableDeclaration.jet" />
</c:iterate>

<sw:anchorSegment anchorId="actionVariables" />

/**
* Instantiates a new <sw:javaType select="$model" />.
*
<sw:modelReference select="$model" />
<sw:auxiliaryModelComponent />
*/
public <sw:javaType select="$model" />() {
}
<c:iterate select="$model/operations" var="currentOperation">
<c:include template="templates/operation/Operation.jet" />
<c:include template="templates/OperationWrapper.jet" />
</c:iterate>

<sw:anchorSegment anchorId="afterStepMethods" />
<c:include template="templates/common/logging/GetLoggerMethod.jet" />
}

The next time you run CRUD scaffolding with these customizations, all the generated Controller and Services will have application logging using SLF4J, including import statements for SLF4J, instance variables and a getter method.

Now....SLF4J is a very useful abstraction for logging, and we recommend that you use it.  However, maybe you prefer using LOG4J directly.  No problem!  Just customize the logging templates to use LOG4J for application logging instead of SLF4J.

Here are the relevant updates to templates:

DeclareLogger.jet


/**
* The LOG4J logging class.
* @generated
*/
static <java:import>org.apache.log4j.Logger</java:import> logger =
<java:import>org.apache.log4j.Logger</java:import>.getRootLogger();

GetLoggerMethod.jet


/** LOG4J
* @generated
*/
public Logger getLogger() {
return logger;
}

The next time you run CRUD scaffolding with these updated customizations, all the generated Controller and Services will have logging using LOG4J.

Piece of cake, right? This post is just one example of the power of code generation customization.  There are many use cases for customization in MyEclipse for Spring, and we hope to share many more use cases with you in the coming months.