I am currently using java and spring boot to get authorized in a API. It depends on the value that users inserts to see weather the api is valid or not.If it's valid it would basically display data.
Main Problem
When user enters wrong value in the end of the api. I get error 500 "internal server error" and it stops my spring application. I want to create an exception where it would catch this error and spits out that there's an error 500 rather than stopping my application. Even with wrong value I want my application to continue running.
Error
When users enter the wrong params I receive an error below
org.springframework.web.client.HttpServerErrorException: 500 Internal Server Error
How can I override it, so that even if user enter wrong data, Don't break my application and continue running. Just display Null for data.
Attempt to handle
I was able to allow my application to continue running with following code below
try { //OauthRestTemplate exhanges credentials for api access
} catch (HttpServerErrorException e ) {
e.getStatusCode();
logger.info(e + "Server bypass, Continue running application");
//allow application to continue running but does not display the actual message that would be on the api.
}
//output
org.springframework.web.client.HttpServerErrorException: 500 Internal Server ErrorServer bypass, Continue running application
But I want it to by pass the status 500 and display the actual message when I am on the api with wrong parameters. I should receive the same values that are printed on the api. Example Below
{"message":"Physical resource does not exist for mac address: D","code":"APRO-2001","timestamp":1490895756655,"type":"com.server.camp.framework.exception.ErrorResponse","status":"INTERNAL_SERVER_ERROR"}
I don't know if this applies to your problem (as you did not provide your code yet) but this might help:
#ResponseStatus(value=HttpStatus.NOT_FOUND, reason="No such Order") // 404
public class OrderNotFoundException extends RuntimeException {
// ...
}
You can basically add the #ResponseStatus to a function inside your class, set the value to the appropriate one (in your case INTERNAL_SERVER_ERROR as shown here).
I hope this helps! If not, please provide your code.
Maybe this link about Exception-Handling in spring might help: https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
Related
I am working on a Java application that pulls messages from an Azure Service Bus queue. I am using the Java Azure API (com.microsoft.windowsazure.services). The problem that I'm experiencing is that the deletion of brokered messages after they had been processed sometimes fails.
My application pulls a message from the queue using the receiveQueueMessage() method on a ServiceBusContract object, using peek-lock receive mode. Once the message had been sucessfully processed, I remove the message from the queue by calling the deleteMessage() method (I believe this method corresponds to the Complete() method in the .NET API).
However, sometimes this method call fails. A com.sun.jersey.api.client.UniformInterfaceException exception is logged to the console by deleteMessage(), but it does not throw this exception (I'll produce the output below). The exception seems to tell that the message could not be found. When this happens, the message stays in the queue. In fact, the next call to receiveQueueMessage() retrieves this message again. The deletion then fails once or twice more, and then it succeeds. The messages retrieved thereafter delete successfully.
Here is the code where the problem occurs:
ReceiveMessageOptions receiveOptions = ReceiveMessageOptions.DEFAULT;
receiveOptions.setReceiveMode(ReceiveMode.PEEK_LOCK);
BrokeredMessage message = serviceBus.receiveQueueMessage("my_queue",receiveOptions).getValue();
// Process the message
System.out.println("Delete message with ID: "+message.getMessageId());
serviceBus.deleteMessage(message);
Here is an example of the output when the problem occurs:
Delete message with ID: 100790000086491
2013/01/22 12:58:29 com.microsoft.windowsazure.services.serviceBus.implementation.ServiceBusExceptionProcessor processCatch
WARNING: com.sun.jersey.api.client.UniformInterfaceException: DELETE https://voyagernetzmessaging.servicebus.windows.net/sms_queue/messages/24/efa56a1c-95e8-4cd6-931a-972eac21563a returned a response status of 404 Not Found
com.sun.jersey.api.client.UniformInterfaceException: DELETE https://voyagernetzmessaging.servicebus.windows.net/sms_queue/messages/24/efa56a1c-95e8-4cd6-931a-972eac21563a returned a response status of 404 Not Found
at com.sun.jersey.api.client.WebResource.voidHandle(WebResource.java:697)
at com.sun.jersey.api.client.WebResource.delete(WebResource.java:261)
at com.microsoft.windowsazure.services.serviceBus.implementation.ServiceBusRestProxy.deleteMessage(ServiceBusRestProxy.java:260)
at com.microsoft.windowsazure.services.serviceBus.implementation.ServiceBusExceptionProcessor.deleteMessage(ServiceBusExceptionProcessor.java:176)
at microworks.voyagernetzmessaging.smsservice.SmsSender$Runner.finalizeSms(SmsSender.java:114)
at microworks.voyagernetzmessaging.smsservice.SmsSender$Runner.finalizeSms(SmsSender.java:119)
at microworks.voyagernetzmessaging.smsservice.SmsSender$Runner.run(SmsSender.java:340)
com.microsoft.windowsazure.services.core.ServiceException: com.sun.jersey.api.client.UniformInterfaceException: DELETE https://voyagernetzmessaging.servicebus.windows.net/sms_queue/messages/24/efa56a1c-95e8-4cd6-931a-972eac21563a returned a response status of 404 Not Found
Response Body: <Error><Code>404</Code><Detail>The lock supplied is invalid. Either the lock expired, or the message has already been removed from the queue..TrackingId:4b112c5a-5919-4680-b6bb-e10a2c081ba3_G15_B9,TimeStamp:1/22/2013 10:58:30 AM</Detail></Error>
at com.microsoft.windowsazure.services.serviceBus.implementation.ServiceBusExceptionProcessor.deleteMessage(ServiceBusExceptionProcessor.java:179)
at microworks.voyagernetzmessaging.smsservice.SmsSender$Runner.finalizeSms(SmsSender.java:114)
at microworks.voyagernetzmessaging.smsservice.SmsSender$Runner.finalizeSms(SmsSender.java:119)
at microworks.voyagernetzmessaging.smsservice.SmsSender$Runner.run(SmsSender.java:340)
Caused by: com.sun.jersey.api.client.UniformInterfaceException: DELETE https://voyagernetzmessaging.servicebus.windows.net/sms_queue/messages/24/efa56a1c-95e8-4cd6-931a-972eac21563a returned a response status of 404 Not Found
at com.sun.jersey.api.client.WebResource.voidHandle(WebResource.java:697)
at com.sun.jersey.api.client.WebResource.delete(WebResource.java:261)
at com.microsoft.windowsazure.services.serviceBus.implementation.ServiceBusRestProxy.deleteMessage(ServiceBusRestProxy.java:260)
at com.microsoft.windowsazure.services.serviceBus.implementation.ServiceBusExceptionProcessor.deleteMessage(ServiceBusExceptionProcessor.java:176)
... 3 more
Do note that the URI in the exception seems to refer to a different message ID (efa56a1c-95e8-4cd6-931a-972eac21563a, while the message's ID is in fact 100790000086491). I do not know if this could be a key to the failure, but I have a hunch.
Another interesting observation: it looks as though the error always happens with the first message that is retrieved from the queue after the application had been started, or after the queue had been empty. All the messages coming thereafter don't seem to ever cause this type of problem.
The queue has a lock duration of 2 minutes, and the processing of the messages takes well under that duration, so an expiring lock cannot be the cause.
Any ideas?
I would suggest you to call Complete() of BrokeredMessage class.
So in your case, try calling:
message.Complete();
When the Service bus sees Complete(), it considers the message to be consumed and removes it from the queue.
The UUID that appears in the URL is a random token that the server uses to track which message is locked; it is not supposed to the be same as the message id. You can access the lock URL using message.getLockLocation().
The code you have looks correct, I cannot see any obvious reason why it would fail, especially in the say you describe. Some things to check:
Check that the message you get is a valid message. If you peek-lock an empty queue, it will return an empty message. Then the lock location should be null. (But that would not cause the failure you see.)
You could get the lock supplied is invalid error if you are trying to delete the same message more than once. That could happen if you have code that notices when the service returns an empty message, and substitutes the previous message. (But that would not explain why trying to delete the message eventually works, unless it is a different message that is getting deleted.)
Hopefully that will help!
In the JavaPNS docs, I see this:
To find out if a push was successfully sent to Apple and that Apple did not return any error-response packet, simply invoke the pushedNotification.isSuccessful() method. A notification might not be successful if any of these conditions occur:
the library rejected the token you provided because of obvious specs violations (ex: token not 64-bytes long, etc.)
the library rejected the payload you provided because of obvious specs violations (ex: payload too large, etc.)
a connection error occurred and the library was not able to communicate with Apple servers
an error occurred with your certificate or keystore (ex: wrong password, invalid keystore format, etc.)
a valid error-response packet was received from Apple servers
and many other possible errors...
But the code snippet provided then does
for (PushedNotification notification : notifications) {
if (notification.isSuccessful()) {
/* Apple accepted the notification and should deliver it */
System.out.println("Push notification sent successfully to: " + notification.getDevice().getToken());
/* Still need to query the Feedback Service regularly */
} else {
String invalidToken = notification.getDevice().getToken();
/* Add code here to remove invalidToken from your database */
/* Find out more about what the problem was */
Exception theProblem = notification.getException();
theProblem.printStackTrace();
/* If the problem was an error-response packet returned by Apple, get it */
ResponsePacket theErrorResponse = notification.getResponse();
if (theErrorResponse != null) {
System.out.println(theErrorResponse.getMessage());
}
}
}
Which seems to imply that isSuccess() == false means an unrecoverable error, and that the device token is not valid.
However, the list of possible reasons did say that isSUccess() might be false due to a legitimate error packet being returned. I don't know, but I imagine one might be returned if Apple failed to send the notification due carrier issues, for example, which means the token is not necessarily invalid.
Is the correct way to read this, then, that isSuccess() == false is an unrecoverable error when sending a message, but not one that requires an exception, like a keystore fail or an inability to connect to the servers at all?
In other words - id isSuccessful() == false, should I really delete the device token from my DB as suggested? The snippet says yes, but the documentation seems to me to suggest otherwise...
Links: http://code.google.com/p/javapns/wiki/ManagingPushErrors
Thanks in advance to anyone who has braved this long, rambling question.
-- Snorkel
The documentation says that you are correct. Technically it means the push failed, but not that it failed because of an exception. It could have failed because of a legitimate failure. (I define legitimate failure as we successfully connected, there were no obvious defects with the message, but the server declined to accept it.) The key line is the following:
IE To find out if a push was successfully sent to Apple and that Apple did not return any error-response packet, simply invoke the pushedNotification.isSuccessful() method.
Your whole question seems pretty roundabout though. In a simple sense, your push failed. Does the distinction between an exception and a failure really matter? Either way its unrecoverable and you need to check the logs to see exactly what happened.
I've already looked for the answer for this question, and I've found the following suggestions:
If you are always expecting to find a value then throw the exception if it is missing. The exception would mean that there was a problem. If the value can be missing or present and both are valid for the application logic then return a null.
Only throw an exception if it is truly an error. If it is expected behavior for the object to not exist, return the null.
But how should I interpret them in my (so casual) case:
My web app controller is receiving request to show details for a user with a certain id. Controller asks the service layer to get the user, and then the service returns the object, if it's found. If not, a redirect to 'default' location is issued.
What should I do when someone passes invalid user id inside the request URL? Should I consider it as "expected behaviour" and return null to the controller, or perhaps should I call it a "problem or unexpected behaviour" and thus throw an exception inside the service method and catch in inside the controller?
Technically it's not a big difference after all, but I'd like to do it the right way by following standard convetions. Thanks in advance for any suggestions.
EDIT:
I assume, that the URLs generated by the app are valid and existing - when clicked by user, the user with a certaing id should be found. I want to know how to handle a situation, when user tries to access URL with wrong (not existing) user id, by manually typing the URL into browser's address bar.
If I understand you correctly, the request containing the user ID is coming from a client (out of your control). Applying the rules of thumb you quoted: invalid user input is an entirely expectable case, which would not require an exception, rather handle the null value gracefully by returning an appropriate error message to the client.
(OTOH if the user id in the request were automatically generated by another app / coming from DB etc, an invalid user ID would be unexpected, thus an exception would be appropriate.)
My personal suggestion would be to log the error details (IP address, the invalid user ID) and re-direct the user to an error page which says that some error has occurred and the administrators have been notified. Click on so-n-so link to go back to your home page etc.
Point being, whether you throw exception or return null, just make sure that the outermost filter or handler "logs" the details before the response is returned to the user.
What should I do when someone passes invalid user id inside the request URL?
You have two choices: show the 'default' page you mentioned or return a "Not found" / 404.
Regarding null, it depends. If you consider null unacceptable for a reference, then annotate it with #NotNull and the annotation shall take care of doing the correct thing upon getting a null reference: that is, throwing an (unchecked) exception (of course you need to work with the amazing #NotNull annotation for this to work).
What your do higher up the chain is up to you: to me returning a 404 to someone trying to fake user IDs sounds really close to optimal.
I access a Sybase database from a Java application. I can connect to it, execute statements, all of this works fine.
My issue is that I would like to handle correctly the cases when connection fails.
From my understanding, it can fail for the following reasons:
Incorrect password
Password expired
Account is locked
So my question is: how can I properly handle these error cases, how can I recognize which one happened?
From several tests, I found out the different cases:
Expired password
In this case, the database allows a connection, but a very limited one. The only thing you can call is the procedure to change password. The connection returned comes with a SQLWarning with the errorcode 4022, and a description stating:
The password has expired, but you are
still allowed to log in. You must
change your password before you can
continue. If a login trigger is set,
it will not be executed.
Thanks to the specific error code, it is possible to recognized the error, and propose to change the password in the client program.
Invalid password and Locked account
There is no difference for both cases. When requesting a connection, it throws a SQLException which links to a SQLWarning as next exception, with the error code 4002, and a very simple description:
Login failed.
As such, there is not really a way to handle these cases specifically.
Bonus case: password expiring soon
When a password will expire soon, the connection returned will contain a SQLWarning with the code 4023, stating:
Your password will expire in %s days.
This allows to show a warning in the client program, proposing the change the password already.
Handle it like you would other messages from the database. Catch the exception a log the message (this will help you identify the cause. At the same time display a message to the user that either a database error occurred or that the database could not be accessed.
I am using Tapestry 5, Smack api 3.1.0.
I have established a connection and am able to communicate with a user through the xmpp server but the replies i get are sent to the standard output as they come in:
Chat chat = connection.getChatManager().createChat("blah#jabber.org", new MessageListener() {
public void processMessage(Chat chat, Message message) {
// Print out any messages we get back to standard out.
System.out.println("Received message: " + message.getBody()); // this works
showonbrowser = message.getBody();
System.out.println(showonbrowser) // this prints nothing
}
};
I am looking to get the replies to my html file so i can read them on the web instead of the console. However, when i try to set message.getBody() to showonbrowser (a property on the page) i see no result. Does anyone know how I get around this?
Regards,
Kace
Smack is multi-threading and it has a nasty habit of eating up exceptions that are thrown (silently.) Most likely you are not using a thread-safe GUI and its throwing an exception that you never get.
I think the processMessage method is being called after the page is rendered.
You are creating a MessageListener instance (through an anonymous class), so you don't know when the processMessage method will be called. I think you would have to do something with AJAX to do partial updates on the page, polling the server and getting any new messages to show them on the page.