Eclipse Zone is brought to you in partnership with:

Tomas Kramar lives in Slovakia, where he works for a company developing software for a major local telecommunication provider. He is also a student at the Slovak University of Technology. Tomas has posted 6 posts at DZone. You can read more from them at their website. View Full User Profile

Effective Eclipse: Custom Templates

02.28.2008
| 175630 views |
  • submit to reddit

The same way I try to avoid the redundancy in my code, the same way I try to avoid the redundancy in my writing. I am lazy and templates do the most writing for me. Eclipse comes bundled with predefined templates, but they are too general and not all of them are too useful. The real power is in custom templates. In this article I would like to show you how to create them and list a few useful pieces for inspiration.

What are templates

Exactly as the name suggests, templates are little pieces of code with defined placeholders. An example of simple template is

System.out.println(${text});

Each template has a name, which serves as a shortcut to the template itself. You type the name, press CTRL + SPACE and it will be expanded.

Our first template would expand to

I will not explain here what it all means, I already did this in my previous post on templates. What is important now, is that the ${text} placeholder (variable) was highlighted and can be edited immediately.

The true power of templates can be fully seen in more complex templates. The first power point lies in the fact, that you can have more than one variable with same name. Our second template will have more variables:

int ${increment} = ${value};
y = ${increment} + ${increment};

and will expand to



When you start typing now, all occurrences of increment variable will be changed. You can then switch to the next variable by pressing TAB key. In the end, you can have



in just three key presses - one for i, one for TAB and one for 2.

To make it even better, the template system provides predefined variables, which will be expanded depending on their context. I will not list them, you can find them under the Insert variable button.



Notice, that you are not getting only a list, you are also getting a description and an usage example.

To make it clear, I will illustrate one builtin variable - ${enclosing_type}. When this one is expanded you will get a name of the class (or interface, enum) in which your template was expanded.

"But how can I use it?", I hear you asking. I have prepared few templates just for inspiration, I believe that after reading this you will find thousands others and I believe that you will create them and share them with us.

Custom templates

Open Window -> Preferences and type Templates into the search box.




You will get a list of all editors, and their respective template settings. This is because templates are closely bound to editors - you will get different builtin variables in different editors. Also note, that your list may vary from my list, it all depends on installed plugins.

Now you must decide what type of template you would like to create. If it is a Java template, which will be applicable in context of classes, interfaces and enums, then choose Java -> Editor -> Templates. If you create a Java template you won't be able to use it in XML editor, that's quite expected.

So click on the New button, to get a dialog. Here it is, in all its glory:




Name is the name of the template. Choose it well, because it will serve as a shortcut to your template. After you type the name of the template (or at least a few characters from its name) and hit CTRL+SPACE it will be expanded.

Description is what you will see next to the template name when the template name is ambiguous.




Pattern is the template body. And the Context? This varies in every editor. If you look in the combobox in Java templates, you will see Java and Javadoc. It is simple a context within the respective editor in which the template would be applicable.

Check Automatically insert if you want the template to expand automatically on ctrl-space when there is no other matching template available. It is usually good idea to leave the checkbox checked, otherwise you would get a template proposal "popup". See what happens when I uncheck it on sysout template.




If I would have checked it, it would automatically expand, as there is no other template matching sysout* pattern.

My list

So here is the list I promised. I have categorized it.

Java (Java->Editor->Templates)
  • logger - create new Logger
    private static final Logger logger = Logger.getLogger(${enclosing_type}.class.getName());
    Notice the usage of ${enclosing_type} variable. This way you can create a logger in few hits. After the template expands, you will probably get red lines, indicating that Logger clas could not be found. Just hit CTRL + SHIFT + O to invoke the organize imports function. You are using shortcuts, aren't you?

  • loglevel - log with specified level
    if(${logger:var(java.util.logging.Logger)}.isLoggable(Level.${LEVEL})) {
    ${logger:var(java.util.logging.Logger)}.${level}(${});
    }
    ${cursor}
    Let me explain the details. ${logger:var(java.util.logging.Logger)} uses a builtin "var" variable. It starts with logger, the default name, in case the var variable finds no match. It is then followed by var(java.util.logging.Logger), what will evaluate to the name of the variable (member or local) of the specified type (in our case of the Logger type). Further, the ${cursor} variable marks the place where the cursor will jump after you press enter. So the result after expanding could be



    You might wonder what is the purpose of the if. It is there only for performance gain. If specified level is not allowed the logging method will never be called and we can spare JVM some string manipulation to build the message.
  • readfile - read text from file

    Never can remember how to open that pesky file and read from it? Nor can I, so I have a template for it.
    BufferedReader in;
    try {
    in = new BufferedReader(new FileReader(${file_name}));
    String str;
    while ((str = in.readLine()) != null) {
    ${process}
    }
    } catch (IOException e) {
    ${handle}
    } finally {
    in.close();
    }
    ${cursor}
Maven (Web and XML -> XML Files -> Templates)
  • dependency - maven dependency
    <dependency>
       <groupId>${groupId}</groupId>   
    <artifactId>${artifactId}</artifactId>
    <version>${version}</version>
    </dependency>
    ${cursor}
  • parent - maven parent project definition
    <parent>
    <artifactId>${artifactId}</artifactId>
    <groupId>${groupId}</groupId>
    <version>${version}</version>
    <relativePath>{$path}/pom.xml</relativePath>
    </parent>
    ${cursor}
web.xml (Web and XML -> XML Files -> Templates)
  • servlet - new servlet definition
    <servlet>
    <servlet-name>${servlet_name}</servlet-name>
    <servlet-class>${servlet_class}</servlet-class>
    <load-on-startup>${0}</load-on-startup>
    </servlet>

    <servlet-mapping>
    <servlet-name>${servlet_name}</servlet-name>
    <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    ${cursor}
JSP pages (Web and XML -> JSP Files -> Templates)
  • spring-text - spring text field with label and error
    <label for="${path}" class="${label_class}"><fmt:message key="${path}"/></label>
    <spring:input path="${path}" cssClass="${input_class}"/>
    <spring:errors path="${path}"/> <br/>
    ${cursor}
  • spring-checkbox
    <label for="${path}" class="${label_class}"><fmt:message key="${path}"/></label>
    <spring:checkbox path="${path}" cssClass="${input_class}"/> <br/>
    ${cursor}
  • spring-select
    <label for="${path}" class="${label_class}"><fmt:message key="${path}"/></label>
    <spring:select path="${path}" cssClass="${input_class}">
    <spring:options items="${items}" itemLabel="${label}" itemValue="${value}"/>
    </spring:select>
    <spring:errors path="${path}"/> <br/>
    ${cursor}
  • spring-generic
    <label for="${path}" class="${label_class}"><fmt:message key="${path}"/></label>
    <spring:${type} path="${path}" cssClass="${input_class}"/>
    <spring:errors path="${path}"/> <br/>
    ${cursor}
    These are my favorites. They regularly save me a huge amount of time. Creating spring forms has never been easier for me.
In some editor types you can set the template to 'new', for example, in XML editor it is new XML. This is really useful, as you can prepare the skeleton of a new file. For example, this is what I use to create new Spring servlet configuration for freemarker application.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:component-scan base-package="" />

<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/"/>
</bean>

<bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/>
<property name="exposeSpringMacroHelpers"><value>true</value></property>
<property name="cache" value="true"/>
<property name="prefix" value="/pages/"/>
<property name="suffix" value=".ftl"/>
</bean>

<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename"><value>messages</value></property>
</bean>
</beans>

Now, I can create new XML file from template and it will be ready to use. Before I knew about templates, I used to copy this from an older project, or search for it in Spring documentation. Now I don't have to..



If you can overcome the initial laziness and create your own templates from the pieces of code you really use, than this investment will shortly return in form of less typing. If you have some interesting templates, please, share them with us.

You can download the templates mentioned in this post and import them using the Import button in the editor template settings.

References
Published at DZone with permission of its author, Tomas Kramar. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Michael Bar-sinai replied on Fri, 2008/02/29 - 10:10am

Cool. Thanks for sharing.

 Here's my "property support" template. It creates a private member variable, setter and getter in one shot:

private ${elemType:nv} ${nv:newName(boolean)}; public ${elemType:nv} get${nv}() { return ${nv}; } public void set${nv}( ${elemType:nv} ${nv}) { this.${nv} = ${nv}; }

The only problem is that it gets the CamelCase wrong. True, it's a 2-letter fix, but I would love to hear about a fix for that ;-)

Matthew Hall replied on Fri, 2008/02/29 - 12:07pm

Tomas: This is a great series, please keep it up. I've been using Eclipse since 2.0 and I still learn something new and valuable from each of your articles.

Now that I've seen how simple it is, I'll be setting up my beanprop template for beans that fire property change events:

private ${elemType:nv} ${nv:newName(boolean)};  

public ${elemType:nv} get${nv}() {
return ${nv};
}

public void set${nv}( ${elemType:nv} ${nv}) {
firePropertyChange("${nv}", this.${nv}, this.${nv} = ${nv});
}

Matthew Hall replied on Fri, 2008/02/29 - 1:08pm

Michael,

Eclipse JDT already has a command, under right-click -> Source -> Generate getters and setters (Alt-Shift-S, R). First you define your private fields, then invoke this command and choose which fields you want to make getters and setters for.

Regards,

Matthew

Robert Sinner replied on Fri, 2008/02/29 - 5:00pm

I have tried to put together a template for iterating through a map recently and its not perfect as there is no variable I can find in eclipse that will suggest a Map, it only suggests a collection which may or may not be a map. I would like to know if there was some way to suggest a Map but even without this is still nice. This assumes your using generics , but you could easily make one without generics for this. I was suprised this wasnt included by default along with the other for templates in eclipse. Keep the eclipse help coming - RS

 

for (Iterator<Map.Entry<${type},${type2}>> it = ${collection}.entrySet().iterator(); it.hasNext();) {
Map.Entry<${type},${type2}> entry = it.next();
${type} key = entry.getKey();
${type2} value = entry.getValue();
// do something with the key and the value
}

 

Robert Sinner replied on Fri, 2008/02/29 - 5:01pm

sorry double post

Tomas Kramar replied on Fri, 2008/02/29 - 5:39pm in response to: Robert Sinner

Robert,

I think you are looking for "var" variable. You can specify any java type and it will be expanded to the best match. In your case, try 

${variableName:var(java.util.Map)} 

Robert Sinner replied on Thu, 2008/03/06 - 1:24am in response to: Tomas Kramar

Thanks Tomas , that seems to just put  variableName though instead of putting the nearest map.

 

Try

for (Iterator<Map.Entry<${type},${type2}>> it = ${variableName:var(java.util.Map)}.entrySet().iterator(); it.hasNext();) {  
Map.Entry<${type},${type2}> entry = it.next();
${type} key = entry.getKey();
${type2} value = entry.getValue();
// do something with the key and the value
}

 

Carlus Henry replied on Fri, 2008/04/25 - 12:07pm

Hre are some code templates that I use:

Jakarta Commons Logging - (which I bind to jaklog)

private static final Log logger = LogFactory.getLog(${primary_type_name}.class);

 

Logger Threshold Testing - (which I bind to ifLogXXX)

if (logger.isDebugEnabled()) {
${line_selection}logger.debug("${cursor}");
}

 

Mike Cacenco replied on Wed, 2008/08/20 - 6:42pm

The problem with adding a template directly under "java" is that it is too general and it will become crowded fast.
Does anybody know please how to add a new contextType to be like a sub-type of the JavaContext for a custom plugin?

The Template page does not allow adding a context directly nor through just the extension point in plugin.xml.

I tried adding in plugin.xml (of the custom plugin):

<extension point="org.eclipse.ui.editors.templates">

<contextType id="java1"
 class="myPlugin.templates.J1ContextType"
 name="Java1 Context">
</contextType>

<template name="Template1"
contextTypeId="java1"
id="myPlugin.templates.Template1"
description="..does something..">
<pattern>
ABC abc = new ABC();
abc.setURL("http"//abc");
</pattern>
</template>

<resolver contextTypeId="java1"
type="src"
class="myPlugin.templates.J1VariableResolver">
</resolver>

</extension>

The comment for ContributionContextTypeRegistry says: ... Editor implementors will usually instantiate a registry and configure the context types available in their editor. <code>ContextType</code>s can be added either directly using {@link #addContextType(TemplateContextType)} or by instantiating and adding a contributed context type using {@link #addContextType(String)}
All nice except that JavaPlugin.getDefault().getTemplateContextRegistry() is protected from the library and crashes the plugin that tries to call it.

Anybody tried to do this in some form? (i.e. set more contexts for the java editor?)

Thanks,

 MVC

Alex Gouvea Vas... replied on Tue, 2008/11/18 - 2:32pm

Considering the follow field, in a class:

private Boolean ok = null;

How would be a template to write the following code?

variables in that code: ok, Boolean (would be Integer, Long, Date, Calendar, or other else that need transformation to write as string, in a web interface).

imports needed: import org.apache.commons.lang.StringUtils;

______

public getOkAsString() {

      return (ok == null) ? "" : ok.toString();

}

public setOkAsString(String ok) {

      this.ok = (StringUtils.isBlank(ok)) ? null : new Boolean(ok);

}

__________

I couldn't do:

- the differents cases for "ok" (needed Upper Case for get and set method names)

- capture type of "ok" field (Boolean, in this example).

__________

This template would be very useful for struts users, or other web developer, since web interface works just with strings.

Sorry my poor english.

Carlus Henry replied on Fri, 2009/01/16 - 4:45pm

Here is another code template that I am using extensively on my current project.

 

 
${:import(org.apache.commons.lang.builder.EqualsBuilder,org.apache.commons.lang.builder.HashCodeBuilder,org.apache.commons.lang.builder.ReflectionToStringBuilder)}
@Override
public boolean equals(Object obj) {
return EqualsBuilder.reflectionEquals(this, obj);
}

@Override
public String toString() {
return ReflectionToStringBuilder.toString(this);
}

@Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}

Mohammad Norouzi replied on Sat, 2009/04/25 - 1:30am

Hi Can anyone tell me how to write a template to create a toString() method in which all the enclosing fields are participated as below:

public class AClass {
   private String field1;
   private String field2;
   private Object field3;


  public String toString() {
      return "field1: " + field1 + ", " +
                 "field2: " + field2 + ", " +
                 "field3: " + field3 ; 

  }


}

thanks

Szabolcs Rugina replied on Mon, 2009/05/18 - 1:36pm in response to: Mohammad Norouzi

Hi,

I usualy used something like:

@Override
public String toString()
{
class FieldNameComparator implements Comparator<Field>
{

@Override
public int compare( Field o1, Field o2 )
{
if ( o1.getName() == null )
{
return -1;
}
if ( o2.getName() == null )
{
return 1;
}
return o1.getName().compareTo( o2.getName() );
}

};

final Class<${primary_type_name}> myClass = ${primary_type_name}.class;
final StringBuffer result = new StringBuffer( myClass.getName() );

//depends if You want just the local or the inherited fields too
final Field[] fields = myClass.getDeclaredFields(); //myClass.getFields( );
final List<Field> fieldList = Arrays.asList( fields );
Collections.sort( fieldList, new FieldNameComparator() );
result.append("\n");
for ( Field field : fieldList )
{
if ( !Modifier.isStatic( field.getModifiers() ) )
{
try
{

result.append( field.getName() ).append( ":" );
result.append( field.get( this ) );
}

catch ( final Exception e )
{
result.append( "ErrorAccessingField" );
}
finally
{
result.append( "\n" );
}
}
}
return result.toString();
}

 

 

Gautam Dev replied on Thu, 2010/10/28 - 1:44am

Nice article. You can look at my fast code plugin for code templates. You can select a bunch a fields and log them, or create toString, etc. http://fast-code.sourceforge.net/

Steve Ulrich replied on Wed, 2010/11/24 - 10:58am in response to: Robert Sinner

I'm lucky with this:

${:import(java.util.Map.Entry)}
for (Entry<${keyType:argType(map, 0)},${valueType:argType(map, 1)}> entry : ${map:var(java.util.Map)}.entrySet()) {
${keyType} key = entry.getKey();
${valueType} value = entry.getValue();
${cursor}
}

Gym Prathap replied on Wed, 2013/05/15 - 9:44am

How getter and setter works in code template option.


Java Training in chennai 

Marcel Hölscher replied on Fri, 2014/08/29 - 5:38am

Hi,

thanks for the nice article!

There's a possibility to completely automate your logger template without the need of doing the necessary imports manually. Just let the template generate the needed import statements. Below is an example where i use the slf4j logging api:

${:import(org.slf4j.Logger, org.slf4j.LoggerFactory)}
private static final Logger logger = LoggerFactory.getLogger(${enclosing_type}.class);

Kind regards

Marcel

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.