Frage

I'm using PropertyUtils.copyProperties() to copy an object's properties via reflection, and it used to work well. Recently however, it started not doing anything.

It doesn't throw an exception, but just will not copy any fields. All the fields of the target object remains null, although there are non-null fields in the source objects.

I don't know how to reproduce this. For me, it happens consistently, but it's inside a project that I can't just publish here. The project uses Play Framework, that does some bytecode manipulation, so that might be the culprit.

Any advice or ideas on what could be causing this, or how to debug? Alternative field-copiers I can try are also welcome (I tried BeanUtils once before, but switched to PropertyUtils because of some caveat I don't remember by now).

War es hilfreich?

Lösung

I think I figured it out. It happened to me today. I was just donig some small test with it, and it didn't work. Here's the code:

 static class TesteP {

    private String a;
    private String b;
    private String c;

    public String getA() {
        return this.a;
    }


    public void setA(String a) {
        this.a = a;
    }



    public String getB() {
        return this.b;
    }


    public void setB(String b) {
        this.b = b;
    }


    public String getC() {
        return this.c;
    }


    public void setC(String c) {
        this.c = c;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this.getClass()).add("a", this.a).add("b", this.b).toString();
    }

}

 static class RestP {

    private String a;

    public String getA() {
        return this.a;
    }

    public void setA(String a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return this.a;
    }
}

public static void main(String[] args)
        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    TesteP p = new TesteP();
    p.setA("AAAA");
    p.setB("BBB");
    TesteP pp = new TesteP();
    RestP p2 = new RestP();
    p2.setA("aaaa");
    PropertyUtils.copyProperties(p,p2);

}

It solved this making the classes public. Maybe one of your classes isn't public. Here's the solution in my case:

 public static class TesteP {

    private String a;
    private String b;
    private String c;


    public String getA() {
        return this.a;
    }


    public void setA(String a) {
        this.a = a;
    }


    public String getB() {
        return this.b;
    }


    public void setB(String b) {
        this.b = b;
    }


    public String getC() {
        return this.c;
    }


    public void setC(String c) {
        this.c = c;
    }

    @Override
    public String toString() {
        return new ToStringBuilder(this.getClass()).add("a", this.a).add("b", this.b).toString();
    }

}

 public static class RestP {

    private String a;

    public String getA() {
        return this.a;
    }

    public void setA(String a) {
        this.a = a;
    }

    @Override
    public String toString() {
        return this.a;
    }
}

public static void main(String[] args)
        throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    TesteP p = new TesteP();
    p.setA("AAAA");
    p.setB("BBB");
    TesteP pp = new TesteP();
    RestP p2 = new RestP();
    p2.setA("aaaa");
    PropertyUtils.copyProperties(p,p2);

}

Andere Tipps

I took the code from this answer and ran it, it failed because of a write-only field I had (setter only, no getter). Odds are that this is what's messing up PropertyUtils.

I found that calling Introspector.getBeanInfo(MyModel.class).getPropertyDescriptors() only returns a partial list of the properties. Reproduced on this github repository.

I added a call to Introspector.flushCaches();, hoping it will solve the issue ... only it didn't.

As a workaround, I implemented a method to copy fields instead of replying on beanutils:

public static <T> void copyFields(T target, T source) throws Exception{
    Class<?> clazz = source.getClass();

    for (Field field : clazz.getFields()) {
        Object value = field.get(source);
        field.set(target, value);
    }
}

Dozer is a more sophisticated bean-copier you might want to try.

To debug your PropertyUtils problem, create a unit test then step through that.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top