I'm using robospice for my RESTful Communication to a backend. Here is the specification of the interface:

## carid [/cars]
### Register a car[POST]
+ Request (application/json)

+ Header

        Accepted-Language: en
        Authorization: Basic xyz

+ Body

        {
            "carId" : "ad885f2b-dbd3-49ad-aa34-a7671cf5e337"
        }

+ Response 200 (application/json)

    {
        "magicQuestionDefined": true,
        "newCar": true
    }

+ Response 401
+ Response 404 (application/json)
    {
        "message" : "No car owner found"
    }

+ Response 400
+ Response 500

Here ist the snipped of my listener, when I receive an error (in my case its only a problem with errors, the normal case returning a json works fine) :

private class RegisterCarRequestListener implements RequestListener<RegisterCarResult> {

    @Override
    public void onRequestFailure(SpiceException e) {

    // e: Networkexception
    // e.cause=RestClientException
    // e.cause.detailMessage="Could not extract response: no suitable HttpMessageConverter found for response type [ch.mycarapp.lib.model.RegisterCarResult] and content type [text/html;charset=iso-8859-1]"
    }

It all works fine until the Backend answers with a 401. In this case I except an Exception of type: HttpStatusCodeException for evaluating the exception status-code. The reason is "e.cause.detailMessage="Could not extract response: no suitable HttpMessageConverter found for response type [ch.mycarapp.lib.model.RegisterCarResult] and content type [text/html;charset=iso-8859-1]" but it is just a status code 401 that gets returned!

The service is created like this:

public class JsonCarService extends SpringAndroidSpiceService {

@Override
public CacheManager createCacheManager(Application application) throws CacheCreationException {
    final CacheManager cacheManager = new CacheManager();
    final JacksonObjectPersisterFactory jacksonObjectPersisterFactory = new JacksonObjectPersisterFactory(application);
    cacheManager.addPersister(jacksonObjectPersisterFactory);
    return cacheManager;
}

@Override
public RestTemplate createRestTemplate() {
    final RestTemplate restTemplate = new RestTemplate();

    // web services support json responses
    final MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();

    // web Services support also Text Messages ( for some error cases
    final StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(Charset.forName("ISO-8859-1"));
    final List<HttpMessageConverter<?>> listHttpMessageConverters = restTemplate.getMessageConverters();

    listHttpMessageConverters.add(jsonConverter);
    listHttpMessageConverters.add(stringConverter);
    restTemplate.setMessageConverters(listHttpMessageConverters);

    return restTemplate;
    }
}

As you can see I have added a stringConverter too, but unfortunately it did not resolve the problem.

public class RegisterCarRequest extends BaseCarSpiceRequest<RegisterCarResult> {

RegisterCarInput input;
private final Context ctx;

public RegisterDeviceRequest(RegisterCarInput input, Context ctx) {
    super(RegisterCarResult.class);
    this.input = input;
    this.ctx = ctx;
}


@Override
public RegisterCarResult loadDataFromNetwork() throws Exception {
    final String url = ctx.getString(R.string.base_url) + "/cars";

    final HttpEntity<?> requestEntity = new HttpEntity<Object>(input, getRequestHeaders());

    final ResponseEntity<RegisterCarResult> response = getRestTemplate().exchange(url, HttpMethod.POST, requestEntity,
            RegisterCarResult.class);

    return response.getBody();
  }
}

The pojo for sending to the server is this one:

public class RegisterCarInput {

private String carId;

public String getCarId() {
    return carId;
}

public void setCarId(String carId) {
    this.carId = carId;
}
}

the pojo for the Response is this Object:

public class RegisterCarResult {

private Boolean magicQuestionDefined;
private Boolean newCar;

public Boolean getMagicQuestionDefined() {
    return magicQuestionDefined;
}

public void setMagicQuestionDefined(Boolean magicQuestionDefined) {
    this.magicQuestionDefined = magicQuestionDefined;
}

public Boolean getNewDevice() {
    return newCar;
}

public void setNewCar(Boolean newCar) {
    this.newCar = newCar;
}

}

The Request gets called like this:

private void performRequest(RegisterCarInput input, User user) {

    final RegisterCarRequest request = new RegisterCarRequest(input, getApplicationContext());
    request.setAuthUser(user);

    spiceManager.execute(request, new RegisterCarRequestListener());
}

Does anybody see a missing link for being able to parse different structures of responses?

Is it really necessary (for robospice) to receive httpstatuscodes (with a content-type=application/Json for errors with no payload and a 401 status code) ? http states in the Listener when the backend returns with a 401 ?

tia Luke

EDITED: I did some investigation and can now say that the backend returns a 403 when my basic authentication is wrong and sends following response:

+ Response 403 (text/html)
HTTP/1.1 403 Forbidden
Date: Wed, 12 Nov 2014 08:26:14 GMT
Server: Apache
Transfer-Encoding: chunked
Content-Type: text/html

97
<html>
  <head>
   <title>
     403 Forbidden
   </title>
  </head>
  <body>
     <h1>Forbidden</h1>
     You tried to access a page without having the required permissions.<br>                                                                                                   
  </body>
</html>

Unfortunately I don't have any influence to the behavior of the backend.

Facts:

  • The calls are working when everything is ok (200) and receiving RegisterCarResult as json
  • The calls are working when only a status code (401) (with no content in the response entity) is returned.
  • The calls are failing when a status code (403) with html content is returned in the entity

So the question, which answer will solve my problem is this:

  • How can I handle RestResponses, which can have different content-types (application/json)(text/html) in their entities with ROBOSPICE?

    1. I want to send a Json with a request to the backend => ok
    2. I want to receive a 200 as response and a application/json in the response entity => ok
    3. I want to receive only a status code 401 with no content => ok
    4. I want to receive a status code 403 with text/html content => HOW?

All those responses(2,3,4) are possible answers to the one request(1)...

0

There are 0 answers