2011-02-02 8 views
5

मैं PropertyUtils.setProperty (वस्तु, नाम, मूल्य) अपाचे कॉमन्स बीन Utils की विधि का उपयोग कर रहा हूँ:क्या यह कॉमन्स बीन उपयोग के साथ घोंसला वाली संपत्ति का स्वचालित रूप से तत्काल हो सकता है?

इन कक्षाओं देते:

public class A { 
    B b; 
} 

public class B { 
    C c; 
} 

public class C { 
} 

और यह:

A a = new A(); 
C c = new C(); 
PropertyUtils.setProperty(a, "b.c", c); //exception 

अगर मैं कोशिश है कि मैं मिलता है: org.apache.commons.beanutils.NestedNullException: 'सेम वर्ग पर' bc 'वर्ग के लिए अशक्त संपत्ति के मूल्य एक '

यह PropertyUtils बताने के लिए है कि अगर एक नेस्टेड संपत्ति है एक शून्य मान गहराई में जाने की कोशिश कर रहा से पहले यह (डिफ़ॉल्ट निर्माता) का दृष्टांत करने की कोशिश संभव है?

कोई अन्य दृष्टिकोण?

आप

उत्तर

8

मैं ऐसा करके इसे हल:

private void instantiateNestedProperties(Object obj, String fieldName) { 
    try { 
     String[] fieldNames = fieldName.split("\\."); 
     if (fieldNames.length > 1) { 
      StringBuffer nestedProperty = new StringBuffer(); 
      for (int i = 0; i < fieldNames.length - 1; i++) { 
       String fn = fieldNames[i]; 
       if (i != 0) { 
        nestedProperty.append("."); 
       } 
       nestedProperty.append(fn); 

       Object value = PropertyUtils.getProperty(obj, nestedProperty.toString()); 

       if (value == null) { 
        PropertyDescriptor propertyDescriptor = PropertyUtils.getPropertyDescriptor(obj, nestedProperty.toString()); 
        Class<?> propertyType = propertyDescriptor.getPropertyType(); 
        Object newInstance = propertyType.newInstance(); 
        PropertyUtils.setProperty(obj, nestedProperty.toString(), newInstance); 
       } 
      } 
     } 
    } catch (IllegalAccessException e) { 
     throw new RuntimeException(e); 
    } catch (InvocationTargetException e) { 
     throw new RuntimeException(e); 
    } catch (NoSuchMethodException e) { 
     throw new RuntimeException(e); 
    } catch (InstantiationException e) { 
     throw new RuntimeException(e); 
    } 
} 
+0

सी को एक पूर्ण बी में सेट करने का प्रयास करने में यह समस्या होगी। सबसे अच्छा तरीका है प्रतिबिंब का उपयोग करके ऑब्जेक्ट को पार करना और इसे बनाना रास्ते में –

-1

धन्यवाद कुछ शोध करने के बाद, करने के लिए संक्षिप्त उत्तर "क्या यह संभव है ..." सवाल नहीं है।

2

एक छोटी सी सुधार:

String fn = fieldNames[i]; 
if (i != 0) { 
     nestedProperty.append("."); 
} 
nestedProperty.append(fn); 
Object value = PropertyUtils.getProperty(obj, nestedProperty.toString()); 
+0

आप सही हैं धन्यवाद! –

0

मैं केवल प्रतिबिंब का इस्तेमाल किया है w/ओ अपाचे पुस्तकालय इस लक्ष्य को हासिल करने के लिए। धारणा यह है कि सभी वस्तुओं को पार करने के लिए सभी पीओजेओ हैं, और डिफ़ॉल्ट निर्माण सार्वजनिक रूप से सुलभ है। इस तरह, प्रत्येक पाश के लिए संदर्भ पथ बनाने की कोई आवश्यकता नहीं है।

public Object getOrCreateEmbeddedObject(Object inputObj,String[] fieldNames) throws Exception { 

    Object cursor = inputObj; 

    //Loop until second last index 
    for (int i = 0; i < fieldNames.length - 1; i++){ 
     Field ff = getClassFieldFrom(cursor,fieldNames[i]); 
     Object child = ff.get(cursor); 
     if(null == child) { 
      Class<?> cls=ff.getType(); 
      child = cls.newInstance(); 
      ff.set(cursor, child); 
     } 
     cursor = child; 
    } 

    return cursor; 
} 

private Field getClassFieldFrom(Object object, String fieldStr) 
      throws NoSuchFieldException { 
     java.lang.reflect.Field ff = object.getClass().getDeclaredField(fieldStr); 
     ff.setAccessible(true); 
     return ff; 
} 

यदि आपके पास मेरे समाधान के लिए कोई सुझाव है, तो कृपया मुझे बताएं।

0

मैं बस डिफ़ॉल्ट रूप से वस्तुओं में से प्रत्येक के instantiating की बहुत ही बुनियादी दृष्टिकोण के लिए चला गया:

public class A { 
    B b = new B(); 
} 

public class B { 
    C c = new C(); 
} 

public class C { 
} 

आदर्श नहीं है, लेकिन यह मेरी स्थिति के लिए काम किया और जटिल सुधारों को शामिल नहीं किया था।

3

मैं जानता हूँ कि प्रश्न Apache Commons PropertyUtils.setProperty के बारे में है, लेकिन Spring Expression Language "SpEL में "जो करता है आप अपनी ज़रुरत के बहुत इसी तरह की सुविधा उपलब्ध है। अभी भी बेहतर है यह सूची और सरणियों भी की गई है। इसके बाद के संस्करण दस्तावेज़ लिंक वसंत के लिए है 4.x लेकिन नीचे दिया गया कोड वसंत 3.2.9 में मेरे लिए काम करता है।

StockOrder stockOrder = new StockOrder(); // Your root class here 

    SpelParserConfiguration config = new SpelParserConfiguration(true,true); // auto create objects if null 
    ExpressionParser parser = new SpelExpressionParser(config); 
    StandardEvaluationContext modelContext = new StandardEvaluationContext(stockOrder); 

    parser.parseExpression("techId").setValue(modelContext, "XXXYYY1"); 
    parser.parseExpression("orderLines[0].partNumber").setValue(modelContext, "65498"); 
    parser.parseExpression("orderLines[0].inventories[0].serialNumber").setValue(modelContext, "54686513216"); 

    System.out.println(ReflectionToStringBuilder.toString(stockOrder));