私はRestEasy2.2.2を使用してJAX-RSWebサービスを開発してTomcat7にデプロイしています。サービスはJAXBを使用してXMLを返します(返す必要があります)。返されるXMLには、次のコードで使用されているのと同様のConcurrentHashMapの表現が含まれている必要があります。
@XmlRootElement(name="items")
@XmlAccessorType(XmlAccessType.NONE)
public class ItemCollection
{
@XmlElement(name="item")
private ConcurrentHashMap<String, Item> items;
public ItemCollection()
{
items = new ConcurrentHashMap<String, item>();
// fill the map
}
}
このItem
クラスには、ConcurrentHashMap
XMLにシリアル化する必要のあるも含まれています。
これはリソースクラスです:
@Path("/items")
public class ItemResource
{
@GET
@Produces(MediaType.APPLICATION_XML)
public ItemCollection getAllItems()
{
// get itemManager
return itemManager.getItems(); // ItemManager holds an instance of ItemCollection
}
}
このコードは実行されますが、コンテンツのないXMLが生成されます。
<items>
<item/>
</items>
私が出力として取得しようとしているのは、次のようなものです。
<items>
<item id="...">
<data>...</data>
<otheritems>
<otheritem id="...">
<someotherdata>...</someotherdata>
</otheritem>
</otheritems>
</item>
<item id="...">
<data>...</data>
<otheritems>
<otheritem id="...">
<someotherdata>...</someotherdata>
</otheritem>
<otheritem id="...">
<someotherdata>...</someotherdata>
</otheritem>
<otheritem id="...">
<someotherdata>...</someotherdata>
</otheritem>
</otheritems>
</item>
</items>
MessageBodyWriter
組み込みの機能が不十分な場合は、実装が必要であることがわかりました。MessageBodyWriter
をマーシャリングするための実装を考え出そうとしましたがConcurrentHashMap
、これまでは機能させることができませんでした(つまり、呼び出されるコードを取得できますが、さまざまな例外を除いて停止します)。
インターフェースをどのようにMessageBodyWriter
(そして)どのように実装して使用すべきかを私は完全には理解していないようです。MessageBodyReader
BillBurkeの「RESTfulJavawithJAX-RS」の本を持っています。JAX-RSサービスの設計に役立つという点では非常に便利ですがMessageBodyWriter
、関連するセクションで機能に関する十分な詳細を見つけることができませんでした。私のインターネット検索でも、私を正しい方向に導くことができるものは何も得られませんでした。
MessageBodyWriter
(およびMessageBodyReader
)インターフェースを適切に実装する方法を誰かが理解するのを手伝ってくれれば幸いです。注釈が欠落しているのか、置き忘れているのか、まったく新しいアプローチが必要なのかはわかりません。
助けてくれてありがとう。
編集:
コードを次のように変更すると、途中で次のようになります。
@XmlRootElement(name="items")
@XmlAccessorType(XmlAccessType.NONE)
public class ItemCollection
{
private ConcurrentHashMap<String, Item> items;
public ItemCollection()
{
items = new ConcurrentHashMap<String, item>();
// fill the map
}
@XmlElement(name="item")
public Collection<Item> getItems()
{
return items.values();
}
}
これにより、必要なXMLが生成されます(上記のサンプルが含まれています)。ただし、このコードは、アンマーシャリングに関しては機能しません。次の例外が発生します。
java.lang.UnsupportedOperationException
java.util.AbstractCollection.add(AbstractCollection.java:221)
com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:290)
com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.addToPack(Lister.java:254)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope.add(Scope.java:106)
com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty$ReceiverImpl.receive(ArrayERProperty.java:195)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(UnmarshallingContext.java:507)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(SAXConnector.java:145)
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(AbstractSAXParser.java:601)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(XMLDocumentFragmentScannerImpl.java:1782)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2938)
com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:200)
com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:173)
javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:137)
javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:142)
javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:151)
javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(AbstractUnmarshallerImpl.java:169)
// ... the rest
その理由は、アンマーシャラーがアイテムをに追加しようとしないように「適切なセッター」がないためCollection
だと思いますが、そのセッターがどのように見えるかはわかりません。誰かがこれを行う方法を知っているなら、私は助けていただければ幸いです。
前もって感謝します。
編集2:
ところで、私は彼が使用することを提案するクリスの返事を見@XmlJavaTypeAdapter
ました。私は提案を試しましたが、必要なXMLに近づきました。ただし、@ XmlJavaTypeAdapterを使用して取得したXMLには、追加のレベルがあります(私の例で見られるように、インスタンス<class><items><item>
の代わりに、クラスのメンバー変数としてインスタンスがあります)。また、個々のマップアイテムの要素名を変更できないようです(これらは常に「アイテム」と呼ばれます)。<items><item>
ConcurrentHashMap
これらは大きな問題ではなく、必要な変更を加えて、必要に応じて一緒に暮らすことができます。でも、できればそもそも持っていたくないです。教育目的で、EDIT 1のコードがアンマーシャリングで機能しない理由(および可能であれば修正方法)も理解したいと思います。
すべての助けを事前に感謝します。