2010-10-29 2 views
4

Обычно я мог копировать значения между двумя java beans, которые имеют идентичные имена свойств, используя beanutils с отражением java, например. PropertyUtils.setProperty (....)Как автоматически копировать значения из java bean в объект сообщения protobuf с использованием java-отражения?

В сообщении protobuf Message мы используем класс построителя сообщений для установки значения. Это работает, но я предпочел бы использовать отражение, чтобы автоматически копировать свойства из bean-компонента в сообщение, поскольку оба имеют одинаковые имена и типы свойств.

Когда я вызываю PropertyUtils.setProperty в объект-конструктор (полученный из message.newBuilder()), я получаю это сообщение.

java.lang.NoSuchMethodException: свойство «testProp» не имеет метод установки в классе «класса teststuff.TestBeanProtos $ TestBeanMessage $ Builder»

Как автоматически копировать значения из Java Bean для Protobuf объекта сообщения (и тиски -versa) с использованием java-отражения?

+0

Do Builder имеет метод setTestProp? –

+0

Я должен указать, что целевой Java-объект является экземпляром com.google.protobuf.GeneratedMessage, которые являются неизменяемыми компонентами. Поэтому использование Dozer или простое чтение/запись отражения в GeneratedMessage не будет работать. – user193116

ответ

0

Вы можете отправить все свойства getClass(). GetFields() и сделать копию с использованием отражения. Это будет СМТ как:

for(Field f : to.getClass().getFields()){ 
    f.set(to, from.getClass().getField(f.getName()).get(from)); 
} 

+ вероятно, вы могли бы использовать field.setAccessible (истина) вызова.

+0

Нет, это не может быть использовано в этом контексте. Конструктор сообщений является подклассом объекта сообщения protobuf.и его методы setter делают много «домашнего хозяйства» как операции; переопределение параметра доступности метода может привести к проблемам с сериализацией сообщений. – user193116

2

Ненавижу отвечать на мой вопрос, но я не могу поверить, что я единственный, кто столкнулся с этой проблемой. Документирование решения здесь, если другие люди также начинают работать с protobuf и java. Использование отражения позволяет набирать десятки геттеров и сеттеров.

Хорошо, мне удалось заставить его работать, используя пример тестового кода, поставляемого с protobuf. Это очень простой случай использования; обычно сообщение будет намного сложнее. Этот код не обрабатывает вложенные сообщения или повторяющиеся сообщения.

public static void setMessageBuilder(com.google.protobuf.GeneratedMessage.Builder message,Descriptors.Descriptor descriptor,Object srcObject) throws Exception { 


    String cname = srcObject.getClass().getName(); 
    /*BeanMapper.getSimpleProperties -- this is a warpper method that gets the list of property names*/ 
    List<String> simpleProps = BeanMapper.getSimpleProperties(srcObject.getClass()); 




    Map map = new HashMap(); 
    for (String pName : simpleProps) { 
     System.out.println(" processing property "+ pName); 
     Object value= PropertyUtils.getProperty(srcObject, pName); 
     if(value==null) continue; 

     Descriptors.FieldDescriptor fd=descriptor.findFieldByName(pName) ; 

     System.out.println(" property "+ pName+" , found fd :"+ (fd==null ? "nul":"ok")); 
     message.setField(fd, value); 
     System.out.println(" property "+ pName+" set ok,"); 

    } 



    return ; 
} 
2

Возможно, я отключусь, но будет protostuff help? Он имеет хорошую расширенную поддержку для работы с другими форматами данных, типами. И даже если у него не было прямой поддержки преобразования, если вы перейдете в/из JSON, есть много вариантов хорошей привязки данных.

+0

Спасибо за голову на протостуф; это кажется очень сильным. Я все еще пытаюсь играть с протостуфом ProtostuffIOUtil. Если бы я мог получить объекты сообщения, правильно составленные из старого компонента, я бы отметил вам ответ в качестве принятого ответа. – user193116

1

Я не знаю размер вашего проекта, но вы можете попробовать Dozer, mapper, который рекурсивно копирует данные из одного объекта в другой одного и того же типа или между различными сложными типами. Поддерживает неявное и явное сопоставление. Я использовал его в большом проекте и работал очень хорошо. Это может быть так же просто, как

Mapper mapper = new DozerBeanMapper(); 
DestinationObject destObject = mapper.map(sourceObject, DestinationObject.class); 
0

У меня такая же проблема, решение немного сложнее.

Используйте вместо этого MethodUtils.invokeMethod .

где имя метода «setXXX».