When can PropertyUtils.copyProperties fail silently?

爷,独闯天下 提交于 2019-12-23 16:21:31

问题


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).


回答1:


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);

}



回答2:


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);
    }
}



回答3:


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.



来源:https://stackoverflow.com/questions/8384814/when-can-propertyutils-copyproperties-fail-silently

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!