如果后端响应带有错误状态代码,则找不到适合的响应类型的HttpMessageConverter

时间:2014-11-11 14:26:01

标签: java android json resttemplate robospice

我使用robospice将RESTful通信用于后端。 这是接口的规范:

## 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

当我收到错误时(在我的情况下,它只是一个错误问题,正常情况下返回一个json工作正常),这是我的监听器的剪切:

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]"
    }

一切正常,直到Backend用401回答。在这种情况下我除了类型异常: HttpStatusCodeException用于评估异常状态代码。 原因是&#34; e.cause.detailMessage =&#34;无法提取响应:没有为响应类型找到合适的HttpMessageConverter [ch.mycarapp.lib.model.RegisterCarResult]和内容类型[text / html; charset = ISO-8859-1]&#34;但它只是一个状态代码401被返回!

服务是这样创建的:

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;
    }
}

正如您所看到的,我也添加了一个stringConverter,但不幸的是它没有解决问题。

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();
  }
}

发送到服务器的pojo是这样的:

public class RegisterCarInput {

private String carId;

public String getCarId() {
    return carId;
}

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

响应的pojo就是这个对象:

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;
}

}

请求被调用如下:

private void performRequest(RegisterCarInput input, User user) {

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

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

是否有人看到缺少能够解析不同响应结构的链接?

是否真的有必要(对于robospice)接收httpstatuscodes(使用 content-type = application / Json表示没有有效载荷和401状态码的错误)?  当后端以401返回时,监听器中的http状态是什么?

TIA 路加

EDITED : 我做了一些调查,现在可以说当我的基本身份验证错误时后端返回403并发送以下响应:

+ 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>

不幸的是,我对后端的行为没有任何影响。

事实:

  • 当一切正常(200)并接收RegisterCarResult为json
  • 时,调用正在工作
  • 当只返回状态代码(401)(在响应实体中没有内容)时,调用正在工作。
  • 当实体中返回带有html内容的状态代码(403)时,调用失败

所以问题是,哪个答案可以解决我的问题:

  • 如何处理RestResponses,它们的实体可以在ROBOSPICE中使用不同的内容类型(application / json)(text / html)?

    1. 我想向后端发送带有请求的Json =&gt;确定
    2. 我想在响应实体中接收200作为响应和application / json =&gt;确定
    3. 我只想收到状态代码401,没有内容=&gt;确定
    4. 我想收到状态代码403,其中包含text / html content =&gt; 如何吗

所有这些回复(2,3,4)都是一个请求的可能答案(1)......

0 个答案:

没有答案