eclipse-ee4j / jaxb-ri

Jaxb RI
https://eclipse-ee4j.github.io/jaxb-ri/
BSD 3-Clause "New" or "Revised" License
202 stars 110 forks source link

Unable to set a generic factory method for @XmlType - factoryMethod / factoryClass #980

Open Tomas-Kraus opened 11 years ago

Tomas-Kraus commented 11 years ago

JAXB implementation does not allow a generic factory method. Let's take a look at this simple example:

**CalculatorInput.java**import javax.inject.Inject;
import javax.inject.Named;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlRootElement(name = "CalculatorInput")
@XmlType(factoryMethod = "getBean", factoryClass = BeanFactory.class)
@Named
public class CalculatorInput {

  @Inject
  Context someContext;
**IocContainerObjectFactory .java**import javax.inject.Named;
import javax.inject.Singleton;

@Named
@Singleton
public class IocContainerObjectFactory {

  // bean factory init omitted 
  public static <T> T getBean(Class<T> clazz) {
    return beanFactory.getBean(clazz);
  }
}

Example provided above is impossible to implement in current JAXB. The problem here is that you either let JAXB invoke no-arg constructor of CalculatorInput class or explicit static factory method inside this class or in specific factory class. Note that you must have one factory method per class which is extremely bulky, not object-oriented, boilerplate, blah blah blah. Basically it's a mistake. I know better than JXAB how to create my objects - I need JAXB only to fill these beans with parsed XML content.

Another argument is that JAXB in the current state completely ignores existence of Dependency Injection (which is a part of Java EE specification). In case JAXB creates my CalculatorInput, someContext attribute will be ignored (thus null) by DI container as it has absolutely no knowledge on this instance. The only correct way to make the injection work is to obtain the new instance from the DI bean / object factory - see IocContainerObjectFactory. OK, it is possible but only in such form (again, bulky, boilerplate, ugly):

**IocContainerObjectFactory .java**import javax.inject.Named;
import javax.inject.Singleton;

@Named
@Singleton
public class IocContainerObjectFactory {

  // bean factory init omitted 
  public static CalculatorInput getCalculatorInput() {
    return beanFactory.getBean(CalculatorInput.class);
  }

  public static CurrencyConverterInput getCurrencyConverterInput() {
    return beanFactory.getBean(CurrencyConverterInput.class);
  }

  // etc. 
}

Imagine what happens if you have more than couple of beans...

Note on JSR-222 specification

JavaDoc of javax.xml.bind.annotation.XmlType says:

**XmlType.java**/**
 * Name of a no-arg factory method in the class specified in <tt>factoryClass</tt> factoryClass(). 
 * 
 */
String factoryMethod() default "";

But, the JSR-222 specification does not explicitly say that it must be a no-arg factory method.

Please correct me if I'm wrong.

Affected Versions

[2.2.7]

Tomas-Kraus commented 6 years ago
Tomas-Kraus commented 11 years ago

@glassfishrobot Commented Reported by pbielicki

Tomas-Kraus commented 11 years ago

@glassfishrobot Commented pbielicki said: how can I upload a patch file? I fixed this problem and I would like to submit my proposal

Tomas-Kraus commented 11 years ago

@glassfishrobot Commented pbielicki said: I sent my patch to dev@jaxb.java.net

Cheers, Przemek

Tomas-Kraus commented 10 years ago

@glassfishrobot Commented pbielicki said: Patch available on GitHub: https://github.com/pbielicki/jaxb/commit/c70183967936ed3e3b0be46eb65694e95c4d583c

Tomas-Kraus commented 11 years ago

@glassfishrobot Commented Was assigned to yaroska

Tomas-Kraus commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA JAXB-980