Search code examples
javaxmljaxbeclipselinkmoxy

Static factory methods in JAXB MOXy


I am defining a static factory method with:

@XmlType(factoryClass=DummyFactory.class, factoryMethod="createNew")
public abstract MyClass() {
}

The reason I am using factory methods is that MyClass is abstract, and how to obtain an instance of it depends on certain annotations of the class. This logic is embedded in the factory method createNew.

In addition, the factory class DummyFactory is abstract. As far as I understand factory classes do not need to provide a default constructor if their factory method is static (http://download.oracle.com/javaee/6/api/javax/xml/bind/annotation/XmlType.html).

This is a raw simplification of how the factory class looks like:

public abstract class DummyFactory {
    public static MyClass createNew() {
        // code for returning a new instance of MyClass
    }   
}

However, when I try to unmarshal a XML document, I am getting the following exception:

Exception [EclipseLink-171] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: The factory class does not define a public default constructor, or the constructor raised an exception.
Internal Exception: java.lang.InstantiationException

First I thought that I did not get something correctly in the explanation of factory classes and methods, but then I tried with JAXB RI and this is working fine there. So my question is:

Is there a way to make MOXy work with abstract factory classes ?

(JAXB RI is giving me other kind of problems, that is the reason I would prefer not using it).


Solution

  • Thank you for entering a bug for this issue (https://bugs.eclipse.org/362984). The issue has been fixed in the EclipseLink 2.4 stream, and will be backported today (Nov 9, 2011) to the EclipseLink 2.3.2 stream. You can try out the fix obtaining a nightly download from:

    Now if you specify a factory class using the @XmlType annotation like:

    @XmlType(factoryClass=DummyFactory.class, factoryMethod="createNew")
    public abstract MyClass() {
    }
    

    The following types of factory classes are supported:

    Factory with Static Methods

    With this bug fix, when MOXy uses the factory method to create an instance of MyClass an instance of DummyFactory is not created.

    public abstract class DummyFactory {
        public static MyClass createNew() {
            // code for returning a new instance of MyClass
        }   
    }
    

    Factory with Instance Methods

    In addition to static methods, MOXy allows you to specify instance level creation methods. For these methods MOXy will create an instance of the factory class.

    public class DummyFactory {
        public MyClass createNew() {
            // code for returning a new instance of MyClass
        }   
    }
    

    This configuration is not allowed in the JAXB RI, and you will get the following exception:

    Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
    Factory class "forum8022136.DummyFactory" does not have static zero args factory method "createNew".
        this problem is related to the following location:
            at forum8022136.MyClass
    
        at com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException$Builder.check(IllegalAnnotationsException.java:91)
        at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.getTypeInfoSet(JAXBContextImpl.java:436)
        at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:277)
        at com.sun.xml.internal.bind.v2.runtime.JAXBContextImpl$JAXBContextBuilder.build(JAXBContextImpl.java:1100)
        at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:143)
        at com.sun.xml.internal.bind.v2.ContextFactory.createContext(ContextFactory.java:110)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:202)
        at javax.xml.bind.ContextFinder.find(ContextFinder.java:376)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:574)
        at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:522)
        at forum8022136.Demo.main(Demo.java:14)