Git Product home page Git Product logo

grails-rest-client-builder's Introduction

Build Status

Rest Client Builder Grails Plugin

Notice

The code for this plugin has moved to a subproject of the Grails Data. Please submit any pull requests there.

Installation

Edit BuildConfig.groovy and add the following dependency:

compile ":rest-client-builder:2.0.0"

For Grails 3.x this plugin is no longer necessary and you should instead just declare a dependency on the core Grails Data library:

 compile 'org.grails:grails-datastore-rest-client'

Basic Usage

For API-style documentation refer to the Groovydocs

The main entry point is the grails.plugins.rest.client.RestBuilder class. Construct and use one of the REST "verbs".

A GET request:

 def resp = rest.get("http://grails.org/api/v1.0/plugin/acegi/")

The response is a Spring ResponseEntity.

There are convenience methods for obtaining JSON:

  resp.json instanceof JSONObject
  resp.json.name == 'acegi'

And XML:

  resp.xml instanceof GPathResult
  resp.xml.name == 'acegi'

POST and PUT requests

POST and PUT requests can be issued with the post and put methods respectively:

        def resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){
            auth System.getProperty("artifactory.user"), System.getProperty("artifactory.pass")
            contentType "application/vnd.org.jfrog.artifactory.security.Group+json"
            json {
                name = "test-group"
                description = "A temporary test group"
            }
        }

In the example above the auth method performs HTTP basic auth, the contentType method sets the content type, and the json method constructs a JSON body.

A POST with URL parameters

        def resp = rest.post('http://someServer/foo/bar?username={username}&password={password}') {
            urlVariables [username:"someDude", password:"abc#123"]
        }

Please note the above url is not a GString with String interpolation but a String that uses the format/convention specified in the RestTemplate javadoc.

http://docs.spring.io/spring/docs/3.2.x/javadoc-api/org/springframework/web/client/RestTemplate.html

Exchanging JSON and XML content

As demonstrated in the previous example you can send JSON data using the json method which accepts the same syntax as Grails' JSONBuilder. Alternatively you can provide a String, or any other valid Java object that is convertable to JSON. The following are also valid examples:

        def resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){
            ...
            contentType "application/vnd.org.jfrog.artifactory.security.Group+json"
            json name: "test-group", description: "A temporary test group"
        }

        def resp = rest.put("http://repo.grails.org/grails/api/security/groups/test-group"){
            ...
            contentType "application/vnd.org.jfrog.artifactory.security.Group+json"
            json '{ name: "test-group", description: "A temporary test group" }'
        }

If you don't explicitly set the contentType like is done above then the default content type for the json method is "application/json".

XML is very similar, there is an xml method that takes a closure to build XML, and object which is convertable to XML or a String of XML.

The response object has xml or json properties for reading the response of the request as demonstratd in the "Basic Usage" section.

Sending custom headers

You can include in your request any additional header:

def resp = rest.put("http://example.org/api/login") {
    header 'X-Auth-Token', '1a2b3c4d5e6f7g8h'
}

Testing

Testing can be done with Spring's RestTemplate mocking APIs. See the tests for RestBuilder itself for an example.

Multipart Requests

Multipart requests are possible by setting properties of the request body to File, URL, byte[] or InputStream instances:

    def resp = rest.post(url) {
        contentType "multipart/form-data"
        zip = new File(pluginPackage)
        pom = new File(pomFile)
        xml = new File(pluginXmlFile)
    }

Connection/Proxy Configuration

Connection and proxy configuration can be specified in the constructor to RestBuilder:

def rest = new RestBuilder(connectTimeout:1000, readTimeout:20000, proxy:['localhost':8888])

The proxy setting can either be map containing the key for the host name and a value for the port or an instance of java.net.Proxy.

grails-rest-client-builder's People

Contributors

alvarosanchez avatar burtbeckwith avatar graemerocher avatar lhotari avatar sdelamo avatar sgates avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grails-rest-client-builder's Issues

Fatal error during compilation

I'm having difficulties installing the plugin. I'm using Grails 2.2.3 and the exception I'm getting is:

Fatal error during compilation org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: URL [jar:file:/Users/jeff/.grails/ivy-cache/org.grails/grails-hibernate/jars/grails-hibernate-2.2.3.jar!/org/codehaus/groovy/grails/compiler/gorm/GormTransformer.class]; nested exception is java.lang.NoClassDefFoundError: org/springframework/core/type/classreading/AnnotationMetadataReadingVisitor

Dependency on grails-core breaks plugin compilation with Grails 2.3.3

Version 2.0.0 of the plugin depends on grails-core 2.3.1. If you include that version of the plugin as a build dependency in your own plugin and try to build your plugin with Grails 2.3.3, you'll get this error:

| Installed plugin rest-client-builder-2.0.0.....
| Error Error executing script Compile: groovy.lang.MissingMethodException: No signature of method: org.codehaus.groovy.grails.compiler.GrailsProjectCompiler.reconfigureClasspath() is applicable for argument types: () values: []
Possible solutions: configureClasspath() (Use --stacktrace to see the full trace)

I have a sample project, although need a way to make it available.

Read timout

This is the code that i am using in my grails application

def rest = new RestBuilder(connectTimeout:60000, readTimeout:60000, proxy:['localhost':8008])
def requestParams = [username:"",password:""]
def resp = rest.post('http://localhost:8008/api/jwt/login?username={username}&password={password}',requestParams) {
contentType "application/x-www-form-urlencoded"
}

It throws the following error when i run

ERROR org.grails.web.errors.GrailsExceptionResolver - SocketTimeoutException occurred when processing request: [GET] /test/index
Read timed out. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_131]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_131]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:8008/api/jwt/login?username=username&password=password":Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
at grails.plugins.rest.client.RestBuilder.invokeRestTemplate(RestBuilder.groovy:310) ~[grails-datastore-rest-client-5.0.0.RC2.jar:na]
at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:274) ~[grails-datastore-rest-client-5.0.0.RC2.jar:na]
at grails.plugins.rest.client.RestBuilder.post(RestBuilder.groovy:158) ~[grails-datastore-rest-client-5.0.0.RC2.jar:na]
at rest.api.TestController.index(TestController.groovy:10) ~[main/:na]
... 3 common frames omitted
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) ~[na:1.8.0_131]
at java.net.SocketInputStream.read(SocketInputStream.java:171) ~[na:1.8.0_131]
at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[na:1.8.0_131]
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246) ~[na:1.8.0_131]
at java.io.BufferedInputStream.read1(BufferedInputStream.java:286) ~[na:1.8.0_131]
at java.io.BufferedInputStream.read(BufferedInputStream.java:345) ~[na:1.8.0_131]
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480) ~[na:1.8.0_131]
... 7 common frames omitted

But, the same URL works forme when I use POSTMAN Tool.
Please help me.

Documention doesn't match current Maven version

The plugin page states "Latest : 1.0.2" but I believe what is in the github repos is 1.0.3 which resulted in some frustration since the section "Exchanging JSON and XML content" doesn't work in 1.0.2 specifically being able to pass a string or a map in the json block.

If 1.0.3 isn't ready to release yet perhaps a static page for 1.0.2 documentation should be linked to from the plugin page, I would think you'd want to do that on an ongoing basis as well.

Rest Client Builder: 2.2.1 Doesn't send XML but does send JSON

I tried using rest builder as such with success:
def rest = new RestBuilder()
def result = rest.post(url){
contentType "application/json"
json "test"
}

However when I change it to XML as below it doesn't send the XML payload and doesn't get picked up on my API:
def rest = new RestBuilder()
def result = rest.post(url){
contentType "application/xml"
xml "test"
}

I checked send xml via curl and it works fine:
curl -i -X POST -H "Content-Type: application/xml" -d 'test' localhost:8090/TestMe/api

question: how to do a regular post like a web form

I'm assuming I'm doing something wrong here..

I'm calling an API that is out of my control and is written in Cold Fusion (shiver). When I send the request like this:

    def resp = rest.post("${baseUrl}/rest/v1/ValidateUser") {
      accept MediaType.ALL.toString(), MediaType.APPLICATION_JSON.toString()
      body StudyId: studyId, siteId: siteId, UN: username,  PW: password

I get a 500 returned and the CF develop said I didn't post/submit any form variables.. his unit test work fine (both using cold fusion to call it and posting standard web based html forms).... Hence my guessing this isn't doing a form post.. Seems like it's just sending a body full of JSON text..

DEBUG client.RestTemplate  - Writing [{StudyId=xxx, siteId=xxxx, UN=sxxxx, PW=xxxxx}] using [org.springframework.http.converter.json.MappingJackson2HttpMessageConverter@5c30cf7d]

Thanks!!!!

Feature Request: Allow turning off automatic redirect following

I know automatically following permanent redirects follows the spec, but I use RestBuilder extensively for integration testing. It would be nice to turn this off so that redirects can be properly tested.

My current workaround looks like this:

RestBuilder restBuilder = new RestBuilder()
restBuilder.restTemplate = new RestTemplate(new HttpRequestFactoryWithoutRedirectFollowing())

and here's the ClientHttpRequestFactory implementation:

class HttpRequestFactoryWithoutRedirectFollowing extends SimpleClientHttpRequestFactory {
    @Override
    protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {
        super.prepareConnection(connection, httpMethod)
        connection.setInstanceFollowRedirects(false)
    }
}

Instead, I think it would be cleaner to turn this off via configuration (similiar to other connection properties). For example:

RestBuilder restBuilder = new RestBuilder(followRedirects: false)

Header 'Accept-Charset' can not be changed in post request

Hi,
I'd like to set Header 'Accept-Charset' to 'UTF-8', this is what I do:

    String data = 'my serialized object'
    RestBuilder client = new RestBuilder()

    client.restTemplate.setMessageConverters([new StringHttpMessageConverter(Charset.forName("UTF-8"))])

    def resp = client.post(uri){
        accept("application/json;charset=UTF-8")
        contentType('application/json;charset=UTF-8')
        header('Accept-Charset', 'UTF-8')
        json(data)
    }

but Header 'Accept-Charset' is not consider and in the http request is alway

Accept-Charset: big5, big5-hkscs, cesu-8, euc-jp, euc-kr, gb18030, gb2312, gbk, ibm-thai, ibm00858, ibm01140, ibm01141, ibm01142, ibm01143, ibm01144, ibm01145, ibm01146, ibm01147, ibm01148, ibm01149, ibm037, ibm1026, ibm1047, ibm273, ibm277, ibm278, ibm280, ibm284, ibm285, ibm290, ibm297, ibm420, ibm424, ibm437, ibm500, ibm775, ibm850, ibm852, ibm855, ibm857, ibm860, ibm861, ibm862, ibm863, ibm864, ibm865, ibm866, ibm868, ibm869, ibm870, ibm871, ibm918, iso-2022-cn, iso-2022-jp, iso-2022-jp-2, iso-2022-kr, iso-8859-1, iso-8859-13, iso-8859-15, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6, iso-8859-7, iso-8859-8, iso-8859-9, jis_x0201, jis_x0212-1990, koi8-r, koi8-u, shift_jis, tis-620, us-ascii, utf-16, utf-16be, utf-16le, utf-32, utf-32be, utf-32le, utf-8, windows-1250, windows-1251, windows-1252, windows-1253, windows-1254, windows-1255, windows-1256, windows-1257, windows-1258, windows-31j, x-big5-hkscs-2001, x-big5-solaris, x-euc-jp-linux, x-euc-tw, x-eucjp-open, x-ibm1006, x-ibm1025, x-ibm1046, x-ibm1097, x-ibm1098, x-ibm1112, x-ibm1122, x-ibm1123, x-ibm1124, x-ibm1364, x-ibm1381, x-ibm1383, x-ibm300, x-ibm33722, x-ibm737, x-ibm833, x-ibm834, x-ibm856, x-ibm874, x-ibm875, x-ibm921, x-ibm922, x-ibm930, x-ibm933, x-ibm935, x-ibm937, x-ibm939, x-ibm942, x-ibm942c, x-ibm943, x-ibm943c, x-ibm948, x-ibm949, x-ibm949c, x-ibm950, x-ibm964, x-ibm970, x-iscii91, x-iso-2022-cn-cns, x-iso-2022-cn-gb, x-iso-8859-11, x-jis0208, x-jisautodetect, x-johab, x-macarabic, x-maccentraleurope, x-maccroatian, x-maccyrillic, x-macdingbat, x-macgreek, x-machebrew, x-maciceland, x-macroman, x-macromania, x-macsymbol, x-macthai, x-macturkish, x-macukraine, x-ms932_0213, x-ms950-hkscs, x-ms950-hkscs-xp, x-mswin-936, x-pck, x-sjis_0213, x-utf-16le-bom, x-utf-32be-bom, x-utf-32le-bom, x-windows-50220, x-windows-50221, x-windows-874, x-windows-949, x-windows-950, x-windows-iso2022jp

How can I set Header 'Accept-Charset' to 'UTF-8'

Thank you

How would you translate given curl call into restbuilder code?

I'm trying to use this plugin to replicate the following curl command:

curl -u CLIENT_ID:CLIENT_SECRET https://api.myfox.me/oauth2/token -d 'grant_type=authorization_code&code=CODE_GENERATED_BY_MYFOX'

But the following code has the server responding that grant_type is missing:

def url = "https://api.myfox.me/oauth2/token"
def resp = rest.post(url, ['grant_type': 'authorization_code', 'code': params.code]) {
      auth clientId, clientSecret
}

Am I doing something wrong or it the error coming from the server I'm connecting to?

Class org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller can not access a member of class org.springframework.beans.GenericTypeAwarePropertyDescriptor with modifiers "public"

I am getting this exception after add grails-rest-client-builder.
This seems to be similar to this post: http://grails.1312388.n4.nabble.com/Marshallers-are-blowing-up-in-2-3-5-anyone-else-td4653954.html
I am not sure how to apply the fix in the last post. Can this be fixed in the plugin?
I am running Grails 2.4.3 and grails-rest-client-builder 2.0.2.

Thanks!

Alex

Exception and stacktrace attached:
Class org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller can not access a member of class org.springframework.beans.GenericTypeAwarePropertyDescriptor with modifiers "public". Stacktrace follows:
Message: Class org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller can not access a member of class org.springframework.beans.GenericTypeAwarePropertyDescriptor with modifiers "public"
Line | Method
->> 202 | value in grails.converters.JSON


| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 162 | convertAnother in ''
| 202 | value . . . . in ''
| 134 | render in ''
| 150 | render . . . . in ''
| 51 | doCall in jingle.asset.service.MusicAlbumsController$_tt__show_closure5_closure9
| 54 | withFormat . . in org.grails.plugins.web.rest.api.ControllersRestApi
| 46 | $tt__show in jingle.asset.service.MusicAlbumsController
| 198 | doFilter . . . in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1142 | runWorker . . in java.util.concurrent.ThreadPoolExecutor
| 617 | run in java.util.concurrent.ThreadPoolExecutor$Worker
^ 745 | run . . . . . in java.lang.Thread

Custom Marshallers Disposed When Calling new RestBuilder()

When calling new RestBuilder from a controller, the custom json marshaling registered in the bootstrap are thrown disposed of and json marshalling returns to default state.

Bootstrap
screen shot 2015-02-24 at 2 09 48 pm

Custom JSON Marshaler Registration
screen shot 2015-02-24 at 2 10 04 pm

Controller Method
screen shot 2015-02-24 at 2 07 59 pm

Json before calling controller method
screen shot 2015-02-24 at 2 08 41 pm

Json after calling controller method
screen shot 2015-02-24 at 2 08 58 pm

JVM: 1.7
Grails: 2.3.8
Plugin: 2.0.3

URI Not Absolute

I'm getting the following stacktrace:

errors.GrailsExceptionResolver IllegalArgumentException occurred when processing request: [GET] /app/recommend
URI is not absolute. Stacktrace follows:
java.lang.IllegalArgumentException: URI is not absolute
    at java.net.URI.toURL(URI.java:1080)
    at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:93)
    at grails.plugins.rest.client.RestBuilder.get(RestBuilder.groovy:53)
    at com.citelighter.RecommendController$_closure1$$ENSn3KFE.doCall(RecommendController.groovy:12)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)

Using this code (snippet):

def resp = new RestBuilder();
def r = resp.get("http://grails.org/api/v1.0/plugin/acegi/");
resp.json instanceof JSONObject;
resp.json.name = "acegi";

This error does not happen if I remove the JSON lines and instead I get a plain text response back.

Cannot use JSON query parameters

Due to the RestTemplate method used (exchange), it expects all query parameters containing "{...}" to be a URI variable. Can you provide a RequestCustomizer method for handling uri variables so this can be done? This would probably be the easiest solution and least invasive.

A little documentation on how to do it and this limitation would be great as well.

I can create a pull request if you'd like me to, just let me know.

RestBuilder#doRequestInternal partially handles exceptions

RestBuilder#doRequestInternal invokes RestTemplate#exchange and wraps it with a try-catch block that handles exceptions of type org.springframework.web.client.HttpClientErrorException.

exchange may also throw exceptions of type org.springframework.web.client.HttpServerErrorException; the server exceptions are uncaught and are propagated to the plugin user.

This creates an inconsistency in the response because the client exceptions are returned wrapped by ErrorResponse.

Getting exception for content type application/json

Hi

I am getting the HttpMessageNotWritableException when I try to execute the following code:

def rest = new RestBuilder(connectTimeout:10000, readTimeout:20000)
def resp = rest.post("http://requestb.in/1mhfid91"){
json {
name = "test-group"
description = "A temporary test group"
}
}

Please suggest if I am missing something.

Here is the Exception message:

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: (was java.lang.NullPointerException) (through reference chain: grails.converters.JSON["depth"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: grails.converters.JSON["depth"])
at grails.plugins.rest.client.RestBuilder.invokeRestTemplate(RestBuilder.groovy:307)
at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:280)
at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:268)
at grails.plugins.rest.client.RestBuilder.post(RestBuilder.groovy:154)
at com.simpleinteract.util.UrlShortenerService$$EObVm8au.shortenUrl(UrlShortenerService.groovy:54)
at Script1.run(Script1.groovy:14)
at org.grails.plugins.console.ConsoleService.eval(ConsoleService.groovy:57)
at org.grails.plugins.console.ConsoleService.eval(ConsoleService.groovy:37)
at org.grails.plugins.console.ConsoleController$_closure2.doCall(ConsoleController.groovy:61)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:195)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: grails.converters.JSON["depth"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:197)
at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:183)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:559)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:143)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:120)
at com.fasterxml.jackson.databind.ObjectMapper.writeValue(ObjectMapper.java:1727)
... 14 more
Caused by: java.lang.NullPointerException
at grails.converters.JSON.getDepth(JSON.java:217)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.get(BeanPropertyWriter.java:653)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:509)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:551)
... 17 more
undefined

consuming certain json breaks 2.X.X

  • When using ":rest-client-builder:2.X.X",
    If you consume a json like the one in Docker API for https://docs.docker.com/engine/reference/api/docker_remote_api_v1.19/#inspect-a-container
    then the JSON converter gets broken and fails to convert domain classes, yielding a quite unexpected Exception
    org.apache.commons.lang.UnhandledException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Error converting Bean with class org.h2.jdbc.JdbcResultSet
  • When using ":rest-client-builder:1.0.3" it works

Dependency error compiling on grails 3.0.11

I'm trying to use the plugin in a project using grails 3.0.11 & gradleWrapperVersion 2.3

In build.gradle I have in dependencies: compile "org.grails:grails-datastore-rest-client"

When compiling I get the next error: Could not resolve all dependencies for configuration ':testRuntime'.

Release binary version

I have need to use the plugin in our plugin framework where our clients can build their own plugins externally and then we load the JARs at runtime in our grails app. Can you possibly release the plugin as a binary version so that I can allow them to pull in the JAR for their external builds?

A good alternative might be to take the RestBuilder class and release it in a public maven repo and have this plugin depend on it. I just keep finding uses for it outside of a grails plugin! :)

If not, I will release it internally as a binary plugin.

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

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

Failures with Grails 2.5.x (and possibly 3.x) and using accept "application/json"

REST client doesn't work with Grails 2.5.x and using accept("application/json") to parse REST JSON responses. The issue is in grails/grails-data-mapping/grails-datastore-rest-client but grails-rest-client-builder will need to use a newer version of org.grails:grails-datastore-rest-client once the fix is merged upstream. I think it's likely an issue in Grails 3.x as well, but I have not confirmed this by trying the plugin with Grails 3.

The fixes are contained here in a pull request for grails-datastore-rest-client:
grails/grails-data-mapping#591

and here, which just shows my grails-datastore-rest-client fork using the above forked/patched grails-datastore-rest-client:
https://github.com/grails-plugins/grails-rest-client-builder/compare/master...ucidentity:v2.1.1-grails2.5-fix?expand=1

Note that https://maven.calnet.berkeley.edu/artifactory/all/ is not a public repository, so in order to get it working locally, you'll need to build https://github.com/ucidentity/grails-data-mapping/tree/3.x-grails2.5-fix-ucb and deploy to your local maven repository.

Not able to import RestBuilder

Hello,
We are using Grails 2.4.5 and are trying to use the RestBuilder class to implement some functional tests for our REST API's.
I have included compile "org.grails.plugins:rest-client-builder:2.1.1" in the BuildConfig.groovy file.
I can see that the plugin is downloaded but do not see the RestBuilder class in any src directory. I also do not see any references to other dependencies that might include RestBuilder.
screen shot 2016-05-26 at 12 26 20 pm

Could this be an issue when the plugin was upgraded/moved for Grails 3.x?
Thanks,
Kathy

How to call rest.get("some url") with header

Hi,
My code is as below:

def getUser(String mid) {
    String HTTPS_URL_GET_USERS = "https://channel-apis.line.naver.jp/v1/profiles?mids=%s"
    def rest = new RestBuilder()
    log.debug("URL = " + String.format(HTTPS_URL_GET_USERS, mid))
    def resp = rest.get(String.format(HTTPS_URL_GET_USERS, mid)) {
        header 'X-Line-ChannelToken', LINE_ACCESS_TOKEN
        contentType "application/json; charset=UTF-8"
    }
    log.debug("user: ${resp.responseEntity.body}")
    def obj = grails.converters.JSON.parse(resp.responseEntity.body)
    return obj
}

When I call this method, the below exception occurs:

Can not deserialize instance of java.lang.String out of START_OBJECT token
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@3ac467f3; line: 1, column: 1]. Stacktrace follows:
com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token
 at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream@3ac467f3; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)
    at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:749)
    at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:59)
    at com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:12)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3051)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2206)
    at grails.plugins.rest.client.RestBuilder.invokeRestTemplate(RestBuilder.groovy:307)
    at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:280)
    at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:268)
    at grails.plugins.rest.client.RestBuilder.get(RestBuilder.groovy:113)
    at com.fet.ebu.imsghub.service.LineService$$EP6OF3Sl.$tt__getUser(LineService.groovy:104)
    at com.fet.ebu.imsghub.v1.LineController.index(LineController.groovy:20)
    at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:198)
    at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

Would you please help me to solve the problem ?
Thank you

JSON - No suitable HttpMessageConverter

Hi, I have a fresh new Grails project with rest-client-plugin 1.0.2 installed.

In a controller I execute the following (copied from the unit test):

def rest = new RestBuilder()

def builder = new JSONBuilder()
JSON j = builder.build {name = "test-group"}

def resp = rest.put("http://localhost:8080/rest-1.0.0-SNAPSHOT/rest/entity/new"){
contentType "application/json"
body j
}

I always get the same error:

"Could not write request: no suitable HttpMessageConverter found for request type [grails.converters.JSON] and content type [application/json]"

Could you please tell me what can I do to solve it.

Thanks.

post params containing '#' are not urlencoded

Everything after the '#' is truncated when submitting a rest.post(url, params map).

I tried to find an alternate strategy for passing query parameters, but could not find an approach that would properly url encode a '#' value.

To reproduce,

def url = "http://someServer/foo/bar"
def requestParams = [username:"someDude", password:"abc#123"]
def restClient = new RestBuilder()
def response = restClient.post(url,requestParams)

The final url that is used on the post is:
http://someServer/foo/bar?username=someDude&password=abc

"class" property propagated to the request

Hello,

When sending post data like this

def resp = rest.post(url){
    auth login, password
    contentType "application/json"
    json {
        user
    }
}

I see that the output contains "class" property.
{"class":"org.icc.callrz.BusinessCard.BusinessCard", ...

I think this should be optional, can you please add a setting to disable this property propagation?

Allow setting request encoding for RestBuilder

Request currently send requests in default encoding ISO-8859-1 specified in StringHttpMessageConverter

To enable custom encoding, I had to use a hack:

RestBuilder rest = new RestBuilder()
rest.restTemplate.setMessageConverters([new StringHttpMessageConverter(Charset.forName("UTF-8"))])

RestBuilder needs a better and more obvious way to customize request encoding.

multipart/fom-data complex field names

Hi,

I'm trying to call an API (mailgun) which requires the use of "complex" field names when sending post requests - i.e. "v:my-custom-data". There seems to be no way to specify "complex" field names without groovy/grails interpreting them as constant expression rather than a variable expression.

Is there a way to do this? or is it not supported?

Jon

StreamUtils not available in Grails 2.1.x

rest-client-builder claims to be supported on Grails 2.0+. However, NullSafeStringHttpMessageConverter.groovy leverages the StreamUtils from Spring 3.2.2+. Grails 2.1.0 is built using Spring 3.1. Thus, I'm getting a ClassNotFoundException when running rest-client-builder on Grails 2.1.0.

Downloading pdf from web service

Hi,

I am using this plugin for getting details from web service. It is working for web service but I couldn't get the file attachment from it.

def attachRead = rest.get('url') {
contentType "application/pdf"
}

        def bodyText = attachRead.body.toString()

Please help me or let me know how to convert this to stream or file.

Not Supporting PATCH request type

Hi,
I'm using grails2.4.4 and grails-rest-client-builder latest version. I'm trying to invoke, PATCH request with this api. Looks like its not yet supported. Could you please help me out:

I'm getting below exception
java.net.ProtocolException
Message: Invalid HTTP method: PATCH

accept('application/xml' not used by resttemplate

using the restbuilder like this:

def rest = new grails.plugins.rest.client.RestBuilder(connectTimeout:10000, readTimeout:20000)
def resp = rest.post("${baseUrl}/rest/v1/fooxml") {
  accept(MediaType.APPLICATION_XML.toString())
  header("u",'foo')
  header("p",'bar')
  body XMLDATA
 }

results in the following debug line:

DEBUG client.RestTemplate  - Setting request Accept header to [text/plain, application/json, */*]

so in turn I get a 406 from the Rest Service..

HTTPS SSL certificate issue

I am calling a simple get request with https protocol and getting a certificate validation exception. Is there any shortcut to disable the SSL certification validation for HTTPS. The exception is as follows:

ERROR org.grails.web.errors.GrailsExceptionResolver - CertificateException occurred when processing request: [GET] /team/index
No subject alternative names present. Stacktrace follows:
java.lang.reflect.InvocationTargetException: null
	at org.grails.core.DefaultGrailsControllerClass$ReflectionInvoker.invoke(DefaultGrailsControllerClass.java:210)
	at org.grails.core.DefaultGrailsControllerClass.invoke(DefaultGrailsControllerClass.java:187)
	at org.grails.web.mapping.mvc.UrlMappingsInfoHandlerAdapter.handle(UrlMappingsInfoHandlerAdapter.groovy:90)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
	at org.springframework.boot.web.filter.ApplicationContextHeaderFilter.doFilterInternal(ApplicationContextHeaderFilter.java:55)
	at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:230)
	at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:202)
	at org.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:77)
	at org.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://192.168.1.100/adminapi/team/": java.security.cert.CertificateException: No subject alternative names present; nested exception is javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present

Issue passing custom header values

I am using the latest grails (2.1.2) with rest-client-builder plugin version 1.0.3. I am trying to pass in a custom request header value (say SEC_USER) to the target server which pre-authenticates a request with this request header value. I am using the following code to pass the value in but I dont get the header value in the receiving end.

RestBuilder rest = new RestBuilder(connectTimeout:5000, readTimeout:20000); 
rest.get("<some uri>") { 
    contentType MediaType.APPLICATION_JSON.toString() 
    header("SEC_USER", "foo") 
} 

Looking at RequestCustomizer in the RestBuilder class the header() method should add a named header to the HttpHeaders field as it calls headers[name] = value

Could this be an issue in the RestTemplate class (method exchange(...)) which this plugin uses internally?

ConverterException on functional -war test

(No JIRA project yet, so I thought I would enter it here)
I'm using the plugin in functional testing, and it works great with a typical test-app functional: run, but fails when doing test-app functional: -war. The reason:

org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Unconvertable Object of class: java.util.LinkedHashMap
org.apache.commons.lang.UnhandledException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Unconvertable Object of class: java.util.LinkedHashMap
    at grails.plugins.rest.client.RequestCustomizer.json(RestBuilder.groovy:182)
    at com.ace.mws.policies.MyFunctionalSpec.test rest client_closure5(MyFunctionalSpec.groovy:83)
    at grails.plugins.rest.client.RestBuilder.doRequestInternal(RestBuilder.groovy:90)
    at grails.plugins.rest.client.RestBuilder.put(RestBuilder.groovy:63)
    at com.ace.mws.policies.MyFunctionalSpec.test rest client(MyFunctionalSpec.groovy:80)
Caused by: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Unconvertable Object of class: java.util.LinkedHashMap
    at grails.converters.JSON.value(JSON.java:197)
    at grails.converters.JSON.render(JSON.java:134)

The code that is failing is the 'json' declaration of the RestBuilder.put method. I am pretty much following your example, which again works great typically but is failing during functional WAR tests:

def resp = rest.put(url) {
  json {
    param1 = "value"
    param2 = "value2"
  }
}

Not sure if it's because the application is not wired up the same in the functional tests where the app is not in the same JVM? I am using the geb plugin which is providing the functional testing abilities.

post json body containing object

I have a problem when using RestBuilder to post data containing json string:
I hope the server side could get the json result as below:
{"to":["u080859b6886c2269b28999fb9677535b"],"toChannel":"1383378250","eventType":"138311608800106203","content":{"contentType":1,"toType":1,"text":"HELLO"}}

My code is as below:
def resp = rest.post("http://localhost:8080/I-MSG_HUB/line/mockReceiving/?uid=WUREKA"){
header 'X-Line-ChannelToken', LINE_ACCESS_TOKEN
contentType "application/json; charset=UTF-8"
//json "${jsonbody}"
json {
to = ["u080859b6886c2269b28999fb9677535b"]
toChannel = "1383378250"
eventType = "138311608800106203"
content = {
contentType = "1"
toType = "1"
text = "HELLO I AM HERE"
}
}
}

But when my server get the json body, it looks like below:
[content:[toType:1, contentType:1], to:[u080859b6886c2269b28999fb9677535b], toChannel:1383378250, eventType:138311608800106203]

As you see, the item "content" is wrong. Besides, it loose item "text"
Can you help me to solve that problem ?
Thank you.

URL's containing a URL encoded space (%20) return a 404

Hi Graeme,

I am using the plugin to consume a Jenkins instance, but some of the view names in there contain (out of my control) spaces. These result in URLs containing spaces (e.g. http://my.jenkins.instance.com/job/something/view/foo%20bar/api/json ). Such URLs fail due to a 404. I assume because the %20 get's url decoded and a request is done with a real space or something.

Example code:

        String url = "https://my.jenkins.instance.com/job/something/view/foo%20bar/api/json"
        def rest = new RestBuilder()
        def resp = rest.get(jsonUrl) {
            auth username, password
        }

        println rest.getStatusCode()

Is it possible to use Grape to use this as a dependency in a local Groovy file?

I am successfully using this plugin in Grails (many thanks btw!), but for iterative coding changes I'd like to just try using this library in some Groovy code in groovyConsole, and quickly try out changes before moving the working code back into my Grails project.

After looking at this page: https://mvnrepository.com/artifact/org.grails.plugins/rest-client-builder/2.1.1 , I tried adding this at the top of my groovy script:
@grab(group='org.grails.plugins', module='rest-client-builder', version='2.1.1')

But when I run the script, I get the following error message:
java.lang.RuntimeException: Error grabbing Grapes -- [unresolved dependency: org.grails.plugins#rest-client-builder;2.1.1: not found]

I also tried it this way, same result:
@Grapes(
@grab(group='org.grails.plugins', module='rest-client-builder', version='2.1.1')
)
Appreciate any help on this.

JSON body comes empty

Trying to reach my REST endpoint the request.JSON is empty after executing this:

        RestResponse response = rest.get("http://localhost:8080/${grailsApplication.metadata.'app.name'}/ws/question") {
            json([
                occurrenceId: 'f6f8a9b8-4d52-49c3-9352-155f154fc96c',
                userId: userKeef.alaUserId,
                tags: 'octopus, orange',
                comment: 'whatever'
            ])
        }

response .xml SAXParseException

When attempting to retrieve xml from the response a SAXParseException is thrown with Message: Content is not allowed in prolog.

def restBuilder = new RestBuilder()
def response = restBuilder.get("http://grails.org/api/v1.0/plugin/acegi/")
print response.xml

Works fine if I do

print response.json

Also doing

def response = restBuilder.get("http://api.openweathermap.org/data/2.5/weather?q=London&mode=xml")
print response.xml

just prints the String GB, which is the only text inside tags in the xml response. Furthermore

def response = restBuilder.get("http://api.openweathermap.org/data/2.5/forecast/daily?q=London&mode=xml&units=metric&cnt=1")
print response.xml

prints out LondonGB0.044, which is all the text inside tags within the xml response.

Any thoughts as to what is going on?

Add cookies to request

Hi, I've been faced with trouble adding cookies to request. Could anyone suggest how can I perform that?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.