Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 332569

Summary: Problem using @XmlJavaTypeAdapter with @XmlElementRef
Product: z_Archived Reporter: Blaise Doughan <blaise.doughan>
Component: EclipselinkAssignee: Nobody - feel free to take it <nobody>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: P3 CC: david.mccann
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Bug Depends on:    
Bug Blocks: 327593    
Attachments:
Description Flags
Code demonstrating the bug
none
Proposed fix
none
Supporting tests none

Description Blaise Doughan CLA 2010-12-14 15:41:43 EST
The following example should produce the following XML:

    <transactionAdd>
        <salesOrderAdd/>
    </transactionAdd>

Instead of:

   <transactionAdd xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
       <txnType xsi:type="invoiceAdd"/>
    </transactionAdd>


EXAMPLE

On the txnType property we will use a combination of @XmlJavaTypeAdapter and @XmlElementRef:

import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlRootElement
public class TransactionAdd {

    private String txnType;

    @XmlJavaTypeAdapter(MyAdapter.class)
    @XmlElementRef
    public String getTxnType() {
        return txnType;
    }

    public void setTxnType(String txnType) {
        this.txnType = txnType;
    }

}

The adapted objects will look like:

import javax.xml.bind.annotation.XmlSeeAlso;

@XmlSeeAlso({InvoiceAdd.class, SalesOrderAdd.class})
public class AbstractAdd {

}

---

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class InvoiceAdd extends AbstractAdd {

}

---

SalesOrderAdd

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class SalesOrderAdd extends AbstractAdd {

}

The XmlAdapter to convert between the String and the adapted objects will look like:

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class MyAdapter extends XmlAdapter<AbstractAdd, String> {

    @Override
    public String unmarshal(AbstractAdd v) throws Exception {
        if(v instanceof SalesOrderAdd) {
            return "salesOrderAdd";
        }
        return "invoiceAdd";
    }

    @Override
    public AbstractAdd marshal(String v) throws Exception {
        if("salesOrderAdd".equals(v)) {
            return new SalesOrderAdd();
        } 
        return new InvoiceAdd();
    }

}

The following demo code can be used:

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(TransactionAdd.class);

        File xml = new File("input.xml");
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        TransactionAdd ta = (TransactionAdd) unmarshaller.unmarshal(xml);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(ta, System.out);
    }

}

For more information see:

  - http://stackoverflow.com/questions/4441692/jaxb-element-name-based-on-object-property/4441822#4441822
Comment 1 Blaise Doughan CLA 2010-12-14 16:01:39 EST
Created attachment 185172 [details]
Code demonstrating the bug
Comment 2 David McCann CLA 2010-12-20 10:22:39 EST
Created attachment 185551 [details]
Proposed fix
Comment 3 David McCann CLA 2010-12-20 10:22:50 EST
Created attachment 185552 [details]
Supporting tests
Comment 4 David McCann CLA 2010-12-20 16:40:00 EST
Reviewed by:  matt.macivor@oracle.com
Tests:  all unit tests pass as expected; jaxb.xmladapter.xmlelementref.XmlAdapterElementRefTestCases; jaxb.xmladapter.xmlelementref.XmlAdapterElementRefListTestCases
Revision:  8732
Comment 5 Eclipse Webmaster CLA 2022-06-09 10:34:07 EDT
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink