2
votes

disclaimer: I'm incredibly amateur at all of this

I'm trying to get the project I'm working on to output JSON in addition the XML. Originally the prior method to do so involved a method that took in an argument of Element and recursively inserted things into an object of type net.sf JSONObject to create the JSON output, and used the normal JAXBContext's Marshaller to marshal into XML.

What I wanted was to use MOXy as my JAXB provider, and then marshal out both XML and JSON from the bindings.

Originally, when the XML was marshalled, I had:

jc = JAXBContext.newInstance("packageA:packageB:packageC...etc.");
public static String marshal(JAXBContext context, JAXBElement<?> je) throws JAXBException {
    StringWriter sout = new StringWriter();
    Marshaller m = context.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);
    m.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
    m.marshal(je, sout);
    return sout.toString();
}

and then

JAXBElement<myObject> jaxb = 
  new JAXBElement<myObject>(myObject_QNAME, myObject.class, null, value);
return XmlResponseMessage(marshal(jc, jaxb));
}

(this is probably important, so I should mention that the application I'm working on uses the spring framework.)

Also, I've read every single one of Blaise's blog posts regarding EclipseLink. Some multiple times. I just have a very shallow understanding of it and would appreciate if instead of linking me to one of his pages you explained whatever solution on it is and why it works

That being said, I tried just including the jaxb.properties file in one of the packages to try to get MOXy as opposed to JAXBElement to get my bindings. however, JAXBContext.newInstance("my list of : delimited packages") just makes the program hang. not even an error, just hangs it. stepping through just shows the call to the EclipseLink newInstance method hanging. I've looked for many hours for solutions online. I have much too many classes to just include in a Class[], and so can't set the property by using an array of classes. which is also the reason I couldn't use the native moxy API instead of using the property file. I think i have EclipseLink set up correctly: I've set eclipselink_home in my environment variables, and added the eclipselink.jar to my buildpath.

1
P.S. A retroactive apology for my poor capitalization and formatting. - Milo Hou

1 Answers

1
votes

UPDATE #2

A fix for this issue has been checked into the EclipseLink 2.4.2 and 2.5.0 streams and a nightly build containing the fix can be downloaded from the following link starting March 12, 2013:


UPDATE #1

After a couple of email exchanges I think the problem you are encountering is due to the following bug. You can use the link to track our progress on this issue.

I'll demonstrate how it manifests itself below:

ObjectFactory

For the problem to occur you need to have an @XmlElementDecl annotation where thename is the same as the substitutionHeadName.

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="foo", substitutionHeadName="foo")
    public JAXBElement<Foo> createBar(Foo foo) {
        return new JAXBElement<Foo>(new QName("foo"), Foo.class, foo);
    }

}

Domain Object (Foo)

Then on one of your domain objects you need to have an @XmlElementRef annotation referencing the element we defined in the @XmlElementDecl.

public class Foo {

    @XmlElementRef(name="foo")
    public Foo foo;

}

Demo

You will see the problem when you create the JAXBContext.

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class, ObjectFactory.class);
        System.out.println(jc.getClass());
    }

}

Trace

MOXy gets in an infinite loop adding the reference element.

...
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
    at org.eclipse.persistence.jaxb.compiler.AnnotationsProcessor.addReferencedElement(AnnotationsProcessor.java:3740)
...

ORIGINAL ANSWER

You could try using the following to create your JAXBContext. It bypasses the standard JAXB impl lookup code by using native MOXy code.

JAXBContext jc = org.eclipse.persistence.jaxb.JAXBContextFactory.createContext("packageA:packageB:packageC...etc.");

If that works we'll know the problem is related to the impl look up code and we can go from there.