JaxB reference resolving

两盒软妹~` 提交于 2019-12-02 01:49:13
Wolfgang Fahl

To better illustrate the point I have modified the question to fit his answer. There is now a generic base class Person and I am trying to use it as per Can generic XmlAdapter be written

I solved the issue of being able to actually make sure the Adapters are used by writing specific derived Classes and using them with @XmlJavaTypeAdapter. I preregister the adapters using:

JAXBContext context = JAXBContext.newInstance(type);
Unmarshaller u = context.createUnmarshaller();
u.setAdapter(Worker.WorkerAdapter.class,new Worker.WorkerAdapter());
u.setAdapter(Trainer.TrainerAdapter.class,new Trainer.TrainerAdapter());

and then unmarshalling twice. The debug shows that the Adapter instance for both passes is the same. Still the lookup somehow seemed to fail ... The reason was the way the @XmlJavaTypeAdapter annotation works see:

What package-info do I annotate with XmlJavaTypeAdapters?

There seem to be multiple modes for @XmlJavaTypeAdapter:

  • it can be an annotation for a class
  • it can be an annotation for a field (getter)
  • it can be used in a package-info.java file to annotate a whole package

At this point I am using all three annotations and now have to debug which ones are necessary. I assume the global annotations (class,package) are not working as expected. The reason might be the type= usage in the @XmlElementWrapper which explicitly calls for a type. Personally I do not understand what is going on yet. At least things are now working as expected.

the local field annotation is now e.g.:

@XmlElementWrapper(name="workers")
@XmlElement(name="Worker", type=Worker.class)
@XmlJavaTypeAdapter(WorkerAdapter.class)

the package-info.java annotation is:

@XmlJavaTypeAdapters({
 @XmlJavaTypeAdapter(value=WorkerAdapter.class,type=Worker.class),
 @XmlJavaTypeAdapter(value=TrainerAdapter.class,type=Trainer.class),
})
package com.bitplan.jaxb.refidtest;

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

the class annotation is:

@XmlJavaTypeAdapter(Worker.WorkerAdapter.class)
public class Worker extends Person {

...

/**
 * Worker Adapter
 * @author wf
 *
 */
public static class WorkerAdapter extends  PersonAdapter<Worker>{
    @Override
    public Worker marshal(Worker me)
            throws Exception {
        return super.marshal(me);
    }


    @Override
    public Worker unmarshal(Worker me) throws Exception {
        return super.unmarshal(me);
    }
}


/**
 * https://stackoverflow.com/questions/7587095/can-jaxb-marshal-by-containment-at-first-then-marshal-by-xmlidref-for-subsequen/7587727#7587727
 * @author wf
 *
 */
public class PersonAdapter<T extends Person> extends XmlAdapter<T, T>{

    public boolean debug=true;

    /**
     * keep track of the elements already seen
     */
    public Map<String,T> lookup=new HashMap<String,T>();


    @Override
    public T marshal(T me)
            throws Exception {
        return me;
    }

    /**
     * show debug information
     * @param title
     * @param key
     * @param me
     * @param found
     */
    public void showDebug(String title,String key,T me, T found) {
        String deref="?";
        if (found!=null)
            deref="->"+found.getId()+"("+found.getClass().getSimpleName()+")";
        if (debug)
            System.err.println(title+": "+key+"("+me.getClass().getSimpleName()+")"+deref+" - "+this);
    }


    @Override
    public T unmarshal(T me)    throws Exception {
        if (me.getId()!=null) {
            showDebug("id",me.getId(),me,null);
            lookup.put(me.getId(), me);
            return  me;
        }
        if (me.getRef()!=null) {
            if (lookup.containsKey(me.getRef())) {
                T meRef=lookup.get(me.getRef());
                showDebug("ref",me.getRef(),me,meRef);
                me.setRef(null);
                            return  meRef;
            } else {
                if (debug)
                    showDebug("ref",me.getRef(),me,null);
            }
        }
        return  me;
    }

}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!