ExternalContext redirect leads to IllegalStateException - java

I am facing a problem that is coming from one of our users. Somehow, the user manages to make multiple redirects with just one click. And by doing this, the redirect method is called multiple times and this leads to the IllegalStateException. I tried to first check if the response is committed and only call the redirect method if the response is not committed. And it works. Just one redirect request instead of all is being sent to the browser. But I was wondering if it's possible to send multiple redirects statements. Is it possible to create a new request with a new response after the old response was committed ?
Here is the working check for the committed redirect:
public static final boolean redirect(String targetPath) {
try {
if(!isCommitted()) {
exContext().redirect(checkAppendContextPath(targetPath));
return true;
}else{
return false;
}
} catch (IOException e) {
if (LOG.isErrorEnabled()) {
LOG.error(String.format(ERROR_REDIRECT, context().getViewRoot().getViewId(), targetPath));
}
return false;
}
}
private static final boolean isCommitted(){
if(exContext().getResponse() instanceof HttpServletResponse){
if(((HttpServletResponse) exContext().getResponse()).isCommitted()){
return true;
}else{
return false;
}
}else{
return false;
}
}

No, requests cannot be made on the server side. They must originate from the client.
I find it hard to believe that multiple requests are triggered from a single click, unless there is JavaScript involved. If JavaScript is involved, check it for bugs. Else, you could try to prevent multiple clicking at the client side. If you are using PrimeFaces and the redirect is triggered from a p:commandButton, you could try using the PrimeFaces Extensions CommandButtonSingleClickRenderer.

Related

Java RabbitMQ consumer.nextMessage always gets same message

We are using Java rabbitMq with spring boot in a distributed service architecture. One service gets an HTTP request and forwards it to an unkown queue for processing. At the same time it has to wait for a response on another queue before it can terminate the HTTP request. (It's a preview request that gets its work done by a renderer).
There can be more than one instance of ServiceA (the HTTP Interface) and ServiceB (the renderer) so with every preview message we also send a unique ID to be used as routing key.
I'm having trouble with the BlockingConsumer. Whenever I call consumer.nextMessage() I get the same message over and over again. This is doubly weird, as for one it should be ACKed and removed from the queue and for another the consumer shouldn't even bother with it as the unique ID we used is no longer bound to the queue. nextMessage even returns before the renderer service is done and has sent its done message back.
Here's the simplified setup:
general
All services use a global DirectExchange for all messages
#Bean
public DirectExchange globalDirectExchange() {
return new DirectExchange(EXCHANGE_NAME, false, true);
}
ServiceA (handles the HTTP request):
private Content requestPreviewByKey(RenderMessage renderMessage, String previewKey) {
String renderDoneRoutingKey= UUID.randomUUID().toString();
renderMessage.setPreviewDoneKey(renderDoneId);
Binding binding = BindingBuilder.bind(previewDoneQueue).to(globalDirectExchange)
.with(renderDoneRoutingKey);
try {
amqpAdmin.declareBinding(binding);
rabbitProducer.sendPreviewRequestToKey(renderMessage, previewKey);
return getContentBlocking();
} catch (Exception e) {
logErrorIfDebug(type, e);
throw new ApiException(BaseErrorCode.COMMUNICATION_ERROR, "Could not render preview");
} finally {
amqpAdmin.removeBinding(binding);
}
}
private Content getContentBlocking() {
BlockingQueueConsumer blockingQueueConsumer = new BlockingQueueConsumer(rabbitMqConfig.connectionFactory(), new DefaultMessagePropertiesConverter(), new ActiveObjectCounter<>(), AcknowledgeMode.AUTO, true, 1, PREVIEW_DONE_QUEUE);
try {
blockingQueueConsumer.start();
Message message = blockingQueueConsumer.nextMessage(waitForPreviewMs);
if (!StringUtils.isEmpty(message)) {
String result = new String(message.getBody());
return JsonUtils.stringToObject(result, Content.class);
}
throw new ApiException("Could not render preview");
} catch (Exception e) {
logError(e);
throw new ApiException("Could not render preview");
} finally {
blockingQueueConsumer.stop();
}
}
Service B
I'll spare you most of the code. My log says everything is going well and as soon as its done the service sends the correct message to the UUID key that was sent with the initial render request.
public void sendPreviewDoneMessage(Content content, String previewDoneKey) {
String message = JsonUtils.objectToString(content);
rabbitTemplate.convertAndSend(globalDirectExchange, previewDoneKey, message);
}
The whole thing works... Once...
The real issues seems to be the consumer setup. Why do I keep getting the same (first) message from the queue when I use nextMessage().
Doesn't creating and removing a Bindung ensure, that only messages bound to that routingKey are even received in that instance? And doesn't nextMessage() acknowledge the message and remove it from the queue?!
Thank's a lot for bearing with me and even more for any helpful answer!
BlockingQueueConsumer is not designed to be used directly; it is a component of the SimpleMessageListenerContainer, which will take care of acking the message after it has been consumed by a listener (the container calls commitIfNecessary).
There may be other unexpected side effects of using this consumer directly.
I strongly advise using the listener container to consume messages.
If you just want to receive messages on demand, use a RabbitTemplate receive() or receiveAndConvert() method instead.

javax.net.ssl.SSLHandshakeException: Connection reset by peer

I use following code to call an Azure mobile backend API in my Android app,
try {
mobileClient.invokeApi("CustomTransaction", senderToCheck,
Boolean.class, new ApiOperationCallback<Boolean>() {
#Override
public void onCompleted(Boolean result,
Exception error, ServiceFilterResponse response) {
if (error == null) {
CheckSender(result);
} else {
dial.dismiss();
Crouton.makeText(MyActivity.this,
"Eror Occured with service",
Style.ALERT).show();
}
}
});
} catch (SecurityException e) {
Log.d(TAG, "CouldNotConnectToSocket", e);
e.printStackTrace();
} catch (IllegalArgumentException e) {
Log.d(TAG, "CouldNotConnectToSocket", e);
e.printStackTrace();
}
Other information:
CustomTransaction - API Controller name;
senderToCheck - JSON parsable data transfer object;
Boolean.class - return type; and 4th parameter is the callback method
All objects are JSON parsable and this worked like several days ago.
So this API call/Azure call always times out giving a What does "connection reset by peer" mean? ,SSLHandShakeExceptionand and most of the time Connect gets Timed out.
Main cause for the problem is com.microsoft.windowsazure.mobileservices.MobileServiceException: Error while processing request.
I tried re-publishing my asp.net web app several times but it never hits controller action where my debugger point is placed when debugging the service call remotely.
I checked if my service is down, found it is up & running then checked Azure management portal logs, found out traceApi messages of some controller action methods. and of SQL Cpu usages and Data out packet sizes., but I never gets a proper reply from anywhere to solve this problem for two weeks now.
In case,if I am correct, think the solution for this problem lies in http://www.webapper.com/blog/index.php/2007/02/09/troubleshooting-javaxnetsslsslhandshakeexception/ but Im not pretty sure on doing it.
Please advise me on getting this fixed

Wicket setPageExpiredErrorPage only for specific page?

Is there any way to do that?
I heard something about implemented RequestCycle, how to acomplish that?
Tried How can I get the responsePage from a RequestCycle in Wicket 1.5? this, but doesnt work.
The reason why you get a PageExpiredException in Wicket is because Wicket is unable to find the page. There is no way of determining the type of the page that is no longer available, because, well, the page actually is no longer there. It ceased to exist, met its maker, bereft of life, rests in peace, its lifecycle are now 'istory, kicked the bucket. It is an ex-page.
So Wicket's only recourse is to serve the PageExpiredException, and there is no way (in Wicket itself) to retrieve the page that was attempted to resurrect.
Now what you can try to do is to store the class of the last rendered page in the session, and use that in your RequestCycleListener implementation of onException() and return the appropriate request handler. In code:
#Override
public void onRequestHandlerExecuted(RequestCycle cycle, IRequestHandler handler) {
Class<? extends Page> p = null;
if(handler instanceof IPageRequestHandler)
p = ((IPageRequestHandler)handler).getPageClass();
else if(handler instanceof IComponentRequestHandler)
p = ((IComponentRequestHandler)handler).getComponent().getPage().getClass();
MySession.get().setLastPageClass(p);
}
#Override
public IRequestHandler onException(RequestCycle cycle, Exception ex) {
Class<? extends Page> pageClass MySession.get().getLastPageClass();
... return some handler based on your logic
}
You might want to check for more IRequestHandler implementations in onRequestHandlerExecuted.
If I understand correctly you want to redirect user only if pageExpired happened from specific page? You can try something like this in you implementation of Application:
getRequestCycleListeners().add(new AbstractRequestCycleListener() {
#Override
public IRequestHandler onException(RequestCycle cycle, Exception e) {
if(e.getClass().equals(PageExpiredException.class)) {
//check if url in request responds to correct mounted page type
if(isPageUrl(cycle.getRequest().getUrl()))) {
return new RenderPageRequestHandler(new PageProvider(MyPage.class));
} else {
return super.onException(cycle, e);
}
} else {
return super.onException(cycle, e);
}
}
}
This assumes few things - that the page at which you got the exception has been mounted, and that you will be able to parse request url to be sure it is it.
I haven't tested it but we are doing something similar.

Does this program introduce a parallel execution?

Here is a simple server application using Bonjour and written in Java. The main part of the code is given here:
public class ServiceAnnouncer implements IServiceAnnouncer, RegisterListener {
private DNSSDRegistration serviceRecord;
private boolean registered;
public boolean isRegistered(){
return registered;
}
public void registerService() {
try {
serviceRecord = DNSSD.register(0,0,null,"_killerapp._tcp", null,null,1234,null,this);
} catch (DNSSDException e) {
// error handling here
}
}
public void unregisterService(){
serviceRecord.stop();
registered = false;
}
public void serviceRegistered(DNSSDRegistration registration, int flags,String serviceName, String regType, String domain){
registered = true;
}
public void operationFailed(DNSSDService registration, int error){
// do error handling here if you want to.
}
}
I understand it in the following way. We can try to register a service calling "registerService" method which, in its turn, calls "DNSSD.register" method. "DNSSD.register" try to register the service and, in general case, it can end up with two results: service was "successfully registered" and "registration failed". In both cases "DNSSD.register" calls a corresponding method (either "serviceRegistered" or "operationFailed") of the object which was given to the DNSSD.register as the last argument. And programmer decides what to put into "serviceRegistered" and "operationFailed". It is clear.
But should I try to register a service from the "operationFailed"? I am afraid that in this way my application will try to register the service too frequently. Should I put some "sleep" or "pause" into "operationFailed"? But in any case, it seems to me, that when the application is unable to register a service it will be also unable to do something else (for example to take care of GUI). Or may be DNSSD.register introduce some kind of parallelism? I mean it starts a new thread but that if I try to register service from "operation Failed", I could generate a huge number of the threads. Can it happen? If it is the case, should it be a problem? And if it is the case, how can I resolve this problem?
Yes, callbacks from the DNSSD APIs can come asynchronously from another thread. This exerpt from the O'Reilly book on ZeroConf networking gives some useful information.
I'm not sure retrying the registration from your operationFailed callback is a good idea. At least without some understanding of why the registration failed, is simply retrying it with the same parameters going to make sense?

How can I reuse a HttpClient connection efficiently?

I am doing HTTP POSTs very frequently (>= 1/sec) to an API endpoint and I want to make sure I'm doing it efficiently. My goal is to succeed or fail as soon as possible, especially since I have separate code to retry failed POSTs. There is a nice page of HttpClient performance tips, but I'm not sure if exhaustively implementing them all will have real benefits. Here is my code right now:
public class Poster {
private String url;
// re-use our request
private HttpClient client;
// re-use our method
private PostMethod method;
public Poster(String url) {
this.url = url;
// Set up the request for reuse.
HttpClientParams clientParams = new HttpClientParams();
clientParams.setSoTimeout(1000); // 1 second timeout.
this.client = new HttpClient(clientParams);
// don't check for stale connections, since we want to be as fast as possible?
// this.client.getParams().setParameter("http.connection.stalecheck", false);
this.method = new PostMethod(this.url);
// custom RetryHandler to prevent retry attempts
HttpMethodRetryHandler myretryhandler = new HttpMethodRetryHandler() {
public boolean retryMethod(final HttpMethod method, final IOException exception, int executionCount) {
// For now, never retry
return false;
}
};
this.method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, myretryhandler);
}
protected boolean sendData(SensorData data) {
NameValuePair[] payload = {
// ...
};
method.setRequestBody(payload);
// Execute it and get the results.
try {
// Execute the POST method.
client.executeMethod(method);
} catch (IOException e) {
// unable to POST, deal with consequences here
method.releaseConnection();
return false;
}
// don't release so that it can be reused?
method.releaseConnection();
return method.getStatusCode() == HttpStatus.SC_OK;
}
}
Would it make sense to disable the check for stale connections? Should I be looking at using the MultiThreadedConnectionManager? Of course, actual benchmarking would help but I wanted to check if my code is on the right track first.
Much of the performance hit of http connections is establishing the socket connection. You can avoid this by using 'keep-alive' http connections. To do this, it's best to use HTTP 1.1 and make sure that "Content-Length: xx" is always set in requests and responses, "Connecction: close" is correctly set when appropriate and is properly acted upon when received.

Categories

Resources