-
Notifications
You must be signed in to change notification settings - Fork 450
Frequently asked questions
I'm trying to use Jetty's alpn-boot
/alpn-agent
package, but am seeing a message about "ALPN unsupported." What's wrong?
First and foremost, please note that since Pushy v0.13.0, ALPN is no longer required and you do not need to use alpn-boot
/alpn-agent
. We strongly recommend updating to the latest version of Pushy as a first option, but if you must use alpn-boot
/alpn-agent
and they aren't set up correctly, you'll probably see an ExceptionInInitializerError
that's ultimately caused by something like this:
Caused by: java.lang.RuntimeException: ALPN unsupported. Is your classpatch configured correctly? See http://www.eclipse.org/jetty/documentation/current/alpn-chapter.html#alpn-starting
Usually, this means one of two things:
-
alpn-boot
isn't on your boot classpath, which is distinct from your normal classpath. Make sure that you're passing an appropriate-Xbootclasspath
argument to the JVM that's running your application. - You haven't set
alpn-agent
as a Java agent. This is also distinct from putting it on your normal classpath. Make sure that you're passing an appropriate-javaagent
argument to the JVM that's running your application.
Please note that you only need to use one of alpn-agent
or alpn-boot
. We recommend alpn-agent
.
Some common pitfalls:
- The profiles from Pushy's own
pom.xml
serve as good examples, but it's important to remember that the only thing they do is set a variable that we ultimately use to set the boot classpath for our unit tests. Copying the profiles into your own project isn't enough; you'll need to make sure that you're actually setting the boot class path when you run your application. - If your application is running in a container of some kind (Tomcat, for example), you'll need to make sure that the container itself has either an appropriate version of
alpn-boot
on its classpath oralpn-agent
set as an agent.
This may mean that your JDK doesn't have the ciphers required by HTTP/2. You may need to use a newer version of Java, an alternate JCE provider (like Bouncy Castle), or a native SSL provider via netty-tcnative
.
I sent a bunch of notifications, and lots (but not all) of them failed with an Http2GoAwayException
or ClientNotConnectedException
. How come?
The odds are good that you're doing something roughly like this:
for (final ApnsPushNotification notification : notifications) {
client.sendNotification(notification);
}
client.disconnect();
It's important to remember that clients operate asynchronously, and it's possible to enqueue notifications more quickly than they're actually sent to the server. It's possible to shut down the client before it ever has a chance to send some of the notifications, in which case notifications that haven't actually been sent to the server will fail with an Http2GoAwayException
.
To avoid this situation, callers should wait for the Futures
returned by ApnsClient#sendNotification
to complete before disconnecting the client.
While old versions of the APNs protocol had a "feedback service" that could provide a list of device tokens that had expired, that functionality has been streamlined significantly in the newer HTTP/2-based APNs API, and the feedback service has been removed from the API entirely. Instead, the APNs server will respond immediately with an "Unregistered"
rejection reason and include a token expiration timestamp if the token has expired, and so callers no longer need to communicate with a separate service to learn about expired tokens.
For Pushy in particular, that means that you can determine if a token has expired if the PushNotificationResponse
you receive when sending a notification returns a non-null
value for getTokenInvalidationTimestamp()
. At the time of this writing, that will only happen if the value returned by getRejectionReason()
is "Unregistered"
, though there are no guarantees that won't change in the future.