Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Classworking toolkit: Annotations vs. configuration files

Annotations may be all the rage, but configuration files still have their uses

Dennis Sosnoski, Consultant, Sosnoski Software Solutions, Inc.
Author photo
Dennis Sosnoski is the founder and lead consultant of Java technology consulting company Sosnoski Software Solutions, Inc., specialists in XML and Web services training and consulting. His professional software development experience spans over 30 years, with the last several years focused on server-side XML and Java technologies. Dennis is the lead developer of the open source JiBX XML Data Binding framework built around Java classworking technology and the associated JibxSoap Web services framework, as well as a committer on the Apache Axis2 Web services framework. He was also one of the expert group members for the JAX-WS 2.0 specification.

Summary:  Annotations let you specify metadata as part of your source code. With this feature, you can embed tool instructions in your code rather than creating separate configuration files that you then need to maintain in parallel to the source code. But, as Java™ consultant Dennis Sosnoski explains, configuration files still have their uses, especially for aspect-like functions that cut across the source code structure of an application.

View more content in this series

Date:  02 Aug 2005
Level:  Intermediate
Also available in:   Japanese

Activity:  298 views
Comments:  

Annotations are one of the major new features of J2SE 5.0, designed to allow metadata about code to be defined as part of the code. Having the metadata inlined with the actual code it references provides locality of reference, so that everything is in one place. This approach makes it easier to maintain the metadata as the corresponding code changes. However, annotations also have some weaknesses.

You can define metadata in other ways besides keeping it inline with the code. I'll lump these alternatives under the general heading of "configuration files" for the purposes of this column, with the understanding that a configuration file approach is anything that uses a separate non-Java file for some form of metadata. This type of approach creates a potential maintenance problem, because the metadata has to refer to code while being physically separate. If the code changes, the metadata may need to be modified, and with a configuration file approach to metadata, you have to remember to go to the separate configuration file and modify it.

In this column, I'm going to discuss the trade-offs between these two approaches as I see them, and look at some of the implications for developers as the Java standards process and many open source projects convert to an ever-more annotation-based approach to metadata.

Historical background

Configuration files were in use long before the development of the Java platform but were generally used just to provide run-time parameters for controlling the execution of an application. The development of the J2EE platform and related component standards brought a different type of configuration file into widespread use, a type that contained information used by a framework in working with application code. One of the earliest examples is the web.xml file used for Java servlet deployment configuration.

The Java platform's support for dynamic classloading and run-time access to class metadata through reflection offers many different ways to use configuration files to control the loading and execution of programs at run time. Developers were quick to take advantage of the flexibility this approach provided. But as framework configuration files proliferated, developers have found these files complex to generate and maintain. Changes to Java source code may require modifications to the configuration files, but that requirement is not shown by anything in the source code -- instead, the developers must be aware of the connection between the source code and the configuration file and remember to keep them in sync.

Enter XDoclet

The popular XDoclet tool was developed to help manage this issue of linkages between files. Rather than maintaining configuration information as separate files, XDoclet allows the configuration information to be embedded in the Java source code by using special Javadoc tags. XDoclet then builds the configuration files as needed from these tags. Using XDoclet, your configuration information can be kept with your source code so that everything you need to track is in one place.

Ask the expert: Dennis Sosnoski on JVM and bytecode issues

For comments or questions about the material covered in this article series, as well as anything else that pertains to Java bytecode, the Java binary class format, or general JVM issues, visit the JVM and Bytecode discussion forum, moderated by Dennis Sosnoski.

XDoclet actually goes well beyond just generating configuration files. It was originally designed for use with EJBs, which require several boilerplate files for each bean in addition to the actual configuration files. XDoclet automatically generates these boilerplate files for an EJB from the basic bean source code, as controlled by the special Javadoc tags. As XDoclet has been extended to deal with many other usages beyond just EJBs, this code generation facility has also been extended. It's an extremely useful tool in situations where boilerplate code is required, helping to keep your source tree free of clutter that contributes nothing to the operation of the application.

XDoclet does suffer from a few limitations. Because it uses simple transformations to convert Javadoc-style comments into configuration files, many aspects of the configuration are not checked for accuracy. In the past, I've had unfortunate experiences with XDoclet because of typos such as misspelling and mismatched quotes around values. Errors of this type get passed through into the generated code or configuration files, which can make it difficult to backtrack to the original source of the problem.

Annotations to the rescue?

Partly inspired by the success of XDoclet, JSR-175 was formed in 2002 to provide a standard means for associating metadata in the form of arbitrary attribute information, with particular Java classes, interfaces, methods, and fields. Although a custom Javadoc tag similar to XDoclet was listed as one possible implementation in the JSR proposal, the final form of JSR-175 metadata support took a very different approach. This support uses extensions to the Java language defining annotations, JavaBean-like groups of name-value pairs that can be added as modifiers on any Java component declaration.

Annotations get around many of the limitations of the XDoclet approach. By using typed values, and allowing particular annotations to be restricted to being used with only some types of Java components, annotations allow a much higher degree of validation than provided by XDoclet. Because annotations are integrated into the Java language definition, they are also more easily processed (as long as you're using JDK 5.0, anyway -- for some pointers on using annotations with earlier JVMs see last month's column). They're also more flexible in terms of how you use them, with options for whether the annotation information is to be included in class files output by the compiler and made available to the application at run time.

Ever since JSR-175 got started, there's been great interest in defining metadata as part of other JSRs. Once the decision was made to include annotations in J2SE 5.0, the use of annotations became part of the planning for many new JSRs scheduled to reach completion after the release of J2SE 5.0. We're starting to see the release of these JSRs to public comment now, and I'll use an example from one of these in the next section.


Trade-offs

Annotations represent a powerful refinement of the XDoclet principle of embedding configuration information in Java source code. The main advantage of this approach is that everything is in one place and the configuration information is associated directly with the Java component. Many types of refactorings of the source code are transparent to annotations for this reason -- the annotations will always apply to the component they're attached to, even when that component is moved or renamed. For other refactorings that require new or modified annotations, everything is in the same location, assuring that the annotations are visible to the developer and increasing the likelihood that they'll remember to make the necessary changes.

Despite the benefits of annotations, I see two main drawbacks to their (over) use. The first is that source code can become cluttered with all sorts of annotations that are irrelevant to the actual program logic, interfering with the readability of the code. The second drawback is that while annotations are ideal for metadata that relates to a particular component, they're not well suited to metadata with cross-component application.

Configuration files, on the other hand, can provide an organized view of a web of relationships that span different components of an application. Because they're separate from the actual source code, they don't interfere with the readability of the Java source code. The main drawback of configuration files is as mentioned earlier -- they're separate artifacts that need to be maintained in parallel with the source code of an application, with no obvious connection between the two.

Annotation (mis)use

As an example of what I consider annotation misuse, Listing 1 gives an excerpt from the annotations example supplied with the early access version of JAX-RPC 2.0 (reproduced here under the publication provision of the Java Research License used for the early access distribution). Disclaimer: Although I'm a member of the JAX-RPC 2.0 expert group, the opinions expressed here are strictly my own and are not intended to reflect those of the expert group as a whole.


Listing 1. JAX-RPC 2.0 annotation example
/*
 * Copyright (c) 2005 Sun Microsystems, Inc.
 * All rights reserved. 
 */
package annotations.server;

import java.rmi.Remote;
import java.rmi.RemoteException;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
import javax.jws.WebResult;
import javax.jws.WebParam;

@WebService(targetNamespace = "http://duke.org", name="AddNumbers")
@SOAPBinding(style=SOAPBinding.Style.RPC, use=SOAPBinding.Use.LITERAL)
public interface AddNumbersIF extends Remote {
    
    @WebMethod(operationName="add", soapAction="urn:addNumbers")
    @WebResult(name="return")
        public int addNumbers(
            @WebParam(name="num1")int number1, 
            @WebParam(name="num2")int number2) throws RemoteException, AddNumbersException;

}

/*
 * Copyright (c) 2005 Sun Microsystems, Inc.
 * All rights reserved. 
 */
package annotations.server;

import javax.jws.WebService;

@WebService(endpointInterface="annotations.server.AddNumbersIF")
public class AddNumbersImpl {
        
    /**
     * @param number1
     * @param number2
     * @return The sum
     * @throws AddNumbersException
     *             if any of the numbers to be added is negative.
     */
        public int addNumbers(int number1, int number2) throws AddNumbersException {
                if (number1 < 0 || number2 < 0) {
                        throw new AddNumbersException("Negative number can't be added!",
                                        "Numbers: " + number1 + ", " + number2);
                }
                return number1 + number2;
        }
}

The Listing 1 code consists of a Web service interface definition and the corresponding implementation class. Although the interface definition is expressed as Java code (of a sort -- when I showed this example as part of a recent presentation, an audience member remarked that he wouldn't have recognized this as Java code if I hadn't identified it as such), it's really just a configuration file coded as annotations.

Does the use of annotations in Listing 1 actually provide any benefits over a separate configuration file? Listing 2 gives a configuration file providing the same information as the Listing 1 annotations (using Apache Axis's internal configuration format). To me, the configuration file form looks cleaner and therefore easier to maintain than the mass of annotations shown in the example. If you really want to tie the implementation class to its use as a Web service (the apparent point of the @WebService annotation in the Listing 1 implementation class), an annotation could still be used just for this purpose (referencing the configuration file, rather than the interface). Otherwise, there's no need to have any special information in the implementation class at all.


Listing 2. Configuration file equivalent to Listing 1 annotations
<deployment xmlns="http://xml.apache.org/axis/wsdd/" 
  xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <service name="AddNumbers" provider="java:RPC" style="rpc" use="literal">
    <namespace>http://duke.org</namespace>
    <parameter name="className" value="annotations.server.AddNumbersImpl"/>
    <parameter name="allowedMethods" value="add"/>
    <operation name="add" qname="tns:addNumbers" returnQName="return">
      <parameter name="num1"/>
      <parameter name="num2"/>
    </operation>
  </service>
</deployment>

Where annotations break down

In the last section, I gave an example of what I see as inappropriate use of annotations, where a separate configuration file would work just as well and be easier to understand. For an example of a case where a configuration file works better than annotations, I'll turn to the JiBX data binding framework -- my own pet classworking project.

JiBX uses bytecode enhancement to add methods to compiled classes that convert instances of the classes to and from XML. The details of the relationship between Java classes and XML is determined by a binding definition, a form of XML configuration file. This configuration is processed by a binding compiler component of the JiBX framework, which implements the actual bytecode enhancement of the compiled classes.

Where JiBX differs from other data binding frameworks (aside from speed -- it's generally several times faster than the alternatives) is in the flexibility of the relationship between Java classes and XML. Most data binding frameworks assume that the structure of Java classes matches the structure of the XML, in that elements with attributes or child elements correspond to JavaBean-like classes, while individual attributes or simple child elements correspond to simple properties of JavaBean-like classes. JiBX drops this assumption and uses binding definitions that allow for structural differences between the Java classes and the XML representation. JiBX even supports multiple bindings to the same classes, with the actual binding to be used for a particular XML document selected at run time.

To illustrate, I'll give a simple example of JiBX flexibility. Listing 3 shows a pair of data classes, with Listings 4 and 5 each giving a different binding definition for these classes along with a corresponding XML document. Both sample XML documents present the same data, and most developers would find it easy to relate these documents to the Listing 3 Java classes despite the very obvious differences in structure of the two XML documents. Most developers also find it easy to understand how the corresponding binding definitions relate to the structure of each XML document.


Listing 3. Data classes for XML binding
package simple;

public class Customer
{
    private Name name;
    private String street1;
    private String street2;
    private String city;
    private String state;
    private String zip;
    private String phone;
    ...
}

package simple;

public class Name
{
    private String firstName;
    private String lastName;
    ...
}


Listing 4. First binding and XML document
<binding name="binding1">
  <mapping name="customer" class="simple.Customer">
    <structure field="name">
      <value name="first-name" field="firstName"/>
      <value name="last-name" field="lastName"/>
    </structure>
    <value name="street" field="street1"/>
    <value name="city" field="city"/>
    <value name="state" field="state"/>
    <value name="zip" field="zip"/>
    <value name="phone" field="phone"/>
  </mapping>
</binding>

<customer>
  <first-name>John</first-name>
  <last-name>Smith</last-name>
  <street>12345 Happy Lane</street>
  <city>Plunk</city>
  <state>WA</state>
  <zip>98059</zip>
  <phone>888.555.1234</phone>
</customer>


Listing 5. Second binding and XML document
<binding name="binding2">
  <mapping name="customer" class="simple.Customer">
    <structure name="name" field="name">
      <value name="first-name" field="firstName"/>
      <value name="last-name" field="lastName"/>
    </structure>
    <structure name="address">
      <value name="street" field="street1"/>
      <value name="city" field="city"/>
      <value style="attribute" name="state" field="state"/>
      <value style="attribute" name="zip" field="zip"/>
    </structure>
    <value style="attribute" name="phone" field="phone"/>
  </mapping>
</binding>

<customer phone="888.555.1234">
  <name>
    <first-name>John</first-name>
    <last-name>Smith</last-name>
  <name>
  <address state="WA" zip="98059">
    <street>12345 Happy Lane</street>
    <city>Plunk</city>
  </address>
</customer>

Now consider what would be involved in using annotations to define the Listings 4 and 5 bindings. Listing 6 gives one version of such annotations. Here, I'm assuming several annotations to represent the different options that can be used in a binding definition, most of them with variations for a single binding (using a simple value) vs. multiple bindings (using arrays of values). Even for this simple example, the result is very messy, and at least to me it seems much more difficult to either read the Java code as such (compared to the unannotated version) or to make sense of the binding definitions (compared to the definitions in Listings 4 and 5).


Listing 6. Annotated Java classes for bindings
package simple;

// Need the JiBXAddedWrappers annotation here because there's no other place to
//  put it. The ugly format of the annotation is necessary because you can't
//  repeat an annotation, and can only have array values of base types.
@JiBXMapping(names={"binding1", "binding2"})
@JiBXAddedWrappers(bindings={"binding2"}, names={"address"}, field-sets={"street1,city.state,zip"})
public class Customer
{
    @JiBXStructure(bindings={"binding1", "binding2"}, names={"", "name"}) private Name name;
    @JiBXValue(name="street") private String street1;
    private String street2;
    @JiBXValue private String city;
    @JiBXValue(bindings={"binding1", "binding2"}, styles={element, attribute}) 
      private String state;
    @JiBXValue(bindings={"binding1", "binding2"}, styles={element, attribute}) 
      private String zip;
    @JiBXValue(bindings={"binding1", "binding2"}, styles={element, attribute}) 
      private String phone;
    ...
}

package simple;

public class Name
{
    @JiBXValue(name="first-name") private String firstName;
    @JiBXValue(name="last-name") private String lastName;
    ...
}

When I started developing JiBX, I originally planned to provide XDoclet support as a convenient alternative for users who didn't want to maintain a separate binding file. Trying to express the full flexibility of JiBX bindings rapidly turned into a mess, though. XDoclet tags suffer from the same limitations as annotations, so the XDoclet version of bindings looked very similar to the Listing 6 annotations version. I decided it was better to just force the use of a binding definition file than to encourage users to start down the pitfall-laden path of defining binding metadata in tags.

Best practices

Hopefully, I've convinced you by this point that annotations are not always better than configuration files. That leaves the issue of deciding which approach works better in a particular use case. To me, it seems that the answer revolves around the type of configuration information you need to represent.

Configuration information that is always going to be linked to a specific Java component (class, method, or field) is a good candidate to be represented by annotations. Annotations work especially well in this case when the configuration is core to the purpose of the code. Because of the limitations on annotations, it's also best when each component can only ever have one configuration. If you need to deal with multiple configurations, especially ones that are conditional on anything outside the Java class containing an annotation, annotations may create more problems than they solve. Finally, annotations cannot be modified without recompiling the Java source code, so anything that needs to be reconfigurable at run time can't use annotations.

In an earlier column, I gave an example of using annotations for automatic construction of toString() methods. Although that was a somewhat trivial example, I think it does show the proper usage of annotations: The annotations were for a purpose that was directly involved with the code (the toString() method), didn't require multiple configurations (because there can only ever be one instance of the method per class), worked only within a class unit, and did not need to be changed at run time.

Configuration files, on the other hand, work best when different Java components are being used in a coordinated way. The JiBX binding definitions from the last section are a great example of this fact, where embedding the configuration in the code with annotations makes both the code and the configuration difficult to understand. Even beyond this confusion issue, I see the data binding function as an aspect (in the AOP sense) that gets applied to the application. From the AOP standpoint, it's clearly best to keep the aspect information (in this case, binding definitions) outside the code.


Conclusions

In this column, I've set out what I see as the weaknesses of an annotation-based approach to configuration information. Despite these weaknesses, I think annotations are a very useful addition to the Java developer's toolkit. On the other hand, I also think they can be overused and that some of the Java standards now under development may be headed in that direction.

For my own JiBX project, I intend to stay with configuration files, because I think these are better suited to represent JiBX bindings. Even so, I'm interested in adding support for JAXB 2.0 annotations in JiBX 2.0 (hopefully both using the annotations directly, and converting them to JiBX binding definition files). That way users who really want to work with annotations will be able to use a standard representation, while users who want the full flexibility of JiBX bindings will be able to use binding definition files instead.

Next month I'm going to delve a little deeper into JiBX. As I write this, I'm wrapping up the JiBX 1.0 production release and plan to start work soon on the changes planned for 2.0. Now's a great time to summarize some of the classworking do's and don'ts I've learned in the course of the JiBX 1.0 development, so that's just what I'll do in next month's column. Come back then for a look behind the curtains at the bytecode generation core of JiBX.


Resources

About the author

Author photo

Dennis Sosnoski is the founder and lead consultant of Java technology consulting company Sosnoski Software Solutions, Inc., specialists in XML and Web services training and consulting. His professional software development experience spans over 30 years, with the last several years focused on server-side XML and Java technologies. Dennis is the lead developer of the open source JiBX XML Data Binding framework built around Java classworking technology and the associated JibxSoap Web services framework, as well as a committer on the Apache Axis2 Web services framework. He was also one of the expert group members for the JAX-WS 2.0 specification.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology
ArticleID=90751
ArticleTitle=Classworking toolkit: Annotations vs. configuration files
publish-date=08022005

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Special offers