Hi
On Sun, Apr 3, 2011 at 10:00 AM, [email protected] <[email protected]>wrote:
> Hi Sergey, you suggested me the solution to use ParameterHandler, this
> would work I think, however I want to reuse my existing XMLAdapters, I have
> hundreds of them in my project, and dont want to create hundreds of new
> ParameterHandlers (actually I not counted them, they get generated).
Reusing existing XmlAdapters makes sense to me, so I updated the trunk/2.3.x
for adapters be checked when processing all types of JAX-RS parameters
Give it a try please with the latest code
thanks, Sergey
> So a fix for the problem which works in my test cases is the following:
>
>
> if
> (!InjectionUtils.isSupportedCollectionOrArray(parameterClass) &&
> parameterClass == parameterType) {
> parameterClass =
> getActualType(parameterClass, parameterType, parameterAnns);
> if (parameterType != parameterClass) {
> // case a XmlAdapter is available
> parameterType = parameterClass;
> Object response =
> createHttpParameterValue(parameter, parameterClass, parameterType, message,
> values, ori);
> response = checkAdapter(response,
> parameterClass, parameterAnns, false);
> return response;
> }
> }
>
> This must be inserted in class JAXRSUtils here:
>
> private static Object processParameter(Class<?> parameterClass,
> Type parameterType,
> Annotation[] parameterAnns,
> Parameter parameter,
> MultivaluedMap<String, String>
> values,
> Message message,
> OperationResourceInfo ori) {
>
> .... else {
>
> //HERE
>
> return createHttpParameterValue(parameter,
> parameterClass,
> parameterType,
> message,
> values,
> ori);
>
> }
> }
>
> Also I copied the three methods checkAdapter/getActualType/getAdapter from
> AbstractJAXBProvider into JAXRSUtils without any change except for making
> them static since they are now called from a static method, so they should
> be better kept in a general utility class.
>
> So actually what the code does, it just marshalling the parameter type
> before calling createHttpParameterValue and finally unmarshalling the result
> of createHttpParameterValue, accordingly to the XmlJavaTypeAdatper found in
> the annotations of the parameter. It works the same way e.g.
> JAXBElementProvider converts the type before / result after reading the
> message body, however I am only interested in the case that we are not
> dealing with a collection or a special generic type, for which I dont see a
> usecase currently.
>
> With this fix, I also want to handle the problem of transmitting e.g. an
> Integer over the network using SOAP or JSON, by defining the Integer to be
> the BoundType and a IntegerWrapper class to be the ValueType and a
> corresponding XmlAdapter converting between those, and by just using the
> annotation @XmlJavaTypeAdatper(IntegerAdapter.class) with a Integer-typed
> parameter. Thus I can easily transmit a Integer over the network - or with
> our previous fix a List of Integer. Of course IntegerWrapper would be a
> custom bean class of mine, but maybe CXF could include such classes and
> corresponding adapters for all primitive types and String.
>
>
>
> Imagine following annotated parameter:
>>>
>>> void methodA(@PathParam("id") @XmlJavaTypeAdapter(XoverY.class) X x) {
>>> doSomethingWith(x);
>>> }
>>>
>>>
>>> The expected semantics is that class Y is instantiated by e.g.
>>> Y.valueOf(id), then the XmlJavaTypeAdapter converts it to an instance of
>>> X.
>>> However the current implementation looks for a valueOf() method in class
>>> X
>>> and not class Y, it just not takes the XmlJavaTypeAdapter annotation into
>>> account. So I actually end up with a not very elegant workaround:
>>>
>>>
>>> void methodA(@PathParam("id") Y y) {
>>> X x = new XoverY().unmarshal(y);
>>> doSomethingWith(x);
>>> }
>>>
>>> I require this glue code in most of my REST methods, so the code looks
>>> not
>>> so nice as it could look, but nevertheless I consider it as a bug.
>>>
>>>
>> I consider it to be a restriction :-).
>>
>> Currently you have two options with converting path vars into beans:
>> 1.
>> void methodA(@PathParam("") Xover x) {
>> }
>>
>> all the captured Path variables will be injected into Xover, example, if
>> we
>> have a path variable 'id' then a Xover.setId method will be invoked.
>>
>> 2. Register a ParameterHandler (as a jaxrs:provider), ex,
>> XoverParameterHandler<Xover>
>>
>> Hope it helps
>>
>> Cheers, Sergey
>>
>>
>
--
Sergey Beryozkin
Application Integration Division of Talend <http://www.talend.com>
http://sberyozkin.blogspot.com