JavaPNS error handling - contradiction in the documentation? - java

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.

Related

Why retryOnConnectionFailure(true) is a solution to OkHttp Error : java.io.IOException: unexpected end of stream

I had this error for quite a while now when i found this.
After using the solution provided by swankjesse the error disappeared.
I just cant seem to understand why this is a solution. I cant find anything online that
explains the reason why this method solves the error.
OkHttp Docs say:
retryOnConnectionFailure
Configure this client to retry or not when a connectivity problem is
encountered. By default, this client silently recovers from the
following problems:
Unreachable IP addresses. If the URL’s host has multiple IP
addresses, failure to reach any individual IP address doesn’t fail the
overall request. This can increase availability of multi-homed
services.
Stale pooled connections. The ConnectionPool reuses sockets to
decrease request latency, but these connections will occasionally time
out.
Unreachable proxy servers. A ProxySelector can be used to attempt multiple proxy servers in sequence, eventually falling back to a
direct connection.
The above is understandable but it does not justify why this is a solution to that error.
Thanks in advance.
This flag allows OkHttpClient to retry a request multiple times when certain conditions are true that mean it is known to be safe. Without this flag the client will return the error immediately for the client to presumably dcide if and when to retry.
private fun isRecoverable(e: IOException, requestSendStarted: Boolean): Boolean {
// If there was a protocol problem, don't recover.
if (e is ProtocolException) {
return false
}
// If there was an interruption don't recover, but if there was a timeout connecting to a route
// we should try the next route (if there is one).
if (e is InterruptedIOException) {
return e is SocketTimeoutException && !requestSendStarted
}
// Look for known client-side or negotiation errors that are unlikely to be fixed by trying
// again with a different route.
if (e is SSLHandshakeException) {
// If the problem was a CertificateException from the X509TrustManager,
// do not retry.
if (e.cause is CertificateException) {
return false
}
}
if (e is SSLPeerUnverifiedException) {
// e.g. a certificate pinning error.
return false
}
// An example of one we might want to retry with a different route is a problem connecting to a
// proxy and would manifest as a standard IOException. Unless it is one we know we should not
// retry, we return true and try a new route.
return true
}
In the most simple case, if we hadn't started sending a request then we know retrying must be safe. Likewise certain response codes like 408 indicate that the server hasn't started any work so we can try again.

How to get TradeCaptureReport (AE) message when using quickfixj?

I am sending a Trade capture report request with 35 = AD. I am getting an acknowledge message back with 35=AQ(TradeCaptureReportRequestAck) with 750 =0 and another acknowledge message 35=AQ with 750=1. However I am not getting any 35=AE(TradeCaptureReport) messages even though there are trades booked on ICE.
I am using quickfixj.
You need to read the ICE FIX Trade Capture interface documentation.
If you don't see any AE messages in your message log, then they're not being sent to you. If you get an AQ/750=0 followed by a AQ/750=1 with no AEs in between, that means you've successfully received a TCR set of size 0.
I am quite familiar with the ICE FIX Trade Capture API. Their documentation is pretty good; please review it to make sure you understand how requests are honored.
As Grant pointed out it is important to differentiate between message received in log file and message received in your application. If the latter is not happening although you are seeing the messages in your log then you need to look at your MessageCracker implementation.

Handling FIX Reject: retrieve FIX message by sequence number in RefSeqNum using QuickFix/J

I am trying to handle a FIX Reject (MsgType 35=3), but I am unclear on how to retrieve the message that is referred to by the FIX Reject message.
The FIX Reject refers to the rejected message by MsgSeqNum, in the RefSeqNum field (tag 45). However I don't know how to get the rejected message by its sequence number. I think it should be possible because the FIX engine can resend messages in a sequence number range (in response to a resend request), so if the engine can do it so should I.
The question: how do I get the message that is referenced by the reject message in the RefSeqNum field?
Do you want to programmatically handle this failure? Generally the lower level rejects should never happen in the production environment. I have always dealt with them while testing and manual inspection of messages to identify the actual message and the tag having the problem.
In any case you can programmatically get the message by:
First looking up the session using Session Session.lookupSession(SessionID sessionId)
Get the MessageStore associated with the Session using MessageStore Session.getStore()
Obtain the actual message using MemoryStore.get(int startSequence, int endSequence, Collection<String> messsages)
You can find API documentation for QuickFIX/J here, or visit the documentation folder.
Note that in step 3 you will have to pass the same sequence number as the start and the end sequence number.

how resolve Address Invalid exception

We tried to send mail using javax.mail. While sending mails we got following exception:
**sendMail - Message Sending Failed: Invalid Addresses;
nested exception is:
javax.mail.SendFailedException: 550 #5.1.0 Address rejected.2013-02-28 13:17:08,236**
What might be the problem?
It means that the receiving server does not recognise the mailbox (the part before the '#') of the e-mail address. It could be that it was misspelled, that it is simply a non-existing name, or it could even be that the receiving server was set to reject a message (e.g. spam) by replying with code 550.
Here is one of many pages that summarises the SMTP reply codes, and gives links to various relevant RFCs: http://www.greenend.org.uk/rjk/tech/smtpreplies.html.
EDIT: I need a bit more space to answer your question than the comments allow.
#RaghuKing, if you look at the Javadoc for javax.mail.SendFailedException, you will notice that you can call 3 methods on such an exception object (inside the catch block):
getInvalidAddresses() to get an array of addresses that are invalid and thus not sent to,
getValidSentAddresses() to get an array of addresses to which this message was sent succesfully, and
getValidUnsentAddresses() to get an array of addresses that are valid but to which the message was not sent to.
(Obviously, if one sends a message to multiple recipients, some may succeed and some fail, but the exception is thrown if there is at least one failure, regardless of how many successes. Obviously also if you are sending to only one address, you will have that one address in only one of these arrays, and it will probably NOT be in the ValidSent list.
These arrays will give you more information how to handle the exception, depending of the type of array an address is in. This will obviously depend on you application, but these might be reasonable suggestions:
Invalid Addresses: tell the user that the message was not sent because the address was wrong, for each invalid address in the list, and provide a way to correct the address, then try to resend to the correct address (or cancel if the user does not provide a different address);
Valid Sent Addresses: Don't resend;
Valid Unsent Addresses: Try to resend to these addresses. Sending probably stopped before getting to these addresses because of a previous incorrect address.
But in the end it is you who has to apply common sense, and perhaps experiment a little with the functions you don't understand until you understand them.
This code can print logs for invalid address(es):
try {
sender.send(message);
}catch (MailSendException me){
detectInvalidAddress(me);
}
private void detectInvalidAddress(MailSendException me) {
Exception[] messageExceptions = me.getMessageExceptions();
if (messageExceptions.length > 0) {
Exception messageException = messageExceptions[0];
if (messageException instanceof SendFailedException) {
SendFailedException sfe = (SendFailedException) messageException;
Address[] invalidAddresses = sfe.getInvalidAddresses();
StringBuilder addressStr = new StringBuilder();
for (Address address : invalidAddresses) {
addressStr.append(address.toString()).append("; ");
}
logger.error("invalid address(es):{}", addressStr);
return;
}
}
logger.error("exception while sending mail.", me);
}
Had experienced this same exception .I realized that i could not send email to unknown users . After consulting , i found out that our SMTP server was not an open mail relay server read Open mail Relay.

Windows Azure: Error when deleting brokered message

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!

Categories

Resources