Rest API - how add custom headers? - android

I want to make POST request with custom header. I can't find information how to do this using AA Rest API - https://github.com/excilys/androidannotations/wiki/Rest%20API .
Should I use ClientHttpRequestInterceptor, which is used for authenticated requests?
https://github.com/excilys/androidannotations/wiki/Authenticated-Rest-Client
Thanks for any help!

There is currently an open issue for this : https://github.com/excilys/androidannotations/issues/323
For now, the only way to do this is with a custom ClientHttpRequestInterceptor. Here is a little example :
#EBean
public class CustomHeaderInterceptor implements ClientHttpRequestInterceptor {
#Override
public ClientHttpResponse intercept(HttpRequest request, byte[] data, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().add("myHeader", "value");
return execution.execute(request, data);
}
}
Then, you need to link it to the restTemplate, like this :
#EBean
public class MyService {
#RestService
RestClient restClient;
#Bean
MobileParametersInterceptor mobileParametersInterceptor;
#AfterInject
public void init() {
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
interceptors.add(mobileParametersInterceptor);
restClient.getRestTemplate().setInterceptors(interceptors);
}
}

Indeed you have to use the ClientHttpRequestInterceptor for custom header.
Currently, it's the only way I know.
See the official documentation of Spring-Android for more informations about the RestTemplate.

Related

Retrofit - use response class with inheritance

I'm trying make reuse of single retrofit api call by inherit from a base response class.
However I'm not able to do it.
I will try to make myself clear with example (It's not a concrete scenario. I'm just trying to figure out the main idea):
Having this response objects and api service:
public class UserDetailsResponse
{
private int userId;
}
public class ExtendedUserDetailsResponse extends UserDetailsResponse
{
private int userAdditionalId;
}
interface APIService
{
#GET("/UserDetails/")
Call<UserDetailsResponse> getUserDetails(#Query("id") String userId);
}
Is there a way of using getUserDetails api with ExtendedUserDetailsResponse object?
This one gives me compilation error:
mService.getUserDetails("123").enqueue(new Callback<ExtendedUserDetailsResponse>()
{
#Override
public void onResponse(Call<ExtendedUserDetailsResponse> call, Response<ExtendedUserDetailsResponse> response)
{
}
#Override
public void onFailure(Call<ExtendedUserDetailsResponse> call, Throwable t)
{
}
});
How can I solve this? or at least something similar to this, without using a new api call for the specific derived class?
Thanks!
You get an error because ExtendedUserDetailsResponse is a UserDetailsResponse, however, UserDetailsResponse is not necessarily an ExtendedUserDetailsResponse.
In order to make it generic, sign your method this way
Call< ExtendedUserDetailsResponse > getUserDetails(#Query("id") String userId);
Then ExtendedUserDetailsResponse will have access to userId
Remember to expose userId with getters and setters so that it get parsed.
You are getting compilation error because you are using the wrong callback object:
Just change this line:
Call<UserDetailsResponse> getUserDetails(#Query("id") String userId);
to
Call<ExtendedUserDetailsResponse> getUserDetails(#Query("id") String userId);
Or depending on the response change the object in the callback
Note that ExtendedUserDetailsResponse will have userId so you can use ExtendedUserDetailsResponse even if the server returns object of type UserDetailsResponse or ExtendedUserDetailsResponse.

Android HttpHelper

I want a helper class for http connection. I am able to write simple code to connect using HttpUrlConnection and Async task and it works well.
But I am confused how can I write a more generic reusable class HttpHelper.
I got this HttpHelper class from internet (It just does a simple get call, I will later extend it to deal with post calls with query parameters), but I am not able to figure out how to call/use this as is. I am confused with the callbacks and the generics.
If I want to make a http request using this call and expect String result, this is what I attempted and it is all with syntax errors.
HttpHelper<String> api = new HttpHelper<>();
api.get("www.google.com", new HttpHelper.Callback<String>{
#Override
String execute(String html){
}
#Override
void finish(String result){
}
});
Thanks for your help
K
you have to call your method like this:
HttpHelper<String> api = new HttpHelper<String>();
api.get("www.google.com", new HttpHelper.Callback<String>{
#Override
String execute(String html){
return html; // This line is very very important.
}
#Override
void finish(String result){
// Do whatever you wan to do with your server response.
}
});
And do check your imports which HttpHelper class your are importing.
This works for me . Happy Coding !!!

Using TLS only with Retrofit in RoboSpice

I've got a basic setup using Robospice with Retrofit in a shell Android application making REST calls, parsing JSON response into a POJO and that I can then use to render in an Activity. I now want to use TLS only for transport security (not SSL). I've read that Retrofit with OkHttp can be used to achieve this but I don't know where to make the update in my code.
I have a basic interface:
public interface RandomAPI {
#GET("/users")
List<User> getUsers(#Path("owner") String owner, #Path("repo") String repo);
#GET("/users/{userid}")
User getUser(#Path("userid") int userID);
}
I have a Service:
public class RandomService extends RetrofitGsonSpiceService {
private final static String BASE_URL = "http://jsonplaceholder.typicode.com";
#Override
public void onCreate() {
super.onCreate();
addRetrofitInterface(RandomAPI.class);
}
#Override
protected String getServerUrl() {
return BASE_URL;
}
}
and finally a request:
public class RandomRequest extends RetrofitSpiceRequest<User, RandomAPI> {
private int userID;
public RandomRequest(int userID) {
super(User.class, RandomAPI.class);
this.userID = userID;
}
#Override
public User loadDataFromNetwork() throws Exception {
return getService().getUser(userID);
}
}
I'm guessing I need to update the Service but not really sure how. I really like the simplicity of this pattern so would like to keep it if possible. I can drop the OkHttp jars into the application but I don't know how to get at the actual implementation of the service, or how to add my custom one so that all requests use it.
Has any one had experience with this that could share some code snippets or point me to an example?
~~ EDIT ~~
Looking into the API for Robospice, looks like my request can just extend SpiceRequest, then within the loadFromNetwork() method I just do plain Retrofit and OkHTTP stuff. Is that the only way though? Thought there would be a way to set your own RestAdapter implementation in RetrofitSpiceService instead of just using the default.
So to do this is actually quite simple. Create a class which extends RetrofitGsonSpiceService and override the createRestAdapterBuilder() method.
e.g.
#Override
protected Builder createRestAdapterBuilder() {
RestAdapter.Builder builder = new RestAdapter.Builder()
.setEndpoint(SERVICE_URL)
.setRequestInterceptor(requestInterceptor);
return builder;
}

Mapping error responses with 200 response code in Retrofit

I'm dealing with an API that I don't control which returns error responses in JSON format, but doesn't return a non-200 response code in that case. Is it still possible to get anything that is an error (as determined by the presence of an "error" property) in the failure callback when using Retrofit? It's safe to assume I can recognise error responses from that API by looking at the message contents.
This is an application-level distinction which means Retrofit doesn't (and shouldn't) care about it.
There's three ways to accomplish what you want, each of which maps to a behavior of Retrofit.
For asynchronous invocation you can use a custom Callback subtype which does the mapping.
public abstract class MyCallback<T extends MyResponse> implements Callback<T> {
#Override public final void success(T data, Response response) {
if (!data.success) {
success(data);
} else {
error(data.error, response);
}
// This is just an example of what a potential common handler could look like.
}
public abstract void success(T data);
public abstract void httpError(Error error, Response response);
}
If you are using the experimental RxJava support you should map the Observable through something which extracts the error.
service.doSomething()
.map(new Func1<SomethingResponse, SomethingResponse>() {
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(..);
Finally, for synchronous you can obviously check at every call site, but you can also wrap the API.
public final class WrappedService implements Service {
private final Service real;
#Override public SomethingResponse doSomething() {
return handleError(real.doSomething());
}
private static <T extends MyResponse> T handleError(T data) {
if (!data.success) {
throw new SomeException(data.error);
}
return data;
}
}
(Hint: You can also use a Proxy to do this for every method automatically!)
The important thing to remember here is that Retrofit's responsibility is to map your HTTP API to a Java API. It is not responsible for applying application-level behavior or constraints to the request or response data. That remains your responsibility.
Looks this is possible in the Converter, from the javadoc:
ConversionException - if conversion was unable to complete. This will trigger a call to
Callback.failure(retrofit.RetrofitError) or throw a RetrofitError. The exception message
should report all necessary information about its cause as the response body will be set to
null.

How exactly should I add header to HTTP Get request with AndroidAnnotations?

I am using approach, described in this question to add my specific header to HTTP get request. But I can't understand how I need to change my code to make interceptor to do his job. Currently I am using something like this:
#RestService
ImwizardClient imwizardClient;
//some code
return imwizardClient.getAllCategories();
where getAllCategories() is method, which makes get request. The request works correctly, but it doesn't add my custom header. So what do I need to change?
Is your Interceptor defined for your RestService class as documented here?
#Rest(interceptors = { HttpBasicAuthenticatorInterceptor.class })
public interface ImwizardClient {
// ... snipped
}
Alternatively, the workaround posted in this thread seems to work reliably. Just define a custom MessageConverter for your RestService class.
public class GsonWithHeadersConverter extends GsonHttpMessageConverter {
#Override
protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {
setHeaders(outputMessage); //My method to put the additional headers :)
super.writeInternal(o, outputMessage);
}
}

Categories

Resources