Category Archives: Java (General)

PHPHOST BLOG

Web Hosting Related Articles You May Need

Dozer: Mapping JAXB Objects to Business/Domain Objects

Dozer is an open source (Apache 2 license) “Java Bean to Java Bean mapper that recursively copies data from one object to another.” As this description from its main web page states, it is used to map two JavaBeans instances for automatic data copying between the instances. Although these can be any of the many types of JavaBeans instances, I will focus this post on using Dozer to map JAXB-generated objects to “business data objects” (sometimes referred to as “domain objects”).

In Java applications making use of the Java Architecture for XML Binding (JAXB), it is very common for developers to write specific business or domain objects for use in the application itself and only use the JAXB-generated objects for reading (unmarshalling) and writing (marshalling) XML. Although using the JAXB-generated objects themselves as the business/domain objects has some appeal (DRY), there are disadvantages to this approach. JAXB-generated classes do not have toString(), equals(Object), or hashCode() implementations, making these generated classes unsuitable for use in many types of collections, unsuitable for comparison other than identity comparison, and unsuitable for easily logging their contents. Manually editing these generated classes after their generation is tedious and is not conducive to regeneration of the JAXB classes again when even slight changes might be made to the source XSD.

Although JAXB2 Basics can be used to ensure that JAXB-generated classes have some of the common methods needs for use in collections, use in comparisons, and for logging of their contents, a potentially even bigger issue with using JAXB-generated classes as domain/business objects is the tight coupling of business logic to XSD this entails. A schema change in an XSD (such as for version update) typically leads to a different package structure for classes generated from that XSD via JAXB. The different package structure then forces all code that imports those JAXB-generated classes to change their import statements. Content changes to the XSD can have even more dramatic impacts, affecting get/set methods on the JAXB classes that would be strewn throughout the application if the JAXB classes are used for domain/business objects.

Assuming that one decides to not use JAXB-generated classes as business/domain classes, there are multiple ways to map the generated JAXB classes to the classes defining the business/domain objects via a “mapping layer” described in code or configuration. To demonstrate two code-based mapping layer implementations and to demonstrate a Dozer-based mapping layer, I introduce some simple examples of JAXB-generated classes and custom built business/domain classes.

The first part of the example for this post is the XSD from which JAXB’x xjc will be instructed to general classes for marshalling to XML described by that XSD or unmarshalling from XML described by that XSD. The XSD, which is shown next, defines a Person element which can have nested MailingAddress and ResidentialAddress elements and two String attributes for first and last names. Note also that the main namespace is http://marxsoftware.blogspot.com/, which JAXB will use to determine the Java package hierarchy for classes generated from this XSD.

Person.xsd


<?xml version="1.0"?>
<xs:schema version="1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:marx="http://marxsoftware.blogspot.com/"
targetNamespace="http://marxsoftware.blogspot.com/"
elementFormDefault="qualified">

<xs:element name="Person" type="marx:PersonType" />

<xs:complexType name="PersonType">
<xs:sequence>
<xs:element name="MailingAddress" type="marx:AddressType" />
<xs:element name="ResidentialAddress" type="marx:AddressType" minOccurs="0" />
</xs:sequence>
<xs:attribute name="firstName" type="xs:string" />
<xs:attribute name="lastName" type="xs:string" />
</xs:complexType>

<xs:complexType name="AddressType">
<xs:attribute name="streetAddress1" type="xs:string" use="required" />
<xs:attribute name="streetAddress2" type="xs:string" use="optional" />
<xs:attribute name="city" type="xs:string" use="required" />
<xs:attribute name="state" type="xs:string" use="required" />
<xs:attribute name="zipcode" type="xs:string" use="required" />
</xs:complexType>

</xs:schema>

When xjc (the JAXB compiler delivered with Oracle’s JDK) is executed against the above XSD, the following four classes are generated in the directory com/blogspot/marxsoftware (derived from the XSD’s namespace): AddressType.java, PersonType.java, ObjectFactory.java, and package-info.java.

The next two code listings are of the two main classes of interest (PersonType.java and AddressType.java) generated by JAXB. The primary purpose of showing them here is as a reminder that they lack methods we often need our business/domain classes to have.

JAXB-generated PersonType.java


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2013.12.03 at 11:44:32 PM MST
//


package com.blogspot.marxsoftware;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;


/**
* <p>Java class for PersonType complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="PersonType">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <sequence>
* <element name="MailingAddress" type="{http://marxsoftware.blogspot.com/}AddressType"/>
* <element name="ResidentialAddress" type="{http://marxsoftware.blogspot.com/}AddressType" minOccurs="0"/>
* </sequence>
* <attribute name="firstName" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="lastName" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PersonType", propOrder = {
"mailingAddress",
"residentialAddress"
})
public class PersonType {

@XmlElement(name = "MailingAddress", required = true)
protected AddressType mailingAddress;
@XmlElement(name = "ResidentialAddress")
protected AddressType residentialAddress;
@XmlAttribute(name = "firstName")
protected String firstName;
@XmlAttribute(name = "lastName")
protected String lastName;

/**
* Gets the value of the mailingAddress property.
*
* @return
* possible object is
* {@link AddressType }
*
*/
public AddressType getMailingAddress() {
return mailingAddress;
}

/**
* Sets the value of the mailingAddress property.
*
* @param value
* allowed object is
* {@link AddressType }
*
*/
public void setMailingAddress(AddressType value) {
this.mailingAddress = value;
}

/**
* Gets the value of the residentialAddress property.
*
* @return
* possible object is
* {@link AddressType }
*
*/
public AddressType getResidentialAddress() {
return residentialAddress;
}

/**
* Sets the value of the residentialAddress property.
*
* @param value
* allowed object is
* {@link AddressType }
*
*/
public void setResidentialAddress(AddressType value) {
this.residentialAddress = value;
}

/**
* Gets the value of the firstName property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getFirstName() {
return firstName;
}

/**
* Sets the value of the firstName property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setFirstName(String value) {
this.firstName = value;
}

/**
* Gets the value of the lastName property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getLastName() {
return lastName;
}

/**
* Sets the value of the lastName property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setLastName(String value) {
this.lastName = value;
}

}

JAXB-generated AddressType.java


//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.4-2
// See http://java.sun.com/xml/jaxb
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2013.12.03 at 11:44:32 PM MST
//


package com.blogspot.marxsoftware;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;


/**
* <p>Java class for AddressType complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="AddressType">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <attribute name="streetAddress1" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="streetAddress2" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="city" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="state" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* <attribute name="zipcode" use="required" type="{http://www.w3.org/2001/XMLSchema}string" />
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AddressType")
public class AddressType {

@XmlAttribute(name = "streetAddress1", required = true)
protected String streetAddress1;
@XmlAttribute(name = "streetAddress2")
protected String streetAddress2;
@XmlAttribute(name = "city", required = true)
protected String city;
@XmlAttribute(name = "state", required = true)
protected String state;
@XmlAttribute(name = "zipcode", required = true)
protected String zipcode;

/**
* Gets the value of the streetAddress1 property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getStreetAddress1() {
return streetAddress1;
}

/**
* Sets the value of the streetAddress1 property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setStreetAddress1(String value) {
this.streetAddress1 = value;
}

/**
* Gets the value of the streetAddress2 property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getStreetAddress2() {
return streetAddress2;
}

/**
* Sets the value of the streetAddress2 property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setStreetAddress2(String value) {
this.streetAddress2 = value;
}

/**
* Gets the value of the city property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getCity() {
return city;
}

/**
* Sets the value of the city property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setCity(String value) {
this.city = value;
}

/**
* Gets the value of the state property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getState() {
return state;
}

/**
* Sets the value of the state property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setState(String value) {
this.state = value;
}

/**
* Gets the value of the zipcode property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getZipcode() {
return zipcode;
}

/**
* Sets the value of the zipcode property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setZipcode(String value) {
this.zipcode = value;
}

}

A common and straightforward tactic for copying data between the JAXB-generated objects and the custom-written business/domain objects is to use the “get” methods of one object and pass its return value to the “set” method of the other object. For example, in the process of unmarshalling/reading XML into the application, the results of “get” methods called on the JAXB-generated objects can be passed to the “set” methods of the business/domain objects. In the opposite direction, marshalling/writing XML can be easily accomplished by passing the result of “get” methods on the domain/business objects to corresponding “set” methods of the JAXB-generated objects. The next code listing is for PersonCoverter.java and illustrates one implementation of this approach.

PersonConverter.java


package dustin.examples.dozerdemo;

import com.blogspot.marxsoftware.AddressType;
import com.blogspot.marxsoftware.ObjectFactory;
import com.blogspot.marxsoftware.PersonType;
import dustin.examples.Address;
import dustin.examples.Person;

/**
* Static functions for converting between JAXB-generated objects and domain
* objects.
*
* @author Dustin
*/
public class PersonConverter
{
/**
* Extract business object {@link dustin.examples.Person} from the JAXB
* generated object {@link com.blogspot.marxsoftware.PersonType}.
*
* @param personType JAXB-generated {@link com.blogspot.marxsoftware.PersonType}
* from which to extract {@link dustin.examples.Person} object.
* @return Instance of {@link dustin.examples.Person} based on the provided
* {@link com.blogspot.marxsoftware.PersonType}.
*/
public static Person extractPersonFromPersonType(final PersonType personType)
{
final String lastName = personType.getLastName();
final String firstName = personType.getFirstName();
final Address residentialAddress =
extractAddressFromAddressType(personType.getResidentialAddress());
final Address mailingAddress =
extractAddressFromAddressType(personType.getMailingAddress());
return new Person(lastName, firstName, residentialAddress, mailingAddress);
}

/**
* Extract business object {@link dustin.examples.Address} from the JAXB
* generated object {@link com.blogspot.marxsoftware.AddressType}.
*
* @param addressType JAXB-generated {@link com.blogspot.marxsoftware.AddressType}
* from which to extract {@link dustin.examples.Address} object.
* @return Instance of {@link dustin.examples.Address} based on the provided
* {@link com.blogspot.marxsoftware.AddressType}.
*/
public static Address extractAddressFromAddressType(final AddressType addressType)
{
return new Address(
addressType.getStreetAddress1(), addressType.getStreetAddress2(),
addressType.getCity(), addressType.getState(), addressType.getZipcode());
}

/**
* Extract an instance of {@link com.blogspot.marxsoftware.PersonType} from
* an instance of {@link dustin.examples.Person}.
*
* @param person Instance of {@link dustin.examples.Person} from which
* instance of JAXB-generated {@link com.blogspot.marxsoftware.PersonType}
* is desired.
* @return Instance of {@link com.blogspot.marxsoftware.PersonType} based on
* provided instance of {@link dustin.examples.Person}.
*/
public static PersonType extractPersonTypeFromPerson(final Person person)
{
final ObjectFactory objectFactory = new ObjectFactory();
final AddressType residentialAddressType =
extractAddressTypeFromAddress(person.getResidentialAddress());
final AddressType mailingAddressType =
extractAddressTypeFromAddress(person.getMailingAddress());

final PersonType personType = objectFactory.createPersonType();
personType.setLastName(person.getLastName());
personType.setFirstName(person.getFirstName());
personType.setResidentialAddress(residentialAddressType);
personType.setMailingAddress(mailingAddressType);

return personType;
}

/**
* Extract an instance of {@link com.blogspot.marxsoftware.AddressType} from
* an instance of {@link dustin.examples.Address}.
*
* @param address Instance of {@link dustin.examples.Address} from which
* instance of JAXB-generated {@link com.blogspot.marxsoftware.AddressType}
* is desired.
* @return Instance of {@link com.blogspot.marxsoftware.AddressType} based on
* provided instance of {@link dustin.examples.Address}.
*/
public static AddressType extractAddressTypeFromAddress(final Address address)
{
final ObjectFactory objectFactory = new ObjectFactory();
final AddressType addressType = objectFactory.createAddressType();
addressType.setStreetAddress1(address.getStreetAddress1());
addressType.setStreetAddress2(address.getStreetAddress2());
addressType.setCity(address.getMunicipality());
addressType.setState(address.getState());
addressType.setZipcode(address.getZipCode());
return addressType;
}
}

The last code listing demonstrated a common third-party class approach to copying data in both directions between the JAXB-generated objects and the domain/business objects. Another approach is to build this copying capability into the domain/business objects themselves. This is shown in the next two code listings for PersonPlus.java and AddressPlus.java which are versions of the previously covered Person.java and Address.java with support added for copying data to and from JAXB-generated objects. For convenience, I added the new methods to the bottom of the classes after the toString implementations.

PersonPlus.java


package dustin.examples;

import com.blogspot.marxsoftware.ObjectFactory;
import com.blogspot.marxsoftware.PersonType;
import java.util.Objects;

/**
* Person class enhanced to support copying to/from JAXB-generated PersonType.
*
* @author Dustin
*/
public class PersonPlus
{
private String lastName;
private String firstName;
private AddressPlus mailingAddress;
private AddressPlus residentialAddress;

public PersonPlus(
final String newLastName,
final String newFirstName,
final AddressPlus newResidentialAddress,
final AddressPlus newMailingAddress)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.residentialAddress = newResidentialAddress;
this.mailingAddress = newMailingAddress;
}

public String getLastName()
{
return this.lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public String getFirstName()
{
return this.firstName;
}

public void setFirstName(String firstName)
{
this.firstName = firstName;
}

public AddressPlus getMailingAddress()
{
return this.mailingAddress;
}

public void setMailingAddress(AddressPlus mailingAddress)
{
this.mailingAddress = mailingAddress;
}

public AddressPlus getResidentialAddress()
{
return this.residentialAddress;
}

public void setResidentialAddress(AddressPlus residentialAddress)
{
this.residentialAddress = residentialAddress;
}

@Override
public int hashCode()
{
int hash = 3;
hash = 19 * hash + Objects.hashCode(this.lastName);
hash = 19 * hash + Objects.hashCode(this.firstName);
hash = 19 * hash + Objects.hashCode(this.mailingAddress);
hash = 19 * hash + Objects.hashCode(this.residentialAddress);
return hash;
}

@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final PersonPlus other = (PersonPlus) obj;
if (!Objects.equals(this.lastName, other.lastName))
{
return false;
}
if (!Objects.equals(this.firstName, other.firstName))
{
return false;
}
if (!Objects.equals(this.mailingAddress, other.mailingAddress))
{
return false;
}
if (!Objects.equals(this.residentialAddress, other.residentialAddress))
{
return false;
}
return true;
}

@Override
public String toString() {
return "PersonPlus{" + "lastName=" + lastName + ", firstName=" + firstName
+ ", mailingAddress=" + mailingAddress + ", residentialAddress="
+ residentialAddress + '}';
}

/**
* Provide a JAXB-generated instance of {@link com.blogspot.marxsoftware.PersonType}
* that corresponds to me.
*
* @return Instance of {@link com.blogspot.marxsoftware.PersonType} that
* corresponds to me.
*/
public PersonType toPersonType()
{
final ObjectFactory objectFactory = new ObjectFactory();
final PersonType personType = objectFactory.createPersonType();
personType.setFirstName(this.firstName);
personType.setLastName(this.lastName);
personType.setResidentialAddress(this.residentialAddress.toAddressType());
personType.setMailingAddress(this.mailingAddress.toAddressType());
return personType;
}

/**
* Provide instance of {@link dustin.examples.PersonPlus} corresponding
* to the provided instance of JAXB-generated object
* {@link com.blogspot.marxsoftware.PersonType}.
*
* @param personType Instance of JAXB-generated object
* {@link com.blogspot.marxsoftware.PersonType}.
* @return Instance of me corresponding to provided JAXB-generated object
* {@link com.blogspot.marxsoftware.PersonType}.
*/
public static PersonPlus fromPersonType(final PersonType personType)
{
final AddressPlus residentialAddress =
AddressPlus.fromAddressType(personType.getResidentialAddress());
final AddressPlus mailingAddress =
AddressPlus.fromAddressType(personType.getMailingAddress());
return new PersonPlus(personType.getLastName(), personType.getFirstName(),
residentialAddress, mailingAddress);
}
}

AddressPlus.java


package dustin.examples;

import com.blogspot.marxsoftware.AddressType;
import com.blogspot.marxsoftware.ObjectFactory;
import java.util.Objects;

/**
* Address class with support for copying to/from JAXB-generated class
* {@link com.blogspot.marxsoftware.AddressType}.
*
* @author Dustin
*/
public class AddressPlus
{
private String streetAddress1;
private String streetAddress2;
private String municipality;
private String state;
private String zipCode;

public AddressPlus(
final String newStreetAddress1,
final String newStreetAddress2,
final String newMunicipality,
final String newState,
final String newZipCode)
{
this.streetAddress1 = newStreetAddress1;
this.streetAddress2 = newStreetAddress2;
this.municipality = newMunicipality;
this.state = newState;
this.zipCode = newZipCode;
}

public String getStreetAddress1()
{
return this.streetAddress1;
}

public void setStreetAddress1(String streetAddress1)
{
this.streetAddress1 = streetAddress1;
}

public String getStreetAddress2()
{
return this.streetAddress2;
}

public void setStreetAddress2(String streetAddress2)
{
this.streetAddress2 = streetAddress2;
}

public String getMunicipality()
{
return this.municipality;
}

public void setMunicipality(String municipality)
{
this.municipality = municipality;
}

public String getState() {
return this.state;
}

public void setState(String state)
{
this.state = state;
}

public String getZipCode()
{
return this.zipCode;
}

public void setZipCode(String zipCode)
{
this.zipCode = zipCode;
}

@Override
public int hashCode()
{
return Objects.hash(
this.streetAddress1, this.streetAddress2, this.municipality,
this.state, this.zipCode);
}

@Override
public boolean equals(Object obj)
{
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final AddressPlus other = (AddressPlus) obj;
if (!Objects.equals(this.streetAddress1, other.streetAddress1))
{
return false;
}
if (!Objects.equals(this.streetAddress2, other.streetAddress2))
{
return false;
}
if (!Objects.equals(this.municipality, other.municipality))
{
return false;
}
if (!Objects.equals(this.state, other.state))
{
return false;
}
if (!Objects.equals(this.zipCode, other.zipCode))
{
return false;
}
return true;
}

@Override
public String toString()
{
return "Address{" + "streetAddress1=" + streetAddress1 + ", streetAddress2="
+ streetAddress2 + ", municipality=" + municipality + ", state=" + state
+ ", zipCode=" + zipCode + '}';
}

/**
* Provide a JAXB-generated instance of {@link com.blogspot.marxsoftware.AddressType}
* that corresponds to an instance of me.
*
* @return Instance of JAXB-generated {@link com.blogspot.marxsoftware.AddressType}
* that corresponds to me.
*/
public AddressType toAddressType()
{
final ObjectFactory objectFactory = new ObjectFactory();
final AddressType addressType = objectFactory.createAddressType();
addressType.setStreetAddress1(this.streetAddress1);
addressType.setStreetAddress2(this.streetAddress2);
addressType.setCity(this.municipality);
addressType.setState(this.state);
addressType.setZipcode(this.zipCode);
return addressType;
}

/**
* Provide instance of {@link dustin.examples.AddressPlus} corresponding
* to the provided instance of JAXB-generated object
* {@link com.blogspot.marxsoftware.AddressType}.
*
* @param addressType Instance of JAXB-generated object
* {@link com.blogspot.marxsoftware.AddressType}.
* @return Instance of me corresponding to provided JAXB-generated object
* {@link com.blogspot.marxsoftware.AddressType}.
*/
public static AddressPlus fromAddressType(final AddressType addressType)
{
return new AddressPlus(
addressType.getStreetAddress1(),
addressType.getStreetAddress2(),
addressType.getCity(),
addressType.getState(),
addressType.getZipcode());
}
}

The two approaches demonstrated above for mapping JAXB-generated objects to business/domain objects will definitely work and for my simple example might be considered the best approaches to use (especially given that NetBeans made the generation of the business/domain objects almost trivial). However, for more significant object hierarchies that require mapping, the Dozer configuration-based mapping might be considered preferable.

Dozer is downloaded from the download page (dozer-5.3.2.jar in this case). The Getting Started page shows that mapping is really easy (minimal configuration) when the attributes of the classes being mapped have the same names. This is not the case in my example in which I intentionally made one attribute “city” and the other “municipality” to make the mapping more interesting. Because these names are different, I need to customize the Dozer mapping and this is done with XML mapping configuration. The necessary mapping file is named with a “default mapping name” of dozerBeanMapping.xml and is shown next. I only needed to map the two fields with different names (city and municipality) because all other fields of the two classes being mapped have the same names and are automatically mapped together without explicit configuration.

dozerBeanMapping.xml


<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net
http://dozer.sourceforge.net/schema/beanmapping.xsd">

<configuration>
<stop-on-errors>true</stop-on-errors>
<date-format>MM/dd/yyyy HH:mm:ss</date-format>
<wildcard>true</wildcard>
</configuration>

<mapping>
<class-a>dustin.examples.Address</class-a>
<class-b>com.blogspot.marxsoftware.AddressType</class-b>
<field>
<a>municipality</a>
<b>city</b>
</field>
</mapping>

</mappings>

Note that XML is not the only approach that can be used to customize Dozer mapping; annotations and programmatic API are also supported.

The Dozer 3rd Party Object Factories page briefly covers using Dozer with JAXB and using the JAXBBeanFactory. It is also recommended that injection be used with Dozer and an example of Spring integration is provided. For my simple example of applying Dozer, I’m not using those approaches, but use the very straight forward instantiation approach. This is shown in the next code listing.

DozerPersonConverter.java


package dustin.examples.dozerdemo;

import com.blogspot.marxsoftware.PersonType;
import dustin.examples.Person;
import java.util.ArrayList;
import java.util.List;
import org.dozer.DozerBeanMapper;

/**
* Dozer-based converter.
*
* @author Dustin
*/
public class DozerPersonConverter
{
static final DozerBeanMapper mapper = new DozerBeanMapper();

static
{
final List<String> mappingFilesNames = new ArrayList<>();
mappingFilesNames.add("dozerBeanMapping.xml");
mapper.setMappingFiles(mappingFilesNames);
}

/**
* Provide an instance of {@link com.blogspot.marxsoftware.PersonType}
* that corresponds with provided {@link dustin.examples.Person} as
* mapped by Dozer Mapper.
*
* @param person Instance of {@link dustin.examples.Person} from which
* {@link com.blogspot.marxsoftware.PersonType} will be extracted.
* @return Instance of {@link com.blogspot.marxsoftware.PersonType} that
* is based on provided {@link dustin.examples.Person} instance.
*/
public PersonType copyPersonTypeFromPerson(final Person person)
{
final PersonType personType =
mapper.map(person, PersonType.class);
return personType;
}

/**
* Provide an instance of {@link dustin.examples.Person} that corresponds
* with the provided {@link com.blogspot.marxsoftware.PersonType} as
* mapped by Dozer Mapper.
*
* @param personType Instance of {@link com.blogspot.marxsoftware.PersonType}
* from which {@link dustin.examples.Person} will be extracted.
* @return Instance of {@link dustin.examples.Person} that is based on the
* provided {@link com.blogspot.marxsoftware.PersonType}.
*/
public Person copyPersonFromPersonType(final PersonType personType)
{
final Person person =
mapper.map(personType, Person.class);
return person;
}
}

The previous example shows how little code is required to map the JAXB-generated objects to business/domain objects. Of course, there was some XML needed, but only for fields with different names. This implies that the more the names of the fields differ, the more configuration is required. However, as long as fields are mostly mapped one-to-one without any special “conversion” logic between them, Dozer replaces much of the tedious code with configuration mapping.

If fields needed to be converted (such as converting meters in one object to kilometers in another object), then this mapping support may be less appealing when custom converters must be written. Dozer mapping can also become more difficult to apply correctly with deeply nested objects, but my example did nest Address within Person as a simple example. Although complex mappings might become less appealing in Dozer, many mappings of JAXB-generated objects to business/domain objects are simple enough mappings to be well served by Dozer.

One last thing I wanted to point out in this post is that Dozer has runtime dependencies on some third-party libraries. Fortunately, these libraries are commonly used in Java projects anyway and are readily available. As the next two images indicate, the required runtime dependencies are SLF4J, Apache Commons Lang, Apache Commons Logging, and Apache BeanUtils.

Dozer Runtime Dependencies Page

NetBeans 7.4 Project Libraries for this Post’s Examples

There is a small amount of effort required to set up Dozer and its dependencies and then to configure mappings, but this effort can be well rewarded with significantly reduced mapping code in many common JAXB-to-business object data copying applications.

Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)

Continue reading

Posted in Dozer, Java (General), JAXB, Syndicated | Comments Off on Dozer: Mapping JAXB Objects to Business/Domain Objects

More Common Red Flags in Java Development

In the post Common Red Flags in Java Development I looked at some practices that are not necessarily wrong or incorrect in and of themselves, but can be indicative of potentially greater problems. These “red flags” are similar to the concept of “code s… Continue reading

Posted in Java (General), Syndicated | Comments Off on More Common Red Flags in Java Development

Uncompressing 7-Zip Files with Groovy and 7-Zip-JBinding

This post demonstrates a Groovy script for uncompressing files with the 7-Zip archive format. The two primary objectives of this post are to demonstrate uncompressing 7-Zip files with Groovy and the handy 7-Zip-JBinding and to call out and demonstrate … Continue reading

Posted in Groovy, Java (General), Syndicated | Comments Off on Uncompressing 7-Zip Files with Groovy and 7-Zip-JBinding

Too Many Parameters in Java Methods, Part 8: Tooling

The first seven posts of my series of dealing with too many parameters expected in Java methods focused on alternative approaches to reduce the number of parameters a method or constructor expects. In this eighth post in the series, I look at tools tha… Continue reading

Posted in Eclipse, IntelliJ IDEA, Java (General), NetBeans, Syndicated | Comments Off on Too Many Parameters in Java Methods, Part 8: Tooling

Too Many Parameters in Java Methods, Part 7: Mutable State

In this seventh post of my series on addressing the issue of too many parameters in a Java method or constructor, I look at using state to reduce the need to pass parameters. One of the reasons I have waited until the 7th post of this series to address this is that it is one of my least favorite approaches for reducing parameters passed to methods and constructors. That stated, there are multiple flavors of this approach and I definitely prefer some flavors over others.

Perhaps the best known and most widely scorned approach in all of software development for using state to reduce parameter methods is the use global variables. Although it may be semantically accurate to say that Java does not have global variables, the reality is that for good or for bad the equivalent of global variables is achieved in Java via public static constructs. A particularly popular way to achieve this in Java is via the Stateful Singleton.

In Patterns of Enterprise Application Architecture, Martin Fowler wrote that “any global data is always guilty until proven innocent.” Global variables and “global-like” constructs in Java are considered bad form for several reasons. They can make it difficult for developers maintaining and reading code to know where the values are defined or last changed or even come from. By their very nature and intent, global data violates the principles of encapsulation and data hiding.

Miško Hevery has written the following regarding the problems of static globals in an object-oriented language:

Accessing global state statically doesn’t clarify those shared dependencies to readers of the constructors and methods that use the Global State. Global State and Singletons make APIs lie about their true dependencies. … The root problem with global state is that it is globally accessible. In an ideal world, an object should be able to interact only with other objects which were directly passed into it (through a constructor, or method call).

Having state available globally reduces the need for parameters because there is no need for one object to pass data to another object if both objects already have direct access to that data. However, as Hevery put it, that’s completely orthogonal to the intent of object-oriented design.

Mutable state is also an increasing problem as concurrent applications become more common. In his JavaOne 2012 presentation on Scala, Scala creator Martin Odersky stated that “every piece of mutable state you have is a liability” in a highly concurrent world and added that the problem is “non-determinism caused by concurrent threads accessing shared mutable state.”

Although there are reasons to avoid mutable state, it still remains a generally popular approach in software development. I think there are several reasons for this including that it’s superfically easy to write mutable state sharing code and mutable shared code does provide ease of access. Some types of mutable data are popular because those types of mutable data have been taught and learned as effective for years. Finally, three are times when mutable state may be the most appropriate solution. For that last reason and to be complete, I now look at how the use of mutable state can reduce the number of parameters a method must expect.

Stateful Singleton and Static Variables

A Java implementation of Singleton and other public Java static fields are generally available to any Java code within the same Java Virtual Machine (JVM) and loaded with the same classloader [for more details, see When is a Singleton not a Singleton?].

Any data stored universally (at least from JVM/classloader perspective) is already available to client code in the same JVM and loaded with the same class loader. Because of this, there is no need to pass that data between clients and methods or constructors in that same JVM/classloader combination.

Instance State

While “statics” are considered “globally available,” narrower instance-level state can also be used in a similar fashion to reduce the need to pass parameters between methods of the same class. An advantage of this over global variables is that the accessibility is limited to instances of the class (private fields) or instances of the class’s children (private fields). Of course, if the fields are public, accessibility is pretty wide open, but the same data is not automatically available to other code in the same JVM/classloader.

The next code listing demonstrates how state data can and sometimes is used to reduce the need for parameters between two methods internal to a given class.

Example of Instance State Used to Avoid Passing Parameters

   /**
    * Simple example of using instance variable so that there is no need to
    * pass parameters to other methods defined in the same class.
    */
   public void doSomethingGoodWithInstanceVariables()
   {
      this.person =
         Person.createInstanceWithNameAndAddressOnly(
            new FullName.FullNameBuilder(new Name("Flintstone"), new Name("Fred")).createFullName(),
            new Address.AddressBuilder(new City("Bedrock"), State.UN).createAddress());
      printPerson();
   }

   /**
    * Prints instance of Person without requiring it to be passed in because it
    * is an instance variable.
    */
   public void printPerson()
   {
      out.println(this.person);
   }

The above example is somewhat contrived and simplified, but does illustrate the point: the instance variable person can be accessed by other instance methods defined in the same class, so that instance does not need to be passed between those instance methods. This does reduce the signature of potentially (public accessibility means it may be used by external methods) internal methods, but also introduces state and now means that the invoked method impacts the state of that same object. In other words, the benefit of not having to pass the parameter comes at the cost of another piece of mutable state. The other side of the trade-off, needing to pass the instance of Person because it is not an instance variable, is shown in the next code listing for comparison.

Example of Passing Parameter Rather than Using Instance Variable

   /**
    * Simple example of passing a parameter rather than using an instance variable.
    */
   public void doSomethingGoodWithoutInstanceVariables()
   {
      final Person person =
         Person.createInstanceWithNameAndAddressOnly(
            new FullName.FullNameBuilder(new Name("Flintstone"), new Name("Fred")).createFullName(),
            new Address.AddressBuilder(new City("Bedrock"), State.UN).createAddress());
      printPerson(person);
   }

   /**
    * Prints instance of Person that is passed in as a parameter.
    * 
    * @param person Instance of Person to be printed.
    */
   public void printPerson(final Person person)
   {
      out.println(person);
   }

The previous two code listings illustrate that parameter passing can be reduced by using instance state. I generally prefer to not use instance state solely to avoid parameter passing. If instance state is needed for other reasons, than the reduction of parameters to be passed is a nice side benefit, but I don’t like introducing unnecessary instance state simply to remove or reduce the number of parameters. Although there was a time when the readability of reduced parameters might have justified instance state in a large single-threaded environment, I feel that the slight readability gain from reduced parameters is not worth the cost of classes that are not thread-safe in an increasingly multi-threaded world. I still don’t like to pass a whole lot of parameters between methods of the same class, but I can use the parameters object (perhaps with a package-private scope class) to reduce the number of these parameters and pass that parameters object around instead of the large number of parameters.

JavaBean Style Construction

The JavaBeans convention/style has become extremely popular in the Java development community. Many frameworks such as Spring Framework and Hibernate rely on classes adhering to the JavaBeans conventions and some of the standards like Java Persistence API also are built around the JavaBeans conventions. There are multiple reasons for the popularity of the JavaBeans style including its ease-of-use and the ability to use reflection against this code adhering to this convention to avoid additional configuration.

The general idea behind the JavaBean style is to instantiate an object with a no-argument constructor and then set its fields via single-argument “set” methods and access it fields via no-argument “get” methods. This is demonstrated in the next code listings. The first listing shows a simple example of a PersonBean class with no-arguments constructor and getter and setter methods. That code listing also includes some of the JavaBeans-style classes it uses. That code listing is followed by code using that JavaBean style class.

Examples of JavaBeans Style Class

public class PersonBean
{
   private FullNameBean name;
   private AddressBean address;
   private Gender gender;
   private EmploymentStatus employment;
   private HomeownerStatus homeOwnerStatus;

   /** No-arguments constructor. */
   public PersonBean() {}

   public FullNameBean getName()
   {
      return this.name;
   }
   
   public void setName(final FullNameBean newName)
   {
      this.name = newName;
   }
   
   public AddressBean getAddress()
   {
      return this.address;
   }
   
   public void setAddress(final AddressBean newAddress)
   {
      this.address = newAddress;
   }

   public Gender getGender()
   {
      return this.gender;
   }
   
   public void setGender(final Gender newGender)
   {
      this.gender = newGender;
   }
   
   public EmploymentStatus getEmployment()
   {
      return this.employment;
   }
   
   public void setEmployment(final EmploymentStatus newEmployment)
   {
      this.employment = newEmployment;
   }

   public HomeownerStatus getHomeOwnerStatus()
   {
      return this.homeOwnerStatus;
   }

   public void setHomeOwnerStatus(final HomeownerStatus newHomeOwnerStatus)
   {
      this.homeOwnerStatus = newHomeOwnerStatus;
   }
}

/**
 * Full name of a person in JavaBean style.
 * 
 * @author Dustin
 */
public final class FullNameBean
{
   private Name lastName;
   private Name firstName;
   private Name middleName;
   private Salutation salutation;
   private Suffix suffix;

   /** No-args constructor for JavaBean style instantiation. */
   private FullNameBean() {}

   public Name getFirstName()
   {
      return this.firstName;
   }

   public void setFirstName(final Name newFirstName)
   {
      this.firstName = newFirstName;
   }

   public Name getLastName()
   {
      return this.lastName;
   }

   public void setLastName(final Name newLastName)
   {
      this.lastName = newLastName;
   }

   public Name getMiddleName()
   {
      return this.middleName;
   }

   public void setMiddleName(final Name newMiddleName)
   {
      this.middleName = newMiddleName;
   }

   public Salutation getSalutation()
   {
      return this.salutation;
   }
 
   public void setSalutation(final Salutation newSalutation)
   {
      this.salutation = newSalutation;
   }

   public Suffix getSuffix()
   {
      return this.suffix;
   }

   public void setSuffix(final Suffix newSuffix)
   {
      this.suffix = newSuffix;
   }

   @Override
   public String toString()
   {
      return  this.salutation + " " + this.firstName + " " + this.middleName
            + this.lastName + ", " + this.suffix;
   }
}


package dustin.examples;

/**
 * Representation of a United States address (JavaBeans style).
 * 
 * @author Dustin
 */
public final class AddressBean
{
   private StreetAddress streetAddress;
   private City city;
   private State state;

   /** No-arguments constructor for JavaBeans-style instantiation. */
   private AddressBean() {}

   public StreetAddress getStreetAddress()
   {
      return this.streetAddress;
   }

   public void setStreetAddress(final StreetAddress newStreetAddress)
   {
      this.streetAddress = newStreetAddress;
   }

   public City getCity()
   {
      return this.city;
   }

   public void setCity(final City newCity)
   {
      this.city = newCity;
   }

   public State getState()
   {
      return this.state;
   }

   public void setState(final State newState)
   {
      this.state = newState;
   }

   @Override
   public String toString()
   {
      return this.streetAddress + ", " + this.city + ", " + this.state;
   }
}

Example of JavaBeans Style Instantiation and Population

   public PersonBean createPerson()
   {
      final PersonBean person = new PersonBean();
      final FullNameBean personName = new FullNameBean();
      personName.setFirstName(new Name("Fred"));
      personName.setLastName(new Name("Flintstone"));
      person.setName(personName);
      final AddressBean address = new AddressBean();
      address.setStreetAddress(new StreetAddress("345 Cave Stone Road"));
      address.setCity(new City("Bedrock"));
      person.setAddress(address);
      return person;
   }

The examples just shown demonstrate how the JavaBeans style approach can be used. This approach makes some concessions to reduce the need to pass a large number of parameters to a class’s constructor. Instead, no parameters are passed to the constructor and each individual attribute that is needed must be set. One of the advantages of the JavaBeans style approach is that readability is enhanced as compared to a constructor with a large number of parameters because each of the “set” methods is hopefully named in a readable way.

The JavaBeans approach is simple to understand and definitely achieves the goal of reducing lengthy parameters in the case of constructors. However, there are some disadvantages to this approach as well. One advantage is a lot of tedious client code for instantiating the object and setting its attributes one-at-a-time. It is easy with this approach to neglect to set a required attribute because there is no way for the compiler to enforce all required parameters be set without leaving the JavaBeans convention. Perhaps most damaging, there are several objects instantiated in this last code listing and these objects exist in different incomplete states from the time they are instantiated until the time the final “set” method is called. During that time, the objects are in what is really an “undefined” or “incomplete” state. The existence of “set” methods necessarily means that the class’s attributes cannot be final, rendering the entire object highly mutable.

Regarding the prevalent use of the JavaBeans pattern in Java, several credible authors have called into question its value. Allen Holub’s controversial article Why getter and setter methods are evil starts off with no holds barred:

Though getter/setter methods are commonplace in Java, they are not particularly object oriented (OO). In fact, they can damage your code’s maintainability. Moreover, the presence of numerous getter and setter methods is a red flag that the program isn’t necessarily well designed from an OO perspective.

Josh Bloch, in his less forceful and more gently persuasive tone, says of the JavaBeans getter/setter style: “The JavaBeans pattern has serious disadvantages of its own” (Effective Java, Second Edition, Item #2). It is in this context that Bloch recommends the builder pattern instead for object construction.

I’m not against using the JavaBeans get/set style when the framework I’ve selected for other reasons requires it and the reasons for using that framework justify it. There are also areas where the JavaBeans style class is particularly well suited such as interacting with a data store and holding data from the data store for use by the application. However, I am not a fan of using the JavaBeans style for instantiating a question simply to avoid the need to pass parameters. I prefer one of the other approaches such as builder for that purpose.

Benefits and Advantages

I’ve covered different approaches to reducing the number of arguments to a method or constructor in this post, but they also share the same trade-off: exposing mutable state to reduce or eliminate the number of parameters that must be passed to a method or to a constructor. The advantages of these approaches are simplicity, generally readable (though “globals” can be difficult to read), and ease of first writing and use. Of course, their biggest advantage from this post’s perspective is that they generally eliminate the need for any parameter passing.

Costs and Disadvantages

The trait that all approaches covered in this post share is the exposure of mutable state. This can lead to an extremely high cost if the code is used in a highly concurrent environment. There is a certain degree of unpredictability when object state is exposed for anyone to tinker with it as they like. It can be difficult to know which code made the wrong change or failed to make a necessary change (such as failing to call a “set” method when populating a newly instantiated object).

Conclusion

Even some of the approaches to reducing parameters that I have covered earlier (such as custom types and parameters objects) can be implemented in such a way that there is (optional) mutable state, but those approaches do not require mutable state. In contrast, the approaches covered in this post to reducing parameters to methods and constructors do require mutable state.

Some of the approaches covered in this post are highly popular despite their drawbacks. This may be for a variety of reasons including prevalence of use in popular frameworks (forcing users of the framework to use that style and also providing examples to others for their own code development). Other reasons for these approaches’ popularity is the relative ease of initial development and the seemingly (deceptively) relatively little thought that needs to go into design with these approaches. In general, I prefer to spend a little more design and implementation effort to use builders and less mutable approaches when practical. However, there are cases where these mutable state approaches work well in reducing the number of parameters passed around and introduce no more risk than was already present. My feeling is that Java developers should carefully consider use of any mutable Java classes and ensure that the mutability is either desired or is a cost that is justified by the reasons for using a mutable state approach.

Original posting available at http://marxsoftware.blogspot.com/ (Inspired by Actual Events)

Continue reading

Posted in Java (General), Syndicated | Comments Off on Too Many Parameters in Java Methods, Part 7: Mutable State

Too Many Parameters in Java Methods, Part 6: Method Returns

In the current series of posts I am writing on reducing the number of parameters required to call Java methods and constructors, I have focused so far on approaches that directly affect the parameters themselves (custom types, parameters objects, build… Continue reading

Posted in Java (General), Syndicated | Comments Off on Too Many Parameters in Java Methods, Part 6: Method Returns

Too Many Parameters in Java Methods, Part 5: Method Naming

In my previous post (Part 4 of my series on dealing with too many parameters in Java methods), I looked at method overloading as one approach to providing clients with versions of methods or constructors requiring fewer parameters. I described some dis… Continue reading

Posted in Java (General), Syndicated | Comments Off on Too Many Parameters in Java Methods, Part 5: Method Naming

Too Many Parameters in Java Methods, Part 4: Overloading

One of the problems with expecting too many parameters to be passed to a Java method is that it is more difficult for the client of that method to be determine that they are passing the appropriate values in the appropriate order. In previous posts, I … Continue reading

Posted in Java (General), Syndicated | Comments Off on Too Many Parameters in Java Methods, Part 4: Overloading

Too Many Parameters in Java Methods, Part 3: Builder Pattern

In my two immediately previous posts, I looked at reducing the number of parameters required for a constructor or method invocation via custom types and parameter objects. In this post, I look at use of the builder pattern to reduce the number of param… Continue reading

Posted in Java (General), NetBeans, Syndicated | Comments Off on Too Many Parameters in Java Methods, Part 3: Builder Pattern

Too Many Parameters in Java Methods, Part 2: Parameters Object

In my previous post, I looked at some of the problems associated with long parameters lists for methods and constructors. In that post, I discussed replacing primitives and built-in types with custom types to improve readability and type safety. That a… Continue reading

Posted in Java (General), Syndicated | Comments Off on Too Many Parameters in Java Methods, Part 2: Parameters Object