構成ファイルには、電話帳の名前など、複数の配列値があります。
<configuration>
<phonebook>
<name>John</name>
<name>Mary</name>
</phonebook>
</configuration>
これらを BeanHelper (または別の方法) を介してこの Bean に読み込みたい:
public interface Phonebook {
public void setName(String[] names);
public String[] getName();
}
または理想的にはjava.util.List<String>
、配列の代わりにリストを使用しますString[]
。インターフェイスの実装は簡単です。
public class MyPhonebook implements Phonebook {
private String[] names;
@Override
public void setName(String[] names) {
this.names = names;
}
@Override
public String[] getName() {
return names;
}
@Override
public String toString() {
return String.join("; ", names);
}
}
メインは次のようになります。
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.ConfigurationRuntimeException;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.beanutils.BeanHelper;
import org.apache.commons.configuration.beanutils.XMLBeanDeclaration;
public class Main {
private static Phonebook myPhonebook;
private static XMLConfiguration config;
public static void main(String[] args) {
// read the configuration
String configFile = "config.xml";
try {
config = new XMLConfiguration();
// config.setAttributeSplittingDisabled(true);
config.setFileName(configFile);
config.load();
} catch (ConfigurationException e) {
e.printStackTrace();
}
// this is to see which keys and values are inside the configuration
config.getKeys().forEachRemaining(
s -> System.out.println(s + " : " + config.getProperty(s)));
// try to create the bean
try {
XMLBeanDeclaration declaration = new XMLBeanDeclaration(config,
"phonebook");
declaration.getBeanProperties().forEach(
(k, v) -> System.out.println(k + " : " + v));
myPhonebook = (Phonebook) BeanHelper.createBean(declaration,
MyPhonebook.class);
} catch (ConfigurationRuntimeException e) {
e.printStackTrace();
}
// print out the bean
System.out.println(myPhonebook);
}
}
これは、Bean を作成しようとすると機能しません。これがConfigurationRuntimeException
原因で発生しますUnsupportedOperationException
。
java.lang.UnsupportedOperationException: Unable to handle collection of type : [Ljava.lang.String; for property name
at org.apache.commons.configuration.beanutils.BeanHelper.createPropertyCollection(BeanHelper.java:335)
at org.apache.commons.configuration.beanutils.BeanHelper.initBean(BeanHelper.java:213)
at org.apache.commons.configuration.beanutils.DefaultBeanFactory.initBeanInstance(DefaultBeanFactory.java:108)
at org.apache.commons.configuration.beanutils.DefaultBeanFactory.createBean(DefaultBeanFactory.java:64)
at org.apache.commons.configuration.beanutils.BeanHelper.createBean(BeanHelper.java:390)
... 2 more
最初に変更しなければならなかったのは、 XMLBeanDeclarationとXMLConfigurationのドキュメントに一致するように XML ファイルのレイアウトを変更することでした。
<configuration>
<phonebook name="John,Mary" />
</configuration>
次にプログラムを実行すると、正常に終了し、出力は次のようになります。
phonebook[@name] : [John, Mary]
name : Mary
Mary
つまりXMLConfiguration
、 は属性名に配列を含む構成ファイルを正しく識別しますが、どういうわけか XMLBeanDeclaration は識別しません。常に最後の値を取ります。
配列を単一の s として読み取ることができるという事実を悪用することで、多かれ少なかれ機能するソリューションを思いつきましたString
。行を追加しましたconfig.setAttributeSplittingDisabled(true);
。結果は次のとおりです。
phonebook[@name] : John,Mary
name : John,Mary
John; Mary
この場合、Bean の作成時にBeanHelper
配列が認識され、正しいメソッドを選択できるように見えます。
これにより構成が少し柔軟性に欠けるので、XMLBeanDeclaration
への呼び出しを避けるために、早い段階で配列を処理することが可能かどうか疑問に思いconfig.setAttributeSplittingDisabled(true);
ます。
Java 8、Configuration 1.10、および BeanUtils 1.9.2 を使用しています。