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);
}
}
Related
I have a problem when I try to make some interfaces and need to implement them with a generic.
My question is how can I use a nothing type like
Nothing in Kotlin
Void in Java
Example:
I have a base class
abstract class Base<Out, In> {
Future<Out> perform(In);
}
normal case I use, it perfect
class Download implements Base<bool, String> {
#override
Future<bool> perform(downloadUrl) async {
// do download and return result here
}
}
In some cases, I don't need to include any parameters.
but it require 2 generic type so I have to include void as input
class DoSomething implements Base<bool, void> {
#override
Future<bool> perform(_) async {
// do some thing here, no use the input parameter
}
}
The problem is when call perform function in DoSomething class it treat void as type of function don't like as Java, it require a input parameter instead of nothing
DoSomething().perform((){});
I don't want to include any parameter in the perform function.
Please give me any suggestions, solution to handle this case.
you can use
function({dynamic optional_parameter})
its an optional parameter you can simply ignore it if you dont want to process/use it and it will be null.
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;
}
I have a function that I want to test which runs in an okHttp callback. I'm trying to test it using Robolectrics but the callback is never executed. I presume that is because the test moves on after request without waiting for okHttp to return. So far I've tried:
ShadowLooper.pauseMainLooper();
Robolectric.flushBackgroundScheduler();
ShadowLooper.unPauseMainLooper();
but that didn't work. Any suggestions?
EDIT:
Here's an example of my code:
ApiClient.sendSomeDataToServer(data, callback);
Where ApiClient is a helper class containing okHttp client. sendSomeDataToServer API call looks something like this:
public static void sendSomeDataToServer(MyObject data, Callback callback){
final Request request = new Request.Builder()
.url(API_SOME_URL)
.post(RequestBody.create(JSON, myObject.getAsJson().toString()))
.build();
sHttpClient.newCall(request).enqueue(callback);
}
Where sHttpClient is an initialised OkHttpClient.
I can test the execution of above by forcing Thread.sleep(5000) inside my test code and providing custom callback. The code I'm trying to test is inside the callback. Any suggestions how I can test that? I really don't want to change the main code to fit the test framework - should be the other way round.
Lets assume you have next code. Interface:
#GET("/user/{id}/photo")
void listUsers(#Path("id") int id, Callback<Photo> cb);
Implementation:
public void fetchData() {
RestAdapter restAdapter = new RestAdapter.Builder()
.setServer("baseURL")
.build();
ClientInterface service = restAdapter.create(ClientInterface.class);
Callback<Photo> callback = new Callback<Photo>() {
#Override
public void success(Photo o, Response response) {
}
#Override
public void failure(RetrofitError retrofitError) {
}
};
service.listUsers(435, callback);
}
First of all you need to change service instantiation to service injection (as parameter or field). I will do it as parameter:
public void fetchData(ClientInterface clients) {
}
After this text is quite trivial:
#Test
public void checkThatServiceSuccessIsProcessed() {
ClientInterface mockedClients = mock(ClientInterface.class);
activity.fetchData(mockedClients);
// get callback
ArgumentCaptor<Callback<Photo>> captor = (ArgumentCaptor<Callback<Photo>>)ArgumentCaptor.forClass(Callback.class);
verify(mockedInterface).listUsers(anything(), captor.capture());
Callback<Photo> passedCallback = captor.value();
// run callback
callback.success(...);
// check your conditions
}
The used library for mocking and verifying is Mockito.
There will be one warning with captor instantiation because of generics but it fixable if you will use #Captor annotation instead of creating captor by hands.
The parameter injection is not perfect, especially for case of activities. This was used to simplify example. Consider for proper injection with library or without. I would encourage you to try Dagger for injections
You can use ArgumentCaptor (Mockito's class).
Reference:
http://www.mdswanson.com/blog/2013/12/16/reliable-android-http-testing-with-retrofit-and-mockito.html
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.
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.