 |
JAXB and interfaces
Posted by kohsuke on June 06, 2006 at 10:00 PM | Comments (13)
Today's question from our users is "why doesn't JAXB handle interfaces?"
First, it's not quite accurate to say "we don't support interfaces". It's just that you need put some annotations to make it work, and it's more restrictive than we'd like it to be. Fore more about how to map interfaces, see the unofficial JAXB guide that I'm compiling.
But what I'd like to talk about today is why JAXB can't handle interfaces like it does classes, and there's a good technical reason for it.
Suppose if you have interfaces annotated just like you'd classes:
@XmlType(name="foo")
interface Foo {
@XmlElement
String getName();
void setName(String);
}
@XmlType(name="bar")
interface Bar {
@XmlElement
String getAddress();
void setAddress(String);
}
OK, so far no big deal, we can map them to two complex types. But now, how do you do this?
interface Zot extends Foo, Bar {
}
class FooImpl extends BaseClass implements Foo {
String getAddress() { ... }
}
It's really not possible to map Zot nor FooImpl to XML Schema concepts --- I mean, you can't do multiple inheritance in XML Schema. Even if you forget the idea of generating a schema, you still can't even bind them to XML, since we can't decide whether address should come before name or vice versa.
Another serious problem is that when you annotated interfaces, your expectation is that JAXB will be able to bind any classes provided that it implements the said interface, but if you think about it, it just doesn't work that easily. For example, how does the unmarshaller create an instance, if it only knows about an interface? Or if you try to marshal an instance of a class that both implements Foo and Bar, how does the JAXB runtime figure out whether it should be marshalled as Foo or marshalled as Bar?
I hope you get some idea of why interfaces and classes are so different.
Now, that said, handling of interfaces in JAXB turns out to be really painful for many people. So I think some improvements would be really nice --- it's just that I'm not too sure how.
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Couldn't you create dynamic proxies for the interfaces?
On another tack, you say: "you still can't even bind them to XML, since we can't decide whether address should come before name or vice versa"
Please don't transfer the weaknesses of XMLSchema to XML, since XMLSchema is not used by anyone who understands to use the full power of XML the right way.
Posted by: tobega on June 06, 2006 at 11:23 PM
-
wrt creating dynamic proxy --- sure, but I doubt if that's the expected semantics.
The ordering issue is a problem even if JAXB abandons the idea of generating a schema. It's an ambiguity that makes a difference in the XML instance document, and it's irrelevant whether it's described by any kind of schema.
(You don't need to tell me how ugly/difficult/what-not XML Schema is. I fell the same way!)
Posted by: kohsuke on June 06, 2006 at 11:42 PM
-
Sorry, I don't see why ordering is an issue, don't you have unique name/namespace combinations to identify elements?
Posted by: tobega on June 08, 2006 at 12:23 AM
-
But in XML, order of elements matter. Unique names are not suffice.
Just look at your Ant build.xml and imagine what would happen if people start ignoring order of elements...
Posted by: kohsuke on June 08, 2006 at 01:00 AM
-
Does the order matter in Ant? I thought the order was defined by dependencies. But if order does matter, then it is the order the author decides, not the order a format specification decides.
Posted by: tobega on June 08, 2006 at 07:35 AM
-
Yes, the order matters in Ant. When you write and then , you expect them to be executed in the order you write them. Otherwise it's a disaster.
Posted by: kohsuke on June 08, 2006 at 08:10 AM
-
Grrr, "when you write <mkdir /> and <javac />" is what I meant.
Posted by: kohsuke on June 08, 2006 at 08:16 AM
-
Oh, that's right! That is an order that is meaningful because it is imposed by the author of the Ant script. But how does that relate to the supposed ordering problem in JAXB?
Posted by: tobega on June 08, 2006 at 10:55 AM
-
That JAXB can't randomly choose the order among elements, and when a class implements multiple interfaces there's no natural way to determine orders among them.
Posted by: kohsuke on June 08, 2006 at 01:31 PM
-
Well, you don't really have an order between properties in a class, either, do you? The order between the properties of different interfaces therefore cannot be meaningful. Only the order that the author of the XML document placed the elements in can be meaningful and when order is important in that way, it can only be represented in java as a sequence of objects.
Posted by: tobega on June 08, 2006 at 09:59 PM
-
Even if you forget the idea of generating a schema, you still can't even bind them to XML, since we can't decide whether address should come before name or vice versa.
The propOrder attribute of XMLType could address this problem.
It would be nice if you would optimize the case of 1 implementation for every interface.
Posted by: lexknuther on June 15, 2006 at 05:49 PM
-
I like the idea of using dynamic proxies too. Often the objects you are dealing with are just value types, with no behaviour. So an interface containing only getters and implemented by a dynamic proxy that returns the values deserialized from XML would work fine. When serializing such an object you call the getters and that's all there is to it.
You point out that there are numerous cases where this won't work, for example if a class inherits more than one annotated interface. Well, fine, then those cases don't work, JAXB refuses to (de)serialize, and users will just have to restrict themselves to the cases that do work. But refusing to treat interfaces at all just because you can't cover every possible use of them seems unreasonable.
Posted by: emcmanus on July 07, 2006 at 03:59 AM
-
I'm running into problems where I have:
public class MyBean
{
@XmlElement(name="foo")
public MyInterface getFoo()
{
...
It complains about getFoo returning an interface.
How about providing an annotation to list known classes that implement the interface? So:
public class MyBean
{
@XmlElement(name="foo")
@XmlImplementations({Impl1.class, Impl2.class})
public MyInterface getFoo()
{
...
This would be a closed list - that is - if the implementation is not listed, then jaxb doesn't know about it and won't marshal/unmarshal it. This would map on to the xsd choice.
Posted by: mpocock on April 08, 2008 at 03:02 PM
|