Send push notifications from Spring Boot server-side application using FCM

As you probably noticed, I familiarize myself with the subject of Firebase Cloud Messaging push notifications recently.

This time I would like to share with you my push notifications server-side application. The app is made with Spring Boot framework.

Provided example covers most common notifications sending use cases such as: sending push notification to a topic, directly to the users’ device or sending messages with additional data payload.

This post is not a step-by-step tutorial. I’ll focus on the most important parts. Fully working example is available on GitHub.

If you don’t have a client-side application to receive push notifications yet, you should consider the use of Ionic app I described earlier. Have fun!

Let’s go

Let’s start from the Firebase integration.

First of all you have to generate your own Firebase SDK admin key. Basically it’s a JSON file with your Firebase project credentials. You’ll need it for server-side authorization (more information).

Login into your Firebase console. Go to Project settings -> Service accounts and then click Generate new private key button.


Generate and save the file. We’ll use it in the next steps.

Spring Boot application

Put generated Firebase Admin SDK JSON file inside your Spring Boot project files (if you don’t have one you can generate it here).

In my case I created google folder inside src/main/resources. Then, in my, I added new key/value pair containing file path.



Now we’ll need Firebase dependencies here so let’s add some. I was using Maven as a dependency manager. In my pom.xml I added:


Now we have to initialize our Firebase application. This is the time to use our app.firebase-configuration-file. I used @Value annotation to inject the path value to the String field.


public class FCMInitializer {

    private String firebaseConfigPath;

    Logger logger = LoggerFactory.getLogger(FCMInitializer.class);

    public void initialize() {
        try {
            FirebaseOptions options = new FirebaseOptions.Builder()
                    .setCredentials(GoogleCredentials.fromStream(new ClassPathResource(firebaseConfigPath).getInputStream())).build();
            if (FirebaseApp.getApps().isEmpty()) {
      "Firebase application has been initialized");
        } catch (IOException e) {


The initialize() method is being called on application start-up thanks to @PostConstruct annotation.

Sending push notifications

The next step is to prepare our push notifications service class.
But first of all I separated following use cases:

  • send push notification to topic using sample data (defined in
  • send scheduled sample push notification to topic (every minute)
  • send push notification with additional data payload (user-defined key/value data object, look at the docs for more information)
  • send push notification without additional data payload
  • send push notification to a specific user

Sending push notification without data payload example from FCMService class:

public class FCMService {


    public void sendMessageWithoutData(PushNotificationRequest request)
            throws InterruptedException, ExecutionException {
        Message message = getPreconfiguredMessageWithoutData(request);
        String response = sendAndGetResponse(message);"Sent message without data. Topic: " + request.getTopic() + ", " + response);


    private String sendAndGetResponse(Message message) throws InterruptedException, ExecutionException {
        return FirebaseMessaging.getInstance().sendAsync(message).get();

    private AndroidConfig getAndroidConfig(String topic) {
        return AndroidConfig.builder()

    private ApnsConfig getApnsConfig(String topic) {
        return ApnsConfig.builder()

    private Message getPreconfiguredMessageWithoutData(PushNotificationRequest request) {
        return getPreconfiguredMessageBuilder(request).setTopic(request.getTopic())


    private Message.Builder getPreconfiguredMessageBuilder(PushNotificationRequest request) {
        AndroidConfig androidConfig = getAndroidConfig(request.getTopic());
        ApnsConfig apnsConfig = getApnsConfig(request.getTopic());
        return Message.builder()
                        new Notification(request.getTitle(), request.getMessage()));


If you really want to you can test it right now by calling proper methods. For clarity purposes I added another layer – PushNotificationService which will be used directly by PushNotificationController in the further steps.

Let’s take a look at PushNotificationService:


public class PushNotificationService {

    private Map<String, String> defaults;

    private Logger logger = LoggerFactory.getLogger(PushNotificationService.class);
    private FCMService fcmService;

    public PushNotificationService(FCMService fcmService) {
        this.fcmService = fcmService;

    @Scheduled(initialDelay = 60000, fixedDelay = 60000)
    public void sendSamplePushNotification() {
        try {
        } catch (InterruptedException | ExecutionException e) {

    public void sendPushNotification(PushNotificationRequest request) {
        try {
            fcmService.sendMessage(getSamplePayloadData(), request);
        } catch (InterruptedException | ExecutionException e) {

    public void sendPushNotificationWithoutData(PushNotificationRequest request) {
        try {
        } catch (InterruptedException | ExecutionException e) {

    public void sendPushNotificationToToken(PushNotificationRequest request) {
        try {
        } catch (InterruptedException | ExecutionException e) {

    private Map<String, String> getSamplePayloadData() {
        Map<String, String> pushData = new HashMap<>();
        pushData.put("messageId", defaults.get("payloadMessageId"));
        pushData.put("text", defaults.get("payloadData") + " " +;
        return pushData;

    private PushNotificationRequest getSamplePushNotificationRequest() {
        PushNotificationRequest request = new PushNotificationRequest(defaults.get("title"),
        return request;


As you see we have a @Value annotation again over here.
Why? Because we have bunch of default values to pass to our methods.

So instead of injecting single value from properties to particular String variable I decided to use Map type for simplicity. It still uses the same @Value annotation.

Again, we store the defaults in So the app.notifications.defaults key looks like this:

app.notifications.defaults={topic: 'common', title: 'Common topic - Hello', message: 'Sending test message \uD83D\uDE42', token: 'ss22t03wz208eg:APA2idkkow223FE_0v5yHxqCLTyxAQafj6nWaqi4QzwZTW004q1PUux63UsFN', payloadMessageId: '123', payloadData: 'Hello. This is payload content.'}

Moreover, you can see we’re using the FCMService directly, passing notifications requests objects to it.

For scheduling I used @Scheduled annotation with initial delay of 1min. (initialDelay parameter) and 1min. sending interval (fixedDelay parameter). Remember to annotate your Application class with @EnableScheduling.


Let’s interact with our services and build a controller.

For presentation purposes I exposed my service methods as REST API endpoints in order to send custom, direct messages (to topic or specific subscriber) with/without data payload or trigger the default notification sending.


public class PushNotificationController {

    private PushNotificationService pushNotificationService;

    public PushNotificationController(PushNotificationService pushNotificationService) {
        this.pushNotificationService = pushNotificationService;

    public ResponseEntity sendNotification(@RequestBody PushNotificationRequest request) {
        return new ResponseEntity<>(new PushNotificationResponse(HttpStatus.OK.value(), "Notification has been sent."), HttpStatus.OK);


    public ResponseEntity sendSampleNotification() {
        return new ResponseEntity<>(new PushNotificationResponse(HttpStatus.OK.value(), "Notification has been sent."), HttpStatus.OK);
} fragment

Test REST endpoints with cURL

Let’s test our endpoints. I used cURL for this task but you can use your favorite HTTP requests tools or write a small client app for this.

  • GET /notification – Trigger sample notification with default values sending
curl -H "Content-Type: application/json" -X GET http://localhost:8080/notification
  • POST /notification/topic – Send a message to a specific topic
curl -d '{"title":"Hello", "message":"The message...", "topic":"contactTopic"}' -H "Content-Type: application/json" -X POST http://localhost:8080/notification/topic
  • POST /notification/token – Send a message to a specific device (with token)
curl -d '{"title":"Hey you!", "message":"Watch out!", "token":"cct00ebz8eg:APA91bFcTkFE_0Qafj6nWv5yHxqCLTyxAaqi4QzwsFNLP5M9G78X8Z5UMZTW004q1PUux63Ut-1WMGVToMNTdB3ZfO8lCZlc4lGpxm7LBdWfkhaUxdbpQ5xIO5cAb-w9H2dBLNHT7i-U", "topic": ""}' -H "Content-Type: application/json" -X POST http://localhost:8080/notification/token
  • POST /notification/data – Send a message to a specific topic with additional payload data.
    Please note: in this case I took defaults from as sample payload. In your application you should probably use third-party API data or persistent data from your database.
curl -d '{"title":"Hello", "message":"Data message", "topic":"contactTopic"}' -H "Content-Type: application/json" -X POST http://localhost:8080/notification/data


If succeeded you should receive following JSON response with code 200:


    "status": 200,
    "message": "Notification has been sent."




Well… If configured properly it just works. I used my Ionic app and Android phone as a client.

Take a look at this screenshot with received notifications:

In this case the client-side app doesn’t handle additional payload data.

Are you curious about the yellow colour of notifications? I set it in NotificationParameter enum along with sound option value (which is default in my case).
See the reference for more additional fields description.


In this post I covered basic Firebase Cloud Messaging integration with Spring Boot application. If you’re looking for server-side push notification implementation I think this is the way to go.

As I mentioned before, the fully working example is available on GitHub. If you’re looking for basic client-side mobile application please take a look at my previous Ionic push notifications app post.

Please note that provided example was tested with Android application. Although I provided some basic Apple Push Notification Service (APNS) configuration you have to deal with potential issues when developing an iOS application. If you managed to do it please let me know.

Good luck!

19 thoughts on “Send push notifications from Spring Boot server-side application using FCM”

  1. Thanks for this tutorials, I have followed your steps closely, but i am having an error, this is the error message “FirebaseApp with name [DEFAULT] doesn’t exist. “, i will be glad if you can find time to help me out. Thanks

        1. Hi Brian. You have to include JSON file generated in your Firebase application console.

          But I tested it once again and it’s not necessary to have this particular file in the back-end project. It works just fine without it. It’s important on the client side – for example in the Ionic app.

  2. Thanks for the tutorial, I have followed the steps and placed the firebase-adminsdk json file inside the google folder. I want to send a notification to the specific device. I have Token, Sender ID, Device ID, and FCMToken, but not getting how to use them in the application properties file.

    URL use: http://localhost:8080/notification/token

    app.notifications.defaults={title:’Hey you!’, message:’Watch out!’, token:’dZ2rMLNNOwM:PA91bF3LbFKiXqOVQR8NcvTyT5M4vsxPZLvRPEDevAoEI0m4sNLxA4eyKqJ5g6zJIzbmushrjbmgHxzJsWnkjrhDGiH-gza-yyncN3wnLV2DRhw3gMGxFT_J7FHrl-5wHW7qKWo’, topic: ‘Any’}

    1. Hi Anand. Thanks for your comment.

      First of all, I’m not sure if it’s because of comments formatting but it looks like your quotation marks are invalid.

      You’re using where the valid ones are: ' (single quotation) or " (double quotation mark).

      Please take a look at this fragment where I used my properties:

      In this example I used it to load the defaults into single Map object using @Value annotation.
      You can try to load them into separate String objects as well. Or even, for the test purposes, you can use your FCM values directly.

      Good luck

  3. Hello Rafal,

    I have deployed the spring boot server side app and it runs okay. But the challenges i am having now is the UI. How do I consume the notification. Kindly provide a source code showing how the api is consume and the messages are displayed

    1. Hi Oma. In my case the client side was built with Ionic Framework. Please take a look here for a reference.

      There’s also a link to the GitHub repository. Hope it helps.

  4. Hi,
    Your tutorial is totally good. I have it works too in my localhost. But, when the project was deployed in weblogic server (i’m packaging it to .war), the notification sending action doesn’t work.

    Can you help me what’s wrong with it?

  5. Hi. By including firebase dependency, google signin verification shows an error :

    java.lang.nosuchmethoderror:;)[b when fcm present

    This error is coming at following line:
    GoogleIdToken googleToken = verifier.verify(requestHeader);

    Can you help me to solve this issue?

  6. Hi @rafal this FCM notifiction tutorial is very helpful to me.please keep posting more about spring technology

    thanks for the post
    Nirav Patel

    1. Hi Nirav, thanks for your comment, I really appreciate it.

      On the blog I’m going to focus on Spring-related technologies in the nearest future, so keep up to date.

      Which aspects of Spring interest you the most?

Leave a Reply

Your email address will not be published. Required fields are marked *