danny.lesnik
danny.lesnik

Reputation: 18639

Copy POJO content from one bean to another

I have few Pojos in different packages, each POJO contains set of the another pojo from the same package. I need to copy all items with the same name from Package B Pojos to objects in Package A.

Eaxmple:

package com.vanilla.packageA;

public class Student{

    private String firstName;
    private String lastName;
    private Set<Course> course;

    //getters and setters ommited

}   

package com.vanilla.packageA;

    public class Course{
    private String courseName;
    private String courseDescription;

    //seters and getters
}

package com.vanilla.packageB;

public class Student{

    private String firstName;
    private String lastName;
    private Address address;
    private Set<Course> course;
    Private Date birtday;

    //getters and setters ommited

}   

package com.vanilla.packageB;

public class Course{
    private String courseName;
    private String courseDescription;
    private <Lecturer> lecturer;
    private Integer hours;

    //seters and getters
} 

I want to copy recursively all items from PackageB classes to packageA classes which exists in PaCkageB and shares the same name.

Updates:

Guys, I understand that that this is stupid question, but I need to maintain this code, now the code is written in the way that they have to call 50 getters and setter, or calling constructor with 50 parameters. Unfortunately, I can't use the same object and I need to copy it, but I must find more "elegant" way to copy tese beans.

Upvotes: 15

Views: 21690

Answers (9)

Nikita Koksharov
Nikita Koksharov

Reputation: 10763

Try jodd library.

Dependency:

<dependency>
    <groupId>org.jodd</groupId>
    <artifactId>jodd-bean</artifactId>
    <version>5.1.6</version>
</dependency>

Code example:

MyObject source = ...
MyObject target = ...
BeanCopy.beans(source, target).declared(true, true).copy();

Upvotes: 0

Fabio Borriello
Fabio Borriello

Reputation: 11

have you tried using BULL? you can find a guide on how to use it on DZone. It offers the possibility to also perform object transformation while coping. Moreover, it performs the copy recursively and don't need getter and setters defined.

Upvotes: 1

KayV
KayV

Reputation: 13835

Using PropertyUtils, you can copy onky the non null properties as follows:

    private void copyNonNullProperties(Object destination,
            Object source) {
        try {
            PropertyUtils.describe(source).entrySet().stream()
                    .filter(source -> source.getValue() != null)
                    .filter(source -> !source.getKey().equals("class"))
                    .forEach(source -> {
                        try {
                            PropertyUtils.setProperty(destination, source.getKey(), source.getValue());
                        } catch (Exception e22) {
                            log.error("Error setting properties : {}", e22.getMessage());
                        }
                    });

        } catch (Exception e1) {
            log.error("Error setting properties : {}", e1.getMessage());
        }

    }

Upvotes: 0

Liviu Stirb
Liviu Stirb

Reputation: 6075

If you already have spring dependencies you could use org.springframework.beans.BeanUtils

BeanUtils.copyProperties(from, to);

Upvotes: 3

Rosdi Kasim
Rosdi Kasim

Reputation: 25956

Any reason why Apache BeanUtils.copyProperties does not work?

Upvotes: 19

Luis Carlos
Luis Carlos

Reputation: 365

Copying fields values are a need I almost every project, for example for do the clone(). I also think that for accomplish some goals isn't necessary import .jars for using only one function. I would like share some little code in which I was working, there are some things that I left in the inkwell but in general it do the work. In this case I use reflection.

public class ObjectCopyTools {

static String[] bases = new String[] {"byte", "short", "int", "long", "float", "double", "char", "boolean"};
static String[] equivalents = new String[] {"Byte", "Short", "Integer", "Long", "Float", "Double", "Character", "Boolean"};

static {

}

private static boolean areEquivalents(String type1, String type2){
    for (int i = 0; i < bases.length; i++) {
        if((type1.equals(bases[i]) && type2.equals(equivalents[i])) 
                || (type2.equals(bases[i]) && type1.equals(equivalents[i]))){
            return true;
        }
    }
    return false;
}

public static <T extends Object, Y extends Object> Y deepReflectionObjectCopy(T origin, Class<Y> resultClass) {
    Class<? extends Object> origClass = origin.getClass();
    Y resultObject = null;
    for (Constructor<?> constructor : resultClass.getConstructors()) {
        if (constructor.getParameterCount() == 0) {
            try {
                resultObject = (Y) constructor.newInstance();
            }catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
            }
            break;
        }
    }
    if(resultObject == null){
        return null;
    }
    Field[] origFields = origClass.getDeclaredFields();
    Field[] destFields = resultObject.getClass().getDeclaredFields();

    Object value = null;
    for(Field dstField: destFields){
        try {
            Field tempOrigField = origClass.getDeclaredField(dstField.getName());
            if(tempOrigField.getType().equals(dstField.getType())
                    || areEquivalents(tempOrigField.getType().getSimpleName(), dstField.getType().getSimpleName())){
                dstField.set(resultObject, tempOrigField.get(origin));
            }
        } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
        }
    }
    return resultObject;
}

Hope this help.

Upvotes: 1

FeelGood
FeelGood

Reputation: 5614

See to mapstruct. This tools generates code, so there is no overhead on reflection.

Upvotes: 5

flo
flo

Reputation: 154

Well.. Dozer may be just the thing you're looking for.

. . . its an object to object mapping framework. The idea is that:

  • Usually it will map by convention.
  • You can override this convention with a mapping file.

. . therefore mapping files are as compact as possible. Its useful for many cases, such as mapping a use-case specify service payload on to the reusable core model objects.

When delivering the SpringSource training courses we used to point out this framework very often.

Upvotes: 6

duffymo
duffymo

Reputation: 308733

If DRY is a bedrock principle of computer science, what reason can you give for two identical, parallel object graphs? Not only have you doubled your maintenance burden, but now you have to develop a recursive method to do nothing but ferry data from one to the other.

Upvotes: 0

Related Questions