5

This question may have been asked before but with new version 2.0 I did not find any correct answer yet.

My problem as below:

public interface  AuthenticationAPI {

    @POST("token")
    Call<String> authenticate(@Body String  body);

}

Then I call:

Retrofit retrofit = new Retrofit.Builder().baseUrl(authenUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();
        AuthenticationAPI authen = retrofit.create(AuthenticationAPI.class);


        try {
            Call<String> call1 = authen.authenticate(authenBody);
            call1.enqueue(new Callback<String>() {
                @Override
                public void onResponse(Response<String> response, Retrofit retrofit) {
                    Log.d("THAIPD", "Success " + response.raw().message());
                }

                @Override
                public void onFailure(Throwable t) {
                    Log.e("THAIPD", " FAIL " + t.getMessage());
                }
            });
        } catch (Exception e) {
            Log.e("THAIPD", e.getMessage());
            e.printStackTrace();
        }

Then I receive the response as protocol=http/1.1, code=400, message=Bad Request, That means my body parameter was not correct.

When I try to make a request by other tool as Postman I get the correct result with code is 200.

I found this answer but with Retrofit 2.0 I can not find TypedString class.

Here is the result when I try by another tool (DHC) enter image description here

Community
  • 1
  • 1
ThaiPD
  • 3,503
  • 3
  • 30
  • 48
  • Did you set any content type ?? try setting the proper content type . Can you share your post man request and response ?? – sreekumar Oct 15 '15 at 09:46
  • thanks for your suggestion @sreekumar . I had upload the image of postman, please help more. – ThaiPD Oct 16 '15 at 09:48
  • Just one question, since you are doing oauth authentication and authorization, do you have to put the oauth parameters in the body? Normally they should be in the headers – Dimitri Oct 17 '15 at 08:19
  • @Dimitri : this is first step, it's authentication. – ThaiPD Oct 17 '15 at 08:20

3 Answers3

11

UPDATE:
Retrofit2.0 has now own converter-scalars module for String and primitives (and their boxed).

com.squareup.retrofit2:converter-scalars

You can write custom Converter and Retrofit repository has a own String Converter implementation sample: ToStringConverterFactory

class ToStringConverterFactory extends Converter.Factory {
  private static final MediaType MEDIA_TYPE = MediaType.parse("text/plain");

  @Override
  public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
    if (String.class.equals(type)) {
      return new Converter<ResponseBody, String>() {
        @Override public String convert(ResponseBody value) throws IOException {
          return value.string();
        }
      };
    }
    return null;
  }

  @Override public Converter<?, RequestBody> toRequestBody(Type type, Annotation[] annotations) {
    if (String.class.equals(type)) {
      return new Converter<String, RequestBody>() {
        @Override public RequestBody convert(String value) throws IOException {
          return RequestBody.create(MEDIA_TYPE, value);
        }
      };
    }
    return null;
  }
}

and related issue are tracked here.

ytRino
  • 1,450
  • 15
  • 28
  • thank you for your answer. It's help me for resolving the problem in sending request. But I my response is an Json object and I also want to convert it to my Java model. So how can I do with same converter ? – ThaiPD Oct 23 '15 at 08:53
  • You can call `addConverterFactory()` multiple times for `ToStringConverterFactory` and `GsonConverterFactory`. – ytRino Oct 24 '15 at 10:19
0

Basically you will need to write a custom Converter

Something like this

public final class StringConverterFactory extends Converter.Factory {

public static StringConverterFactory create(){
    return new StringConverterFactory();
}

@Override
public Converter<ResponseBody, ?> fromResponseBody(Type type, Annotation[] annotations) {
    return new ConfigurationServiceConverter();
}

final class ConfigurationServiceConverter implements Converter<ResponseBody, String>{

    @Override
    public String convert(ResponseBody value) throws IOException {
        BufferedReader r = new BufferedReader(new InputStreamReader(value.byteStream()));
        StringBuilder total = new StringBuilder();
        String line;
        while ((line = r.readLine()) != null) {
            total.append(line);
        }
        return total.toString();
    }
}
}

and add this using addConverterFactory

WenChao
  • 3,586
  • 6
  • 32
  • 46
  • in current version of retrofit (2.0) I can not see that the interface converter as: public interface Converter So can you have a look again? Thanks! – ThaiPD Oct 20 '15 at 05:16
  • Are you saying the Converter interface doesn't exist in 2.0? I'm using 2.0 as well, can you double check? – WenChao Oct 21 '15 at 00:10
  • Converter interface is exist in 2.0 but its type is Converter not Converter – ThaiPD Oct 21 '15 at 09:51
  • Ah, Sorry, I think I was using beta1, it seems like it has changed in beta2. But anyway the implementation should be very similar. ;) – WenChao Oct 21 '15 at 23:20
  • Hi, I just created a version for beta2, please have a try. – WenChao Oct 22 '15 at 03:54
  • 1 thing to remember is the order of adding converter factory matters. you want to have something like: retrofit = new Retrofit.Builder() .client(OkHttpClient) .baseUrl("base url") .addConverterFactory(new ToStringConverterFactory().addConverterFactory(MoshiConverterFactory.create(getM‌​oshi()).asLenient()) .build(); – Shervin Najafi Mar 18 '16 at 07:42
0

Maybe I am wrong, but you are missing a "/"

@POST("token")  --->  @POST("/token")
Mikelis Kaneps
  • 4,576
  • 2
  • 34
  • 48