4

構成ファイルには、電話帳の名前など、複数の配列値があります。

<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

最初に変更しなければならなかったのは、 XMLBeanDeclarationXMLConfigurationのドキュメントに一致するように 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 を使用しています。

4

0 に答える 0