2

I am using EclipseLink JPA and JAXB (MOXy) to convert JPA entities to XML. For a normal one-to-many operation the system work fine but if this relationship is bidirectional and one of the entities has a composite id, uses a java.util.Map class, the system throw an exception.

The relationship is:

Table1:

Fields: id, col1. 
Primary Key: id

Table2:

Fields: id, table1_id, col1
Primary Key: (id, table1_id)

My classes:

Class Table 1:

@Entity
@Table(name = "table1")
@XmlRootElement
public class Table1 implements Serializable {

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "table1")
    @MapKey(name = "table2PK")
    @XmlElement    
    @XmlInverseReference(mappedBy="table1")
    private Map<Table2PK, Table2> table2;

    @XmlElementWrapper(name="table2s")
    public Map<Table2PK, Table2> getTable2() {
        return table2;
    }

    // Gettters and setters methods
}

Class Table2:

@Entity
@Table(name = "table2")
@XmlRootElement
public class Table2 implements Serializable {

    @EmbeddedId
    protected Table2PK table2PK;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "table1_id", insertable = false, unique = false, nullable = false, updatable = false)
    private Table1 table1;

    // Gettters and setters methods
}

Class Table2PK:

@Embeddable
public class Table2PK implements Serializable {

    @Basic(optional = false)
    @Column(name = "id")
    private int id;
    @Basic(optional = false)
    @Column(name = "table1_id")
    private int table1Id;

    // Gettters and setters methods
}

THe JPA works fine but the JAXB marshal and unmarshal operation with this code:

JAXBContext jc1 = JAXBContext.newInstance(Table1.class);

Marshaller marshaller = jc2.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(ts, System.out);

A javax.xml.bind.JAXBException is throwed.

The message is:

Exception [EclipseLink-110] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Descriptor is missing for class [java.util.Map].
Mapping: org.eclipse.persistence.oxm.mappings.XMLInverseReferenceMapping[table2]
Descriptor: XMLDescriptor(org.jbiowhpersistence.datasets.gene.gene.entities.Table1 --> [DatabaseTable(table1)])

Exception [EclipseLink-110] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Descriptor is missing for class [java.util.Map].
Mapping: org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping[table2]
Descriptor: XMLDescriptor(org.jbiowhpersistence.datasets.gene.gene.entities.Table1 --> [DatabaseTable(table1)])

What is wrong in my class definiton? Thanking in advance and best regards.

2 Answers2

1

EclipseLink JAXB (MOXy) does not support @XmlInverseReference on a field/property of type java.util.Map. Part of the reason for not supporting this is avoiding the complexity of specifying when the inverse reference applies to: key only, value only, or to both key and value.

bdoughan
  • 147,609
  • 23
  • 300
  • 400
0

a Map is not mappable using JAXB. You need to create an equivalent class that is mappable. Then you create an XMlAdapter to convert from unmappable to mappable objects.

for example:

class MapType{
    public List<MapEntryType> mapEntries = new ArrayList<MapEntryType>();
}

class MapEntryType {     
         @XmlAttribute   public Integer key;       
         @XmlValue   public String value;   
}

You can find how to create the XMLAdapter on this Link

Hope it helps.

Lahniep
  • 719
  • 1
  • 11
  • 30
  • 2
    `java.util.Map` is mappable with JAXB (see: http://blog.bdoughan.com/2013/03/jaxb-and-javautilmap.html). An `XmlAdaper` is required to be used when you want to customize how the `Map` is represented in XML. – bdoughan Nov 13 '13 at 17:32