Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Reflection: Invoking Setter and Getter method for collection type Object

I have two different packages of User define Objects.....

1) ws.lender.dto (all Objects exists in this package are source side).
2) copl.com.dto (all Objects exists in this package are destination side).

Objects hierarchy and Objects name different in both side. I wan to copy source side object to destination side object field by field or via getter and setter using Reflection.

For Example

Source side Objects

   package ws.lender.dto;

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "CustomerAddresses", propOrder = {
        "previousAddresses"
    })
    public class CustomerAddresses {

        protected PreviousAddresses previousAddresses;

        public PreviousAddresses getPreviousAddresses() {
            return previousAddresses;
        }

        public void setPreviousAddresses(PreviousAddresses value) {
            this.previousAddresses = value;
        }

    }


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PreviousAddresses", propOrder = {
    "previousAddress"
})
public class PreviousAddresses {

    @XmlElement(name = "PreviousAddress", required = true)
    protected List<PreviousAddress> previousAddress;

    public List<PreviousAddress> getPreviousAddress() {
        if (previousAddress == null) {
            previousAddress = new ArrayList<PreviousAddress>();
        }
        return this.previousAddress;
    }
}


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "PreviousAddress", propOrder = {

    "streetNo",
    "streetName"
})
public class PreviousAddress {

    @XmlElement(name = "StreetNo", required = true)
    protected String streetNo;
    @XmlElement(name = "StreetName", required = true)
    protected String streetName;

    public String getStreetNo() {
        return streetNo;
    }
    public void setStreetNo(String value) {
        this.streetNo = value;
    }
    public String getStreetName() {
        return streetName;
    }
    public void setStreetName(String value) {
        this.streetName = value;
    }
}

Destination side Objects

package copl.com.dto;

@javax.persistence.Entity
public class Customer implements java.io.Serializable
{
private Set<CustomerAddress> customerAddresses;

   public Set<CustomerAddress> getCustomerAddresses()
    {
        return customerAddresses;
    }

        public void setCustomerAddresses(Set<CustomerAddress> customerAddresses)
    {
        this.customerAddresses = customerAddresses;
    }
}

@javax.persistence.Entity
public class CustomerAddress implements java.io.Serializable
{   
    private String unitNumber;
    private String streetName;
    private String streetNumber;

   public String getUnitNumber()
    {
        return unitNumber;
    }   
        public void setUnitNumber(String unitNumber)
    {
        this.unitNumber = unitNumber;
    }
        public String getStreetName()
    {
        return streetName;
    }
       public String getStreetNumber()
    {
        return streetNumber;
    }
        public void setStreetName(String streetName)
    {
        this.streetName = streetName;
    }

    public void setStreetNumber(String streetNumber)
    {
        this.streetNumber = streetNumber;
    }
}   
like image 586
Z.I.J Avatar asked Jan 22 '16 10:01

Z.I.J


2 Answers

I think you could use MapStruct to mapping between POJO's that has different attribute names.

But your scenario is complex, because you want to convert ws.lender.dto.CustomerAddresses to copl.com.dto.Customer, and this implies to convert a List<ws.lender.dto.PreviousAddress> contained into a ws.lender.dto.PreviousAddresses object, to a Set<copl.com.dto.CustomerAddress> contained into a copl.com.dto.Customer object.

So, I will explain step by step.

1. Convert from ws.lender.dto.PreviousAddress to copl.com.dto.CustomerAddress

To do this conversion you need an interface (MapStruct will create an instance for this) responsible for mapping from source object to destination object:

import ws.lender.dto.PreviousAddress;
import copl.com.dto.CustomerAddress;

@Mapper
public interface CustomerAddressesMapper{

    CustomerAddressesMapper INSTANCE = Mappers.getMapper( CustomerAddressesMapper.class );

    @Mappings(@Mapping(source = "streetNo", target = "streetNumber")
    CustomerAddress previousToCustomerObject(PreviousAddress address);
}

This interface will map a PreviousAddress object to a CustomerAddress considering that streetNo attribute has to be mapped to streetNumber. There is no mapping for unitNumber attribute cause there is no source for it.

2. Convert a List<ws.lender.dto.PreviousAddress> to Set<copl.com.dto.CustomerAddress>

Now you have to add another mapping method to existing CustomerAddressesMapper interface:

Set<CustomerAddress> previousToCustomerSet(List<PreviousAddress> addresses);

This method will use the former previousToCustomerObject to convert every element of source list to destination set.

3. Convert from ws.lender.dto.CustomerAddresses to copl.com.dto.Customer

Finally, you need to add the last mapping method to CustomerAddressesMapper interface:

@Mappings(@Mapping(source = "previousAddresses.previousAddress", target = "customerAddresses")
Customer customerAddrsToCustomerObject(CustomerAddresses addresses);

This is the where you map an origin object, converting previousAddresses.previousAddress attribute to customerAddresses attribute, using former methods.

4. Using the mapper

To use the mapper you have to write some code as following:

CustomerAddressesMapper mapper = CustomerAddressesMapper.INSTANCE;
CustomerAddresses origin = //Retrieve it from anywhere
Customer dest = mapper.customerAddrsToCustomerObject(origin);

5. Setup

MapStruct is a source code generator, so you need to properly configure your pom.xml to include MapStruct dependency and to invoke this code generation. You can see how to do this here

Well I don't build and run this code, but this is the way to do it.

Hope it helps!

like image 161
malaguna Avatar answered Sep 17 '22 19:09

malaguna


I have studied many objects mapping frameworks for this assignments like

  • Orika
  • MapStruct
  • ModelMapper
  • Dozer
  • Commons-BeanUtils

Finally I choose the Orika framework to complete that above Objects to Objects mapping. We can do the that mapping via other mapper framework, but I was like Orika framework because this framework very easy to use for mapping Objects to Objects.

I will explain step by step.

1. Create the Objects of Source side Object and Destination side Object.

like this..

    Customer destination = new Customer();
    CustomerAddresses source = new CustomerAddresses();
    source = filledCustomerAddressesObject();

2. Constructing the DefaultMapperFactory

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

3. Mapping fields

    ClassMapBuilder<CustomerAddresses, Customer> builder;
    
    builder= mapperFactory.classMap(CustomerAddresses.class, Customer.class).constructorA();

    builder.field("previousAddresses.previousAddress{streetNo}","customerAddresses{streetNumber}");
    builder.field("previousAddresses.previousAddress{streetName}","customerAddresses{streetName}");
    
    builder.register();

    BoundMapperFacade<CustomerAddresses, Customer> boundMapper;
    
    boundMapper = mapperFactory.getMapperFacade(CustomerAddresses.class, Customer.class);
    
    destination = boundMapper.map(source, destination);

Its work fine Cheers

like image 27
Z.I.J Avatar answered Sep 17 '22 19:09

Z.I.J