grails-plugins / grails-rest-client-builder

REST client plugin that uses Spring's RestTemplate
http://grails.org/plugin/rest-client-builder
Apache License 2.0
65 stars 32 forks source link

This annoyed me! Expected a string but was BEGIN_OBJECT at line 1 column 2. #40

Open biniama opened 9 years ago

biniama commented 9 years ago

Error 2015-07-09 13:30:22,849 [http-bio-8080-exec-4] ERROR errors.GrailsExceptionResolver - IllegalStateException occurred when processing request: [GET] /recipes-mashup/bigOven/batch Expected a string but was BEGIN_OBJECT at line 1 column 2. Stacktrace follows: Message: Expected a string but was BEGIN_OBJECT at line 1 column 2 Line | Method ->> 821 | nextString in com.google.gson.stream.JsonReader


| 358 | read in com.google.gson.internal.bind.TypeAdapters$13 | 346 | read . . . . . . . in '' | 803 | fromJson in com.google.gson.Gson | 768 | fromJson . . . . . in '' | 312 | invokeRestTemplate in grails.plugins.rest.client.RestBuilder | 273 | doRequestInternal in '' | 261 | doRequestInternal in '' | 106 | get . . . . . . . in '' | 29 | getBatch in com.bonial.hackathon.services.BigOvenService | 16 | batch . . . . . . in com.bonial.hackathon.BigOvenController | 198 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter | 63 | doFilter . . . . . in grails.plugin.cache.web.filter.AbstractFilter | 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor | 615 | run . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker ^ 745 | run in java.lang.Thread

graemerocher commented 9 years ago

Great that it annoyed you, but please provide more information than this, we cannot possibly reproduce if you just paste a stack trace

biniama commented 9 years ago

This is the code I tried it with.

    String api_key = "123"

    RestBuilder rest = new RestBuilder()

    def resp = rest.get('http://api.bigoven.com/recipes?pg=1&rpp=9&title_kw=cake&api_key=$api_key')   {
        accept 'application/json'
        contentType 'application/json'
    }

    render resp.json

I found a workaround, /* WORKAROUND * error: * "org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2; * found from: https://jira.grails.org/browse/GPREST-13 * / rest.restTemplate.messageConverters.removeAll { it.class.name == 'org.springframework.http.converter.json.GsonHttpMessageConverter' }

But, I still need a solution.

Plus, the returned value's content type is not 'application/json' rather 'text/html;charset=utf-8'

pablovilas commented 9 years ago

I've the same problem, any idea?

pablovilas commented 9 years ago

Well, looking at the code I've found a solution

def resp = rest.get('http://api.bigoven.com/recipes?pg=1&rpp=9&title_kw=cake&api_key=$api_key') { contentType 'application/json' accept JsonObject }

You must replace 'application/json' with JsonObject, I think that both ways should be supported. Good luck

matthijsbierman commented 9 years ago

For the old behaviour, which will parse it into a org.codehaus.groovy.grails.web.json.JSONObject use:

import org.codehaus.groovy.grails.web.json.JSONObject
...
rest.post(url) {
    accept JSONObject, 'application/json'
}
bobbywarner commented 9 years ago

This works just fine for me:

accept("application/json")

So, not sure how to replicate. Can you please post a sample app that demonstrates the problem?

matthijsbierman commented 9 years ago

Sure. The problem may be related to the fact that I'm unit testing with MockRestServiceServer. If you create a new app with Grails 2.5.1:

grails create-app app

And then overwrite/add these files: https://dl.dropboxusercontent.com/u/55056243/example.tar.gz. Update dependencies.

In TestService you can toggle between the two accept statements. Using accept 'application/json' will fail.

bkoehm commented 8 years ago

I believe I have fixed this with the information contained in: https://github.com/grails-plugins/grails-rest-client-builder/issues/44

biniama commented 8 years ago

@matthijsbierman 's solution worked. I am closing the issue.

matthijsbierman commented 8 years ago

Glad that it helped, but I don't believe you should have closed the issue already. There is still a problem, because it should work out of the box. It should only be closed once the bug is fixed upstream, as @bkoehm mentioned.

biniama commented 8 years ago

I am re-openning. I spent time trying to cast the output to JSON and perform operations on the JSON but with out success.

graemerocher commented 8 years ago

Use the new version of the underlying JAR to solve the problem:

 compile 'org.grails:grails-datastore-rest-client:5.0.0.RC2'
dustindclark commented 8 years ago

@graemerocher, in Grails 2.5.3, updating the JAR results in this issue

ClassNotFoundException: org.grails.web.converters.configuration.ConvertersConfigurationHolder

I assume that's because the fix only applies to Grails 3.X. Any solution for 2.5.3 (short of refactoring a bunch of code per the workarounds above)?

Omnipresent commented 8 years ago

I'm having the same error on 2.5.2 using 2.0.0 version of the plugin.

Below code reproduces the problem

            def resp = rest.post("https://www.google.com/recaptcha/api/siteverify") {
            accept("application/json")
            urlVariables secret:"asdfsdf", response: "lkjklj"
        }
dustindclark commented 8 years ago

@Omnipresent, the workaround mentioned above works on 2.5.x. Here's my snippet:

RestBuilder rest = new RestBuilder()
//Workaround per https://github.com/grails-plugins/grails-rest-client-builder/issues/40
rest.restTemplate.messageConverters.removeAll {
     it.class.name == 'org.springframework.http.converter.json.GsonHttpMessageConverter'
}
rest.post...
Omnipresent commented 8 years ago

@dustindclark Thanks, that works.

For completeness sake

        RestBuilder rest = new RestBuilder()
        rest.restTemplate.messageConverters.removeAll {
            it.class.name == 'org.springframework.http.converter.json.GsonHttpMessageConverter'
        }
        def resp = rest.post("https://www.google.com/recaptcha/api/siteverify?secret=df&response="+params["g-recaptcha-response"])
        def json = resp.json
wijnand1 commented 8 years ago

For others having this problem in grails 2.5.3: this workaround can be generalized by overwriting the default constructor for the RestBuilder. In Bootstrap.groovy include this:

RestBuilder.metaClass.constructor = { ->
    def constructor = RestBuilder.class.getConstructor()
    def instance = constructor.newInstance()
    instance.restTemplate.messageConverters.removeAll { it.class.name == 'org.springframework.http.converter.json.GsonHttpMessageConverter' }
    instance
}
tservin commented 5 years ago

hi im working on observe 5.4 data base but my java keep going into error. java.lang.illegalState Exeption:Expected BEGIN_ARRAY but was STRING at line 1 column 1 path $ can any oone help