📜 ⬆️ ⬇️

Mailing Push Notifications with SpringBoot Server

Foreword


Greetings. Recently, I faced a task - to set up push notifications on the site. This was the first time I came across this article that helped me a lot. It already has a description of the server side, but, in the process of studying this topic, I found a more convenient way to implement the means of the Firebase library itself. Actually, I would like to tell you about him, because I could not find a clear explanation on the Internet.

Also, this article may be useful for programming in Node.js, Python, and Go, since the library is also available in these languages.

Directly to the point


In this article I will talk only about the server side.
(You can customize the client part using the same article )
So:

This JSON file contains the configuration necessary for the Firebase library.
Now let's do the server
')
For convenience, we will declare the path to the downloaded file in application.properties

fcm.service-account-file = /path/to/file.json 

Add the necessary dependencies to pom.xml

 <dependency> <groupId>com.google.firebase</groupId> <artifactId>firebase-admin</artifactId> <version>6.7.0</version> </dependency> 

Create a bin that returns our JSON:

 @ConfigurationProperties(prefix = "fcm") @Component public class FcmSettings { private String serviceAccountFile; public String getServiceAccountFile() { return this.serviceAccountFile; } public void setServiceAccountFile(String serviceAccountFile) { this.serviceAccountFile = serviceAccountFile; } } 


Config object

 public class PushNotifyConf { private String title; private String body; private String icon; private String click_action; private String ttlInSeconds; public PushNotifyConf() { } public PushNotifyConf(String title, String body, String icon, String click_action, String ttlInSeconds) { this.title = title; this.body = body; this.icon = icon; this.click_action = click_action; this.ttlInSeconds = ttlInSeconds; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public String getClick_action() { return click_action; } public void setClick_action(String click_action) { this.click_action = click_action; } public String getTtlInSeconds() { return ttlInSeconds; } public void setTtlInSeconds(String ttlInSeconds) { this.ttlInSeconds = ttlInSeconds; } } 

Fields:


And the service, in which all the logic of sending notifications will be:

 @Service public class FcmClient { public FcmClient(FcmSettings settings) { Path p = Paths.get(settings.getServiceAccountFile()); try (InputStream serviceAccount = Files.newInputStream(p)) { FirebaseOptions options = new FirebaseOptions.Builder() .setCredentials(GoogleCredentials.fromStream(serviceAccount)) .build(); FirebaseApp.initializeApp(options); } catch (IOException e) { Logger.getLogger(FcmClient.class.getName()) .log(Level.SEVERE, null, e); } } public String sendByTopic(PushNotifyConf conf, String topic) throws InterruptedException, ExecutionException { Message message = Message.builder().setTopic(topic) .setWebpushConfig(WebpushConfig.builder() .putHeader("ttl", conf.getTtlInSeconds()) .setNotification(createBuilder(conf).build()) .build()) .build(); String response = FirebaseMessaging.getInstance() .sendAsync(message) .get(); return response; } public String sendPersonal(PushNotifyConf conf, String clientToken) throws ExecutionException, InterruptedException { Message message = Message.builder().setToken(clientToken) .setWebpushConfig(WebpushConfig.builder() .putHeader("ttl", conf.getTtlInSeconds()) .setNotification(createBuilder(conf).build()) .build()) .build(); String response = FirebaseMessaging.getInstance() .sendAsync(message) .get(); return response; } public void subscribeUsers(String topic, List<String> clientTokens) throws FirebaseMessagingException { for (String token : clientTokens) { TopicManagementResponse response = FirebaseMessaging.getInstance() .subscribeToTopic(Collections.singletonList(token), topic); } } private WebpushNotification.Builder createBuilder(PushNotifyConf conf){ WebpushNotification.Builder builder = WebpushNotification.builder(); builder.addAction(new WebpushNotification .Action(conf.getClick_action(), "")) .setImage(conf.getIcon()) .setTitle(conf.getTitle()) .setBody(conf.getBody()); return builder; } } 

Me: - Firebase, why so many bildim?
Firebase: - Because
  1. The constructor is used to initialize FirebaseApp using our JSON file.
  2. The sendByTopic () method sends notifications to users who subscribe to a given topic.
  3. The subscribeUsers () method subscribes to the topic of users (clientTokens).
    can be executed asynchronously, it uses .subscribeToTopicAsync ()

  4. The sendPersonal () method implements sending a personal notification to the user (clientToken)
  5. The createBuilder () method creates a message.

Result

image

Another browser

image
There are no icons because Ubuntu :)

Summing up



In fact, the Firebase library collects for us JSON of the following form:

 {from: "Server key"​ notification: {​​ title: " Habr" actions: (1) [​​​ 0: Object { action: "https://habr.com/ru/top/", title: "" } ]​​ length: 1​​ body: "- "​​ image: "https://habrastorage.org/webt/7i/k5/77/7ik577fzskgywduy_2mfauq1gxs.png"​​ } ​priority: "normal"} 

And on the client side, you already parse it as you like.

Thanks for attention!

Useful links:


firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/messaging/WebpushNotification

habr.com/en/post/321924/#otpravka-uvedomleniy-s-servera

firebase.google.com/docs/web/setup

Source: https://habr.com/ru/post/442202/


All Articles