tags:

views:

56

answers:

2

I'm trying to unmarshal a simple xml document from a public api from Convio. I'm not getting any compiler errors with the following code, but it won't produce a result either. The values are null. If I remove the schema and namespace items from the xml document and remove the namespace attribute from the POJO then it will run just fine. What am I missing to be able to work with the xsd document / namespace?

XML example that I'm trying to parse

<?xml version='1.0' encoding='UTF-8'?>
<getSingleSignOnTokenResponse xsi:schemaLocation="http://convio.com/crm/v1.0 http://service.convio.net/xmlschema/crm.public.v1.xsd" xmlns="http://convio.com/crm/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
  <token>abcdefghijklmnopqrstuvwxyz</token>
  <cons_id>0123456789</cons_id>
</getSingleSignOnTokenResponse>

And the POJO with annotations:

@XmlRootElement(name = "getSingleSignOnTokenResponse", namespace = "http://convio.com/crm/v1.0")
public class SingleSignOnResponseBean
{
  @XmlElement(name = "token")
  public String token;
  @XmlElement(name = "cons_id")
  public int consId;
}

Now, I'm using Jersey to do the actual work, but since I couldn't get it to unmarshal using Jersey, I set up an unmarshaller by hand using a static xml file on my machine of the XML result above:

    JAXBContext jc = JAXBContext.newInstance(new Class[] {org.orgname.utility.convio.sso.api.SingleSignOnResponseBean.class});
    Unmarshaller u = jc.createUnmarshaller();
    SingleSignOnResponseBean bean2 = (SingleSignOnResponseBean) u.unmarshal(new File("C:/token.xml"));
    System.out.println(bean2.token);

This is probably very simple and I'm just not seeing it on why it won't work if the schema and namespace elements are defined. I've seen some other comments about setting up some sort of SAX filter to strip out the namespace, but since I'm coming in via a REST call from jersey directly I don't believe I have the opportunity to do that. Any ideas?

A: 

The namespace is not "inherited" by the fields on the bound class. You need to define the namespace on the fields as well:

@XmlRootElement(name = "getSingleSignOnTokenResponse", namespace = "http://convio.com/crm/v1.0")
public class SingleSignOnResponseBean
{
  @XmlElement(name = "token", namespace = "http://convio.com/crm/v1.0")
  public String token;
  @XmlElement(name = "cons_id", namespace = "http://convio.com/crm/v1.0")
  public int consId;
}

If you omit them, then the fields go back to the "default" namespace (i.e. no namespace).

It's mildly irritating, but that's the way it is.

skaffman
Perfect! I knew I had to have been missing something extremely simple. That is mildly irritating especially after spending half an afternoon fighting it. Thanks.
rmeans
A: 

You could add a package level annotation (this is done on a class called package-info) and specify elementFormDefault="qualified", then you wouldn't need to qualify each @XmlElement annotation.

@javax.xml.bind.annotation.XmlSchema(
   namespace="http://convio.com/crm/v1.0".
   elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) 
package com.convio.crm; 

For more information on JAXB and namespaces see:

Blaise Doughan