1

I have structure similar like this one below:

public class FirstObject {
    private List<SecondObject> myListOne;

    ...only getter method...
    ...no setter method for the list due to it is generated from wsdl 
}

public class SecondObject {
    private List<ThirdObject> myListTwo;

    ...only getter method...
    ...no setter method for the list due to it is generated from wsdl
}

public class ThirdObject {
    private String firstName;
    private String lastName;

    ...setters and getters...
}

The main issue are setter methods for the lists. If you try with PropertyMap or even with Providers you have to use setter methods and I cannot make them manually because all objects will be regenerated from wsdl each time when I run mvn eclipse:eclipse command.

UPDATE:

You can find my source code on following link: https://github.com/ervinfetic/modelmapper-issue-one

Is there any solution how to make this with Converter??

1 Answer 1

1

If you are not able to have setters, you can configure ModelMapper to access by field. Just enable FieldMatching and the FieldAccessLevel as private like your list properties

modelMapper.getConfiguration()
  .setFieldMatchingEnabled(true)
  .setFieldAccessLevel(AccessLevel.PRIVATE);

Example:

Class FirstObject:

public class FirstObject {

    private String name;

    private List<FirstObjectList> objectList = new ArrayList<FirstObjectList>();

    public String getName() {
        return name;
    }

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

    public List<FirstObjectList> getObjectList() {
        return objectList;
    }
}

Class FirstObjectList:

public class FirstObjectList {

    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

}

So we are looking to map FirstObject to our SecondObject class which has exactly the same structure (properties):

Class SecondObject:

public class SecondObject {

    private String name;

    private List<SecondObjectList> objectList;

    public String getName() {
        return name;
    }

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

    public List<SecondObjectList> getObjectList() {
        return objectList;
    }

}

Class SecondObjectList:

public class SecondObjectList {

    private String id;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

Then we need to create our ModelMapper instance and configure it as field matching and private access level.

public void test(){
    ModelMapper mapper = new ModelMapper();
    mapper.getConfiguration().setFieldMatchingEnabled(true);
    mapper.getConfiguration().setFieldAccessLevel(Configuration.AccessLevel.PRIVATE);


    FirstObject firstObject = new FirstObject();
    firstObject.setName("Hola");

    FirstObjectList firstObjectList = new FirstObjectList();
    firstObjectList.setId("1");

    firstObject.getObjectList().add(firstObjectList);

    SecondObject second = mapper.map(firstObject, SecondObject.class);

    assertEquals(firstObject.getName(), second.getName());

    assertEquals(firstObject.getObjectList().size(), second.getObjectList().size());    
    assertEquals(firstObject.getObjectList().get(0).getId(), second.getObjectList().get(0).getId());
}

All has been mapped perfectly. So it works.

  • Output:

SecondObject{name='Hola', objectList=[SecondObjectList{id='1'}]}

But if haven't enabled FieldMatching or set the Field Access Level as Private your list won't be mapped:

  • Output:

SecondObject{name='Hola', objectList=null}

UPDATE

If you have nested lists you mayset the naming convention as mutators to avoid multiple matching error, just configuring it like next:

 modelMapper.getConfiguration()
.setSourceNamingConvention(NamingConventions.JAVABEANS_MUTATOR);

Otherwise, if you don't want to do it by field access, you can create a Converter to handle this kind of matching:

public class ListConverter implements Converter<List<SecondObject>, List<ThirdObject>> {

    @Override
    public List<ThirdObject> convert(MappingContext<List<SecondObject>, List<PromoConditionEntity>> context) {
       //A java 8 mapping example
       return context.getSource()
          .stream()
          .map(this::convertToThirdObject)
        .collect(Collectors.toList());
    }

    private ThirdObject convertToThirdObject(SecondObject s) {
       //your impl map SecondObject to ThirdObject
       ...
     }
}

Finally, Don't forget to add the converter to your modelmapper isntance:

modelMapper.addConverter(new ListConverter());
Sign up to request clarification or add additional context in comments.

2 Comments

Your response make sense. I will try it asap. It would be great if this example works.
I've got the solution to your error just add: modelMapper.getConfiguration().setSourceNamingConvention(NamingConventions.JAVABEANS_MUTATOR) set the access with set and disable getter access.;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.