XMLの構成ファイルがあります。これは次のようになります。
<configuration>
<database>
<host></host>
<port></port>
</database>
<queue>
<host></host>
<port></port>
<type></type>
</queue>
</configuration>
JAXB / xjcを使用してこの構成のJavaクラスを生成したいのですが、これらのクラスを生成し、これらの1つのレベルをツリーにアンマーシャリングしたいと思います。Configuration.javaを受け取るのではなく、Database.javaとQueue.javaが必要です(これらをGuice管理対象アプリケーションに個別に挿入できるようにするため)。私は(現在)これを行う方法を見ていませんが、間違ったことを探している可能性があります。
いくつかの実験の後、これらのクラスを生成し、クラスに基づいてこれらを設定して返すことができるソリューションを見つけました。
最初に、含まれているクラス(この例ではデータベースとキュー)を生成するbindings.xjbファイルを追加しました
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
</jaxb:bindings>
ただし、JAXBはDatabaseクラスまたはQueueクラスを使用してマーシャリングを解除することはできず、Configurationクラスのみを使用してマーシャリングを解除できます(これは私が何かを見逃した可能性がある場所です)。できます
JAXBContext context = JAXBContext.newInstance(Configuration.class);
Unmarshaller um = context.createUnmarshaller();
Configuration conf = (Configuration) um.unmarhal(xmlFile);
だがしかし
JAXBContext context = JAXBContext.newInstance(Database.class);
Unmarshaller um = context.createUnmarshaller();
Database db = (Database) um.unmarhal(xmlFile);
ただし、ConfigurationオブジェクトのインスタンスでgetDatabase()を呼び出すことでデータベースオブジェクトを取得できるため、リフレクションを使用してこれをジェネリックにすることもできます(このコードキャッシュの結果を適切な場所に作成することは別の演習です)。
T item = null;
try {
JAXBContext context = JAXBContext.newInstance(Configuration.class);
Unmarshaller um = context.createUnmarshaller();
Configuration conf = (Configuration) um.unmarshal(xmlFile);
Method[] allMethods = Configuration.class.getDeclaredMethods();
for (Method method : allMethods)
{
if (method.getReturnType().equals(clazz))
{
item = (T) method.invoke(conf);
break;
}
}
} catch (JAXBException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new ConfigException("Failure detected while loading configuration", e);
}
return item;
これが最善の解決策かどうかはわかりませんが(昨日JAXBを使い始めたばかりです)、目標を達成しているようです。