Zach
Zach

Reputation: 2155

Is it possible to use JAXB to map from schema to a java.util.Map?

I have an existing XML schema that contains a type that I would like to map to a Java Map of some sort using JAXB. My build process takes the schema and creates the beans. I would like to customize this process by having one of the complexTypes in my schema map to a java.util.Map. I've read somewhere that JAXB "can't do interfaces." I'm not sure if that applies in this case, but if so I'd be fine with it mapping to a HashMap. Also, it doesn't necessarily have to be the complexType that maps to a Map, it could be an element if that's what's required.

I control my JAXB generation using a .xjb file, so I'm looking for some <jaxb:bindings> to put in there. I've tried the following, but it does not work:

<jaxb:bindings schemaLocation="myschema.xsd" node="/xs:schema">
    <jaxb:globalBindings>
        <jaxb:serializable uid="1"/>
    </jaxb:globalBindings>
    <jaxb:schemaBindings>
        <jaxb:package name="com.myschema.client.types"/>
    </jaxb:schemaBindings>
    <jaxb:bindings node="//xs:complexType[@name='MapType']">
            <jaxb:javaType name="java.util.HashMap"
            parseMethod="com.myschema.common.MapConverter.parseObjectToMap"
            printMethod="com.myschema.common.MapConverter.printMapToObject" />
    </jaxb:bindings>
</jaxb:bindings>

Edit: I've added more detail on the above binding that I've already tried. It generates the following error during schema compile:

[jaxb] [ERROR] compiler was unable to honor this javaType customization. It is attached to a wrong place, or its inconsistent with other bindings.

<jaxb:javaType> will not work because it can only be used for mapping between XML Schema primitives and Java types. Since I want to map between a complex type and a Java type, I cannot use this.

Upvotes: 17

Views: 17692

Answers (3)

Laurent Schoelens
Laurent Schoelens

Reputation: 2848

Very old question but new answer possible when this PR will be merged.

With this new PR, xjc:javaType will now handle generic types.

It has been tested with jaxb-tools' maven-plugin with the following example syntax :

<jaxb:bindings node=".//xsd:attribute[@name='subRatings']">
  <jaxb:property>
    <jaxb:baseType>
      <xjc:javaType name="java.util.List&lt;java.lang.String&gt;" adapter="org.jvnet.jaxb.xml.bind.annotation.adapters.CommaDelimitedStringAdapter"/>
    </jaxb:baseType>
  </jaxb:property>
</jaxb:bindings>

The generated java class property looks like below with no more import java.util.List<String>; erroneous import

@XmlAttribute(name = "subRatings")
@XmlJavaTypeAdapter(CommaDelimitedStringAdapter.class)
protected List<String> subRatings;

It fixes the #209 and #737 issues in jaxb-ri repository

Upvotes: 0

skaffman
skaffman

Reputation: 403551

Your XJC file is using the "standard" javaType directive, which I believe is limited to converting String values to and from a representative java type. As such, it's only suitable for converting simple element and attribute content.

The XJC tool provides an enhanced version of javaType, which in theory should be able to handle more complex structures. Unfortunately, this has yet to be implemented:

https://java.net/jira/browse/JAXB-209 (unresolved)

For instance, being able to map a schema type to a HashMap might be a likely requirement for those using model driven design/implementation. AFAICS, this is not possible today. Therefore, one must manually edit the generated code.

Looks like you're out of luck.

Upvotes: 10

maximdim
maximdim

Reputation: 8169

Have you looked at example here (Customized mapping of HashMap): http://java.sun.com/javase/6/docs/api/javax/xml/bind/annotation/adapters/XmlAdapter.html

Need to create custom XmlAdapter I'm afraid.

Upvotes: 6

Related Questions