Вопрос

I am using Retrofit to connect to a user configurable URL, the issue I am having is how to handle a blank URL. As expected the RestAdapter.Builder throws an IllegalArgumentException when the server is null/blank, which means it is not possible to call create to generate the retrofit interface, leaving me with a null interface.

For example using the following API interface;

interface IApiService {
        @POST("/{path}/api/{userid}/calls/Action")
        void startCall(@Path("path") String path, @Path("userid") String userid, @Body Action action, Callback<Response> callback);

        @PUT("/{path}/api/{userid}/calls/Action")
        void addToCall(@Path("path") String path, @Path("userid") String userid, @Body Action action, Callback<Response> callback);
} 

I have created a wrapper class for the Retrofit interface as the callback type is a Retrofit Callback, and I wish to be able to swap this out if needed.

public class ApiServiceWrapper implements IAPiServiceWrapper {

        private IApiService mAPiService;

        @Inject
        ApiServiceWrapper(Settings settings, RequestInterceptor requestInterceptor) {

            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setServer(settings.getUrl())
                    .setRequestInterceptor(requestInterceptor)
                    .setConverter(new ActionConverter())
                    .build();

            mAPiService = restAdapter.create(IApiService.class);
        }

        public void startCall(String path, String userid, Action action, final IApiResultCallback<Response> callback) {
            mAPiService.startCall(path, userid, action, new Callback<Response>() {
                @Override
                public void success(Response response, Response response2) {
                    callback.success();
                }

                @Override
                public void failure(RetrofitError error) {
                    callback.failure(error.getResponse().getReason());
                }
            });
        }

        public void addToCall(String path, String userid, Action action, final IApiResultCallback<Response> callback) {
            mAPiService.addToCall(path, userid, action, new Callback<Response>() {
                @Override
                public void success(Response response, Response response2) {
                    callback.success();
                }

                @Override
                public void failure(RetrofitError error) {
                    callback.failure(error.getResponse().getReason());
                }
            });
        }
    }

So how should I handle an Exception thrown by the RestAdapter.Builder?

In my eyes it seems sensible to check if the settings.getUrl() returns a valid URL, if it does then populate the interface with Retrofit. But how do I handle the case when the URL is empty, one solution would be to check for null, eg;

public void startCall(String path, String userid, Action action, final IApiResultCallback<Response> callback) {
    if (mAPiService != null) {
        mAPiService.startCall(path, userid, action, new Callback<Response>() {
            @Override
            public void success(Response response, Response response2) {
                callback.success();
            }

            @Override
            public void failure(RetrofitError error) {
                callback.failure(error.getResponse().getReason());
            }
        });
    } else {
           callback.failure("Some reason here :D");
    }
}

This works but my API interfaces are quite big and I would rather not have to check for null on every call.

What would be nice is if I could set the mAPiService to an invalid implementation which instantly just calls failure with a message, for example;

@Inject
ApiServiceWrapper(Settings settings, RequestInterceptor requestInterceptor) {
        if (TextUtils.isEmpty(settings.getUrl())) {
            mAPiService = new InvalidSettingsApiService("some error")
        } else {
            RestAdapter restAdapter = new RestAdapter.Builder()
                    .setServer(settings.getUrl())
                    .setRequestInterceptor(requestInterceptor)
                    .setConverter(new ActionConverter())
                    .build();

            mAPiService = restAdapter.create(IApiService.class);
        }
}

But this is not possible as the IApiService interface uses the Retrofit Callback interface which requires a failure parameter of RetrofitError.

Are any of the options I have listed ok? or is there a better solution to handling the case of not being able to generate the interface?

Это было полезно?

Решение

I am using Retrofit to connect to a user configurable URL...

You should validate and reject blank URLs from their origin immediately. Your app should never make it far enough to build the RestAdapter with an invalid URL.

A big reason for immediate rejection is avoiding the masking of problems. If there's bad data it needs to be surfaced as soon as it's seen rather than hiding it behind a fake implementation of the interface which rejects API calls.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top