1

I have an application that loads some parameters from an xml file:

JAXBContext jc = JAXBContext.newInstance(MyParams.class);
Unmarshaller u = jc.createUnmarshaller();
MyParams obj = (MyParams) u.unmarshal(inputStream);

I would like to make MyParams Singleton, is it possible? How?

telebog
  • 1,706
  • 5
  • 25
  • 34

2 Answers2

1

Well, you probably can override JAXB's instantiation mechanism somehow to reuse an existing instance (your singleton) instead of creating a new instance.

As a side not, I thought this should work with ObjectFactory but it did not for me:

Why is the ObjectFactory not used during unmarshalling?

But from my pont of view this would be not the best design. In this case any unmarshalling of the MyParams will go into the same instance.

My suggestion would be to unmarshal into a distinct instance first and then merge these unmarshalled params into your singleton. Singleton per se is often an anti-pattern, but marrying it with JAXB unmarshalling would take the potential "anti-" even further.

Update

Seems like you can use @XmlType annotation with factoryClass and factoryMethod to specify how the instances of MyParams should be created.

So probably something like:

@XmlType(factoryClass=MyParamsFactory.class, factoryMethod="createMyParams")
public class MyParams {
    ...

    public static MyParams getInstance() { ... }
}

public class MyParamsFactory {
    public MyParams createMyParams() { return MyParams.getInstance(); }
}

should work.

However, as I said, I think it is not a good idea to unmarshal to singleton. This is an explicit warning.

Community
  • 1
  • 1
lexicore
  • 42,748
  • 17
  • 132
  • 221
  • `createMyParams` should be static as specified for factoryClass in http://docs.oracle.com/javaee/6/api/index.html?javax/xml/bind/annotation/XmlType.html – Daniel Puiu Aug 29 '17 at 07:09
1

The above answer on using @XmlType with a factory class and method is correct. It is rare, but there are situations where a singleton makes sense in XML.

I have a case where I want to marshall/unmarshall values, such as dates, strings, integers, etc. One of the value types is null. In my hierachy, a Java null reference means unspecified, so I want an explicit Null class to mean a value that is specified to be null.

Naturally, there is no reason to have more than once instance of Null, so it is a singleton. I put the factory class inside Null, as follows:

@XmlRootElement(name = "null")
@XmlType(factoryClass = Null.Factory.class, factoryMethod = "nullInstance")
public final class Null extends Value {
  public static class Factory {
    public static Null nullInstance(
    ) {
      return INSTANCE;
    }
  }

  public static final Null INSTANCE = new Null();

  // Construct

  /**
   * Construct
   */
  private Null(
  ) {
    if (INSTANCE != null) {
      throw new RuntimeException("Null is a singleton class");
    }
  }

  // Object

  @Override
  public String toString(
  ) {
    return getClass().getSimpleName();
  }

  // Value

  @Override
  public boolean isCompound(
  ) {
    return false;
  }

  @Override
  public boolean isScalar(
  ) {
    return true;
  }
}
Greg
  • 561
  • 3
  • 9