users@jersey.java.net

Re: [Jersey] Jersey - JAXB Marshalling Error - Field Name Similar to Method Name - Bug?

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Mon, 20 Apr 2009 13:29:39 +0200

Hi James,

This is a JAXB configuration issue, the JAXB runtime thinks there are
two properties to be serialized with the same name, one that is the
protected and field and one which is the JavaBean property method.

See here:

   https://jaxb.dev.java.net/tutorial/section_6_2_5-Controlling-Element-Selection-XmlAccessorType-XmlTransient.html
#Controlling%20Element%20Selection:%20XmlAccessorType,%20XmlTransient

   "If JAXB binds a class to XML, then, by default, all public members
will be bound, i.e., public getter and setter
    pairs, or public fields. Any protected, package-visible or private
member is bound if it is annotated with a suitable
    annotation such as XmlElement or XmlAttribute."

If you annotate your Artifact class with the annotation:

   @XmlAccessorType(XmlAccessType.FIELD)

then you do not need to annotate the fields with @XmlElement and the
setter/getter methods will be ignored.

Paul.

On Apr 20, 2009, at 12:13 PM, James Allchin wrote:

> Hi,
>
> New to all web service frameworks in Java. But think I may have
> found a bug with Jersey REST Web services and JAXB (I am using JAX-
> RS 2.1 with JDK 1.6)
>
> I am using Jersey with Tomcat 6.0. I have a really simple web
> service which returns an object called Artifact using a GET method.
>
> I am using standard annotations to allow the the Artifact class to
> be marshalled and serialized correctly into XML.
>
> Here is my Artifact class:
>
> @javax.xml.bind.annotation.XmlRootElement
> public class Artifact {
>
>
> @javax.xml.bind.annotation.XmlElement
> protected long artifactId;
>
> @javax.xml.bind.annotation.XmlElement
> protected String artifactType;
>
>
> public Artifact() {
>
> }
>
> /**
> * @return the artifactId
> */
>
> public long getArtifactId() {
> return artifactId;
> }
>
>
> /**
> * @param artifactId the artifactId to set
> */
> public void setArtifactId(long artifactId) {
>
> this.artifactId = artifactId;
> }
>
> /**
> * @return the artifactType
> */
> public String getArtifactType() {
>
> return artifactType;
> }
>
> /**
> * @param artifactType the artifactType to set
> */
> public void setArtifactType(String artifactType) {
>
> this.artifactType = artifactType;
> }
>
> }
>
>
> As you can see the class has 2 fields artifactId and artifactType.
>
> It also simple getter and setter accessor methods.
>
> When trying to return this object in the web service - I get the
> following error:
>
> java.io.IOException: Error marshalling JAXB object of type "class
> com.knowledgemill.entities.Artifact".
>
> com
> .sun
> .jersey
> .impl
> .provider
> .entity
> .AbstractRootElementProvider
> .writeTo(AbstractRootElementProvider.java:117)
>
>
>
> The hint in the error messages is:
> com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 2 counts of
> IllegalAnnotationExceptions
> Class has two properties of the same name "artifactId"
>
> this problem is related to the following location:
> at public long com.knowledgemill.entities.Artifact.getArtifactId()
>
> at com.knowledgemill.entities.Artifact
> this problem is related to the following location:
> at protected long com.knowledgemill.entities.Artifact.artifactId
>
> at com.knowledgemill.entities.Artifact
> Class has two properties of the same name "artifactType"
> this problem is related to the following location:
>
> at public java.lang.String
> com.knowledgemill.entities.Artifact.getArtifactType()
> at com.knowledgemill.entities.Artifact
> this problem is related to the following location:
>
> at protected java.lang.String
> com.knowledgemill.entities.Artifact.artifactType
> at com.knowledgemill.entities.Artifact
>
>
> Basically the framework seems to think that artifactId and
> artifactType are declared twice.
>
> If I rename the get methods so that they do not read as
> getArtifactId and getArtifactType then it works fine:
>
> getArtifactId -> getArtId
> getArtifactType -> getArtType
>
> The code now looks like this:
>
> /*
> * To change this template, choose Tools | Templates
> * and open the template in the editor.
> */
>
> package com.knowledgemill.entities;
>
>
> /**
> *
> * @author km
> */
> @javax.xml.bind.annotation.XmlRootElement
> public class Artifact {
>
>
> @javax.xml.bind.annotation.XmlElement
> protected long artifactId;
>
> @javax.xml.bind.annotation.XmlElement
> protected String artifactType;
>
>
> public Artifact() {
>
> }
>
> /**
> * @return the artifactId
> */
>
> public long getArtId() {
> return artifactId;
> }
>
>
> /**
> * @param artifactId the artifactId to set
> */
> public void setArtifactId(long artifactId) {
>
> this.artifactId = artifactId;
> }
>
> /**
> * @return the artifactType
> */
> public String getArtType() {
>
> return artifactType;
> }
>
> /**
> * @param artifactType the artifactType to set
> */
> public void setArtifactType(String artifactType) {
>
> this.artifactType = artifactType;
> }
>
> }
>
>
> With the methods renamed it now works fine. This looks some kind of
> bug to me?
>
> Can anyone help? - I would like to keep my accessor methods with a
> meaningful name. It's a pretty nasty workaround.
>
> Cheers
>
> James