13

I've found this doc on how to post JSON data using HttpBuilder. I'm new to this, but it is very straightforward example and easy to follow. Here is the code, assuming I had imported all required dependencies.

def http = new HTTPBuilder( 'http://example.com/handler.php' )
http.request( POST, JSON ) { req ->
    body = [name:'bob', title:'construction worker']

     response.success = { resp, json ->
        // response handling here
    }
}

Now my problem is, I'm getting an exception of

java.lang.NullPointerException
    at groovyx.net.http.HTTPBuilder$RequestConfigDelegate.setBody(HTTPBuilder.java:1131)

Did I miss something? I'll greatly appreciate any help you can do.

Rob Hruska
  • 118,520
  • 32
  • 167
  • 192
Chris Laconsay
  • 402
  • 1
  • 3
  • 17
  • the answers seem to be outdated; the import mentioned in the answers is no longer found; to see how to post json data in groovy, try this: https://stackoverflow.com/questions/25692515/groovy-built-in-rest-http-client – jmarina Jun 29 '23 at 09:43

5 Answers5

18

I took a look at HttpBuilder.java:1131, and I'm guessing that the content type encoder that it retrieves in that method is null.

Most of the POST examples here set the requestContentType property in the builder, which is what it looks like the code is using to get that encoder. Try setting it like this:

import groovyx.net.http.ContentType

http.request(POST) {
    uri.path = 'http://example.com/handler.php'
    body = [name: 'bob', title: 'construction worker']
    requestContentType = ContentType.JSON

    response.success = { resp ->
        println "Success! ${resp.status}"
    }

    response.failure = { resp ->
        println "Request failed with status ${resp.status}"
    }
}
Rob Hruska
  • 118,520
  • 32
  • 167
  • 192
  • Thank you for the response, but still no good :( java.lang.NullPointerExceptionat groovyx.net.http.HTTPBuilder$RequestConfigDelegate.setBody(HTTPBuilder.java:1147) Had you tried that example on your machine? Does it work? And also, on the value of uri.path, does it need to be an existing path? – Chris Laconsay Jul 26 '11 at 15:24
  • Looks like you got farther along; the new NPE is when it's trying to find the appropriate response handler. The request probably failed, so you'll want a failure handler. I'll update my example. – Rob Hruska Jul 26 '11 at 15:48
  • *"on the value of uri.path, does it need to be an existing path"* - If the host doesn't exist, you'll get some sort of connection error. If it does exist but the resource you're POSTing to doesn't exist, you'll get an HTTP 404 or something. – Rob Hruska Jul 26 '11 at 16:03
  • No good at all, I'm still getting the same NPE using the example that you had provided. I think exception gets thrown before reaching the failure handler line. – Chris Laconsay Jul 27 '11 at 02:24
  • It worked for me. I had an `NPE at groovyx.net.http.HTTPBuilder$RequestConfigDelegate.setBody(HTTPBuilder.java:1200)` and was fixed by adding the requestContentType. Thanks – acorello Jan 08 '13 at 12:35
  • If you are running groovy file standalone. Remember to import HTTPBuilder into groovy file @Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1') – Arjang Jan 31 '17 at 16:51
  • the only problem, if I try to post object as json, it puts empty string on null String fields, but I really need nulls – dmitryvim Mar 17 '17 at 12:01
8

I had the same problem a while ago and found a blog that noted the 'requestContentType' should be set before 'body'. Since then, I've added the comment 'Set ConentType before body or risk null pointer' in each of my httpBuilder methods.

Here's the change I would suggest for your code:

import groovyx.net.http.ContentType

http.request(POST) {
    uri.path = 'http://example.com/handler.php'
    // Note: Set ConentType before body or risk null pointer.
    requestContentType = ContentType.JSON
    body = [name: 'bob', title: 'construction worker']

    response.success = { resp ->
        println "Success! ${resp.status}"
    }

    response.failure = { resp ->
        println "Request failed with status ${resp.status}"
    }
}

Cheers!

Robert
  • 675
  • 8
  • 16
  • the only problem, if I try to post object as json, it puts empty string on null String fields, but I really need nulls – dmitryvim Mar 17 '17 at 12:01
  • Hi dmitryvim, Are you talking about the POST request's response JSON? Or are you attempting to set string fields within the body JSON to null? – Robert May 31 '17 at 19:14
2

If you need to execute a POST with contentType JSON and pass a complex json data, try to convert your body manually:

def attributes = [a:[b:[c:[]]], d:[]] //Complex structure
def http = new HTTPBuilder("your-url")
http.auth.basic('user', 'pass') // Optional
http.request (POST, ContentType.JSON) { req ->
  uri.path = path
  body = (attributes as JSON).toString()
  response.success = { resp, json -> }
  response.failure = { resp, json -> }
}    
1

I found an answer in this post: POST with HTTPBuilder -> NullPointerException?

It's not the accepted answer, but it worked for me. You may need to set the content type before you specify the 'body' attribute. It seems silly to me, but there it is. You could also use the 'send contentType, [attrs]' syntax, but I found it more difficult to unit test. Hope this helps (late as it is)!

Community
  • 1
  • 1
Michael D Johnson
  • 889
  • 1
  • 10
  • 21
-1

I gave up on HTTPBuilder in my Grails application (for POST at least) and used the sendHttps method offered here.

(Bear in mind that if you are using straight Groovy outside of a Grails app, the techniques for de/encoding the JSON will be different to those below)

Just replace the content-type with application/json in the following lines of sendHttps()

httpPost.setHeader("Content-Type", "text/xml")
...
reqEntity.setContentType("text/xml")

You will also be responsible for marshalling your JSON data

 import grails.converters.*

 def uploadContact(Contact contact){  
   def packet = [
      person : [
       first_name: contact.firstName,
       last_name: contact.lastName,
       email: contact.email,
       company_name: contact.company
      ]
   ] as JSON //encode as JSON
  def response = sendHttps(SOME_URL, packet.toString())
  def json = JSON.parse(response) //decode response 
  // do something with json
}
Community
  • 1
  • 1
perlyking
  • 557
  • 7
  • 14