On 11/08/2011 12:36 PM, Jakub Podlesak wrote:
> Hi Farrukh,
>
> I meant to keep the client intact, and update the server to only take
> the RemoveObjectsRequest entity:
> public Response putRequest(RemoveObjectsRequest req)
> the above should work fine.
The problem is that I really need to accept all types of
RegistryRequestType sub-types in that resource method.
>
> What might help you to fix the original issue would be to provide a
> JAXBContext resolver
> to return a JAXBContext aware of all the JAXB beans involved in your
> RegistryRequestType hierarchy, i.e something like follows:
I have a JAXBContextResolver that does something similar:
@Provider
public final class JAXBContextResolver implements
ContextResolver<JAXBContext> {
private final JAXBContext context;
private static final Log LOG =
LogFactory.getLog(JAXBContextResolver.class);
public JAXBContextResolver() throws Exception {
LOG.debug("org.freebxml.omar.server.interfaces.rest.JAXBContextResolver
constructor");
this.context = new JSONJAXBContext(
JSONConfiguration.natural().build(),
BindingUtility.jaxbContextPath);
}
public JAXBContext getContext(Class<?> objectType) {
String pkgName = objectType.getPackage().getName();
String[] pkgs = BindingUtility.jaxbContextPath.split(":");
//Get the set of fully-qualified package names for my JAXB context classes
List pkgs2 = Arrays.asList(pkgs);
boolean found = pkgs2.contains(pkgName);
LOG.debug("objectType: " + objectType + " found: " + found);
return found ? context : null;
}
}
Any other suggestions beside a paired down reproducable test case come
to mind?
Again thanks so very much for your help and being mindful of your
valuable time I want to restate that this issue is not a high priority
as there is a workaround.
>
> @Provider
> public class JAXBContextResolver implements
> ContextResolver<JAXBContext> {
> private JAXBContext context;
> private final Class[] cTypes = {RegistryRequestType.class,
> RemoveObjectsRequest.class /* all other classes extending the
> RegistryRequestType class */ };
> private final Set<Class> types;
> public JAXBContextResolver() {
> try {
> this.types = new HashSet<Class>(Arrays.asList(cTypes));
> this.context = JAXBContext.newInstance(cTypes);
> } catch (JAXBException ex) {
> throw new RuntimeException(ex);
> }
> }
>
> @Override
> public JAXBContext getContext(Class<?> c) {
> return types.contains(c) ? context : null;
> }
> }
>
> Does it help?
>
> ~Jakub
>
>
> On 8.11.2011 15:38, Farrukh Najmi wrote:
>>
>> Hi Jakub,
>>
>> I did not understand what you want me to try. The request entity
>> needs to be a RemoveObjectsRequest element. In my JAXB generated
>> bindings there are the following classes:
>>
>> public class RegistryRequestType {
>> ...
>> }
>>
>> public class RemoveObjectsRequest extends RegistryRequestType {
>> ...
>> }
>>
>> In my resource method I expect RegistryRequestType param to have the
>> specific sub-type of RegistryRequestType (e.g. RemoveObjectsRequest)
>> based on the element that was in teh request entity.
>>
>> With that summary what were you suggesting I try? Also, why is my
>> assumption on expected behavior incorrect? It seems to make sense
>> that jersey server should be able to unmarshall a
>> RemoveObjectsRequest type and pass it as a RegistryRequestType to my
>> resource method.
>>
>> Thank you for your kind help.
>>
>> On 11/08/2011 08:31 AM, Jakub Podlesak wrote:
>>> Possibly. Do you have any chance to try out with the same type,
>>> ideally just RemoveObjectsRequest?
>>>
>>> ~Jakub
>>>
>>> On 8.11.2011 13:27, Farrukh Najmi wrote:
>>>> Hi Jakub,
>>>>
>>>> At the beginin of this thread I mentioned that RemoveObjectsRequest
>>>> extends RegistryRequestType. Therefor I assumed that it was OK to
>>>> pass a RemoveObjectsRequest where the resource method is expecting
>>>> a RegistryRequestType. Am I wrong in this assumption?
>>>>
>>>> On 11/08/2011 03:44 AM, Jakub Podlesak wrote:
>>>>> Hi Farrukh,
>>>>>
>>>>> please see in lines...
>>>>>
>>>>> On 7.11.2011 21:09, Farrukh Najmi wrote:
>>>>>>
>>>>>> Hi Jakub,
>>>>>>
>>>>>> There does not seem to be any difference whether I do either of
>>>>>> the following on client side:
>>>>>>
>>>>>> RemoveObjectsRequest removeRequest = ...;
>>>>>
>>>>> The above removeRequest is of the *RemoveObjectsRequest* type
>>>>>
>>>>>> ClientResponse resp =
>>>>>> webResource.accept(MediaType.APPLICATION_XML).
>>>>>> type(MediaType.APPLICATION_XML).
>>>>>> entity(removeRequest).
>>>>>
>>>>> and is passed here to the client
>>>>>
>>>>>> put(ClientResponse.class);
>>>>>>
>>>>>> Or.
>>>>>>
>>>>>> ClientResponse resp =
>>>>>> webResource.accept(MediaType.APPLICATION_XML).
>>>>>> type(MediaType.APPLICATION_XML).
>>>>>> entity(BindingUtility.marshalObject(removeRequest)).
>>>>>> //marshalls RemoveObjectsRequest object to a String
>>>>>> put(ClientResponse.class);
>>>>>>
>>>>>> In both cases if the resource method signature is:
>>>>>>
>>>>>> public Response putRequest(RegistryRequestType req)
>>>>>
>>>>> while above you are consuming *RegistryRequestType*, you mention
>>>>> this also in the following line.
>>>>> My suggestion was to try sending and consuming the very same type.
>>>>>
>>>>> ~Jakub
>>>>>
>>>>>>
>>>>>> then I get a RegistryRequestType instance rather than a
>>>>>> RemoveObjectsRequest instance.
>>>>>>
>>>>>> The workaround I did on the server side to change the method
>>>>>> signature to:
>>>>>>
>>>>>> public Response putRequest(String entityStr);
>>>>>>
>>>>>> and then unmarshalling from string manually works in both cases.
>>>>>>
>>>>>> This is not high priority but I am curious why this does not work
>>>>>> as expected. Making a reproducable test case is not trivial but I
>>>>>> would be glad to help debug this further if you think it could be
>>>>>> an issue that needs filiing and eventual fixing.
>>>>>>
>>>>>> Thanks very much for your help.
>>>>>>
>>>>>> On 11/07/2011 11:41 AM, Jakub Podlesak wrote:
>>>>>>> Hi Farrukh,
>>>>>>>
>>>>>>> The problem was that on the client side you referred to your own
>>>>>>> BindingUtility to serialize
>>>>>>> the XML for you, while on the server side you expected Jersey to
>>>>>>> automatically
>>>>>>> pick up whatever the BindingUtility produced.
>>>>>>>
>>>>>>> What happens if you directly passed a RegistryRequestType to the
>>>>>>> web resource entity method on the client side?
>>>>>>> I presume that should work all right for you...
>>>>>>>
>>>>>>> ~Jakub
>>>>>>>
>>>>>>>
>>>>>>> On 7.11.2011 16:15, Farrukh Najmi wrote:
>>>>>>>> On 11/07/2011 09:18 AM, Farrukh Najmi wrote:
>>>>>>>>> Hi Guys,
>>>>>>>>>
>>>>>>>>> I have an XML Schema as follows:
>>>>>>>>>
>>>>>>>>> <complexType name="RegistryRequestType">
>>>>>>>>> ...
>>>>>>>>> </complexType>
>>>>>>>>>
>>>>>>>>> <element name="RemoveObjectsRequest">
>>>>>>>>> <complexType>
>>>>>>>>> <complexContent>
>>>>>>>>> <extension base="rs:RegistryRequestType">
>>>>>>>>> ....
>>>>>>>>> </extension>
>>>>>>>>> </complexContent>
>>>>>>>>> </complexType>
>>>>>>>>>
>>>>>>>>> I use JAXB to generate bindings for above schema as follows:
>>>>>>>>>
>>>>>>>>> public class RegistryRequestType {
>>>>>>>>> ...
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> public class RemoveObjectsRequest extends RegistryRequestType {
>>>>>>>>> ...
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> I have a jersey server resource method as follows:
>>>>>>>>>
>>>>>>>>> @PUT
>>>>>>>>> @Consumes({"application/xml"})
>>>>>>>>> @Produces({"application/xml"})
>>>>>>>>> @Path("/requests")
>>>>>>>>> public Response putRequest(RegistryRequestType req) {
>>>>>>>>> }
>>>>>>>>>
>>>>>>>>> I issue a client PUT request where entity is a
>>>>>>>>> RemoveObjectsRequest element using following code:
>>>>>>>>>
>>>>>>>>> RemoveObjectsRequest removeRequest = ...
>>>>>>>>> ClientResponse resp =
>>>>>>>>> webResource.accept(MediaType.APPLICATION_XML).
>>>>>>>>> type(MediaType.APPLICATION_XML).
>>>>>>>>>
>>>>>>>>> entity(BindingUtility.marshalObject(removeRequest)).
>>>>>>>>> //marshalls RemoveObjectsRequest object to String
>>>>>>>>> put(ClientResponse.class);
>>>>>>>>>
>>>>>>>>> When my putRequest() resource method is called, I expect the
>>>>>>>>> req param to be set to an object of type RemoveObjectsRequest.
>>>>>>>>> Instead it is set to a an object where the type is
>>>>>>>>> RegistryRequestType and data members of the
>>>>>>>>> RemoveObjectsRequest are not set.
>>>>>>>>>
>>>>>>>>> Is this a issue in jersey (note I am using 1.10) or do I have
>>>>>>>>> faulty assumption on what to expect?
>>>>>>>>>
>>>>>>>>> If the expected behavior is not possible then what is the way
>>>>>>>>> to get the raw entity from the request within my resource
>>>>>>>>> method so I can unmarshall it as needed.
>>>>>>>>>
>>>>>>>>> Thank you for your help.
>>>>>>>>>
>>>>>>>>
>>>>>>>> I was able to workaround the issue by specifying a String param
>>>>>>>> in my resource method for receiving the request entity. I then
>>>>>>>> used my JAXB unmarshaller to unmarshall from a StringReader
>>>>>>>> created with that String.
>>>>>>>>
>>>>>>>> @PUT
>>>>>>>> @Consumes({"application/xml"})
>>>>>>>> @Produces({"application/xml"})
>>>>>>>> @Path("/requests")
>>>>>>>> public Response putRequest(String entityStr) {
>>>>>>>> try {
>>>>>>>> StringReader reader = new StringReader(entityStr);
>>>>>>>> Unmarshaller u = ...;
>>>>>>>> RegistryRequestType req = (RegistryRequestType)
>>>>>>>> u.unmarshal(reader);
>>>>>>>>
>>>>>>>> //The req object is now correctly an instance of
>>>>>>>> RemoveObjectsRequest
>>>>>>>>
>>>>>>>> ...
>>>>>>>> return response;
>>>>>>>> } catch (JAXBException ex) {
>>>>>>>> ...
>>>>>>>> }
>>>>>>>> }
>>>>>>>>
>>>>>>>>
>>>>>>>> I am still curious why the behavior I expected is not what
>>>>>>>> jersey server does.
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>
>>
>>
>
--
Regards,
Farrukh Najmi
Web: http://www.wellfleetsoftware.com