notnoop / java-apns Goto Github PK
View Code? Open in Web Editor NEWJava Apple Push Notification Service Provider
Home Page: notnoop.github.com/java-apns
License: BSD 3-Clause "New" or "Revised" License
Java Apple Push Notification Service Provider
Home Page: notnoop.github.com/java-apns
License: BSD 3-Clause "New" or "Revised" License
I created an ApnsService using the "asQueued" parameter in the builder. While debugging other problems I thought I might have to call "start" on the service so I added that line in not realizing that the "build" method of the builder called start for me. Looking at the code, it looks like calling start twice is intended to be handled (restart?) because it stops it before re-starting. However, I think there is a problem with the logic. It correctly recreates the thread but it leaves the member variable "started" as false because on line 66 of QueuedApnsService it sets it as true, but the stop method sets it as false.
I think the solution is to move lines 66 and lines 67 below the call to stop on line 69.
Hi notoop,
first thank you very much for your great work on the java-apns lib. The lib was really helpful for me to understand how Apple Push Notifications work. I just have one issue which i couldn't resolve right now (using version 1.6:
If i send a single message to a Collection of Receivers(via their token) i get the following log:
15:55:42.187 [main] DEBUG c.n.apns.internal.ApnsConnectionImpl - Made a new connection to APNS
15:55:42.909 [main] DEBUG c.n.apns.internal.ApnsConnectionImpl - Message "com.notnoop.apns.EnhancedApnsNotification@1063a555" sent
15:55:42.909 [main] DEBUG c.n.apns.internal.ApnsConnectionImpl - Message "com.notnoop.apns.EnhancedApnsNotification@1063a574" sent
15:55:42.910 [main] DEBUG c.n.apns.internal.ApnsConnectionImpl - Message "com.notnoop.apns.EnhancedApnsNotification@107944a6" sent
Error: INVALID_TOKEN
Identifier: 1
The error code is delivered to my ApnsDelegate where connectionClosed is called.
All tokens which were sent are fake tokens, because right now the iPhone App is still in development so we don't receive any real tokens yet.
So my question is, why is there only one error message after sending? What happens with
the other messages? I have no feedback if they were accepted (they are not because of the
fake tokens) but i will never know this because i can't receive them. Is this a limitation of the Apple Push Notifications or just of the lib?
Thank you very much for your help!
MonitoringThread throws SocketException when the socket being monitored closes. This happens, for example, when using the ReconnectPolicy.EVERY_HALF_HOUR. The relevant socket gets closed and a new one gets reset. Meanwhile, the MonitoringThread is still tracking that closed socket. The method call
in.read(bytes)
in ApnsConnectionImpl.MonitoringThread is blocking until something happens. Unfortunately, that something happens to be the closing of the socket, at which point it throws java.net.SocketException.
To reproduce issue:
Potential fixes:
I spent too much time on this to get so little result. The shame.
All exceptions thrown from the lib are wrapped in RuntimeException, I guess to avoid having to handle them however it makes it much more complicated to use and present errors to the user of the application. In some cases (for feedback service) the actual cause of the problem gets wrapped in two RuntimeExceptions.
I would much prefer having to handle the "real" exceptions and be confident that my code is rubust and error prune instead of having to browse the source to the lib to actually know when to expect exceptions, which leads to a maintenance problem at the end.
Just a suggestion to an improvement to a really good lib
I am getting a handshake failure at the begining of the conversation between my code and the sandbox/feedback servers of Apple. In my code, i construct an input stream, pointing to a p12 file that contains the original CSR (and thus my private key) and the certificate received from Apple using this CSR. After debugging, i noticed that my code does not send a certificate to the Apple's servers. After enabling the debug output for ssl, i also noticed that Apple's servers, at the end of ServerHello message they request a client certificate but do not provide an array of Cert Authorities as it is expected, as you can see from the following output:
Thread-7, READ: TLSv1 Handshake, length = 14
*** CertificateRequest
Cert Types: RSA, DSS, ECDSA
Cert Authorities:
*** ServerHelloDone
Has anybody else faced such an issue? Am i doing something wrong? Any answer will be greatly appreciated.
I would like to see JARs available for download for version 0.1.4, please. (It appears that java-apns is on version 0.1.4, but only 0.1.2 is available.) It would also be nice to have src JARs in here as well. Thanks!
When we try to send a notification to an inactive device, Apple drops our connection and further messages are not sent.
I know that I can trace this with using a delegate with connectionClosed method.
The question is, how can we restore the connection afterwards, any idea?
push notification with collection of token using :
service.push(listTokenByte,payloadByte);
is recommended or not?
I've a webapp sending out notification to the sandbox and another standalone test app sending notification to the sand box as well with the same cert and the same set of devices. In my webapp, the notification is not being delivered; but it delivers fine from my simple test app. There is no exception in the case when the notification is not delivered. I stepped into the code at ApnsConnectionImpl.sendMessage(), and compared the difference. I found the socket is at connectionState = 1 and the ssl session is still with SSL_NULL_WITH_NULL_NULL cipher suite. In the successful case, the ssl session is with SSL_RSA_WITH_RC4_128_MD5 cipher suite.
Do you have any idea what would be the problem?
Thanks.
kc
iPhone OS 4.0 is now supporting launch-image property.
The filename of an image file in the application bundle; it may include the extension or omit it. The image is used as the launch image when users tap the action button or move the action slider. If this property is not specified, the system either uses the previous snapshot,uses the image identified by the UILaunchImageFile key in the application’s Info.plist file, or falls back to Default.png.
http://notnoop.github.com/m2-repo gives a 404
ApnsServiceBuilder.withNoErrorDetection() seems to set errorDetection to true (the default value) instead of false, so it is always enabled:
public ApnsServiceBuilder withNoErrorDetection() {
this.errorDetection = true;
return this;
}
My uneducated guess is that the problem comes down to the SOCKS proxy socket not being closed when the main socket is closed; I see a connect but no close's anywhere for the underlyingSocket in ApnsConnectionImpl.
com.notnoop.exceptions.NetworkIOException: java.net.SocketException: already connected
at com.notnoop.apns.internal.ApnsConnectionImpl.socket(ApnsConnectionImpl.java:146) [apns-0.1.5.jar:na]
at com.notnoop.apns.internal.ApnsConnectionImpl.sendMessage(ApnsConnectionImpl.java:160) [apns-0.1.5.jar:na]
at com.notnoop.apns.internal.ApnsServiceImpl.push(ApnsServiceImpl.java:46) [apns-0.1.5.jar:na]
at com.notnoop.apns.internal.AbstractApnsService.push(AbstractApnsService.java:52) [apns-0.1.5.jar:na]
at com.notnoop.apns.internal.ApnsServiceImpl.push(ApnsServiceImpl.java:36) [apns-0.1.5.jar:na]
...
Caused by: java.net.SocketException: already connected
at java.net.Socket.connect(Socket.java:500) [na:1.6.0_07]
at java.net.Socket.connect(Socket.java:469) [na:1.6.0_07]
at com.notnoop.apns.internal.ApnsConnectionImpl.socket(ApnsConnectionImpl.java:135) [apns-0.1.5.jar:na]
... 73 common frames omitted
Any one has any idea about this exception. It was working unto yerterday.
Couldn't connec to APNS server
java.net.UnknownHostException: gateway.sandbox.push.apple.com
I was doing some testing and it seems that sandbox doesn't respond anymore right now because I'm getting the following exception when I try to push a message:
org.apache.mina.core.RuntimeIoException: Failed to get the session.
at org.apache.mina.core.future.DefaultConnectFuture.getSession(DefaultConnectFuture.java:60)
at com.notnoop.apns.internal.MinaAdaptor.push(MinaAdaptor.java:48)
at org.epseelon.conferenceguide.MessageService$_sendMessageToDevices_closure2.doCall(MessageService.groovy:52)
at org.epseelon.conferenceguide.MessageService.sendMessageToDevices(MessageService.groovy:40)
at org.epseelon.conferenceguide.MessageService$$FastClassByCGLIB$$faaef4dd.invoke()
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.epseelon.conferenceguide.MessageService$$EnhancerByCGLIB$$43987da7.sendMessageToDevices()
at org.epseelon.conferenceguide.SessionController$_closure6.doCall(SessionController.groovy:73)
at org.epseelon.conferenceguide.SessionController$_closure6.doCall(SessionController.groovy)
Caused by: java.net.ConnectException: Connection refused
at org.apache.mina.transport.socket.nio.NioSocketConnector.finishConnect(NioSocketConnector.java:223)
at org.apache.mina.transport.socket.nio.NioSocketConnector.finishConnect(NioSocketConnector.java:45)
at org.apache.mina.core.polling.AbstractPollingIoConnector.processConnections(AbstractPollingIoConnector.java:431)
at org.apache.mina.core.polling.AbstractPollingIoConnector.access$500(AbstractPollingIoConnector.java:63)
at org.apache.mina.core.polling.AbstractPollingIoConnector$Connector.run(AbstractPollingIoConnector.java:480)
at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:64)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:637)
Does it ring a bell? Maybe you could catch this exception inside ApnsService.push() and turn it into a more understandable exception. What do you think?
Despite using the 'default' sound no sound is emmited:
PayloadBuilder apnsPayLoad = APNS.newPayload();
apnsPayLoad.alertBody(textMessage);
apnsPayLoad.sound("default");
thanks for your Help,
Hi,
I'm investigating using your library to send push notifications. I was wondering is it possible to send multiple messages via a single service i.e.
String payload = APNS.newPayload()
.badge(3)
.customField("secret", "what do you think?");
.localizedKey("GAME_PLAY_REQUEST_FORMAT")
.localizedArguments("Jenna", "Frank")
.actionKey("Play").build();
service.push(token1, payload1);
service.push(token2, payload2);
or do you have to build the service object for each individual push call? I can't tell from the documentation.
Look forward to hearing from you.
Any updates needed to support this requirement from Apple?
On December 22, 2010, the production Apple Push Notification service will begin to use a 2048-bit TLS/SSL certificate that provides a more secure connection between your provider server and the Apple Push Notification service.
To ensure you can continue to validate your server's connection to the Apple Push Notification service, you will need to update your push notification server with a copy of the 2048-bit root certificate from Entrust's website. This will not require a change to your iOS apps -- this update only applies to provider servers.
Hi,
I'm trying to make a connections pool with error detection (with no success...). I've found in the ApnsConnectionImpl class code that the copy() method, wich is called by ApnsPooledConnection, doesn't take the errorDetection field value.
Is it an implementation choice or an oversight ?
Thanks
Hi,
First I would like to thank you for the great job you've already done with this library.
Is there any chance of adding support for retrieving tokens from the feedback service?
Thanks,
David
From Stackoverflow 1759101: Multiple iPhone APN messages, single connection
Apple will silently drop your connection if it receives an invalid device token or a message that's too long. The next couple of messages after that will fail because they're just sent into the ether, essentially - the connection is closed, but the TCP window isn't exhausted.
At Urban Airship, where I work, we have a debug mode to use when people test their applications with push on our service. This will pause for a little bit after sending a message to ensure that this wasn't the issue - if the connection drops, we know it's an issue with the device token and report an error as such. A similar method might be a good way for you to check that this is, or is not, what's going on. Obviously this kills throughput and so we don't recommend it for a production environment.
Hi,
unfortunately your jar is not usable in Glassfish 2.1 because it needs a newer version of Jackson than the one which comes bundled with Glassfish. Because of the classloading delegation the older version which is in $GLASSFISH/lib is loaded first. This leads to the following error:
javax.ejb.EJBException
at com.sun.ejb.containers.BaseContainer.processSystemException(BaseContainer.java:3903)
at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:3803)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:3605)
at com.sun.ejb.containers.WebServiceInvocationHandler.invoke(WebServiceInvocationHandler.java:201)
at $Proxy148.push(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.enterprise.webservice.InvokerImpl.invoke(InvokerImpl.java:78)
at com.sun.enterprise.webservice.EjbInvokerImpl.invoke(EjbInvokerImpl.java:82)
at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:146)
at com.sun.xml.ws.server.sei.EndpointMethodHandler.invoke(EndpointMethodHandler.java:257)
at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:93)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:106)
at com.sun.enterprise.webservice.MonitoringPipe.process(MonitoringPipe.java:147)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:115)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
at com.sun.xml.ws.api.pipe.helper.AbstractTubeImpl.process(AbstractTubeImpl.java:106)
at com.sun.xml.ws.tx.service.TxServerPipe.process(TxServerPipe.java:317)
at com.sun.enterprise.webservice.CommonServerSecurityPipe.processRequest(CommonServerSecurityPipe.java:222)
at com.sun.enterprise.webservice.CommonServerSecurityPipe.process(CommonServerSecurityPipe.java:133)
at com.sun.xml.ws.api.pipe.helper.PipeAdapter.processRequest(PipeAdapter.java:115)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:595)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:554)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:539)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:436)
at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:243)
at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:444)
at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:244)
at com.sun.xml.ws.transport.http.servlet.ServletAdapter.handle(ServletAdapter.java:135)
at com.sun.enterprise.webservice.Ejb3MessageDispatcher.handlePost(Ejb3MessageDispatcher.java:113)
at com.sun.enterprise.webservice.Ejb3MessageDispatcher.invoke(Ejb3MessageDispatcher.java:87)
at com.sun.enterprise.webservice.EjbWebServiceServlet.dispatchToEjbEndpoint(EjbWebServiceServlet.java:231)
at com.sun.enterprise.webservice.EjbWebServiceServlet.service(EjbWebServiceServlet.java:157)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:847)
at com.sun.enterprise.web.AdHocContextValve.invoke(AdHocContextValve.java:114)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:87)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:222)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1093)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:166)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:648)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:593)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:587)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:1093)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:291)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.invokeAdapter(DefaultProcessorTask.java:666)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.doProcess(DefaultProcessorTask.java:597)
at com.sun.enterprise.web.connector.grizzly.DefaultProcessorTask.process(DefaultProcessorTask.java:872)
at com.sun.enterprise.web.connector.grizzly.DefaultReadTask.executeProcessorTask(DefaultReadTask.java:341)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLReadTask.process(SSLReadTask.java:444)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLReadTask.doTask(SSLReadTask.java:230)
at com.sun.enterprise.web.connector.grizzly.TaskBase.run(TaskBase.java:264)
at com.sun.enterprise.web.connector.grizzly.ssl.SSLWorkerThread.run(SSLWorkerThread.java:106)
Caused by: java.lang.NoClassDefFoundError: Could not initialize class com.notnoop.apns.PayloadBuilder
at com.notnoop.apns.APNS.newPayload(APNS.java:48)
at com.service2media.m2active.m2push.Push.push(Push.java:162)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011)
at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:175)
at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:2929)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:4020)
at com.sun.ejb.containers.WebServiceInvocationHandler.invoke(WebServiceInvocationHandler.java:190)
... 63 more
Does anyone see a potential solution?
Regards,
Herman Meerlo
It'll be great if the library has a debug mode to detect common beginners errors. Needless to say the error messages should be quite meaningful to the audience.
Sample:
Whenever I push notifications and stop the service I see this error message.
[ApnsConnectionImpl] Exception while waiting for error code
java.net.SocketException: Socket closed
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:755)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
at java.io.InputStream.read(InputStream.java:85)
at com.notnoop.apns.internal.ApnsConnectionImpl$1MonitoringThread.run(ApnsConnectionImpl.java:102)
It looks to me like the problem is that the Monitoring thread reads the socket even though the socket has been closed by the stop method. My code is basically just this:
ApnsService service = null;
try{
service = APNS.newService()
.withCert(SSL_CERTIFICATE_FILE, SSL_CERTIFICATE_PASSWORD)
.withGatewayDestination(APPLE_APN_HOST, APPLE_APN_PORT)
.withFeedbackDestination(APPLE_APN_FEEDBACK_HOST, APPLE_APN_FEEDBACK_PORT)
.withReconnectPolicy(ReconnectPolicy.Provided.NEVER)
.build();
service.push(destination, payload);
finally{
service.stop();
}
PayloadBuilder.resizeAlertBody() does not handle multi-byte characters. First, the postfix size in bytes can be larger than its string length, resulting in an oversize payload. Second, it chops off a number of characters, when actually only the calculates number of bytes are needed.
The tricky thing is how to truncate a UTF-8 encoded byte array correctly, so we don't split characters in the middle. I have Groovy code to do this, which I can contribute if you like (can be trivially translated to Java).
For the Newsstand notification, the payload will need to contain the following:
{
‘aps’:{
‘content-available’:1
}
}
Can this support be added to the PayloadBuilder class? Or maybe at least make "aps" a public or protected member the caller can write to directly. The customField() function cannot be used since it writes to the "root" element and not to the "aps" element.
Please see this video for more details about Newsstand support.
Hi,
Your project seems to be the most advanced one compared to javapns and apns4j, in terms of features and documentation. But since you don't provide a binary distribution yet, I downloaded source from github and launched mvn install on the command line. But I miss 3 dependencies (logback-classic, json-lib and mina-core) and before tinkering with the respective projects and recreate those dependencies in my local repository, I wanted to make sure they are not already available somewhere in a repository that is just configured locally on your machine?
Also, are you thinking of releasing a binary distribution soon?
Cheers.
Hi,
I can't see how to add multiple Map entries to a payload using the builder pattern. Say I have a Map of custom fields I want to add to APNS.newPayload().addCustomField(key, value) today I would have to do something awful like this -
if (map.size == 1)
{
.... get the key1 value1 out of the map
APNS.newPayload().addCustomField(key1, value1)....
}
if (map.size == 2)
{
.... get the key1 value1, key2, value2 out of the map
APNS.newPayload().addCustomField(key1, value1).addCustomField(key2, value2)....
}
if (map.size == 3)
{
......
It would be much handier to have
APNS.newPayload().addCustomFieldMap(Map map).....
Unless I am missing something obvious of course.
Thanks
Lindsay
Hi,
It would be great to deploy a test jar. Some utility classes are very useful.
It would be also great to deploy javadoc & source jars.
Here are some configuration to add to pom project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<goals>
<goal>jar</goal>
<goal>javadoc</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.0.4</version>
<executions>
<execution>
<id>bind-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
ApnsService has a nice push method that takes a collection of String deviceTokens and a payload. And from what I've seen, you decode those deviceTokens to turn them into byte[] arrays.
In my case, deviceToken's are stored directly as byte[].
So would it be possible for you to add a public void push(Collection<byte[]> deviceTokens, String payload) method to ApnsService?
Is it on the roadmap to upload releases to central maven repository ?
http://maven.apache.org/guides/mini/guide-central-repository-upload.html
Please support the enhanced notification format, which allows passing an expiry date.
Hi
Am using MAC 10.5.8. I am unable to install this tool using the installation guide given in this blog. I downloaded and trying through "apns-0.1.2-jar-with-dependencies.jar". Can someone please help me how to install this?
The method com.notnoop.apns.internal.ApnsConnectionImpl.socket() can connect to a socks proxy and then use that socket to connect to Apple's push service. Although com.notnoop.apns.internal.ApnsFeedbackConnection.getInactiveDevicesImpl() only can connect directly to Apple's feedback service. Can you please add the missing socks proxy functionality into the ApnsFeedbackConnection class?
Stephen
Is there a reason you chose to use the delegate methods on a separate thread to return the status event from the push()? It makes life much more difficult for the caller of push() because they have no clue when that async event will come in.
Also it seems you are returning the error code in connectionClosed() which seems misleading to me? Shouldn't that be the failed message send?
Hi!
Following the description on the wiki page I updated my keystore to include all the keys from Apple's apns service. However, when I talk to the feedback server, I do still get an SSLHandshakeException. Before the update, the Exception was
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Now it's
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_expired
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1657)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:932)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1096)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:744)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:50)
at java.io.DataInputStream.readInt(DataInputStream.java:370)
at com.notnoop.apns.internal.Utilities.parseFeedbackStreamRaw(Utilities.java:192)
I think it would be helpful if this project would use some kind of AllTrustingSSLSocketFactory, not bothering with what f***up Apple is doing with it's servers.
Regards
Christian
Hi
I noticed the license file, but I cannot see if its based on any of the public and regular used licenses such as: Apache, BSD, LGPL etc.
The reason I am asking is that we would like to integrate Apache Camel with this project, and thus we must ensure there are no license implications doing so.
The Apache Software Foundation has a license policy which outlines approved here:
http://www.apache.org/legal/3party.html
But we can hose the integration outside Apache as we do
http://code.google.com/a/apache-extras.org/p/camel-extra/?redir=1
Regards
Claus Ibsen
I notice that the Downloads only has release JARs up to 0.1.2 but there are tags and source bundles available for 0.1.3 and 0.1.4. Please explain. Is there a reason for the absence of 0.1.3 or 0.1.4 JARs? Is the code at those tags considered stable and "safe to use?"
Thanks.
http://notnoop.github.com/m2-repo is returning as invalid. Is it moved or some admin issue with github?
Thanks.
kam
When using a socks proxy, the pool mode won't work.
In fact the instanciation of the ApnsSockets always use null as the proxy object passed to the constructor even if the proxy is setted in the ApnsConnectionImpl.
There is a simple fix to do in the copy() method to get it work as needed.
Tell me if you need a patch for this.
I'm running into an issue which is causing the number of sockets to increase over time as I perform more service.push()'s. The lsof -p of the process shows these increasing:
java 13741 root 386u sock 0,4 0t0 2475108674 can't identify protocol
Eventually my process hits the open file limit and craps out after trying to open a new socket (which happens to be to the DB).
I'm not using any special configuration for reconnect policy and such:
ApnsService service = APNS.newService()
.withCert( cert, pass )
.withSandboxDestination()
.build();
Any ideas?
It would be nice to be able to configure some aspects of the Executor used for pooled connections. Right now, I think if all the threads in the pool are busy, say, attempting a retry when an IOException is raised, incoming push requests are rejected by the Executor, and the delegate's messageSendFailed() method is not called.
Java's ThreadPoolExecutor allows a custom RejectedExecutionHandler to decide what to do. For example, I would like to be able to specify that java-apns block while the threads are busy (CallerRunsPolicy), or just to discard the incoming requests (DiscardPolicy).
There is no parameter to set the Socket timeout, so in case of network failure, the system will wait very long time before it receives an error and report it to the delegate.
If the connection to the APN Server is not available for some reason (firewall, apple service down, network down etc) or if DNS is unavailable making it impossible to lookup the apple server, then the socket() method in the ApnsConnectionImpl will loop forever (or at least until a connection is established) it should retry in the same way as the sendMessage method below, perhaps with some more delay I don't know, but it should have a limit.
The library auto-generates the identifier for use with the enhanced notification format (in AbstractApnsService.java). If there is a problem with a particular push, Apple returns the identifier associated with the problematic push, and the library wraps it up in a DeliveryError object that is returned from the ApnsDelegate's connectionClosed() callback.
However, there is no way to retrieve the identifier that is generated at the time the push is sent. So we cannot associate the identifier we receive in connectionClosed() with the token or message that caused the problem.
I'm using this library to send notifications and it's great. I want to get the error-response after pushed the message, and I created my implementation of ApnsDelegate. however the method 'connectionClosed' never been called in my program. I debugged and found it's blocked at ApnsConnectionImpl.monitorSocket, it tried to read the response from socket, but nothing returned and it's blocked.
any idea for this?
When a password was not defined on keyStore generation I have the following situations:
1 - Using a null password in APNS.newService().withCert(certificate.p12, password) returns a "NullPointerException";
2 - Using an empty password in APNS.newService().withCert(certificate.p12, password) returns "java.io.IOException: failed to decrypt safe contents entry: java.lang.ArithmeticException: / by zero"
I am using java-apns in my push notification server. The process is run as an Apache Commons daemon using jsvc. I have a thread that runs every 'N' seconds and checks for new notifications. If it finds any it attempts to send them out. From the stack trace below, the error happens on line 80 of my NotificationManager class. The code I have on that line is:
String payload = APNS.newPayload().alertBody(notification.getMessage()).
badge(0).sound("default").build();
And this raises the exception below:
Exception in thread "Timer-0" java.lang.VerifyError: Cannot inherit from final class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:632)
at java.lang.ClassLoader.defineClass(ClassLoader.java:616)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at com.notnoop.apns.PayloadBuilder.<clinit>(PayloadBuilder.java:47)
at ca.site.mobile.apns.service.NotificationManager.sendNotification(NotificationManager.java:80)
at ca.site.mobile.apns.service.NotificationManager.purgeNotifications(NotificationManager.java:64)
at ca.site.mobile.apns.service.NotificationChecker$1.checkForNotifications(NotificationChecker.java:46)
at ca.site.mobile.apns.service.NotificationChecker$1.run(NotificationChecker.java:41)
at ca.site.mobile.apns.scheduling.Scheduler$SchedulerTimerTask.run(Scheduler.java:18)
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
I've tried this on both Mac OSX and Linux running Java 1.6 with the same result. I am able to run that same line of code in a standalone java application (not using jsvc) without error but when run from within the daemon I get that error. I think it might have to do with running this as part of a daemon. Any ideas?
Thanks.
Where I try to run my code to get feedback information, nothing return . Why ? Can some advice be given ? My code is shown bellow .
ApnsService apn = APNS.newService().withCert("_dev_key.p12", "_")
.withFeedbackDestination("feedback.sandbox.push.apple.com",2196).withSandboxDestination().build();
apn.start();
Map a= apn.getInactiveDevices();
System.out.println ( a.size() );
Thanks .
When running in pooled connection mode, one connection is initially created in the build method as well as one ReconnectPolicy instance. Once the threads in the pool starts to become used a copy (clone) of the initial connection is created and placed in the pool (using ThreadLocal). The problem occurs when running with the EveryHalfHour reconnect policy and the reason is that only one instance is ever created of this class and because it contains state (lastRunning) we have trouble. All threads in the pool share the same instance, and therefore when one connection has been reconnected, then all connections are defined as being reconnected which they are not. After some time Apple hangs up the connection silently, and this is not identified by the socket which therefore just believes it is connected. This results in the java-apns lib behaiving like everything is OK, but actually most of the notifications being sent never go trough.
I have locally corrected the problem by adding a copy method to the ReconnectPolicy interface as well as implementations and then call this whenever the connection object is being copied (cloned). This ensures that each connection has it's own reconnectpolicy and therefore that all connections are renewed every half hour.
Btw. is there a good reason why the connection is always reconnected when it has existed 30 minutes - typically it should only be necessary when it has been idle for 30 min or more?
Anyway I can send you my solution if you like, but it takes 3 min to impl. (o;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.