6

I have to communicate with the following four RESTServices.

Germany (Default): http://url.com/suggest?query=
Austria http://url.com:82/suggest?query=
Swiss: http://url.com:83/suggest?query=
Spain: http://url.com:84/suggest?query=

Basically I have to call the same RESTService on different TCP-Ports for each Country. When I create a Retrofit-RestAdapter, I have to provide a Endpoint (base-url):

RestAdapter.Builder builder = new RestAdapter.Builder();
    ObjectMapper mapper = new ObjectMapper();
    builder.setEndpoint("http://url.com");

If I want to access those four RESTServices mentioned above, do I have to create a RestAdapter for each of them? Or is it possible to use only one RestAdapter-instance?

I tried to solve the problem by adding the TCP-Port as part of the RestInterface-annotation, but this does not work:

public interface AutoSuggestRemote {
    @GET (":{port}/suggest")
    public Response getSuggestions(@Path ("port") Integer httpPort, @Query ("query") String query);
}

I get the following exception in Logcat:

java.lang.IllegalArgumentException: AutoSuggestRemote.getSuggestions: URL path ":{port}/suggest" must start with '/'.
        at retrofit.RestMethodInfo.methodError(RestMethodInfo.java:123)
        at retrofit.RestMethodInfo.parsePath(RestMethodInfo.java:212)
        at retrofit.RestMethodInfo.parseMethodAnnotations(RestMethodInfo.java:165)
        at retrofit.RestMethodInfo.init(RestMethodInfo.java:133)
        at retrofit.RestAdapter$RestHandler.invokeRequest(RestAdapter.java:294)
        at retrofit.RestAdapter$RestHandler.invoke(RestAdapter.java:240)
        at $Proxy3.getSuggestions(Native Method)

Therefore my question, if I have to create a RestAdapter-instance for each RESTService, or is there a way to communicat with all four services by using the same RestAdapter-instance.

Janusz
  • 187,060
  • 113
  • 301
  • 369
Christopher
  • 9,682
  • 7
  • 47
  • 76
  • 2
    Will a user be wanting to query different access points dynamically? Or could you just put the URL in `strings.xml` and change it by locale? e.g. `/res/values-de/strings.xml -> url.com` and `/res/values-es/strings.xml -> url.com:84` – swanson Jun 26 '14 at 18:28
  • Yeah this helps. The url is based on the country in the Locale. Therefore I use this code to determine the correct base url: String baseUrl = context.getString(R.string.suggest_url_germany); String curISOCode = curLocale.getISO3Country(); if ("AUT".equalsIgnoreCase(curISOCode)) { baseUrl = ctx.getString(R.string.suggest_url_austria); } else if ("CHE".equalsIgnoreCase(curISOCode)) { baseUrl = ctx.getString(R.string.suggest_url_swiss); } else if ("ESP".equalsIgnoreCase(curISOCode)) { baseUrl = ctx.getString(R.string.suggest_url_spain); } – Christopher Jun 27 '14 at 07:12
  • Then I would make use of Android's built-in localization for strings. Then you could do `builder.setEndpoint(ctx.getString(R.string.base_url))` always and it would look up the correct string for the current locale. In `values-de/strings.xml` define `base_url` as `url.com` and in `values-es/strings.xml` define `base_url` as `url.com:84` – swanson Jun 27 '14 at 18:05
  • As I know resources are language-specific, not country specific. But I have to differentiate from country, not language. But thanks for this hint. – Christopher Jun 30 '14 at 05:47

1 Answers1

0

Retrofit consults the EndPoint class each times it does a request. As previously answered by @JakeWharton in the question Dynamic Paths in Retrofit you could extend the EndPoint class with your own implementation and dynamically set the appropriate port as desired.

Here's the code provided by @JakeWharton modified for your specific purpose.

public final class FooEndpoint implements Endpoint {
  private static final String BASE = "http://192.168.1.64:";

  private String url;

  public void setPort(String port) {
    url = BASE + port;
  }

  @Override public String getName() {
    return "default";
  }

  @Override public String getUrl() {
    if (url == null) throw new IllegalStateException("port not set.");
    return url;
  }
}

You can then use the reference to this FooEndPoint instance to change the port dynamically or once when you initialise. If you choose to set the port once when initialized then you would simply do this.

FooEndPoint endPoint = new FooEndPoint();
endPoint.setPort(loadPortFromSomeWhere());

RestAdapter.Builder builder = new RestAdapter.Builder();
    builder.setEndpoint(endPoint);

This will allow you to use a single RestAdapter with multiple ports.

Community
  • 1
  • 1
Miguel
  • 19,793
  • 8
  • 56
  • 46