Mapping Objects to XML Files using Java 5 Annotations

转载 2004年10月19日 09:57:00

2004-10-17 The Java Specialists' Newsletter [Issue 097] - Mapping Objects to XML Files using Java 5 Annotations

Author: Amotz Anner

JDK version: Sun JDK 1.5.0-b64

Category: Language

You can subscribe from our home page: (which also hosts all previous issues, available free of charge :-)

Welcome to the 97th edition of The Java(tm) Specialists' Newsletter. We had a beautiful day down here in Cape Town, South Africa. This morning I was concerned because it was cloudy, but fortunately it cleared up for our braai. In South Africa, a popular pass-time is to make a fire with wood, then once this has burnt down, to grill some lamb chops, sausage or chicken on the coals. We only braai once the coals are completely burnt, to avoid having flames leap up and burn the meat. The coals have to be so hot that you cannot hold your hand at the level of the meat for more than eight seconds. Some wood holds its heat longer, and you must make sure that the flavour of the meat is not adversely affected by the wood you choose. The braai is more for the social interaction than for the food and so it is common to start the fire only after the guests have arrived. Another interesting tradition is to invite guests for a braai, but ask them to bring their own meat and drinks, and maybe a salad. We call that a bring-and-braai. The company is very important, and although we sometimes braai on our own, we usually prefer to have lots of happy friendly faces around. For example, today we were 17!

So, if you visit South Africa, and tell me when you will be in Cape Town, you will probably be invited to a "braai". We will probably ask you to bring some of the food, and when you arrive, I will still be chopping the wood, but besides that, it is a lot of fun, and you should accept the invitation :)

I find it amazing how quickly some people pick up a new technology. Amotz Anner sent me an example of how you can use annotations to write some very interesting code. Then Amotz did me a huge favour and wrote this newsletter. Thank you very very much.

Amotz is the Founder of X.M.L. Systems Ltd located on:
46, Jerusalem St. Flat 9B
Kfar-Saba 44369
Cell: +972 (54) 686-0707

That was not the only interesting communication with Amotz. He discovered that in the JDK 1.5.0, if you compile code that uses the ternary if-else operator, with one side of the results null then it can deliver wrong results if you immediately assign this to a final local variable. This compiler bug has been fixed and will be available in the next release. For more details, please look at our posts on JavaLobby and TheServerSide.

This bug does concern me. With most Java bugs that I have seen, upgrading to a new JRE solves the problem. With this bug, you need to upgrade AND recompile all your sources. It is easy for this bug to make it into your production code library, and unless you have a very good test procedure, you might never pick it up. So, be warned!

Enough from me, over to Amotz...

Mapping Objects to XML Files using Java 5 Annotations

The following is an example of using the new annotation capability of Java 5.0 to extend the expressiveness of Java.

My code relies on XML to declare all sort of components, and then have Java classes construct themselves from those declarations. It is NOT a persistence framework, for the following reason:

I consider the XML declaration to be primary, and the Java class to be secondary, a mere tool to realize the declaratory intent of the XML document. In contrast, in a persistence framework, the Java class is primary and the XML document is just a vehicle used to contain persistence data, and has no standing in and of itself.

So my requirement is that the Java class adapts itself to the XML declaration rather than the other way around. I also did not want to use any external IDL-type definitions to match Java classes to XML.

Prior to annotations, I was severely limited in my choices. What I could, and did do, was to use reflection to look for all public fields of a class whose names match those of an XML attribute in the appropriate declaration, and initialize those fields from the attribute value. This was a fragile solution, since there was no clear indication as to the special status of the names of those fields, and all to often I broke my code by changing field names, thus breaking the connection to the XML declaration.

Then came annotations and solved all my problems in one fell swoop. With them I can:

  1. Clearly indicate which fields are initialized from an XML declaration.
  2. Dissolve the field name - attribute name bond.
  3. Extend usage from just XML attributes to XML elements as well.
  4. Supply centrally/locally defined default values.

So how is that magic achieved? In four easy steps, of course.

Step 1: Annotation is defined

First, an annotation is defined, in the same way as an interface would be, as follows:


     @ FromXml {
  String xPath()  ;
  String dflt()  ;
   trim() ;

Step 2: Fields are Annotated

Second, fields have to be annotated. Syntactically, annotations are modifiers, so the result looks like:

  @FromXml public int a;
  @FromXml(xPath = , dflt = )  String color;

Step 3: Call initializer

The third easy step is to call the initializer with a Class and Element references:

    XmlConstructor.constructFromXml(this, elem, false);

A more complete example is our ComponenSlider class that manages a slider that can be configured using XML and annotations. You need the dom4j jar file to get this to compile.


 ComponentSlider {
  @FromXml  inverted = ;
  @FromXml  min = Integer.MIN_VALUE;
  @FromXml  max = Integer.MIN_VALUE;
  @FromXml  minorTickInterval = Integer.MIN_VALUE;
  @FromXml  majorTickInterval = Integer.MIN_VALUE;
  @FromXml  snapToTick = ;

   ComponentSlider(JSlider slider, Element def) {
    XmlConstructor.constructFromXml(, def);
     (minorTickInterval != Integer.MIN_VALUE) {
     (majorTickInterval != Integer.MIN_VALUE) {

Step 4: Supply constructFromXml method (once)

And finally, but just once, the above method has to be supplied. It looks like:


 XmlConstructor {
   constructFromXml(Object obj, Element elem) {
    constructFromXml(obj, elem, );

   constructFromXml(Object o, Element element,
                                       useSuper) {
     (element == ) {
    Class aClass = getAppropriateClass(o, useSuper);

     (Field field : aClass.getDeclaredFields()) {
      FromXml fromXml = field.getAnnotation(FromXml.);
       (fromXml != ) {
        handleAnnotatedField(fromXml, element, field, o);

   handleAnnotatedField(FromXml fromXml,
                                           Element element,
                                           Field field, Object o) {
    String value = getValue(fromXml.xPath(), element, field, fromXml);
     (!isEmpty(value)) {
       (fromXml.trim()) {
        value = value.trim();
      setField(field, o, value);

   String getValue(String xPath, Element element,
                                 Field field, FromXml fromXml) {
    String value = ;
     (!isEmpty(xPath)) {
      Node node = element.selectSingleNode(xPath);
       (node != ) {
        value = node.getText();
    }  {
      value = element.attributeValue(field.getName());

     (value == ) {
      value = fromXml.dflt();

   setField(Field field, Object o, String value) {
    Class type = field.getType();
       (type.equals(.)) {
        field.setInt(o, asHexInt(value));
      }  (type.equals(String.)) {
        field.set(o, value.intern());
      }  (type.equals(.)) {
        field.setDouble(o, Double.parseDouble(value));
      }  (type.equals(.)) {
        field.setBoolean(o, asBoolean(value));
      }  (type.equals(.)) {
        field.setChar(o, value.charAt());
    }  (IllegalAccessException ex) {

   Class getAppropriateClass(Object o,  useSuper) {
    Class aClass = o.getClass();
     (useSuper) {
      aClass = aClass.getSuperclass();

   isEmpty(String test) {
     test ==  || test.length() == ;

   asHexInt(String value) {
     (value.toLowerCase().startsWith()) {
       Integer.parseInt(value.substring(), );

   asBoolean(String option) {
     (!isEmpty(option)) {
      String opt = option.toLowerCase();
       .equals(opt) || .equals(opt)
          || .equals(opt) || .equals(opt);

Very simple, really.

Next, we create an XML file that contains the attributes for the Slider class:

<?xml version="1.0" encoding="UTF-8"?>
<Slider xmlns:xsi=''
  min="20" max="180" minorTickInterval="2" majorTickInterval="10">

And an example class that uses the ComponentSlider:


 AnnotationDemo  JFrame {
   JSlider slider =  JSlider();

   AnnotationDemo(Element sliderDef) {
     ComponentSlider(slider, sliderDef);

   Element loadSliderXMLFile(String filename)
       FileNotFoundException, DocumentException {
    Element sliderDef = ;
    SAXReader xmlReader =  SAXReader();
    File file =  File(filename);
     (file.exists() && file.canRead()) {
      Document doc = FileInputStream(file));
      sliderDef = doc.getRootElement();
     (sliderDef == ) {

   main(String args[])  Exception {
    Element sliderDef = loadSliderXMLFile(args[]);
    AnnotationDemo frame =  AnnotationDemo(sliderDef);
    frame.setSize(, );

I have not done it yet, but I can now initialize multi-dimensional arrays, lists, collections or what-not by straightforward extensions of the above code. Obviously, it made no sense before annotations, as XML attributes appear at most once. But with elements, there is no such limitation, and there is nothing to prevent database queries and/or other trickery.

Left as an exercise to the reader, is another annotation which would be used to associate "slider" directly with "weightSlider.xml", making annotation usage consistent, well documented and safe.

Have fun.


P.S. I (Heinz) refactored Amotz's code a bit, so if you find bugs or do not like the style of the code, blame me :)

Copyright 2000-2004 Maximum Solutions, South Africa

Reprint Rights. Copyright subsists in all the material included in this email, but you may freely share the entire email with anyone you feel may be interested, and you may reprint excerpts both online and offline provided that you acknowledge the source as follows: This material from The Java(tm) Specialists' Newsletter by Maximum Solutions (South Africa). Please contact Maximum Solutions for more information.

Java and Sun are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Maximum Solutions is independent of Sun Microsystems, Inc.


  • javajz
  • javajz
  • 2009年03月05日 00:16
  • 670

解决Add Hibernate mapping annotations to POJO (Hibernate 3.2 and above)不可选问题

今天一个项目要使用hibernate的注解 使得POJO类和数据库之间的联系通过加在POJO类里的注解就能实现 然后老师让我们把某个练手项目下model文件夹里的.java文件以及.hbm.xml文件...
  • dayouxian
  • dayouxian
  • 2016年03月18日 09:20
  • 1287

hibernate自动映射(注解向)问题add hibernate mapping annotations to pojo为灰色

  • Pashudeanan
  • Pashudeanan
  • 2016年08月02日 16:13
  • 650

Hibernate添加 annotation注解实体【AddHibernate mapping annotations to POJO 灰色点不了】

  • mingming_vip
  • mingming_vip
  • 2014年07月15日 10:51
  • 1963


从XML转换到JSON的方法有多种, 不过都要依赖第三方的库来实现转化,不过有了eBay提供的xml-2-json.xlst模板,你会发现转换原来很轻松.xml-2-json.xslt的代码大致如下(...
  • isaaq
  • isaaq
  • 2006年12月09日 16:56
  • 3068


注意事项(1): 实体类 - 数据库 — xml(jdbc) Integ...
  • xuanzhangran
  • xuanzhangran
  • 2017年02月18日 11:31
  • 1612

Annotation VS. XML VS. interface

  • chenxn_317
  • chenxn_317
  • 2007年11月16日 16:19
  • 430

Elasticsearch5.3 如何创建mapping demo

其实很简单 首先我们先要最基本Test写好废话不多说直接上代码 package; import org.el...
  • Mrswon
  • Mrswon
  • 2017年06月30日 19:36
  • 795

102.You want to import schema objects of the HR user using Oracle Data Pump from the development dat

102.You want to import schema objects of the HR user using Oracle Data Pump from the development dat...
  • dwj19830118
  • dwj19830118
  • 2016年07月31日 23:33
  • 749

spring myibatis集成报错:java.lang.NoClassDefFoundError: org/apache/ibatis/mapping/DatabaseIdProvider

异常错误:org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sqlSess...
  • Hu199055
  • Hu199055
  • 2017年04月10日 15:50
  • 1224
您举报文章:Mapping Objects to XML Files using Java 5 Annotations