Jay has posted 2 posts at DZone. View Full User Profile

Useful Eclipse Code Templates

07.23.2008
| 30322 views |
  • submit to reddit

Eclipse's Java editor allows you to define code templates. You can use them to code complete things that you type all the time, such as get logger, logger.debug, etc.

Go to Windows->Preferences->Java->Editor->Templates , and put in the following templates

name:getlog

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


name:debug

if (logger.isDebugEnabled()) {
logger.debug(${Message}, ${exception});
}


name:error

logger.error(${Message}, ${exception});



name:info

logger.info(${Message}, ${exception});


name:warn

logger.warn(${Message}, ${exception});


name:const

private static final ${type} ${name} = new ${type} ${cursor};

After you have these templates setup, type the first few characters of the template name and hit ctrl-space, the editor will code complete the template. For example, type getlog, ctrl-space, and enter will declare a logger variable named logge.

By the way, Eclipse has quite a few built-in templates out of the box. I use some of them all the time, such as

'main' - creates a main method
'trycatch' - try catch
'Test' - creates a junit4 test method
'sysout' - System.out.println

Published at DZone with permission of its author, Jay Liang.

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

Tags:

Comments

Lzszlo Hogyishivjak replied on Wed, 2008/07/23 - 7:53am

  1. if (logger.isDebugEnabled()) {  
  2. logger.debug(${Message}, ${exception});  
  3. }

Is this a good practice? logger.debug will check if the level is high enough, so why double-check it?

Herman Lintvelt replied on Wed, 2008/07/23 - 10:54am in response to: Lzszlo Hogyishivjak

The issue comes in if ${Message} is a build up string, using something like String.format(...) or MessageFormat.format(..), since that will get called before the parameter gets passed to logger.debug(...), thus doing something that might not be necessary to execute if debug logging is not enabled.

And in a lot of applications, every millisecond counts. 

Peter Schuebl replied on Wed, 2008/07/23 - 12:13pm

Eclipse 3.4 has one nice little feature there that I've been waiting for for a while.

You can specify an import statement in your template. In most projects I've been working on log4j is the logging framework and Eclipse never knew which Logger to import.

Type Filters was one way to work around that but being able to specify the import statement in the logger is way better.

----

${:import(org.apache.log4j.Logger)}
private static final Logger log = Logger.getLogger(${enclosing_type}.class);

Alain O'Dea replied on Wed, 2008/07/23 - 12:17pm

I wrote a decorator for commons Log that allows you to call all its methods as if you were calling MessageFormat.format(). The advantage lies in the implementation which I chose where it actually wraps the message in an Object whose toString() calls MessageFormat.format(). This means that the only overhead of logging to a disabled log level is an Object allocation rather than a complete formatting of a potentially complete MessageFormat.

A call such as decoratedLog.info("Iteration {0} of {1}", 15, 100) calls underlyingLog.info(getMessage("Iteration {0} of {1}", 15, 100)).

Log#getMessage(String, Object...) and Log#info(String, Object...) are implemented as follows:

private static Object message(final String pattern, final Object... arguments)
{
    return new Object()
    {
        public String toString()
        {
            return MessageFormat.format(pattern, arguments);
        }
    };
}

public void info(String pattern, Object... arguments)
{
    log.info(message(pattern, arguments));
}

This allows you to write elegant logging code without worrying about a heavy performance impact. It does mean that you have to decorate LogFactory as well, but that is pretty trivial and only affects the imports of client code. What do you guys think of this approach?

Eric Jablow replied on Thu, 2008/07/24 - 12:26am

If one wants to log an object, and the format one needs is expensive to produce, one should register an ObjectRenderer for its class.  One registers it in the log4j.xml file, and then one can use LOGGER.debug(renderableObject) without the surrounding if.

Jay Liang replied on Thu, 2008/07/24 - 5:32am

Can someone explain to me why we want to go thru all the fuss to avoid checking logger.isDebugEnabled() before calling debug? Even if that is in fact an unnecessary double check, it should not affect the performance of production because you are supposed to disabled DEBUG in production. So the isDebugEnabled() will be checked only once in production whether it's being checked explicitly using if (logger.isDebugEnabled()) {  } or implictly by the logger internally by examing the log level.

Dave Newton replied on Thu, 2008/07/24 - 7:46am in response to: Jay Liang

@zl25drexel: That was already answered: it's cheaper to skip evalution of an expensive log statement.

Without a surrounding isDebugEnabled() the expensive log statement will be executed and the results passed to debug(), which then does its own isDebugEnabled() check.

It may be unnecessary from a logical standpoint, but it isn't always unnecessary from a performance standpoint.

Andrew Newdigate replied on Fri, 2008/07/25 - 9:52am

Another fairly useful template for iterating over the entries in a map:

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

    ${cursor}
}

Marc Ende replied on Mon, 2008/07/28 - 3:34am

Logging templates are nice but I found the log4e plugin more useful than using these templates.

Omar Palomino S... replied on Wed, 2008/07/30 - 3:59pm in response to: Marc Ende

I think that loading an aditional plugin for loggers is overkill. The plugin would be fine if it gives some configurations wizards and consoles for popular loggers.

Dave Newton replied on Wed, 2008/07/30 - 4:12pm in response to: Omar Palomino Sandoval

@Omar: The plugin does far more than simple templates can.

If you looked at the screenshot you would see there is at least some functionality for changing the logging framework (evidenced by the "Exchange logging framework of this class" context menu option), and because it has access to the AST can provide way more functionality than available via templates.

Charles Martin replied on Wed, 2008/07/30 - 4:18pm

A few qns:

(1) Where are these templates documented?

(2) Is there a repository/web site of useful templates somewhere?

(3) Is there a similar way to create such templates for Ruby in the RDT?

Thanks

 

Charles

 

Omar Palomino S... replied on Wed, 2008/07/30 - 4:39pm in response to: Dave Newton

Ok, they give you more functionality that simple templates, but I think that more important that generated loggers and templates is a tool that helps to take advantage of the all functionalities the logger framework can offer. For an instance a control panel or a wizard.

Dave Newton replied on Wed, 2008/07/30 - 4:47pm in response to: Omar Palomino Sandoval

I'm sure we'll all be interested in seeing what you have when you're done; until then, I'm happy enough with templates or Log4E.

Omar Palomino S... replied on Thu, 2008/07/31 - 10:29am in response to: Dave Newton

My point is that the tool is OK if you want another Eclipse plugin, but and interesting challenge would we the configuration setup that i've mentioned before.

Instead of try to argue that is the "best tool ever" (sic) you could mention other interesting features about Log4E, like the ones that they mention in this blog.

http://almaer.com/blog/log4e-eclipse-plugin-for-log4j-does-a-great-job-of-anti-aop

I think that the function that replace all sysout statements for logger is kind of cool, once the project is ongoing.

Just my 2 cents.

Jörg Gottschling replied on Fri, 2008/08/08 - 1:33am in response to: Alain O'Dea

Alain:  You're code would be no benefit to performance, if you do not check for isInfoEnabled before executing message(String, Object...). I think it would slow it down, because the formatting is nice, but expensive. Also The JVM builds an Array for the vararg-argument. If you are interessted in very good performance. You should offer some overloaded methods, with one, two, three, or more arguments, so no Array must be build, especially if the logging is not done.

But it's a very elegant solution. Doesn't offer plain log4j something similar?

BTW: Logging was only a performance issues to me, when really logging heavily for debbuging or when performing costly operations to build up the message, like using commons langs ToStringBuilder.reflectionToString.

Kisito Momo replied on Fri, 2008/08/08 - 2:27am

I think's that templating is a quick way to use copy/paste. And copy/paste is a bad way to write a program.May be using an appropriate Framework (AOP?)is a better way to manage logging

Omar Palomino S... replied on Fri, 2008/08/08 - 10:26am in response to: Kisito Momo

Hi Kisito,

 I definitely agree with you. In despite of integrated the logger templates suggested in this post for the needed logger points, like debugging message or  some transaction information, my base method logging information relies in a Logging Advice, configurated with Spring AOP.

Javier Serrano ... replied on Mon, 2011/12/05 - 5:30am

Hi all,

I've got another template very usefull, generates ToString, hashcode and equals using commos-lang.

Here it is:

${: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);
}

Hope it will be usefull

Comment viewing options

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