私たちのアプリケーションにはかなり一般的なパターンがあります。Xmlでオブジェクトのセット(またはリスト)を構成します。これらはすべて共通のインターフェースを実装します。起動時に、アプリケーションはXmlを読み取り、JAXBを使用してオブジェクトのリストを作成/構成します。JAXBのみを使用してこれを行うための「正しい方法」を(さまざまな投稿を何度も読んだ後)理解したことはありません。
たとえば、インターフェイスFee
と、いくつかの共通のプロパティ、いくつかの異なるプロパティ、および非常に異なる動作を持つ複数の具体的な実装クラスがあります。アプリケーションが使用する料金のリストを構成するために使用するXmlは次のとおりです。
<fees>
<fee type="Commission" name="commission" rate="0.000125" />
<fee type="FINRAPerShare" name="FINRA" rate="0.000119" />
<fee type="SEC" name="SEC" rate="0.0000224" />
<fee type="Route" name="ROUTES">
<routes>
<route>
<name>NYSE</name>
<rates>
<billing code="2" rate="-.0014" normalized="A" />
<billing code="1" rate=".0029" normalized="R" />
</rates>
</route>
</routes>
...
</fee>
</fees>
上記のXmlでは、各<fee>
要素はFeeインターフェースの具体的なサブクラスに対応しています。このtype
属性は、インスタンス化するタイプに関する情報を提供し、インスタンス化されると、JAXBアンマーシャリングは残りのXmlのプロパティを適用します。
私はいつもこのようなことをすることに頼らなければなりません:
private void addFees(TradeFeeCalculator calculator) throws Exception {
NodeList feeElements = configDocument.getElementsByTagName("fee");
for (int i = 0; i < feeElements.getLength(); i++) {
Element feeElement = (Element) feeElements.item(i);
TradeFee fee = createFee(feeElement);
calculator.add(fee);
}
}
private TradeFee createFee(Element feeElement) {
try {
String type = feeElement.getAttribute("type");
LOG.info("createFee(): creating TradeFee for type=" + type);
Class<?> clazz = getClassFromType(type);
TradeFee fee = (TradeFee) JAXBConfigurator.createAndConfigure(clazz, feeElement);
return fee;
} catch (Exception e) {
throw new RuntimeException("Trade Fees are misconfigured, xml which caused this=" + XmlUtils.toString(feeElement), e);
}
}
上記のコードでは、JAXBConfigurator
は、アンマーシャリングのためのJAXBオブジェクトの単純なラッパーです。
public static Object createAndConfigure(Class<?> clazz, Node startNode) {
try {
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller unmarshaller = context.createUnmarshaller();
@SuppressWarnings("rawtypes")
JAXBElement configElement = unmarshaller.unmarshal(startNode, clazz);
return configElement.getValue();
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
最後に、上記のコードの最後に、Xmlで構成されたタイプを含むリストが表示されます。
上記のように要素を反復するコードを記述せずに、JAXBにこれを自動的に実行させる方法はありますか?