users@jaxb.java.net

Re: JAXB instantiates extra HashSet layer

From: Dmitri Colebatch <dim_at_colebatch.com>
Date: Sat, 1 Jul 2006 16:34:59 +1000

Hi Thang,

I should have replied to this earlier but have been behind on my inbox.

When unmarshalling collections JAXB uses XmlJavaTypeAdapter to adapt
each item in the set (as opposed to the collection itself).

So, without going into it to much, what I think is happening in your
case is that JAXB is getting the result of your SetAdapter and
sticking in a HashSet (as you've noticed).

I'm not sure what you're trying to do, but I ran into this issue when
I had this sort of construct:

<foo>
  <bars>
    <bar> ... </bar>
  </bars>
</foo>

and I then had:

class Foo
{
  @XmlJavaTypeAdapter(MyAdapterThanTurnsBarsIntoSetOfBarInstances.class)
  Set<Bar> bars;
}

I was finding the same as you. After some help on the list I changed this to:

class Foo
{
  @XmlElementWrapper(name="bars")
  Set<Bar> bars;
}

see https://jaxb.dev.java.net/nonav/jaxb20-fcs/docs/api/javax/xml/bind/annotation/XmlElementWrapper.html
for more info.

hth
dim

On 6/29/06, Thang X. Le <tle_at_neptium.com> wrote:
> Hi,
>
> This seems a basic question, but I haven't found it
> anywhere. The default mapping from <xs:sequence>
> is to a List<Object>. But how can I have it mapped
> to a Set<Object>?
>
> I was looking into the datatypeconverter sample in
> JAXB distribution. I tried to add an Adapter class to
> convert from Items type to a Set. This is the new
> POType:
> public class POType {
> ....
> @XmlJavaTypeAdapter(SetAdapter .class)
> private java.util.Set items;
>
> public java.util.Set getItems() {
> return items;
> }
> public void setItems(java.util.Set value) {
> this.items = value;
> }
> }
>
> And this is the adapter
> package primer.myPo;
>
> import javax.xml.bind.annotation.adapters.XmlAdapter;
> import java.util.*;
>
> public class SetAdapter
> extends XmlAdapter<Items, java.util.Set>
> {
> public java.util.Set unmarshal(Items value) {
> Set<Items.Item> s = new
> java.util.concurrent.CopyOnWriteArraySet<Items.Item>();
> List<Items.Item> l = value.getItem();
> for (Iterator<Items.Item> ite = l.listIterator(); ite.hasNext(); ) {
> Items.Item item = ite.next();
> s.add(item);
> }
> return s;
> }
>
> public Items marshal(java.util.Set value) {
> Items i = new Items();
> List<Items.Item> l = i.getItem();
> for (Iterator ite = value.iterator(); ite.hasNext(); ) {
> l.add((Items.Item)ite.next());
> }
> return i;
> }
> }
>
> Everything else stays the same (as in the sample).
> Now, the marshalling/unmarshalling does work. However,
> POType.items is now not a Set<Items.Item>, but a
> HashSet<Set<Items.Item>>. This I don't understand. Where
> did this HashSet come from? Why did JAXB implicitly creates
> it? Why wasn't the method POType.setItems(Set) called?
> And if it wasn't called, how could POType.items be instantiated,
> when it is a private field?
>
> Someone with the knowledge please shed some insights.
> Thank you very much.
>
> ------- End of forwarded message -------
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jaxb.dev.java.net
> For additional commands, e-mail: users-help_at_jaxb.dev.java.net
>
>