Skip to main content.

Overview

JBeanMapper is a java library for converting javabeans to javabeans using rules defined in an XML mapping document.

To use JBeanMapper, calling code "registers" mappings with the BeanMapper. These mappings can be registered in code explicitly, or from an XML mapping document. Calling code then simply calls map on the BeanMapper to perform the conversion.

Installation

Download and put in your classpath JBeanMapper jar, commons-beanutils-1.6.1.jar, commons-digester-1.5.jar, and commons-logging-1.0.2.jar.

XML Mappings Documents

The schema for xml mappings is found here, and an explanation of the elements follows.

Simple Property Mappings

Most mappings can most easily be expressed using an XML document. The XML document contains the rules for the JavaBean transformation. Suppose we want to map ComplexPersonBean to ComplexPersonBean2 where the beans are defined as:

public class ComplexPersonBean {

  private String name;
  private String title;
  private String age;
  private ComplexAddressBean address;


  public ComplexAddressBean getAddress() {
    return address;
  }

  public void setAddress(ComplexAddressBean address) {
    this.address = address;
  }

  public String getAge() {
    return age;
  }

  public void setAge(String age) {
    this.age = age;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }
}


public class ComplexAddressBean {

  private String address;

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

}


public class ComplexPersonBean2 {

  private String myName;
  private int myAge;
  private ComplexAddressBean2 myAddress;

  public String getMyName() {

    return myName;
  }

  public void setMyName(String myName) {
    this.myName = myName;
  }

  public ComplexAddressBean2 getMyAddress() {
    return myAddress;
  }

  public void setMyAddress(ComplexAddressBean2 myAddress) {
    this.myAddress = myAddress;
  }

  public int getMyAge() {
    return myAge;
  }

  public void setMyAge(int myAge) {
    this.myAge = myAge;
  }

}

public class ComplexAddressBean2 {

  private String myAddress;
  private String title;

  public String getMyAddress() {
    return myAddress;
  }

  public void setMyAddress(String myAddress) {
    this.myAddress = myAddress;
  }

  public String getTitle() {
    return title;
  }

  public void setTitle(String title) {
    this.title = title;
  }

}
        
For the first example, we'll just map the properties name, and address of ComplexPersonBean to properties myName and myAddress of ComplexPersonBean2. The XML document would look like:
<bean-mappings>
    <bean-mapping src="org.jbeanmapper.docs.ComplexPersonBean"
                     target="org.jbeanmapper.docs.ComplexPersonBean2">
        <property-mapping src="name" target="myName"/>
        <property-mapping src="address" target="myAddress"/>
    </bean-mapping>
    <bean-mapping src="org.jbeanmapper.docs.ComplexAddressBean"
                     target="org.jbeanmapper.docs.ComplexAddressBean2" >
        <property-mapping src="address" target="myAddress"/>
    </bean-mapping>
</bean-mappings>
      

The following code could be used to perform the transform:

ComplexPersonBean personBean = new ComplexPersonBean();
personBean.setName("Henry");
ComplexAddressBean addressBean = new ComplexAddressBean();
addressBean.setAddress("12 Here Street");
personBean.setAddress(addressBean);
BeanMapper mapper = new BeanMapper();
InputSource source = new InputSource(new FileReader("/path/to/mappingfile/mapping.xml"));
mapper.registerBeanMappings(source);
ComplexPersonBean2 personBean2 = (ComplexPersonBean2)mapper.map(personBean);
    

Default Property Mappings

The <default-property-mappings> tag is used to populate the bean mapping with the default property mappings. The default property mappings are all property mappings from the source bean to the target bean that meet the following criteria: If the property is not convertable with a DefaultBeanConverter, you will need to explicitly map the property with a custom property mapping before using the default bean mappings; otherwise, the mapping will fail.

For example, given the following two classes:

public class PersonBean1 {
  private String name;
  private String address;
  private String phone;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public String getPhone() {
    return phone;
  }

  public void setPhone(String phone) {
    this.phone = phone;
  }
}


public class SimplePerson {
  private String name;
  private String address;
  private String phone;

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getAddress() {
    return address;
  }

  public void setAddress(String address) {
    this.address = address;
  }

  public String getPhone() {
    return phone;
  }

  public void setPhone(String phone) {
    this.phone = phone;
  }
}
The following xml can be used to map all properties of PersonBean1 to all properties of SimplePerson:
<bean-mappings>
    <bean-mapping src="org.jbeanmapper.docs.PersonBean1" target="org.jbeanmapper.docs.SimplePerson">
      <default-property-mappings/>
    </bean-mapping>
</bean-mappings>
To map only the phone property of PersonBean1 to SimplePerson either of the two following xml documents could be used:



Using the default-property-mappings tag:
<bean-mappings>
    <bean-mapping src="org.jbeanmapper.docs.PersonBean1" target="org.jbeanmapper.docs.SimplePerson">
      <default-property-mappings excludes="address, name"/>
    </bean-mapping>
</bean-mappings>
Using the property-mapping tag:
<bean-mappings>
    <bean-mapping src="org.jbeanmapper.docs.PersonBean1" target="org.jbeanmapper.docs.SimplePerson">
      <property-mapping src="phone" target="phone"/>
    </bean-mapping>
</bean-mappings>

Custom Creators

Suppose that rather than relying on JBeanMapper's default implementation to instantiate ComplexPesonBean2, we want to use a Factory method or perform some other special instantiation. This can be done by implementing the BeanCreator interface. The BeanCreator interface has a single method:
public Object createBean(Class clazz, MappingContext context);
Suppose a ComplexPersonBean2Creator was created that implements BeanCreator. To use the new ComplexPersonBean2Creator would require a simple change to the mapping file to indicate that a custom creator is should be used:

<bean-mappings>
    <bean-mapping src="org.jbeanmapper.docs.ComplexPersonBean"
                     target="org.jbeanmapper.docs.ComplexPersonBean2"
                     creator="org.jbeanmapper.docs.ComplexPersonBean2Creator">
        <property-mapping src="name" target="myName"/>
        <property-mapping src="address" target="myAddress"/>
    </bean-mapping>
    <bean-mapping src="org.jbeanmapper.docs.ComplexAddressBean"
                     target="org.jbeanmapper.docs.ComplexAddressBean2" >
        <property-mapping src="address" target="myAddress"/>
    </bean-mapping>
</bean-mappings>
      

Converters

Now suppose we wanted to map the age property of ComplexPersonBean to the myAge property of ComplexPersonBean2. In ComplexPersonBean the property age is a String. In ComplexPersonBean2 the myAge property is an int. To convert from the String to the int, we can create a BeanConverter or use any of the classes that implement org.apache.commons.beanutils.Converter defined in the apache commons-beanutils project. For this example, to use the IntegerConverter from commons-beanutils, the mapping file would look like:
   <bean-mappings>
       <bean-mapping src="org.jbeanmapper.docs.ComplexPersonBean"
                        target="org.jbeanmapper.docs.ComplexPersonBean2"
                        creator="org.jbeanmapper.docs.ComplexPersonBean2Creator">
           <property-mapping src="name" target="myName"/>
           <property-mapping src="age"
                        target="myAge"
                        converter="org.apache.commons.beanutils.converters.IntegerConverter"/>
           <property-mapping src="address" target="myAddress"/>
       </bean-mapping>
       <bean-mapping src="org.jbeanmapper.docs.ComplexAddressBean"
                        target="org.jbeanmapper.docs.ComplexAddressBean2" >
           <property-mapping src="address" target="myAddress"/>
       </bean-mapping>
   </bean-mappings>
      

Nested target-bean properties

Often, a bean needs to map a property to a nested property of the target bean. For example, suppose we want to map the title property of ComplexPersonBean to the title property of the myAddress property of ComplexPersonBean2. This can be done using a "dot" notation to indicate nested beans. The mapping file would look like:
   <bean-mappings>
       <bean-mapping src="org.jbeanmapper.docs.ComplexPersonBean" target="org.jbeanmapper.docs.ComplexPersonBean2"
                        creator="org.jbeanmapper.docs.ComplexPersonBean2Creator">
           <property-mapping src="name" target="myName"/>
           <property-mapping src="age"
                                target="myAge"
                                converter="org.apache.commons.beanutils.converters.IntegerConverter"/>
           <property-mapping src="address" target="myAddress"/>
           <property-mapping src="title" target="myAddress.title"/> 
       </bean-mapping>
       <bean-mapping src="org.jbeanmapper.docs.ComplexAddressBean" target="org.jbeanmapper.docs.ComplexAddressBean2" >
           <property-mapping src="address" target="myAddress"/>
       </bean-mapping>
   </bean-mappings>
      

Custom PropertyMapper

On rare occasions, there may be a need to completely handle the mapping of a property. By implement the PropertyMapper interface, the complete handling of a mapping can be customized. A custom PropertyMapper can be specified in the XML document as follows:
   <bean-mappings>
       <bean-mapping src="org.jbeanmapper.docs.ComplexPersonBean"
                        target="org.jbeanmapper.docs.ComplexPersonBean2"
                        creator="org.jbeanmapper.docs.ComplexPersonBean2Creator">
           <property-mapping src="name"
                                target="myName"
                                mapping-class"org.jbeanmapper.docs.MyPropertyMapper"/>
           <property-mapping src="age"
                                target="myAge"
                                converter="org.apache.commons.beanutils.converters.IntegerConverter"/>
           <property-mapping src="address" target="myAddress"/>
           <property-mapping src="title" target="myAddress.title"/>
       </bean-mapping>
       <bean-mapping src="org.jbeanmapper.docs.ComplexAddressBean"
                        target="org.jbeanmapper.docs.ComplexAddressBean2" >
           <property-mapping src="address" target="myAddress"/>
       </bean-mapping>
   </bean-mappings>
      

Collections, Arrays, and Maps

Collections, Arrays and Maps are supported in JBeanMapper. If a Collection or Map is encountered as a root object (the value passed into BeanMapper.map()), the return object will of the same type as the Collection or Map parameter. If an array is encountered as a parameter, the return object will be an array of the type as indicated by the mapping for the component type of the parameter array.

If a Collection is encountered as a property of a javabean, it will be mapped to the Collection or array type of the destination property. If the destination property is not a Collection or Array, mapping will fail with a PropertyMappingException.

If an array is encountered as a property of a javabean, it will be mapped to the Collection or array type of the destination property. If the destination property is not a Collection or Array, mapping will fail with a PropertyMappingException.

If a Map is encountered as a property of a javabean, it will be mapped to the Map type of the destination property. If the destination property is not a Map, mapping will fail with a PropertyMappingException.

Creating Simple Mappings Programmatically

If the source and target JavaBeans have the same property names and types, they can be registered very simply with the BeanMapper's register method. Below is a simple example registering a simple mapping with the BeanMapper. Suppose we have the two JavaBeans below:

		 public class PersonBean1 {
		   private String name;

		   public String getName() {
		     return name;
		   }

		   public void setName(String name) {
		     this.name = name;
		   }
		 }


		 public class SimplePerson {
		   private String name;

		   public String getName() {
		     return name;
		   }

		   public void setName(String name) {
		     this.name = name;
		   }
		 }
		         

The following code can be used to map from PersonBean1 to a SimplePerson:

		 BeanMapper mapper = new BeanMapper();
		 PersonBean1 personBean1 = new PersonBean1();
		 personBean1.setName("test");
		 SimplePerson personBean2 = (SimplePerson)mapper.map(personBean1, SimplePerson.class);
		       

Creating Complex Mappings Programmatically

Complex mappings can be registered programmatically by creating a BeanMapping object and adding it to the BeanMapper with the addBeanMapping method.