Handling extended mixed content in JAXB
Recently an issue came up to handle extended mixed content better with JAXB.
Just to clarify in the beginning, my opinion is that when somebody is designing a schema which is supposed to be machine processed (not something for some kind of UI rendering), it is a good decision to avoid use of mixed content, especially when designing a large schema with a lot of type extensions. Mapping that kind of schema to any binding framework is usually complex and leads to complications and slowdown of development. JAXB has never been designed to handle these cases in a convenient way - it is a Java <-> XML mapping framework, and it's not possible to represent this kind of content in a hierarchy of Java objects.
General recommendation for JAXB, if you come up to a corner case is to use customizations. If none of the many customizations help, you shall use the DOM customization (https://jaxb.dev.java.net/guide/Avoid_strong_databinding.html#Mapping_to_DOM) which is able to handle 100% schema structures, like this:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0">
<xs:element>
<xs:complexType>
<xs:sequence>
<xs:any maxOccurs="unbounded" processContents="skip">
<xs:annotation><xs:appinfo>
<jaxb:dom/>
</xs:appinfo></xs:annotation>
</xs:any>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
With this customization, the underlying contents are stored in DOM tree, and thus you get unlimited capabilities to modify/access the tree structure. You loose the convenient JAXB mapping approach of course.
As I mentioned in the beginning, one corner case is handling multiple extensions with mixed content.
Usual way how JAXB handles this, is to generate 'content' property as List> where ? is the common denominator of the potential content. Then, using @XmlElementRefs and @XmlElementRef annotations, it specifies which elements are expected in the tree.
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MyBaseType", propOrder = {
"content"
})
@XmlSeeAlso({
MyExtendedType.class
})
public class MyBaseType {@XmlElementRefs({
@XmlElementRef(name = "element2", type = JAXBElement.class),
@XmlElementRef(name = "element1", type = JAXBElement.class)
})
@XmlMixed
protected Listcontent; public List
getContent() {
if (content == null) {
content = new ArrayList();
}
return this.content;
}
}@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "MyExtendedType")
public class MyExtendedType extends MyBaseType {
}
Since we are talking about mixed content, 'String' is one of the elements, so in the end you end up either with List<Object>, List<Serializable> or List<String>. Not very convenient, but still you can work with it in usual JAXB way.
However, the bigger problem comes when you do need to use a schema like this:
<xs:complexType name="BaseTypeWithElementsExtended" mixed="true">
<xs:sequence>
<xs:element name="element1" type="xs:string" />
<xs:element name="element2" type="xs:string" />
</xs:sequence>
</xs:complexType><xs:complexType name="ExtendedTypeWithElements" mixed="true">
<xs:complexContent mixed="true">
<xs:extension base="BaseTypeWithElementsExtended">
<xs:sequence>
<xs:element name="element3" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType><xs:complexType name="ExtendedType2" mixed="true">
<xs:complexContent mixed="true">
<xs:extension base="ExtendedTypeWithElements">
<xs:sequence>
<xs:element name="element4" type="xs:string" />
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType><xs:element name="MultiExtendedTypeWithElements" type="ExtendedType2"/>
The main difference is that there are multiple extensions (all of them mixed of course). The usual JAXB approach doesn't work here, because JAXB generates this kind of content:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ExtendedType2")
public class ExtendedType2 extends ExtendedTypeWithElements {
}@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ExtendedTypeWithElements")
@XmlSeeAlso({
RestrictedType2 .class,
ExtendedType2 .class
})
public class ExtendedTypeWithElements extends BaseTypeWithElementsExtended {
}@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BaseTypeWithElementsExtended", propOrder = {
"content"
})
@XmlSeeAlso({
RestrictedTypeWithElements.class,
ExtendedTypeWithElements.class
})
public class BaseTypeWithElementsExtended {
@XmlElementRefs({
@XmlElementRef(name = "element1", type = JAXBElement.class),
@XmlElementRef(name = "element2", type = JAXBElement.class)
})
@XmlMixed
protected Listcontent; public List
getContent() {
if (content == null) {
content = new ArrayList();
}
return this.content;
}
}
Hmm, now how do you represent element3 or element4?
You've got the "content" property, which is supposed to hold the mixed content, but at the same time, you've got extensions which introduce another type of content. With Java, you can't put another "content" variable with another set of annotations to the subclasses. So, I decided to add one more global customization for those who cannot modify their schemas and need to handle this case directly through jaxb. The customization goes like this:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings generateMixedExtensions="true"/>
</jaxb:bindings>
When this customization is present (either inline or externally), the behaviour of JAXB changes slightly, and the code it generates for schema above looks like this:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ExtendedType2")
public class ExtendedType2 extends ExtendedTypeWithElements {@XmlElementRefs({
@XmlElementRef(name = "element1", type = JAXBElement.class),
@XmlElementRef(name = "element2", type = JAXBElement.class),
@XmlElementRef(name = "element3", type = JAXBElement.class),
@XmlElementRef(name = "element4", type = JAXBElement.class)
})
@XmlMixed
@OverrideAnnotationOf
protected ListcontentOverrideForExtendedType2;
}@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "ExtendedTypeWithElements")
@XmlSeeAlso({
RestrictedType2 .class,
ExtendedType2 .class
})
public class ExtendedTypeWithElements extends BaseTypeWithElementsExtended {@XmlElementRefs({
@XmlElementRef(name = "element1", type = JAXBElement.class),
@XmlElementRef(name = "element2", type = JAXBElement.class),
@XmlElementRef(name = "element3", type = JAXBElement.class)
})
@XmlMixed
@OverrideAnnotationOf
protected ListcontentOverrideForExtendedTypeWithElements;
}public class BaseTypeWithElementsExtended {
@XmlElementRefs({
@XmlElementRef(name = "element1", type = JAXBElement.class),
@XmlElementRef(name = "element2", type = JAXBElement.class)
})
@XmlMixed
protected Listcontent; public List
getContent() {
if (content == null) {
content = new ArrayList();
}
return this.content;
}
}
There's a proprietary annotation to allow overriding the content property with a different content. When JAXB runtime finds the dummy content property, it modifies it's internal representation of the original 'content' property to allow a larger set of elements, as defined in the annotations.
The code is in current JAXB nightly builds, so give it a try and we can improve/modify it before next release based on your comments. Either send them to JAXB forums, or directly to me.
Posted at 07:05PM Nov 19, 2008 by mgrebac in Sun | Comments[0]
Grails and web service development with Metro - little update
I've seen several comments where people had issues using the Metro plugin for Grails framework. I fixed the problems and updated installation instructions a bit, so if you use the latest plugin release (1.0.1), you shall be fine. I also updated the plugin to comply with Grails 1.0.3. Check it out at:
https://jax-ws-commons.dev.java.net/grails/
Posted at 06:08PM Jul 15, 2008 by mgrebac in Sun | Comments[9]
Mr. Groovy at Prague Sun site
Yesterday (Wed18th), thanks to the ServerSide symposium happening in Prague, we had a chance to chat with Guillaume Laforge, the Groovy guy.
Guillaume visited the Prague's Sun site, where he gave a presentation on Groovy success stories, to describe where and how the Groovy is used and how it helps in development/production environments, then we had a chance to chat and ask some questions.


Technorati Profile
Posted at 01:50PM Jun 19, 2008 by mgrebac in Sun | Comments[0]
Grails and web service development with Metro
I searched through my blog entries, and realized that I somehow forgot to blog about the Metro Plugin for Grails framework I introduced in the beginning of this year. So, this is an attempt to do a (late) little advertising.
If you use Grails, you are certainly aware of it's plugin system. I decided to wrote a little Metro plugin which enables you to expose your Groovy/Grails classes as Metro web services in a simple and easy way using natural Grails commands, such as
grails create-service
and natural Metro annotations, such as @WebService, like this:
import javax.jws.*
@WebService(targetNamespace="http://com.calculator")
class CalculatorService {
@WebMethod
def int add(int i, int j) {
return i+j;
}
@WebMethod
def multiply(int i, int j) {
return i*j;
}
}
Those are the only things you need to do to develop web services with Grails after installing the plugin. You can find exact installation/how to use instructions at plugin website. Currently I host the plugin as a subproject of JAX-WS Commons project, but am working on making sure it is hosted at Grails plugin site as well.
Btw, I recently found also these instructions on how to use the Metro Grails plugin to develop contract-first (WSDL first) web services, which gives exactly the areas where I planned to improve the plugin in. So in future, the instructions might get even more simple.
Posted at 01:21PM Jun 18, 2008 by mgrebac in Sun | Comments[13]
JAXB
Well, you might have already read Kohsuke's blog about JAXB 2.2 maintenance release. Hudson is his baby now, and he's moving away from JAXB duties.
The reason I mention it on my blog is that I'm going to take over the JAXB work going forward.
I'll leave it with that note for now, maybe I'll write more later on.

Posted at 01:26PM Jun 04, 2008 by mgrebac in Sun | Comments[0]
GlassFish v2 plugin for Grails Framework
The GlassFish v2 plugin for Grails is out! See the screenshot from update tool:

You can find more information about this integration, as well as integration of GlassFish with other scripting languages at GlassFish scripting pages, or in the setup instructions.
Posted at 03:02PM May 14, 2008 by mgrebac in Sun | Comments[0]
Grails plugin for GlassFish v3 TP2 available
Recently I've been looking at Grails distribution, altogether with Groovy language of course. Couple of days ago, aligned with GlassFish v3 TP2 release, we published Grails package to GlassFish's update center. If you are interested in Grails, see also some other recent additions, like Metro support for Grails framework.
[Read More]Posted at 02:14PM May 06, 2008 by mgrebac in Sun | Comments[0]
Java and Microsoft Interoperability Hands On Lab
Hi,
time's up for this year's JavaOne. WSIT is there as well. Besides all technical sessions, you can also try things yourself.
Me, Sreejith A K and Fabian Ritzmann will guide you through Sun Java and Microsoft WCF interoperability step by step at JavaOne's Hands-on-lab session on Wednesday 9th:
3:50 PM - 5:20 PM LAB-3350 Make Java Technology and .NET 3.0 Interoperability Work With WSIT
If you don't plan to attend this year, or there's no place left, you can still try everything safe at home on your computer. The lab will be accessible online, and we'll provide a forum where we'll try to answer all your issues, questions, requests. Stay tuned, I'll post the necessary info here soon.
Posted at 10:17PM May 07, 2007 by mgrebac in Sun |
Secure Conversation in your hands
Want to try WSIT and the new MS interoperable technologies? Kumar just posted a description on how to implement secure web service in Netbeans with Secure Conversation minimizing the required message flow:
How to configure Secure Conversation using Netbeans.
I plan to convert this into a flash demo like these: http://websvc.netbeans.org/wsit/ (see section Getting Started) for those who prefer watching videos. So, stay tuned!
Posted at 10:47AM Jul 21, 2006 by mgrebac in Sun |
