Retrofit custom timeout is not working - java

I am using retrofit version 2.3.0 and OkHttp version 3.8.1. I am facing a problem that I cannot change timeout for my requests. I was searching for answer in google and there is only one solution - Change timeouts in OkHttpClient and set it to retrofit builder, but it is not working :/. here is a code that I use for changing timeouts:
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson));
builder.client(new OkHttpClient.Builder()
.connectTimeout(50000, TimeUnit.MILLISECONDS)
.readTimeout(50000, TimeUnit.MILLISECONDS).build());
retrofit = builder.build();
But after this requests still lasts for 10 seconds and I get SocketTimoutException
EDIT
I have done some more research and I was testing it with different versions of Retrofit. I stoped on retrofit version 2.0.1 and this version also not allows me to change timeout :/. Have someone got any idea what to do now?
EDIT 2
I have this problem now in two places. I will describe the use case so maybe it will help with finding the solution.
use 1:
I want to download file from remote server. I call web service and I wait for response with file stream. I need to wait longer because web service needs to get file from database and put it into hard drive (there is no possibility to change it). When file is big copying it to hard drive takes time and application receives SocketTimeoutException.
use 2:
I upload file to the server (and it works fine). After upload I need to let web service know that it should load file into the database. I send the request and situation is similar to the use 1, because when file is big, loading takes much time and I get SocketTimeoutException.
UPDATE
I would like to clear up situation. The problem was occurring because I had the second OkHttpClient assigned to the Retrofit which was overriding timeout. If someone will have a similar problem I recommend to check if there is a similar situation to the one I was facing (second OkHttpClient that overrides timeout).

Did you try setting the .writeTimeout on the client:
.writeTimeout(50, TimeUnit.SECONDS)
Also while testing you can pass the timeout duration to 0 if you want the request to not timeout.
And also, the request would fail if there is any connectivity problem or server is not available. Try sending the same request using Postman.

Related

Can okHTTP3 make interceptions even when an external API is making the requests?

I had a general question regarding okHTTP, and I was hoping someone could clear things up for me. I want to intercept the HTTP headers on all outgoing network requests from my app. Here is the example provided on the okHTTP github:
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new LoggingInterceptor())
.build();
Request request = new Request.Builder()
.url("http://www.publicobject.com/helloworld.txt")
.header("User-Agent", "OkHttp Example")
.build();
Response response = client.newCall(request).execute();
response.body().close();
My problem is that I am using an external API to make the requests that I need in my application. Does this exclude me from being able to intercept the HTTP headers since it is the API building the request and not me? If so, is there any way to get around this? Thank you.
Ultimately it is always possible. 1 good answer, 3 bad answers depending on how critical it is...
The API will usually provide access to make changes to the default OkHttpClient it builds so you can set things like a proxy. Try to do this first.
less clean options you probably don't want to do.
You can MITM attack the client yourself. e.g. something like https://www.charlesproxy.com/
You can probably use reflection to get into the internal APIs of the library and change the client, but this is brittle and could still be technically impossible.
You can attack it via java bytecode agents https://github.com/yschimke/agentdebug

Retrofit - Different API responses on different devices

The problem exactly like the following
I have one api which can provide some data and one apk,
I got my api response with my device and another different old response on the emulator with the same apk!
The emulator response is up to date with the latest changes while the other different response is before the changes.
The app uses retrofit without caching.
So what could be the problem?
Request contains only one header (access token)
Response contains headers like (ETag, Access-Control-Max-Age) but retrofit should not deal with them as there is no cache at all.
Screen shot from postman :
Also when waiting for a while all devices become up to date!
Are you sure with this?
The app uses retrofit without caching
Based on this https://github.com/square/retrofit/issues/678, I think that retrofit (OkHttp inside retrofit) caching your query.
You can change this behavior by 2 ways:
add ?_t=TIMESTAMP into your app query url
remove 'Access-Control-Max-Age' header from your server response
Or you can create new OkHttp client to retrofit and write something like that:
new OkHttpClient.Builder().cache(null).build();
or
Request.cacheControl(CacheControl.FORCE_NETWORK)
So what could be the problem?
If you dont' find the problem on the client, you should look for it on the server side. Any kind of caching (on the database, or on the HTTP response level) can show this behavior.
Without further knowledge about your setup and your test environment it is impossible to figure out what the problem could be. You write
Also when waiting for a while all devices become up to date
What does that mean? How do you determine, if your devices are up to date?
In your complicated case, with backend involved, you should provide an example project on Github where this behavior can be reproduced.

Jersey update user on front-end while a big request is running

Currently I'm working on a single page application with java/jersey running as my back-end. But at the moment I have some requests that take a while (over 10 seconds). I was wondering if its possible to send updates back to the client with jersey?
I wanna use like a status bar but I have no clue how far the request is without updates from the back-end.
I couldn't find anything about this topic searching on google/stackoverflow. Maybe I'm using the wrong search terms.
If you don't want to use websockets there are a few approaches you can take.
Provide API to client that takes clientId and optionally processId and gives status of the process running on server.
Then client can have Javascript to asynchronously call this API and update progress bar.
In addition you can have server side Jersey resource start long running process asynchronously and immediately return response with estimated time and processId.

Jsoup, Reddit, OAuth2, and 429 HTTP Errors

So I'm trying to write an executable JAR for a small subreddit I run.
I have a post that Jsoup connects to and reads all the URLs on that page. In another method, it then connects to all those URLs (that are just comments on the post) and gets the HTML from the comments and saves them to a HashMap.
This is great however I am getting a 429 HTTP Error. So to resolve this, I added a short 5 second wait. Now I'm getting a SocketTimeoutException "Read timed out". Once I lowered the time down to 3 seconds, I was bouncing between the two.
Now I run a few Reddit bots with Python and I'm able to make a lot more requests than what I'm doing here. I actually have a single bot that makes thousands of requests every minute. So I know it's possible to make these requests.
My question essentially is, how am I able to make multiple requests to Reddit and avoid the 429 HTTP Error? I'm using Jsoup to connect and read the HTML.
While I'm sure connecting to Reddit via. their OAuth2 API will fix the issues, I have no idea how to actually use OAuth2 in Java (I actually use a wrapper in Python so it's fair to say I don't know at all) and I don't know how to then use that with Jsoup.
My question essentially is, how am I able to make multiple requests to Reddit and avoid the 429 HTTP Error?
You answer this yourself:
While I'm sure connecting to Reddit via. their OAuth2 API will fix the issues,
As specified in the API documentation, you get twice as many requests per second if authenticated using OAuth.
Have you looked around for examples on how to handle OAuth flows in Java?
You might also find it easier to use one of the wrapper libraries for Java, instead of handling all this yourself.
Just set header and you can easily pass it
User-Agent: super happy flair bot by /u/spladug

How I can change default timeout for web services call on Google app engine?

My Google App Engine application use a web service, this web service is pretty slow to respond and sometimes my application crashes :
java.net.SocketTimeoutException: Timeout while fetching URL: http://...
To call this web service, I use classes generated with wsimport (Java tool to parse an existing WSDL file and generate required files).
I need to change the default deadline (5 seconds) either for this call or globally for all my app URL fetches.
App engine docs :
You can set a deadline for a request, the most amount of time the service will wait for a response. By default, the deadline for a fetch is 5 seconds. The maximum deadline is 60 seconds for HTTP requests and 10 minutes for task queue and cron job requests. When using the URLConnection interface, the service uses the connection timeout (setConnectTimeout()) plus the read timeout (setReadTimeout()) as the deadline.
Source : https://developers.google.com/appengine/docs/java/urlfetch/#Java_Making_requests
I tried to add this lines (in strong below) in my code to change the deadline but it did'nt work :
URL urlConnection = new URL(url);
URLConnection connection = urlConnection.openConnection();
connection.setConnectTimeout(180000); // 3 minutes
connection.setReadTimeout(180000); // 3 minutes
SWS webService = new SWS(urlConnection, new QName("http://...", "SWS"));
Note : SWS is the main class generated by wsimport from my WSDL
Posted this here a min ago, as there was also no accepted answer: Can I globally set the timeout of HTTP connections?
For App Engine with JAX-WS you have to set the request context (tested today with SDK 1.9.15). For normal machines you cannot go higher than 60s and would have to switch to the bigger machines (Bx) for better use a task queue.
For local testing you would normally use BindingProviderProperties.CONNECT_TIMEOUT and BindingProviderProperties.REQUEST_TIMEOUT, but they are not on the App Engine JRE White List and your code inspection might constantly warn you about that.
The equivalent strings can be used though:
com.sun.xml.internal.ws.connect.timeout
com.sun.xml.internal.ws.connect.timeout
For deployment to App Engine:
com.sun.xml.ws.connect.timeout
com.sun.xml.ws.request.timeout
A full example how to apply that to auto-generated code from JAX-WS 2.x, values have to be provided in milliseconds:
#WebEndpoint(name = "Your.RandomServicePort")
public YourServiceInterface getYourRandomServicePort() {
YourRandomServiceInterface port = super.getPort(YOURRANDOMSERVICE_QNAME_PORT, YourRandomServiceInterface.class);
Map<String, Object> requestContext = ((BindingProvider)port).getRequestContext();
requestContext.put("com.sun.xml.ws.connect.timeout", 10000);
requestContext.put("com.sun.xml.ws.request.timeout", 10000);
return port;
}
This question had gone without an upvoted answer for a long time, and although the other answer is good, I want to raise two issues which take us outside the scope of this seemingly neat-and-tidy Q&A:
The issue of "changing the default timeout for web services calls on App Engine" depends what we mean by a web services call. There are many services within the Google Cloud Platform, within the wider web itself, and then there are the Java-specific notion of WSDL. All of these will have different methods, found in the relevant documentation, for changing timeout deadlines.
There have been cases where setting deadlines was not working due to an issue on the platform, as reported in the Public Issue Tracker for App Engine. If anybody reading this answer is experiencing a similar issue, feel free to open a Defect Report there, and we will quickly respond and attempt to fix an issue if one exists.

Categories

Resources