2

I have an api which is working fine when it comes to XML post request. the XML is recieved in the Post body and processed accordingly. Here is the header of method

@POST
@Path ("{"+num+"}/"+STATUS+"."+XML)
@Consumes (MediaType.APPLICATION_XML)
@Produces (MediaType.APPLICATION_XML)
public Response getStatusXML (@PathParam(num) String num,
        JAXBElement<OrderStatusRequestType> jaxbOrderStatusRequestType,
        @Context UriInfo requestUriInfo,
        @Context SecurityContext securityContext){

    OrderStatusRequestType orderStatusRequestType = jaxbOrderStatusRequestType.getValue();

    return processRequest (num, XML, orderStatusRequestType, securityContext);
}

This WS is called with this POST body

<orderStatusRequest>
    <vendor>32658</vendor>
    <key>232X1</key>
</orderStatusRequest>

I have XML schema for that and this request is working fine as per requirement. I get the jaxbObject and i get the orderStatusRequest as well. However, When i try to call my json webservice, I get null orderStatusRequest. I have a separate method to consume json.

@POST
@Path ("{"+num+"}/"+STATUS+"."+JSON)
@Consumes (MediaType.APPLICATION_JSON)
@Produces (MediaType.APPLICATION_JSON)
public Response getStatusJSON(@PathParam(num) String num,
        JAXBElement<OrderStatusRequestType> jaxbOrderStatusRequestType,
        @Context UriInfo requestUriInfo,
        @Context SecurityContext securityContext){
    OrderStatusRequestType orderStatusRequestType= jaxbOrderStatusRequestType.getValue();

    return processRequest (num, JSON, orderStatusRequestType, securityContext);
}

I am sending following json in post request

{"orderStatusRequest":{"vendor":"32658","key":"232X1"}}

I get null object in my jaxbElement .. I am unable to understand why. For convenience, here is my XML Schema

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified" attributeFormDefault="unqualified">

    <xs:complexType name="orderStatusRequestType">
        <xs:sequence>
            <xs:element name="vendor" type="xs:string" minOccurs="1" maxOccurs="1"/>
            <xs:element name="key" type="xs:string" minOccurs="1" maxOccurs="1"/>
        </xs:sequence>
    </xs:complexType>

            <xs:element name="orderStatusRequest" type="orderStatusRequestType"/>


</xs:schema>

I wrote a client and send the JSON request

    ClientResponse clientResponse = service.path("api")
    .path("v1")
    .path("personal")
    .path("orders")
    .path(num)
    .path("status.json").accept(MediaType.APPLICATION_JSON).post(ClientResponse.class, jaxbOst);

And it gave me error status 415 i.e content type isn't supported. However, with only 2 modification i.e. status.xml and MediaType.APPLICATION_XML works fine.


Update 2: With Fiddler, I am able to hit the webservice with JSON. But Jersey isn't marchling the input POST body into specific objects. I am getting null in vendor and key fields.


UPDATED 3 I am able to consume the JSON from Fiddler. The JSON is {"vendor":"32658","key":"232X1"}. I was wrapping it under another object earlier. BUT I am still unable to send a request using Jersey Client. What i am guessing is that my JAXB Object is giving XML when i try to post. How can i make sure that when I use objectFactory.createOderRequestStatus, it will be translated into JSON and not XML ?

Em Ae
  • 8,167
  • 27
  • 95
  • 162
  • I've no idea why 415 has to be thrown, but did you try capitalizing the first letter 'o' of `orderStatusRequest` in the request body/payload? – asgs Sep 19 '12 at 01:12
  • yes. though it has nothing to do with with since the schema for xml has small 'o'. I guess i am missing some basic thing in this test case. Probably i am too tired to figure it out. – Em Ae Sep 19 '12 at 01:41

1 Answers1

1

The 415 indicates that your client is not sending the correct content type in the request. If you look at your path, for both the XML and the JSON methods, they are identical so you'll need to ensure your client sends the correct content path in order to distinguish which method will service your request. Otherwise Jersey will just pick the first one, which is what is happening here.

There is discussion on this topic in another thread. I haven't tried it myself however can you add some headers to your client to see if that works? Perhaps something like the following:

ClientResponse clientResponse = service.path("api")
                                .path("v1")
                                .path("personal")
                                .path("orders")
                                .path(num)
                                .path("status.json")
                                .accept(MediaType.APPLICATION_JSON)
                                .header("content-type", MediaType.APPLICATION_JSON)
                                .post(ClientResponse.class, jaxbOst);
Community
  • 1
  • 1
ramsinb
  • 1,985
  • 12
  • 17
  • If this is the case, the OP can specify both the formats in the `@consumes`, `@produces` annotations as below: `@Consumes("application/xml", "application/json") @Produces("application/xml", "application/json")` – asgs Sep 19 '12 at 02:17
  • 1
    I was discussing with a colleague on exactly that and we believe that is the better way as well. Given the URI is suppose to identify a resource in REST it is more appropriate to combine the methods instead of separating them with the URI. – ramsinb Sep 19 '12 at 02:43
  • Please look at my original post. I have mentioned it already that i have 2 different methods. the one which consumes XML is getStatusXML and the other which consumes JSON is getStatusJSON. Both of these methods are annotated with appropriate `consume` and `produce` annotation. – Em Ae Sep 19 '12 at 16:35
  • @Em Ae if fiddler works and your jersey client doesn't then that further proves my point your jersey client is not telling your jersey endpoint what continent type your request actually is. It has nothing to do with the actual continent being XML or JSOn (of course you'll need to fix that too if it's really an issue). So again check the content-type of your client! Further the better approach would be not consume/produce both XML/JSOn types in the same method so that URL REST URI does not need to be content type aware... – ramsinb Sep 19 '12 at 20:33
  • I believe the problem is in JAXB Object which i am passing in `post` method. The `accept` method of `service` is being used to specify the content-type but i believe that the object is being marshed to XML and thats why I get 415 error since my method is expecting JSON in response body and not XML. But to further investigate, how can i check what content type is being set by Jersey Client ? – Em Ae Sep 19 '12 at 21:19
  • You can use jersey's logging filter available [here](http://jersey.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/client/filter/LoggingFilter.html) you just need to your client through `addFilter` an instance of the logging filter. There has to be plenty of examples showing how this works. [Here](http://stackoverflow.com/questions/6860661/jersey-print-the-actual-request) is one I found doing a quick search. – ramsinb Sep 19 '12 at 22:04