20

What does JAXB need a public no-arg constructor for, during marshalling?

 Marshaller msh = ctx.createMarshaller();
 msh.marshal(object, System.out);

I'm passing an object, not a class. Why does JAXB need a constructor? To construct what?

InfernalRapture
  • 572
  • 7
  • 19
yegor256
  • 102,010
  • 123
  • 446
  • 597
  • Nitpick: I'm pretty sure it doesn't need a *public* no-arg constructor. It just needs *any* no-arg constructor. It can be protected/private/package-private if you like. – Tyler Jun 02 '11 at 18:08

3 Answers3

8

A JAXB implementation should not need a no-arg constructor during a marshal operation. JAXB does require one for unmarshalling. Normally the absence of a no-arg constructor causes an error when the JAXBContext is created. The JAXB implementation you are using may be delaying initialization until an actual operation is performed.

In general support for multi-arg constructors is something we should consider in a future version of JAXB. In the EclipseLink implementation of JAXB (MOXy) we have an enhancement request open for this functionality (feel free to add relevant details):

In the current version of JAXB you could use an XmlAdapter to support this use case:

bdoughan
  • 147,609
  • 23
  • 300
  • 400
  • With `XmlAdapter` I have to know the internal structure of the class being marshaled. In this case why can't I just add a no-arg constructor? – yegor256 Nov 11 '10 at 15:03
  • 2
    @Vincenzo you could definitely just add a no-arg constructor. If for some reason you could not modify your model classes, an XmlAdapter could be used. – bdoughan Nov 11 '10 at 15:15
6

As others have noted, it shouldn't really need one but (at least in Sun's implementation) it does. You can get around this with a dummy constructor:

private MyObject() {
    throw new UnsupportedOperationException("No-arg constructor is just to keep JAXB from complaining");
}
David Moles
  • 48,006
  • 27
  • 136
  • 235
  • 1
    You can't throw exception here, JAXB actually uses this c-tor – Kirill Nov 15 '16 at 16:36
  • That depends on whether JAXB is constructing the object or whether ([as the OP comments](http://stackoverflow.com/questions/4155361/what-jaxb-needs-a-public-no-arg-constructor-for/12921496?noredirect=1#comment4484733_4155388)) you're constructing it yourself and passing an instance to `marshal()`. – David Moles Nov 16 '16 at 17:54
4

The same as many frameworks - simplicity and consistency. It allows the library to simple call Class.newInstance() without having to worry about how to specify certain dependencies for a constructor that takes them. JAXB doesn't want to concern itself with full-on Dependency Injection above and beyond the attribute-based setting it already does.

It's a shame in some ways as it means these classes can't be immutable, but that's the trade-off to be made.

Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
  • As long as you don't specifiy what parameter is where in the constructor, I see no way for JAXB to find this out. The reflection api gives only the types, no names for the arguments to the constructor. How should it know that the first parameter (String) is the name and not an ID or sthg like that? – ZeissS Nov 11 '10 at 14:32
  • 3
    I know what a public no-arg constructor is for, but why JAXB needs it during marshaling? I'm passing an instance to `marshal()`, not a class. – yegor256 Nov 11 '10 at 14:38
  • 2
    @Vincenzo - good point. One could propose that JAXB uses the same metadata-processing package for both marshalling and unmarshalling. And regardless of the fact you pas an *instance*, JAXB will almost certainly call `getClass()` in order to inspect the class structure when determining how to marshall it. You're right though, that it shouldn't *need* the constructor; perhaps this is a limitation on the basis of reusing the same metadata processor for both marshalling and unmarshalling and hence applying the nullary constructor requirement to both. – Andrzej Doyle Nov 11 '10 at 14:59