You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by dponos <dp...@cisco.com> on 2011/07/01 00:35:24 UTC

Re: @XMLRootElement for parameters in REST method signatures

Thank you Stephen,  your information definitely helps.  I am able to work
around the issue this way. 

Over the last day, I experimented more with the the classes that I was able
to generate the @XmlRootElement annotation for, but still had issues when
using them as parameters in my REST service method signatures. 


I looked closer into the error message I was getting, messages like this:  

JAXBException occurred : unexpected element (uri:"", local:"Foo"). Expected
elements are <{http://acme.com/model}Foo>,..... 



I noticed that the unexpected element has a namespace of "local" and the
expected element is there, but has a namespace value that came from the XSD.    

I performed an experiment by copying "Foo" to a different package with no
other changes other than changes the name to something like Foo2, and the
problem went away. 


So this is leading me to believe that my issue is really some sort of
namespace issue.   My client will be a javascript client.  I am currently
testing with Firefox Poster, with the json object in the request body.  The
json object looks like this : 

{
    "Foo":  
        { 
            "name":"bar"
        } 
} 


There is nothing in the client that is specifying a namespace.  I've been
told that the client does not specify a namespace for the object.  

So I am wondering if there is some sort of filter/interceptor I need to
write or configure in order to match "Foo" with "{http://acme.com/model}Foo"



--
View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4540370.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: @XMLRootElement for parameters in REST method signatures

Posted by dponos <dp...@cisco.com>.
dponos wrote:
> 
> 
> I've been stepping through code to find out why the fields of Foo aren't
> getting set.  I noticed that in the UnmarshallingContext, there is an
> "expectText()" method that is returning false.  It is returning false
> because the loader is an instance of Discarder.   
> 

I made a mistake in this statement.  The expectText() method is in
StAXStreamConnector, not UnmarshallContext.   

--
View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4543000.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: @XMLRootElement for parameters in REST method signatures

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi

please see comments below

On Wed, Jul 6, 2011 at 12:01 AM, dponos <dp...@cisco.com> wrote:
>
> Sergey Beryozkin-5 wrote:
>>
>>
>>>
>>> FYI, I am not on version 2.4.0 yet, so I am not using the Transform
>>> feature.
>>> I am still using inTransformElements on the provider.  Not sure if that
>>> makes a difference for being able to use wildcards or not.
>>
>> Wildcards should be supported starting from CXF 2.2.7, even when
>> configuring providers directly, instead of
>> applying a feature, so please report a bug if you work with CXF 2.2.7+
>>
>> Thanks, Sergey
>>
>>
>
> I just verified that wildcards are working in version 2.2.7
>
> The project I am working on is using 2.2.6.
>
> To summarize, here is what I needed to do in order to successfully use
> generated classes from an XSD  as parameters in REST service methods :
>
> 1.  The Element should be defined something like :
>
> <xs:element name="fooType">
>    <xs:complextType>
>            .
>            .
>    </xs:complextType>
> </xs:element>
>
> as apposed to :
>
> <xs:complexType name="FooType">
>    .
>    .
> </xs:complexType>
> <xs:element name="foo" type="tns:FooType"/>
>
>
> This will result in the @XmlRootElement getting generated, which is needed
> for the Class to exist
> as a paramter in the REST API method signature.
>
>
> 2. Add the following to the inTransformElements property for the provider
> (Spring example).....
>
> <entry key="*" value="{http://somevalue}*" />
>
> 3.  Make sure I am using version 2.2.7+ of the cxf-bundle.
>
>
Configuring JAXB or JSON providers to work with types such as Foo
without @XmlRootElement (jaxbElementMap property or 'widlcard'
marshalAsJaxbElement/unmarshalAsJaxbElement properties) and applying
Transform feature should work starting from 2.4.0/2.3.5. I'm pretty
sure I fixed the issue to do with Transform feature not working with
JAXBElements.
If using anonymous complex types is possible then things are OK,
otherwise a bit more help from the runtime may be needed...

thanks, Sergey

Re: @XMLRootElement for parameters in REST method signatures

Posted by dponos <dp...@cisco.com>.
Sergey Beryozkin-5 wrote:
> 
> 
>>
>> FYI, I am not on version 2.4.0 yet, so I am not using the Transform
>> feature.
>> I am still using inTransformElements on the provider.  Not sure if that
>> makes a difference for being able to use wildcards or not.
> 
> Wildcards should be supported starting from CXF 2.2.7, even when
> configuring providers directly, instead of
> applying a feature, so please report a bug if you work with CXF 2.2.7+
> 
> Thanks, Sergey
> 
> 

I just verified that wildcards are working in version 2.2.7  

The project I am working on is using 2.2.6.   

To summarize, here is what I needed to do in order to successfully use
generated classes from an XSD  as parameters in REST service methods : 

1.  The Element should be defined something like : 

<xs:element name="fooType">
    <xs:complextType>
            .
            .
    </xs:complextType>
</xs:element> 

as apposed to : 

<xs:complexType name="FooType">
    .
    .
</xs:complexType> 
<xs:element name="foo" type="tns:FooType"/> 


This will result in the @XmlRootElement getting generated, which is needed
for the Class to exist
as a paramter in the REST API method signature. 


2. Add the following to the inTransformElements property for the provider
(Spring example).....

<entry key="*" value="{http://somevalue}*" />  

3.  Make sure I am using version 2.2.7+ of the cxf-bundle. 




--
View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4555121.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: @XMLRootElement for parameters in REST method signatures

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi

>> So, instead of configuring TransformFeature's inTransformElements with
>>
>> "Foo" : "{http://somevalue}Foo"
>>
>> try
>>
>> "*" : "{http://somevalue}*"
>>
>> which reads as "qualify all the incoming elements with
>> http://somevalue namespace"
>>
>>
>
> Ah yes, I should have experimented the fields within the Class as well as
> the Class itself.
>
> I was able to reach success when I specified the actual field names,
> i.e......
>
> "fooId": "{http://somevalue}fooId"
>
>
> I am not able to the the "*" wildcard to work.  I'm continuing to try a few
> different variations to see if I can get that to work.
>
> FYI, I am not on version 2.4.0 yet, so I am not using the Transform feature.
> I am still using inTransformElements on the provider.  Not sure if that
> makes a difference for being able to use wildcards or not.

Wildcards should be supported starting from CXF 2.2.7, even when
configuring providers directly, instead of
applying a feature, so please report a bug if you work with CXF 2.2.7+

Thanks, Sergey

>
> Thanks again for your help.  I now have a much better understanding of
> what's going on.
>
>
>
>
>
> --
> View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4554208.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>



-- 
Sergey Beryozkin

http://sberyozkin.blogspot.com
Talend - http://www.talend.com

Re: @XMLRootElement for parameters in REST method signatures

Posted by dponos <dp...@cisco.com>.
Sergey Beryozkin-5 wrote:
> 
> 
> I suspect it's because Foo schema is actually setting an
> elementFormQualified attribute to true.
> So, even though we bypassed an initial JAXB error, the actual Foo
> children in the incoming sequence are still expected to be qualified
> but this time JAXB just ignores them.
> So, instead of configuring TransformFeature's inTransformElements with
> 
> "Foo" : "{http://somevalue}Foo"
> 
> try
> 
> "*" : "{http://somevalue}*"
> 
> which reads as "qualify all the incoming elements with
> http://somevalue namespace"
> 
> 

Ah yes, I should have experimented the fields within the Class as well as
the Class itself. 

I was able to reach success when I specified the actual field names,
i.e...... 

"fooId": "{http://somevalue}fooId"


I am not able to the the "*" wildcard to work.  I'm continuing to try a few
different variations to see if I can get that to work. 

FYI, I am not on version 2.4.0 yet, so I am not using the Transform feature. 
I am still using inTransformElements on the provider.  Not sure if that
makes a difference for being able to use wildcards or not. 

Thanks again for your help.  I now have a much better understanding of
what's going on. 





--
View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4554208.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: @XMLRootElement for parameters in REST method signatures

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi

On Fri, Jul 1, 2011 at 7:49 PM, dponos <dp...@cisco.com> wrote:
>
> Sergey Beryozkin-5 wrote:
>>
>> Forgot to mention that in earlier CXF versions one can get the same
>> transformation done by explicitly configuring JSON or JAXB providers:
>>
>> http://cxf.apache.org/docs/jax-rs-data-bindings.html#JAX-RSDataBindings-CustomizingJAXBXMLandJSONinputandoutput
>>
>>
>
> Thanks for your replies Sergey.  All the information you posted helps me a
> lot.
>
> I'm not using version 2.4 yet, but I was able to successfully get past the
> error by configuring my JSONProvider with the transformation.
>
> I can't declare total victory yet because the fields for the object are not
> getting populated and I wind up with an empty Foo object in my REST service
> method.
>

I suspect it's because Foo schema is actually setting an
elementFormQualified attribute to true.
So, even though we bypassed an initial JAXB error, the actual Foo
children in the incoming sequence are still expected to be qualified
but this time JAXB just ignores them.
So, instead of configuring TransformFeature's inTransformElements with

"Foo" : "{http://somevalue}Foo"

try

"*" : "{http://somevalue}*"

which reads as "qualify all the incoming elements with
http://somevalue namespace"

HTH,
Sergey


> I've been stepping through code to find out why the fields of Foo aren't
> getting set.  I noticed that in the UnmarshallingContext, there is an
> "expectText()" method that is returning false.  It is returning false
> because the loader is an instance of Discarder.
>
> When I step through the same code for a non-generated class that I don't
> have to transform the incoming namespace for, the loader is an instance of
> LeafPropertyLoader.
>
> So I am currently trying to find out how the loader gets assigned.  If I can
> get passed this issue, I think my problem will be completely solved.
>
>
>
>
> --
> View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4542987.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>



-- 
Sergey Beryozkin

Application Integration Division of Talend
http://sberyozkin.blogspot.com

Re: @XMLRootElement for parameters in REST method signatures

Posted by dponos <dp...@cisco.com>.
Sergey Beryozkin-5 wrote:
> 
> Forgot to mention that in earlier CXF versions one can get the same
> transformation done by explicitly configuring JSON or JAXB providers:
> 
> http://cxf.apache.org/docs/jax-rs-data-bindings.html#JAX-RSDataBindings-CustomizingJAXBXMLandJSONinputandoutput
> 
> 

Thanks for your replies Sergey.  All the information you posted helps me a
lot. 

I'm not using version 2.4 yet, but I was able to successfully get past the
error by configuring my JSONProvider with the transformation. 

I can't declare total victory yet because the fields for the object are not
getting populated and I wind up with an empty Foo object in my REST service
method. 

I've been stepping through code to find out why the fields of Foo aren't
getting set.  I noticed that in the UnmarshallingContext, there is an
"expectText()" method that is returning false.  It is returning false
because the loader is an instance of Discarder.   

When I step through the same code for a non-generated class that I don't
have to transform the incoming namespace for, the loader is an instance of
LeafPropertyLoader. 

So I am currently trying to find out how the loader gets assigned.  If I can
get passed this issue, I think my problem will be completely solved. 




--
View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4542987.html
Sent from the cxf-user mailing list archive at Nabble.com.

Re: @XMLRootElement for parameters in REST method signatures

Posted by Sergey Beryozkin <sb...@gmail.com>.
Forgot to mention that in earlier CXF versions one can get the same
transformation done by explicitly configuring JSON or JAXB providers:

http://cxf.apache.org/docs/jax-rs-data-bindings.html#JAX-RSDataBindings-CustomizingJAXBXMLandJSONinputandoutput

Sergey

On Fri, Jul 1, 2011 at 10:51 AM, Sergey Beryozkin <sb...@gmail.com> wrote:
> Hi,
>
> On Thu, Jun 30, 2011 at 11:35 PM, dponos <dp...@cisco.com> wrote:
>> Thank you Stephen,  your information definitely helps.  I am able to work
>> around the issue this way.
>>
> Starting with CXF 2.4.0 one can solve this issue by configuring
> TransformFeature [1] on the server side (and/or client side if
> needed), example, when using Spring:
>



> <bean id="transformFeature" class="org.apache.cxf.feature.StaxTransfromFeature">
>  <property name="inTransformElements">
>    <map>
>      <entry key="Foo" value="{http://acme.com/model}Foo"/>
>     </map>
>  </property>
> </bean>
>
> and then link to it:
> <jaxrs:server>
>    <jaxrs:features>
>       <ref bean="transformFeature"/>
>    </jaxrs:features>
> </jaxrs:server>
>
> This feature instance will qualify a chosen element in the coming XML
> stream coming from default JSONProvider, before this specific element
> is consumed by JAXB
>
> Hope it helps
> Sergey
>
>
> [1] http://cxf.apache.org/docs/transformationfeature.html#TransformationFeature-JAXRS
>
>
>>
>>
>> --
>> View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4540370.html
>> Sent from the cxf-user mailing list archive at Nabble.com.
>>
>
>
>
> --
> Sergey Beryozkin
>
> Application Integration Division of Talend
> http://sberyozkin.blogspot.com
>

Re: @XMLRootElement for parameters in REST method signatures

Posted by Sergey Beryozkin <sb...@gmail.com>.
Hi,

On Thu, Jun 30, 2011 at 11:35 PM, dponos <dp...@cisco.com> wrote:
> Thank you Stephen,  your information definitely helps.  I am able to work
> around the issue this way.
>
> Over the last day, I experimented more with the the classes that I was able
> to generate the @XmlRootElement annotation for, but still had issues when
> using them as parameters in my REST service method signatures.
>
>
> I looked closer into the error message I was getting, messages like this:
>
> JAXBException occurred : unexpected element (uri:"", local:"Foo"). Expected
> elements are <{http://acme.com/model}Foo>,.....
>
>
>
> I noticed that the unexpected element has a namespace of "local" and the
> expected element is there, but has a namespace value that came from the XSD.
>
> I performed an experiment by copying "Foo" to a different package with no
> other changes other than changes the name to something like Foo2, and the
> problem went away.
>

I guess this is because JAXB understands from the generated
ObjectFactory that Foo is actually namespace qualified and enforces
it. Renaming it to Foo2 class in a diff package works because Foo2 has
no @XMLRootElement and unmarshalling XMLType-annotated classes with
JAXBElement  probably does not need to know the root element name.

By the way I reckon the reason you got the error earlier on even after
forcing the JAXB generator to add @XMLRootElement was caused by the
unqualified content coming from the client, as you explained below...

>
> So this is leading me to believe that my issue is really some sort of
> namespace issue.   My client will be a javascript client.  I am currently
> testing with Firefox Poster, with the json object in the request body.  The
> json object looks like this :
>
> {
>    "Foo":
>        {
>            "name":"bar"
>        }
> }
>
>
> There is nothing in the client that is specifying a namespace.  I've been
> told that the client does not specify a namespace for the object.
>
> So I am wondering if there is some sort of filter/interceptor I need to
> write or configure in order to match "Foo" with "{http://acme.com/model}Foo"
>

It does look like that the original problem you reported is caused by
the fact the client is submitting an unqualified response.
Starting with CXF 2.4.0 one can solve this issue by configuring
TransformFeature [1] on the server side (and/or client side if
needed), example, when using Spring:

<bean id="transformFeature" class="org.apache.cxf.feature.StaxTransfromFeature">
  <property name="inTransformElements">
    <map>
      <entry key="Foo" value="{http://acme.com/model}Foo"/>
     </map>
  </property>
</bean>

and then link to it:
<jaxrs:server>
    <jaxrs:features>
       <ref bean="transformFeature"/>
    </jaxrs:features>
</jaxrs:server>

This feature instance will qualify a chosen element in the coming XML
stream coming from default JSONProvider, before this specific element
is consumed by JAXB

Hope it helps
Sergey


[1] http://cxf.apache.org/docs/transformationfeature.html#TransformationFeature-JAXRS


>
>
> --
> View this message in context: http://cxf.547215.n5.nabble.com/XMLRootElement-for-parameters-in-REST-method-signatures-tp4537057p4540370.html
> Sent from the cxf-user mailing list archive at Nabble.com.
>



-- 
Sergey Beryozkin

Application Integration Division of Talend
http://sberyozkin.blogspot.com