Page 1 of 1

REST api POST data not unmarsalled

Posted: Thu Oct 25, 2012 6:42 am
by bjliu
I'm using BroadleafCommerce 2.1 and trying to modify REST api to support more functionality.

Out of the box and my own implementation of GET request with query parameter works great. But when I try to POST xml or json in the request body, the data posted not unmarshalled to object according to definition in the wrapper class and the parameter in the endpoint method is null.

I debugged the code and found the problem probably lies in BroadleafMessageBodyReaderWriter. In the method readFrom, the value from to call genericType = getApiWrapper(type, lookupType) is java.lang.Class, as such in the later xmlRootElementProvider.readFrom unmarshall method call, xml is not unmarshalled.

I'm not sure if there are errors in my request. I googled some and find using JAXBElement<type> as request parameter in endpoint method can get xml unmarshalled to object but this is not working with json.

Can somebody help me with this? Thanks.

Re: REST api POST data not unmarsalled

Posted: Mon Nov 19, 2012 11:47 am
by ktisdell
What are you trying to POST? Catalog data, order data, customer data, etc? There are a number of APIs that are currently read only, such as catalog. Also, we found that trying to POST extended objects using JSON doesn't work out of the box. The reason is that JSON does not specify which object to deserialize to. So the framework depends on the method signature to determine which class to instantiate. Please let me know exactly what you are trying to do and I'll try to answer your question more directly. My guess is that the best thing for you to do is write your own endpoint to post an extended object. Your endpoint will look something like this:

@POST
@Path("mypath/")
public void someMethod(@Context HttpServletRequest request, MyExtendedWrapper myWrapper) {
...
}

One point to make is that we need to remove the JAX-RS annotations from the framework. We need to leave it up to you to specify the paths, and delegate to a super class for most of these operations. This will make these issues easier to deal with.

Re: REST api POST data not unmarsalled

Posted: Tue Mar 19, 2013 5:36 pm
by TNuzzi
Was there any resolution to this, I am having the same issue. I have created a Custom Endpoint with Custom Wrappers. The @GET works just fine (for both single and array of wrappers). However, when I am trying to use the @POST and create a wrapper that deserialize the passed in JSON. It always seems to be null and the same issue bjliu brought up is happening.

My question is how do I have the JSON deserialized and placed in the wrapper?

Thanks,

Tony

Re: REST api POST data not unmarsalled

Posted: Wed Mar 20, 2013 10:56 am
by TNuzzi
All,
After much pain and debugging I was able to get it working. In my situation, I will only be use JSON (no need for XML parse). I ended up modifying BroadleadMessageBodyReaderWriter.getApiWrapper.

Can someone from broadleaf let me know if there is an issue with doing this?

I ended up making the following change:

Code: Select all

        @SuppressWarnings("rawtypes")
    protected Type getApiWrapper(Class<?> type, Type lookupType) {
        initializeTypeMap();
        if (lookupType instanceof Class) {
            Class<?> clz = typeMap.get(((Class)lookupType).getName());
            if (clz == null) {
                return null;
            }
            if (Collection.class.isAssignableFrom(type)) {
                Type[] paramType = { clz };
                return new ParameterizedTypeImpl(paramType, type, null);
            } else if (type.isArray()) {
                return Array
                        .newInstance(clz, 0)
                        .getClass();
            } else {
                // Return the lookup type if not a collection or array
                // return clz.getClass();
               return lookupType;
            }
        }
       
        return null;
    }


Re: REST api POST data not unmarsalled

Posted: Wed Mar 20, 2013 12:08 pm
by phillipuniverse
Awesome, thanks for posting a possible solution. We will try to look over this by end of week and make the appropriate framework change if it's reasonable. Which version of Broadleaf are you on?

Re: REST api POST data not unmarsalled

Posted: Wed Mar 20, 2013 12:44 pm
by TNuzzi
I made the change in the 2.2.0-GA source.

Thanks,

Tony

Re: REST api POST data not unmarsalled

Posted: Mon Mar 25, 2013 4:22 pm
by ktisdell
I think that looks ok. We are likely going to remove or refactor that class for several reasons. It was created to allow for automatic discovery of wrapper types. However, like providing a UI, it's often advantageous to allow the implementor full control. The way to do this will likely be similar to our strategy for providing Spring MVC Controllers. The API will be provided by an abstract endpoint class, but it will be up to the implementor to extend the endpoint to provide request mappings (i.e. @Path annotations). This will allow the implementor to explicitly control what is being marshalled / unmarshalled for each path. What we've attempted to do is provide all of this out of the box. But the more pragmatic approach will be to provide the abstract base class with methods, and allow you to extend the base class and provide your own types that will be produced and consumed, and map these to your own paths.

Re: REST api POST data not unmarsalled

Posted: Wed Apr 03, 2013 2:56 am
by swyd
Hi guys, on this subject, since i had the same issue, and solved the same way some time back. I wanted to post my experience, i had another issue with this, Jersey Servlet was scanning all packages on classpath(does this by default), and even when i created an extending class to override the above mentioned one, created a bean to reference, it was still using the original one, so since i wasn't scanning it through spring, i guessed it was Jersey, the way i solved it was i limited the packages that Jersey scan's by configuring the sevlet

<servlet>
<servlet-name>JerseyServlet</servlet-name>
<servlet-class>
com.sun.jersey.spi.spring.container.servlet.SpringServlet
</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>package.name;org.codehaus.jackson.jaxrs;...</param-value>
</init-param>
</servlet>

just list the packages that need to be scanned for jax-rs annotations, and on another note, Jackson (org.codehaus.jackson.jaxrs) is a much better behaved JSON provider, same behaviour on XML, and this is how you tell Jersey to use it. One of the examples is that it doesn't return null but a valid JSON response { }, and forms JSON lists much better.

Re: REST api POST data not unmarsalled

Posted: Wed Apr 03, 2013 2:55 pm
by TNuzzi
@swyd Thanks for let me know about this. I was wondering why the default broadleaf classes were being loaded and did not realize it was Jersey was loading them rather than Spring.