A Web Push library with minimal dependencies for Java 17 and above. Supports payloads and VAPID.
For Gradle, add the following dependency to build.gradle:
compile group: 'dev.blanke.webpush', name: 'webpush', version: '6.1.0'For Maven, add the following dependency to pom.xml:
<dependency> <groupId>dev.blanke.webpush</groupId> <artifactId>webpush</artifactId> <version>6.1.1</version> </dependency>This library depends on BouncyCastle, which acts as a Java Cryptography Extension (JCE) provider. BouncyCastle's JARs are signed, and depending on how you package your application, you may need to include BouncyCastle yourself as well.
In addition to dev.blanke.webpush:webpush, an implementation of the JwtFactory interface is required. Currently, three implementations exist: Jose4jJwtFactory, HelidonJwtFactory, and NimbusJwtFactory. One of the following dependencies must be added depending on which JWT library should be used for creating, signing, and serializing JWTs:
<dependency> <groupId>dev.blanke.webpush.jwt</groupId> <artifactId>webpush-jwt-helidon</artifactId> <version>6.1.1</version> </dependency><dependency> <groupId>dev.blanke.webpush.jwt</groupId> <artifactId>webpush-jwt-jose4j</artifactId> <version>6.1.1</version> </dependency><dependency> <groupId>dev.blanke.webpush.jwt</groupId> <artifactId>webpush-jwt-nimbus</artifactId> <version>6.1.1</version> </dependency>Most projects are based on a framework which ships its own library for handling JWT. To avoid introducing a new dependency with duplicate functionality, it is recommended to implement the JwtFactory adapter interface which should be straightforward.
This library is meant to be used as a Java API. However, it also exposes a CLI to easily generate a VAPID keypair and send a push notification.
A command-line interface is available to easily generate a VAPID keypair and to try sending a notification.
$ cd webpush-cli && mvn exec:java Usage: <main class> [command] [command options] Commands: generate-key Generate a VAPID keypair Usage: generate-key send-notification Send a push notification Usage: send-notification [options] Options: --subscription A subscription in JSON format. --publicKey The public key as base64url encoded string. --privateKey The private key as base64url encoded string. --payload The message to send. Default: Hello, world! --ttl The number of seconds that the push service should retain the message. For example, to generate a keypair and output the keys in base64 URL encoding:
$ mvn exec:java -Dexec.args='generate-key' PublicKey: BGgL7I82SAQM78oyGwaJdrQFhVfZqL9h4Y18BLtgJQ-9pSGXwxqAWQudqmcv41RcWgk1ssUeItv4-8khxbhYveM= PrivateKey: ANlfcVVFB4JiMYcI74_h9h04QZ1Ks96AyEa1yrMgDwn3 Use the public key in the call to pushManager.subscribe to get a subscription. Then, to send a notification:
$ mvn exec:java -Dexec.args='send-notification --endpoint="https://fcm.googleapis.com/fcm/send/fH-M3xRoLms:APA91bGB0rkNdxTFsXaJGyyyY7LtEmtHJXy8EqW48zSssxDXXACWCvc9eXjBVU54nrBkARTj4Xvl303PoNc0_rwAMrY9dvkQzi9fkaKLP0vlwoB0uqKygPeL77Y19VYHbj_v_FolUlHa" --key="BOtBVgsHVWXzwhDAoFE8P2IgQvabz_tuJjIlNacmS3XZ3fRDuVWiBp8bPR3vHCA78edquclcXXYb-olcj3QtIZ4=" --auth="IOScBh9LW5mJ_K2JwXyNqQ==" --publicKey="BGgL7I82SAQM78oyGwaJdrQFhVfZqL9h4Y18BLtgJQ-9pSGXwxqAWQudqmcv41RcWgk1ssUeItv4-8khxbhYveM=" --privateKey="ANlfcVVFB4JiMYcI74_h9h04QZ1Ks96AyEa1yrMgDwn3" --payload="Hello world"' First, make sure you add the BouncyCastle security provider:
Security.addProvider(new BouncyCastleProvider());Then, construct a PushService using PushService.builder(). The implementation provided by this library uses the java.net.http.HttpClient introduced in Java 11 and supports both synchronous and asynchronous sending of notifications.
var pushService = PushService.builder() // ... .build();Then, create a notification based on the user's subscription:
var notification = Notification.builder() // ... .build();To send a push notification:
pushService.send(notification);See wiki/Usage-Example for detailed usage instructions. If you plan on using VAPID, read wiki/VAPID.
There may not be enough entropy to generate a random seed, which is common on headless servers. There exist two ways to overcome this problem:
-
Install haveged, a "random number generator that remedies low-entropy conditions in the Linux random device that can occur under some workloads, especially on headless servers." This tutorial explains how to install haveged on different Linux distributions.
-
Change the source for random number generation in the JVM from
/dev/randomto/dev/urandom. This page offers some explanation.
To give credit where credit is due, the PushService is mostly a Java port of marco-c/web-push. The HttpEce class is mostly a Java port of martinthomson/encrypted-content-encoding.
- Generic Event Delivery Using HTTP Push
- Message Encryption for Web Push
- Encrypted Content-Encoding for HTTP
- Voluntary Application Server Identification for Web Push
- Web Push Book
- Simple Push Demo
- Web Push: Data Encryption Test Page
- Push Companion
The web-push-libs organization hosts implementations of the Web Push protocol in several languages:
- For PHP, see web-push-libs/web-push-php
- For NodeJS, see web-push-libs/web-push
- For Python, see web-push-libs/pywebpush
- For C#, see web-push-libs/web-push-csharp
- For Scala, see zivver/web-push