users@jersey.java.net

Re: [Jersey] Jersey Issues with JAXB classes without _at_XmlRootElement - XSD, XJC, Inheritance

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 06 Oct 2009 09:44:57 +0200

On Oct 5, 2009, at 7:03 PM, James Allchin wrote:

> Ah OK - thanks Paul... interesting...
>
> This will certainly help with the GETs. I will give it a go.
>
> As you point out I will still be affected by GETs with List<T> based
> return types.
>

Yes. I am not sure what to do about that case. Unfortunately you may
have to resort to using the uglier JAXBElement :-(


> I suspect I will also be facing similar issues with POST, PUT, and
> DELETE where I wish to unmarshall the Artifact(s) directly from the
> XML/JSON payload of these methods.
>

Unmarshalling will work based for a the type of a method parameter
that is annotated with @XmlType. So it should work if you declare the
Artifact type. JAXB should create the underlying root element instance
based on the root element in the XML document.

So, assuming you have a JAXB context resolver configured
appropriately, you should be able to do:

  @POST
  public Response post(Artifact a) {
     return Response.ok(a).build(); // work around restriction of
return type being too restrictive.
  }

Paul.


> Thanks,
>
> James
>
> -----Original Message-----
> From: Paul Sandoz [mailto:Paul.Sandoz_at_Sun.COM]
> Sent: Monday, October 05, 2009 10:00 AM
> To: users_at_jersey.dev.java.net
> Subject: Re: [Jersey] Jersey Issues with JAXB classes without
> @XmlRootElement - XSD, XJC, Inheritance
>
> Hi James,
>
> I am not sure that annotating Artifact with @XmlRootElement is the
> right approach. Because, i presume, when you marshall you want to the
> root element to be that of the concrete type.
>
> I think Jersey is being too restrictive. Currently the type that is
> utilized to analyze whether JAXB can be utilized is the return type of
> the method. I suspect you are doing the following:
>
> @GET
> public Artifact get(...) {
> Artifact a = ... // create an instance of EmailArtifact
> return a;
> }
>
> Correct?
>
> Can you try the following workaround:
>
> @GET
> public Response get(...) {
> Artifact a = ... // create an instance of EmailArtifact
> return Response.ok(a).build();
> }
>
> does the above work?
>
> If so I need to fix things such that the return type of the method is
> only used if:
>
> method.getReturnType() != method.getGenericReturnType()
>
> i.e. we need to utilize the return type of the method say when
> returning List<T>.
>
> Paul.
>
> On Oct 3, 2009, at 9:56 PM, James Allchin wrote:
>
>> Hi,
>>
>> Although not directly related to Jersey - there is a side-effect
>> problem caused to Jersey by XSD, XJC and class inheritance. I
>> therefore, hope that someone has seen this before...
>>
>> Essentially, if you have complex types that extend other complex
>> types within your XSD, then the resulting base classes do not have
>> an @XmlRootElement annotation. This causes problems for Jersey it
>> seems because natively we can do GETs PUTs etc against JAXB classes
>> that have the @XmlType annotation only (without the @XmlRootElement).
>>
>> I do not want to resort to having to use JAXBElement type methods
>> through an ObjectFactory (I have seen this on previous postings).
>>
>> Has anyone from the group experienced this and solved it (without
>> manually adding back in the XmlRootElement annotation to the base
>> classes)?
>>
>> For more information, I have also included the original question
>> that I posed on StackOverflow below.
>>
>> Thanks for any help you can give.
>>
>> Regards,
>>
>> James
>> ------------------------------
>>
>> I have a relatively simple XSD file defining my XML schema. The
>> complex types within the XSD take advantage of inheritance using the
>> tags. The problem I having is that I need all complex types to
>> generate Java Classes with the @XmlRootElement.
>>
>> Unfortunately, the way in which XJC generates the classes means that
>> only derived class gets the @XmlRootElement (not the base class). I
>> am using the simple global binding directive to ensure that it
>> solves many of the other issues that I have faced with XJC.
>>
>> Here is an example snippet of the XSD:
>>
>> <xs:element name="Artifact" type="kmcs:Artifact"/>
>> <xs:element name="EmailArtifact" type="kmcs:EmailArtifact"/>
>>
>> <xs:complexType name="Artifact">
>> <xs:sequence>
>> <xs:element name="artifactId" type="xs:string" minOccurs="0"/>
>> <xs:element name="artifactType" type="xs:string"
>> minOccurs="0"/>
>> <xs:element name="contentHash" type="xs:string" minOccurs="0"/>
>> </xs:sequence>
>> </xs:complexType>
>>
>> <xs:complexType name="EmailArtifact">
>> <xs:complexContent>
>> <xs:extension base="kmcs:Artifact">
>> <xs:sequence>
>> <xs:element name="subject" type="xs:string"
>> minOccurs="0"/>
>> <xs:element name="threadSubject" type="xs:string"
>> minOccurs="0"/>
>> <xs:element name="from" type="xs:string"
>> minOccurs="0"/>
>> <xs:element name="to" type="xs:string" minOccurs="0"/>
>> <xs:element name="cc" type="xs:string" minOccurs="0"/>
>> <xs:element name="bcc" type="xs:string" minOccurs="0"/>
>> <xs:element name="messageId" type="xs:string"
>> minOccurs="0"/>
>> <xs:element name="date" type="xs:date" minOccurs="0"/>
>> <xs:element name="size" type="xs:long" minOccurs="0"/>
>> <xs:element name="hasAttachment" type="xs:boolean"
>> minOccurs="0"/>
>> <xs:element name="sensitivity" type="xs:string"
>> minOccurs="0"/>
>> <xs:element name="headerHash" type="xs:string"
>> minOccurs="0"/>
>> </xs:sequence>
>> </xs:extension>
>> </xs:complexContent>
>> </xs:complexType>
>>
>> As we can see from the above snippet, EmailArtifact extends Artifact.
>>
>> The java class code for EmailArtifact contains the following:
>>
>> @XmlAccessorType(XmlAccessType.FIELD)
>> @XmlType(name = "EmailArtifact", propOrder = {
>> "subject",
>> "threadSubject",
>> "from",
>> "to",
>> "cc",
>> "bcc",
>> "messageId",
>> "date",
>> "size",
>> "hasAttachment",
>> "sensitivity",
>> "headerHash"
>> })
>> @XmlSeeAlso({
>> ExtendedEmail.class
>> })
>> @XmlRootElement(name = "EmailArtifact")
>> public class EmailArtifact
>> extends Artifact
>> {
>>
>> protected String subject;
>> protected String threadSubject;
>> protected String from;
>> protected String to;
>> protected String cc;
>> protected String bcc;
>> protected String messageId;
>> @XmlSchemaType(name = "date")
>> protected XMLGregorianCalendar date;
>> protected Long size;
>> protected Boolean hasAttachment;
>> protected String sensitivity;
>> protected String headerHash;
>>
>> The java class code for Artifact contains the following:
>>
>> @XmlAccessorType(XmlAccessType.FIELD)
>> @XmlType(name = "Artifact", propOrder = {
>> "artifactId",
>> "artifactType",
>> "contentHash"
>> })
>> @XmlSeeAlso({
>> ManagedDocArtifact.class,
>> EmailArtifact.class
>> })
>> public class Artifact {
>>
>> protected String artifactId;
>> protected String artifactType;
>> protected String contentHash;
>>
>> In the EmailArtifact we can see that it contains the @XmlRootElement
>> but the base type Artifact does not contain @XmlRootElement.
>>
>> How can you force XJC to generate @XmlRootElement for all classes
>> including the base types.
>>
>> Thanks,
>>
>> James
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
>> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>