Trying to post a JSON object gives a nullpointer at HTTPBuilder

918 views
Skip to first unread message

Kim

unread,
Sep 4, 2011, 3:55:23 PM9/4/11
to REST assured
When we try following code, analogue to one of the many examples in
the restAssured tests found at
https://github.com/jayway/rest-assured/blob/master/examples/rest-assured-itest-java/src/test/java/com/jayway/restassured/itest/java/JSONPostITest.java,
we get nullpointers using restAssured 1.2.3.

Code used:

given()
.cookie("cookiearg 1", "cookiearg2")
.cookie("cookiearg 3", "cookiearg4")
.body("{ \"message\" : \"hello world\"}")
.with()
.contentType("application/CustomMediaType")
.then()
.expect()
.statusCode(200)
.when()
.post("/acceptHelloWorld");

Gives the following exception:

java.lang.NullPointerException
at groovyx.net.http.HTTPBuilder
$RequestConfigDelegate.setBody(HTTPBuilder.java:1147)
at groovyx.net.http.HTTPBuilder
$RequestConfigDelegate.setPropertiesFromMap(HTTPBuilder.java:1065)
at groovyx.net.http.HTTPBuilder.post(HTTPBuilder.java:340)
at groovyx.net.http.HTTPBuilder$post.call(Unknown Source)
at
com.jayway.restassured.internal.RequestSpecificationImpl.sendRequest(RequestSpecificationImpl.groovy:
525)
at com.jayway.restassured.internal.RequestSpecificationImpl.this
$2$sendRequest(RequestSpecificationImpl.groovy)
at com.jayway.restassured.internal.RequestSpecificationImpl$this
$2$sendRequest.call(Unknown Source)
at
com.jayway.restassured.internal.filter.RootFilter.filter(RootFilter.groovy:
28)
at com.jayway.restassured.filter.Filter$filter.call(Unknown Source)
at
com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.groovy:
45)
at com.jayway.restassured.filter.FilterContext$next.call(Unknown
Source)
at
com.jayway.restassured.internal.RequestSpecificationImpl.invokeFilterChain(RequestSpecificationImpl.groovy:
465)
at com.jayway.restassured.internal.RequestSpecificationImpl
$invokeFilterChain.callCurrent(Unknown Source)
at
com.jayway.restassured.internal.RequestSpecificationImpl.applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy:
681)
at com.jayway.restassured.internal.RequestSpecificationImpl.this
$2$applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy)
at com.jayway.restassured.internal.RequestSpecificationImpl$this
$2$applyPathParamsAndSendRequest.callCurrent(Unknown Source)
at
com.jayway.restassured.internal.RequestSpecificationImpl.post(RequestSpecificationImpl.groovy:
111)
at com.jayway.restassured.specification.RequestSender
$post.call(Unknown Source)
at
com.jayway.restassured.internal.ResponseSpecificationImpl.post(ResponseSpecificationImpl.groovy:
222)
....

Johan Haleby

unread,
Sep 4, 2011, 4:28:12 PM9/4/11
to rest-a...@googlegroups.com
Hi,

I think I know why this happens. If you remove the "content type" I
guess that you won't run into a NPE. The reason for this is that
HTTPBuilder has something called an EncoderRegistry that encodes the
message body based on the content type and if it fails to find an
encoder for the given content-type then (sadly) a NPE is thrown. Today
there's how ever no way of registering a custom encoder from the Rest
Assured API. This is something that needs to be added! And perhaps I can
try to override the default behavior of HTTPBuilder to stop it from
throwing a NPE as soon as it encounters an unknown content type and just
default to suitable one.

I've personally never had the need to add a custom encoder myself until
I implemented support for multi-part form data (which will be included
in the next release) thus it has not been a priority so far. But now
it's probably one of the most crucial things to support.

/Johan

Johan Haleby

unread,
Sep 5, 2011, 2:22:10 AM9/5/11
to rest-a...@googlegroups.com
Ok so I've implemented so that when using a request body with a "custom" content-type the body is URL Encoded by default. I've committed this to trunk. Please try it out if it works by depending on Rest Assured 1.2.4-SNAPSHOT by adding the following repo to maven:

<repositories>
        <repository>
            <id>sonatype</id>
            <snapshots />
        </repository>
</repositories>

/Johan

Kim

unread,
Sep 5, 2011, 3:10:02 AM9/5/11
to REST assured
Hi johan,

Thanks for the quick reply!!

However i added 1.2.4-SNAPSHOT and tried it but still gives errors :

Using the following rest assured options:

RestAssured.registerParser("application/vnd.customcontent-v2.0+json",
Parser.JSON);
RestAssured.responseContentType("application/vnd.customcontent-
v2.0+json");

and the following method :
given()
.cookie("cookiearg 1", "cookiearg2")
.cookie("cookiearg 3", "cookiearg4")
.body("{ \"message\" : \"hello world\"}")
.contentType("application/vnd.customcontent-v2.0+json")
.then()
.expect()
.statusCode(200)
.when()
.put("/rest/contentTypebug/");

we get this :
groovyx.net.http.ResponseParseException: Unsupported Media Type
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:484)
at com.jayway.restassured.internal.RequestSpecificationImpl$1.super
$2$doRequest(RequestSpecificationImpl.groovy)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:
90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058)
at
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:
127)
at com.jayway.restassured.internal.RequestSpecificationImpl
$1.doRequest(RequestSpecificationImpl.groovy:548)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:427)
at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:376)
at groovyx.net.http.HTTPBuilder$request.call(Unknown Source)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:
40)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:
116)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:
132)
at
com.jayway.restassured.internal.RequestSpecificationImpl.sendHttpRequest(RequestSpecificationImpl.groovy:
638)
at com.jayway.restassured.internal.RequestSpecificationImpl.this
$2$sendHttpRequest(RequestSpecificationImpl.groovy)
at com.jayway.restassured.internal.RequestSpecificationImpl$this
$2$sendHttpRequest.callCurrent(Unknown Source)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:
44)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:
141)
at
com.jayway.restassured.internal.RequestSpecificationImpl.sendRequest(RequestSpecificationImpl.groovy:
595)
at com.jayway.restassured.internal.RequestSpecificationImpl.this
$2$sendRequest(RequestSpecificationImpl.groovy)
at com.jayway.restassured.internal.RequestSpecificationImpl$this
$2$sendRequest.call(Unknown Source)
at
com.jayway.restassured.internal.filter.RootFilter.filter(RootFilter.groovy:
28)
at com.jayway.restassured.filter.Filter$filter.call(Unknown Source)
at
com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.groovy:
45)
at com.jayway.restassured.filter.FilterContext$next.call(Unknown
Source)
at
com.jayway.restassured.internal.RequestSpecificationImpl.invokeFilterChain(RequestSpecificationImpl.groovy:
517)
at com.jayway.restassured.internal.RequestSpecificationImpl
$invokeFilterChain.callCurrent(Unknown Source)
at
com.jayway.restassured.internal.RequestSpecificationImpl.applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy:
781)
at com.jayway.restassured.internal.RequestSpecificationImpl.this
$2$applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy)
at com.jayway.restassured.internal.RequestSpecificationImpl$this
$2$applyPathParamsAndSendRequest.callCurrent(Unknown Source)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:
44)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:
141)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:
157)
at
com.jayway.restassured.internal.RequestSpecificationImpl.put(RequestSpecificationImpl.groovy:
121)
at com.jayway.restassured.specification.RequestSender
$put.call(Unknown Source)
at
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:
40)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:
116)
at
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:
128)
at
com.jayway.restassured.internal.ResponseSpecificationImpl.put(ResponseSpecificationImpl.groovy:
226)
...
Caused by: net.sf.json.JSONException: Invalid JSON String
at net.sf.json.JSONSerializer.toJSON(JSONSerializer.java:143)
at net.sf.json.JSONSerializer.toJSON(JSONSerializer.java:103)
at net.sf.json.groovy.JsonSlurper.parseText(JsonSlurper.java:80)
at net.sf.json.groovy.JsonSlurper.parse(JsonSlurper.java:76)
at groovyx.net.http.ParserRegistry.parseJSON(ParserRegistry.java:266)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at
org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:
90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1058)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:923)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:886)
at groovy.lang.Closure.call(Closure.java:282)
at groovy.lang.Closure.call(Closure.java:295)
at groovyx.net.http.HTTPBuilder.parseResponse(HTTPBuilder.java:545)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:478)
... 66 more

note the invalid json exception, but we give a valid JSON object.

Also if we don't add the "RestAssured.responseContentType("application/
vnd.customcontent-v2.0+json");" then we get a 415 from resteasy, so i
think the .contentType("application/vnd.customcontent-v2.0+json")
doesn't do much.

On Sep 5, 8:22 am, Johan Haleby <johan.hal...@gmail.com> wrote:
> Ok so I've implemented so that when using a request body with a "custom"
> content-type the body is URL Encoded by default. I've committed this to
> trunk. Please try it out if it works by depending on Rest Assured
> 1.2.4-SNAPSHOT by adding the following repo to maven:
>
> <repositories>
>         <repository>
>             <id>sonatype</id>
>             <url>https://oss.sonatype.org/content/repositories/snapshots/
> </url>
>             <snapshots />
>         </repository>
> </repositories>
>
> /Johan
>
> On Sun, Sep 4, 2011 at 10:28 PM, Johan Haleby <johan.hal...@gmail.com>wrote:
>
> > Hi,
>
> > I think I know why this happens. If you remove the "content type" I guess
> > that you won't run into a NPE. The reason for this is that HTTPBuilder has
> > something called an EncoderRegistry that encodes the message body based on
> > the content type and if it fails to find an encoder for the given
> > content-type then (sadly) a NPE is thrown. Today there's how ever no way of
> > registering a custom encoder from the Rest Assured API. This is something
> > that needs to be added! And perhaps I can try to override the default
> > behavior of HTTPBuilder to stop it from throwing a NPE as soon as it
> > encounters an unknown content type and just default to suitable one.
>
> > I've personally never had the need to add a custom encoder myself until I
> > implemented support for multi-part form data (which will be included in the
> > next release) thus it has not been a priority so far. But now it's probably
> > one of the most crucial things to support.
>
> > /Johan
>
> > On 09/04/2011 09:55 PM, Kim wrote:
>
> >> When we try following code, analogue to one of the many examples in
> >> the restAssured tests found at
> >>https://github.com/jayway/**rest-assured/blob/master/**
> >> examples/rest-assured-itest-**java/src/test/java/com/jayway/**
> >> restassured/itest/java/**JSONPostITest.java<https://github.com/jayway/rest-assured/blob/master/examples/rest-assu...>
> >> ,
> >> we get nullpointers using restAssured 1.2.3.
>
> >> Code used:
>
> >> given()
> >>                .cookie("cookiearg 1", "cookiearg2")
> >>                .cookie("cookiearg 3", "cookiearg4")
> >>                .body("{ \"message\" : \"hello world\"}")
> >>         .with()
> >>                .contentType("application/**CustomMediaType")
> >>         .then()
> >>         .expect()
> >>                .statusCode(200)
> >>         .when()
> >>                .post("/acceptHelloWorld");
>
> >> Gives the following exception:
>
> >> java.lang.NullPointerException
> >>        at groovyx.net.http.HTTPBuilder
> >> $RequestConfigDelegate.**setBody(HTTPBuilder.java:1147)
> >>        at groovyx.net.http.HTTPBuilder
> >> $RequestConfigDelegate.**setPropertiesFromMap(**HTTPBuilder.java:1065)
> >>        at groovyx.net.http.HTTPBuilder.**post(HTTPBuilder.java:340)
> >>        at groovyx.net.http.HTTPBuilder$**post.call(Unknown Source)
> >>        at
> >> com.jayway.restassured.**internal.**RequestSpecificationImpl.**
> >> sendRequest(**RequestSpecificationImpl.**groovy:
> >> 525)
> >>        at com.jayway.restassured.**internal.**
> >> RequestSpecificationImpl.this
> >> $2$sendRequest(**RequestSpecificationImpl.**groovy)
> >>        at com.jayway.restassured.**internal.**
> >> RequestSpecificationImpl$this
> >> $2$sendRequest.call(Unknown Source)
> >>        at
> >> com.jayway.restassured.**internal.filter.RootFilter.**
> >> filter(RootFilter.groovy:
> >> 28)
> >>        at com.jayway.restassured.filter.**Filter$filter.call(Unknown
> >> Source)
> >>        at
> >> com.jayway.restassured.**internal.filter.**FilterContextImpl.next(**
> >> FilterContextImpl.groovy:
> >> 45)
> >>        at com.jayway.restassured.filter.**FilterContext$next.call(**
> >> Unknown
> >> Source)
> >>        at
> >> com.jayway.restassured.**internal.**RequestSpecificationImpl.**
> >> invokeFilterChain(**RequestSpecificationImpl.**groovy:
> >> 465)
> >>        at com.jayway.restassured.**internal.**RequestSpecificationImpl
> >> $invokeFilterChain.**callCurrent(Unknown Source)
> >>        at
> >> com.jayway.restassured.**internal.**RequestSpecificationImpl.**
> >> applyPathParamsAndSendRequest(**RequestSpecificationImpl.**groovy:
> >> 681)
> >>        at com.jayway.restassured.**internal.**
> >> RequestSpecificationImpl.this
> >> $2$**applyPathParamsAndSendRequest(**RequestSpecificationImpl.**groovy)
> >>        at com.jayway.restassured.**internal.**
> >> RequestSpecificationImpl$this
> >> $2$**applyPathParamsAndSendRequest.**callCurrent(Unknown Source)
> >>        at
> >> com.jayway.restassured.**internal.**RequestSpecificationImpl.post(**
> >> RequestSpecificationImpl.**groovy:
> >> 111)
> >>        at com.jayway.restassured.**specification.RequestSender
> >> $post.call(Unknown Source)
> >>        at
> >> com.jayway.restassured.**internal.**ResponseSpecificationImpl.**post(**
> >> ResponseSpecificationImpl.**groovy:
> >> 222)
> >> ....

Johan Haleby

unread,
Sep 5, 2011, 6:10:32 AM9/5/11
to rest-a...@googlegroups.com
Hi,

Somewhere at the end of the stack-trace it says "Caused by: net.sf.json.JSONException: Invalid JSON String" so it does try to parse it as JSON which should indicate that the parser is registered correctly. What if you print the response body and verify manually that it's actually JSON? (just add a call to "log()" somewhere in your rest assured statement, e.g. given().log(). .. ).

/Johan

Johan Haleby

unread,
Sep 5, 2011, 6:52:59 AM9/5/11
to rest-a...@googlegroups.com
I get the same exception if I return something that is not JSON so I really suspect that your server does not return a JSON string.

/Johan
Reply all
Reply to author
Forward
0 new messages