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). 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


Reply via email to