3

I'm using retrofit2 to comunicate with a webapi. I need to set the URL of the webapi dynamically beacuase the user can change it, so i use the @Url annotation to specify it like this:

@POST
Call<LoginResponse> login(@Url String url, @Body LoginRequest user);

In one of the operations, i need to send some path parameters to the server, so i do this:

@GET
Call<DataResponse> getOrder(@Url String url,
                             @Header(WEBAPI_EMAIL_HEDER) String email,
                             @Header(WEBAPI_TOKEN_ID_HEDER) String token,
                             @Path("id") int id);

When i call the operation getOrder(...), an exception is rised by retrofit because i am not suppoused to use @Url and @Path parameters in the same operation.

This is the exception:

java.lang.IllegalArgumentException: @Path parameters may not be used with @Url. (parameter #4)

One solution is to replace the id parameter on the url and use only the @Url parameter in the invokation. But i think this is not the best way, beacuase i will be doing this with all the operations with @Path parameters.

Is there any other cleaner solution? Maybe using another retrofit2 annotation?

Thanks in advance.

Pablo
  • 2,581
  • 3
  • 16
  • 31
  • 1
    You have to configure retrofit to use an endpoint URL if you wish to utilize the Path annotation. In the example above, retrofit will not know where to place id because it wasn't defined in the GET description – AgileNinja Apr 26 '16 at 21:50
  • I am calling with this url parameter value: "http://webapi.example.com/v1/orders/{id}.json". So, the url has the id parameter defined. – Pablo Apr 26 '16 at 22:00

2 Answers2

6

As described in the post Retrofit 2 - Dynamic URL, the @Url notation assumes that the String is a fully defined URL and does not check whether it contains @Path variables.

To use the @Path annotation, you have to configure an endpoint URL and include the @Path variable inside the @GET() annotation.

Community
  • 1
  • 1
AgileNinja
  • 914
  • 1
  • 7
  • 20
2

There is a workaround. Incase of a dynamic Url with some variable path, we can define a string format with paths denoted by %s arguments. E.g: Suppose the dynamic url with path is : https://www.example.com/users/{id}/whoami

Here we can just replace {id} with %s. So now it becomes,

val formatString = https://www.example.com/users/%s/whoami

Now we can use it as a format string and replace it with required id.

val url = formatString.format(id)

and in the retrofit interface, use @Url parameter in the function.

    interface AnyService {
      fun whoAmI(@Url url:String): Call<ResponseBody>
    }

Incase you are using MVVM architecture, you can call the formatting code in the concerned repository.

Rishabh Maurya
  • 1,448
  • 3
  • 22
  • 40