I created a class by extending HystrixCommand and configured timeout for the request using below code
HystrixCommandProperties.Setter().withExecutionIsolationThreadTimeoutInMilliseconds(int milliSec);
Also overriden fallBack method when request not returns response within timeout specified
#Override
protected JSONObject run() throws Exception
{
// performed some http call
final HttpEntity<String> httpEntity = new HttpEntity<>(httpHeaders);
ResponseEntity<String> response = restTemplate.exchange(requestUrl, HttpMethod.GET, httpEntity, JSONObject.class)
.getBody();
System.out.println(response);
return response;
}
#Override
protected JSONObject getFallback()
{
final JSONObject json = new JSONObject();
json.put("status", "900");
json.put("message", "Request Failed");
return json;
}
Am getting fallBack method response whenever request takes more time than timeout specified which is expected.
But, what I observed is, when timeout occurs fallBack response is getting returned, and the response of the request which is executed in run method is coming later and am not able to hold or return as we returned the fallback response as soon as timeout.
Is there any way I can return that response ?
Thanks in advance.
Related
I am trying to integrate Twilio to my AngularJS and spring MVC application. After following Twilio documentation I set up at front end device setup and calling etc. In Java class I am generating a token, and passing that token while making the call. In java the code is:
#RequestMapping(value = "/phoneCalling", method {
RequestMethod.GET, RequestMethod.POST
})
public #ResponseBody Phone phoneCalling(HttpServletRequest request, HttpServletResponse response, #RequestParam String leadPhone) {
try {
Number number = new Number.Builder(leadPhone).build();
Dial dial = new Dial.Builder().number(number).build();
VoiceResponse responseVR = new VoiceResponse.Builder().dial(dial).build();
System.out.println(responseVR.toXml());
} catch (TwiMLException e) {
e.printStackTrace();
}
return null;
}
At twilio TwiML, I set request URL as:
https://865c048b.ngrok.io/ZingyCRM/phoneCalling/
As I am testing locally, so used ngrok. But after clicking on make a call, it gives me voice message as application error occurred. I believe the TwiML request URL I might be setting wrong, can some one help here?
I am using ConnectionRequest and downloadImageToStorage to download an image from a web server. The webserver is returning a 307 with a location, that next url returns a 301 with another location, that location finally returns the actual image.
I defined a FailureCallback, but it is not getting called at all. All I can see is a message on the device screen that indicates the error and has a retry/cancel buttons.
Here is my code
FailureCallback<Image> failure = new FailureCallback<Image>() {
public void onError(Object sender, Throwable err, int errorCode, String errorMessage) {
System.out.println(errorCode);
if (errorCode == 307 || errorCode == 301) {
System.out.println(sender.getClass().getName());
}
}
};
ConnectionRequest request = new ConnectionRequest();
request.setUrl(url);
request.setHttpMethod("GET");
request.downloadImageToStorage("img_" + imgCount, (img) -> {
SpanLabel t = new SpanLabel();
t.add(BorderLayout.CENTER, img);
myform.add(t);
}, failure);
++imgCount;
How can I capture these errors so I can get the Location from the Response objects and call those with new ConnectionRequests?
Note that I can see the chain of error codes and locations when I use the debugger in Chrome to get the image that I am trying to load.
Thanks
To capture error code and error message setReadResponseForErrors method should be called and override handleErrorResponseCode method of ConnectionRequest as shown in below code
request .setReadResponseForErrors(true);
#Override
protected void handleErrorResponseCode(int code, String message) {
Dialog.show("Message", " code "+ code+" msg "+message, "ok", null);
}
As Shai mentioned in his comment, there was a bug that caused 307 to be interpreted as an error response, rather than a redirect. This should now be fixed in the latest, and this should cause your example to work.
There is also another bug which has not been fixed that prevents the onError() callback from being called when there is an error response code. This will be fixed soon. In the mean time, your example should work (and the onError() will not be called) with 301 and 307 response codes.
I have a following class:
public class SessionStore {
Subject<Session, Session> subject;
public SessionStore() {
subject = new SerializedSubject<>(BehaviorSubject.create(new Session());
}
public void set(Session session) {
subject.onNext(session);
}
public Observable<UserSession> observe() {
return subject.distinctUntilChanged();
}
}
In activity I observe the session and perform network operation on each change:
private Subscription init() {
return sessionStore
.observe()
.flatMap(new Func1<Session, Observable<Object>>() {
#Override
public Observable<Object> call(Session session) {
return (session.isValid()
? retrofitService.getThingForValid()
: retrofitService.getThingForInalid())
.subscribeOn(Schedulers.io());
}
})
.subscribe(...);
}
Now I have an Okhttp request interceptor, in which I set the session instance from valid to invalid when network response is non 200 code.
This is what happens:
On initial subscription to session store the getThingForValid() is executed, and fails.
OkHttp intercepts the fail and sets new session.
Session store emits a new, now invalid session.
The new emission executes a getThingForInvalid() method.
What is important to know is that this execution happens in the middle of the previous Retrofit call. This is because OkHttp client is wrapped by Retrofit and all interceptors are executed before Retrofit returns.
Having this in mind, you realize that the second call is being executed and processed by Retrofit already, while the first one hasn't finished yet.
As the first call finishes, it throws HttpException because response was non 200 code.
The xception kills the rx stream and with it the second call.
I have tried to ignore this exception in stream but the second call is cancelled by Retrofit anyways.
Do you have any ideas how to make my concept work please?
if you get response code 401 in case of token expiration:
you need to add Authenticator in to OkHttpClient.Builder
builder.authenticator(new Authenticator() {
#Override
public Request authenticate(Route route, Response response) throws IOException {
final LoginResponse newLoginResponse = refreshTokenClient.refreshToken();
//save new token locally, if needed
return response
.request()
.newBuilder()
.removeHeader("Api-Auth-Token") // removing old header
.addHeader("Api-Auth-Token", newLoginResponse.getAuthToken())
.build();
}
});
where
public interface RefreshTokenService {
#PUT("/api/v1/tokens")
LoginResponse refreshToken();
}
But pay attention: this Authenticator will run each time when response code is 401.
I am getting a strange situation at the code below which simply routes request to Google and returns response.
It works well but when I activate the line commented out as "//Activating this line causes empty response on browser" to print out returned response from http endpoint (Google), response is disappear, nothing is displayed on browser. I thought it might be related with input stream of http response which can be consumed only once and I activated Stream Caching on context but nothing changed.
Apache Camel version is 2.11.0
Any suggestions are greatly appreciated, thanks in advance.
public class GoogleCaller {
public static void main(String[] args) throws Exception {
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder() {
public void configure() {
from("jetty:http://0.0.0.0:8081/myapp/")
.to("jetty://http://www.google.com?bridgeEndpoint=true&throwExceptionOnFailure=false")
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
System.out.println("Response received from Google, is streamCaching = " + exchange.getContext().isStreamCaching());
System.out.println("----------------------------------------------IN MESSAGE--------------------------------------------------------------");
System.out.println(exchange.getIn().getBody(String.class));
System.out.println("----------------------------------------------OUT MESSAGE--------------------------------------------------------------");
//System.out.println(exchange.getOut().getBody(String.class)); //Activating this line causes empty response on browser
}
});
}
});
context.setTracing(true);
context.setStreamCaching(true);
context.start();
}
}
As you use a custom processor to process the message, you should keep it in mind the in message of the exchange has response message from the google, if you are using exchange.getOut(), camel will create a new empty out message for you and treat it as response message.
Because you don't set the out message body in the processor, it makes sense that you get the empty response in the browser.
So here I am,got some help from some web tutorials and performing following Asynchronous call. I want to return an object of type UserInfo from following async call. But I'm not sure how the program flows after request.BeginResponse(). Is it something like an additional ref parameter of type UserInfo can be passed to callback method?
UserInfo GetUserInfoAsync()
{
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.Credentials = new NetworkCredential("myID", "myPWD");
request.Method = "GET";
request.Accept = "application/json";
object data = new object();
RequestState state = new RequestState(request, data, url);
IAsyncResult asr = request.BeginGetResponse(new AsyncCallback(myCallback), state);
return null; //Need guidence here;
}
private static void myCallback(IAsyncResult result)
{
RequestState state = (RequestState)result.AsyncState;
WebRequest request = (WebRequest)state.Request;
HttpWebResponse response =(HttpWebResponse)request.EndGetResponse(result);
Stream s = response.GetResponseStream();
StreamReader readStream = new StreamReader(s);
string dataString = readStream.ReadToEnd();
response.Close();
s.Close();
readStream.Close();
UserInfo ui = ParseJSON(dataString );
}
Your GetUserInfoAsync method will return before the request has completed. That's the meaning of it being asynchronous. You need to make your callback take appropriate action with the UserInfo it's just received - e.g. calling back into the UI thread (using Dispatcher) to update the UI.
You could make your GetUserInfo call wait until it's got a result - but you basically shouldn't. The whole point of asynchronous calls is to avoid blocking.
You need to handle the data in your callback. If you need to return the user info from your initial method call, you need a synchronous operation. There's no way to have that information available until the operation completes.
return null; //Need guidence here;
You cannot return anything meaningful at that point. Use event from callback to notify that result is ready.