Cron job for email using quartz schedular in java springboot

Created by: Ahilan A

Posted Date: 20/7/2024

Share

Cron job for email using quartz schedular in java springboot


1.   Description of the Application:

   what is cron job

                     A cron job is a scheduled task that runs at specified intervals, often used for repetitive tasks like backups,maintenance, or sending emails..

   what is springboot

                      Spring Boot is a project that is built on the top of the Spring Framework. It provides an easier and faster way to set up, configure, and run both simple and web-based applications.


2.   How to write cron expression:

ยท        There are 6 Asterisks(******) by default in cron expression as shown below. Further each asterisk has some meaning as they denote a value. These values can be assigned as Second, Minute, Hours, Day, Month, WeekDay respectively in sequence as shown below.

 

 

ยท        A Cron Expression can accept symbols : * โ€“ , / ?

ยท        Comma denotes possible values 0 0 4,6 * * *

Above expression denotes execute given task every day 4:00:00AM and 6:00:00 AM

ยท        Dash (-) denotes a range, which means consider all possible values between the range 0 0 4-6 * * *

To illustrate, above expression just denotes โ€˜execute given task every day 4:00:00AM, 5:00:00AM and 6:00:00 AMโ€™

ยท        Asterisk(*) denotes any/every/all value

ยท        Forward slash(/) denotes a period of time

ยท        Question mark(?) denotes any value, but it is applied only at Day & WeekDay when month value is given.

English names can also be used for the day-of-month and day-of-week fields. Use the first three letters of the particular day or month (case does not matter).


3.  Cron expression exercise with examples using springboot schedular:


Examples using pointof time...

ยท     Write a cron expression that executes a task everyday at 8 AM

 0 0 8 * * *       

ยท     Write a cron expression that executes a task at 9AM and 9PM every day

 0 0 9,21 * * *        


Examples using pointof time continuedโ€ฆ.

ยท        Write a cron expression that executes a task every year on Aug 25th 9AM

 0 0 9 25 8 *

ยท        How to write a cron expression that executes a task on the hour 9AM to 6PM weekdays.

 0 0 8-18 * * MON-FRI  


Examples using period of timeโ€ฆ.

a.   Use slash(/) for period of time at all positions except week days.

ยท       How to write a cron expression that executes a task for every 15 sec gap

  */15 * * * * *       


ยท      At what time the task will be executed by cron expression : 0  0/30  8-10  *  *  *

               Ans:   8:00, 8:30, 9:00, 9:30, 10:00 and 10:30 every day


ยท      At what time the task will be executed by cron expression : 0/20  30/10  10  *  *  *

      Ans:  Every Day

      Start at โ€“ 10:30:00 AM

      Next at โ€“ 10:40:20 AM, 10:50:40 AM

      Next โ€“ Next Day at 10:30:00 AM and so onโ€ฆ                                       

.

 4.  How to Schedule Cron Jobs for email alerts Using Quartz Scheduler in Java springboot?


Create springboot project and then,

Java version 17

Maven version 3.9.8


1.      Add dependency:

          
<<dependency>

                <groupId>mysql</groupId>

                <artifactId>mysql-connector-java</artifactId>

                <version>8.0.28</version> <!-- Use the latest version available -->

 </dependency>

  <dependency>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-starter-web</artifactId>

  </dependency>

<dependency>

            <groupId>org.simplejavamail</groupId>

            <artifactId>simple-java-mail</artifactId>

            <version>5.1.3</version>
 </dependency>
 
<dependency>

            <groupId>org.quartz-scheduler</groupId>

            <artifactId>quartz</artifactId>

            <version>2.3.0</version>

</dependency>
 

 

 in Alert controller file,set cron time...


        String time = "18:02";

        String cronexpression = CronUtil.createCronExpressionforalert(time);

        log.debug("cronexpression{}",cronexpression);

        alertRuleSettings.setConsolidatedAlertReportSchedule(cronexpression);

 

This will create Cron time

in cron util,we have method for cron expression


      public static String createCronExpressionforalert(String time) {

        String cronExpression = null;

        if (!StringUtils.isEmpty(time)) {

            String[] timeParts = time.split(":");

            if (timeParts.length == 2) {

                String hour = timeParts[0];

                String minute = timeParts[1];

                // cronExpression = generateCronExpression("0","26/10", hour, "*", "*", "?", "*");

                cronExpression = generateCronExpression("0", minute, hour, "*", "*", "?", "*");
            }

        }

        return cronExpression;

    } 

    public static String generateCronExpression(final String seconds, final String minutes, final String hours,

            final String dayOfMonth, final String month, final String dayOfWeek, final String year) {

        return String.format("%1$s %2$s %3$s %4$s %5$s %6$s %7$s", seconds, minutes, hours, dayOfMonth, month, dayOfWeek, year);

    }
}


5.   Configuring MySQL database, Quartz Scheduler, and Mail Sender

                         

Letโ€™s configure Quartz Scheduler, MySQL database, and Spring Mail. MySQL database will be used for storing Quartz Jobs, and Spring Mail will be used to send emails.


Open src/main/resources/application.properties file and add the following properties -


         

  ## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
  
  spring.datasource.url = jdbc:mysql://localhost:3306/quartz_demo?useSSL=false
  
  spring.datasource.username = root
  
  spring.datasource.password =
  
   
  
  ## QuartzProperties
  
  spring.quartz.job-store-type = jdbc
  
  spring.quartz.properties.org.quartz.threadPool.threadCount = 5
  
  Readmore
  
   
  
  ## MailProperties
  
  spring.mail.host=smtp.gmail.com
  
  spring.mail.port=587
  
  spring.mail.username=test@gmail.com
  
  spring.mail.password=
  
  spring.mail.properties.mail.smtp.auth=true
  
  spring.mail.properties.mail.smtp.starttls.enable=true
  


Youโ€™ll need to create a MySQL database named quartz_demo. Also, donโ€™t forget to change the spring.datasource.username and spring.datasource.password properties as per your MySQL installation.


Weโ€™ll be using Gmailโ€™s SMTP server for sending emails. Please add your password in the spring.mail.password property. You may also pass this property at runtime as command line argument or set it in the environment variable.



Create Quartz Tables


Quartz is an open source job scheduling framework that can be integrated within Java applications. It has powerful features and provides these features with simple usage and integration


         
  BLOB_DATA BLOB NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_CALENDARS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  CALENDAR_NAME VARCHAR(190) NOT NULL,
  
  CALENDAR BLOB NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_FIRED_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  ENTRY_ID VARCHAR(95) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  INSTANCE_NAME VARCHAR(190) NOT NULL,
  
  FIRED_TIME BIGINT(13) NOT NULL,
  
  SCHED_TIME BIGINT(13) NOT NULL,
  
  PRIORITY INTEGER NOT NULL,
  
  STATE VARCHAR(16) NOT NULL,
  
  JOB_NAME VARCHAR(190) NULL,
  
  JOB_GROUP VARCHAR(190) NULL,
  
  IS_NONCONCURRENT VARCHAR(1) NULL,
  
  REQUESTS_RECOVERY VARCHAR(1) NULL,
  
  PRIMARY KEY (SCHED_NAME,ENTRY_ID))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_SCHEDULER_STATE (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  INSTANCE_NAME VARCHAR(190) NOT NULL,
  
  LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
  
  CHECKIN_INTERVAL BIGINT(13) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_LOCKS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  LOCK_NAME VARCHAR(40) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,LOCK_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
  
  CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
  
   
  
  CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
  
  CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
  
   
  
  CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
  
  CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
  
  CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  
   
  
  commit;
  
  CREATE TABLE QRTZ_JOB_DETAILS(
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  JOB_NAME VARCHAR(190) NOT NULL,
  
  JOB_GROUP VARCHAR(190) NOT NULL,
  
  DESCRIPTION VARCHAR(250) NULL,
  
  JOB_CLASS_NAME VARCHAR(250) NOT NULL,
  
  IS_DURABLE VARCHAR(1) NOT NULL,                  
  
  IS_NONCONCURRENT VARCHAR(1) NOT NULL,
  
  IS_UPDATE_DATA VARCHAR(1) NOT NULL,
  
  REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
  
  JOB_DATA BLOB NULL,
  
  PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  JOB_NAME VARCHAR(190) NOT NULL,
  
  JOB_GROUP VARCHAR(190) NOT NULL,
  
  DESCRIPTION VARCHAR(250) NULL,
  
  NEXT_FIRE_TIME BIGINT(13) NULL,
  
  PREV_FIRE_TIME BIGINT(13) NULL,
  
  PRIORITY INTEGER NULL,
  
  TRIGGER_STATE VARCHAR(16) NOT NULL,
  
  TRIGGER_TYPE VARCHAR(8) NOT NULL,
  
  START_TIME BIGINT(13) NOT NULL,
  
  END_TIME BIGINT(13) NULL,
  
  CALENDAR_NAME VARCHAR(190) NULL,
  
  MISFIRE_INSTR SMALLINT(2) NULL,
  
  JOB_DATA BLOB NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
  
  REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  REPEAT_COUNT BIGINT(7) NOT NULL,
  
  REPEAT_INTERVAL BIGINT(12) NOT NULL,
  
  TIMES_TRIGGERED BIGINT(10) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_CRON_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  CRON_EXPRESSION VARCHAR(120) NOT NULL,
  
  TIME_ZONE_ID VARCHAR(80),
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  
    (
  
      SCHED_NAME VARCHAR(120) NOT NULL,
  
      TRIGGER_NAME VARCHAR(190) NOT NULL,
  
      TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
      STR_PROP_1 VARCHAR(512) NULL,
  
      STR_PROP_2 VARCHAR(512) NULL,
  
      STR_PROP_3 VARCHAR(512) NULL,
  
      INT_PROP_1 INT NULL,
  
      INT_PROP_2 INT NULL,
  
      LONG_PROP_1 BIGINT NULL,
  
      LONG_PROP_2 BIGINT NULL,
  
      DEC_PROP_1 NUMERIC(13,4) NULL,
  
      DEC_PROP_2 NUMERIC(13,4) NULL,
  
      BOOL_PROP_1 VARCHAR(1) NULL,
  
      BOOL_PROP_2 VARCHAR(1) NULL,
  
      PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
      FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_BLOB_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  BLOB_DATA BLOB NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_CALENDARS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  CALENDAR_NAME VARCHAR(190) NOT NULL,
  
  CALENDAR BLOB NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_FIRED_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  ENTRY_ID VARCHAR(95) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  INSTANCE_NAME VARCHAR(190) NOT NULL,
  
  FIRED_TIME BIGINT(13) NOT NULL,
  
  SCHED_TIME BIGINT(13) NOT NULL,
  
  PRIORITY INTEGER NOT NULL,
  
  STATE VARCHAR(16) NOT NULL,
  
  JOB_NAME VARCHAR(190) NULL,
  
  JOB_GROUP VARCHAR(190) NULL,
  
  IS_NONCONCURRENT VARCHAR(1) NULL,
  
  REQUESTS_RECOVERY VARCHAR(1) NULL,
  
  PRIMARY KEY (SCHED_NAME,ENTRY_ID))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_SCHEDULER_STATE (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  INSTANCE_NAME VARCHAR(190) NOT NULL,
  
  LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
  
  CHECKIN_INTERVAL BIGINT(13) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_LOCKS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  LOCK_NAME VARCHAR(40) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,LOCK_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
  
  CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
  
   
  
  CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
  
  CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
  
   
  
  CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
  
  CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
  
  CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  
   
  
  commit;
  
   



We should create quartz table manually,

 

                             we must run your database schema scripts, as seen one example above. You can find scripts in the below link. Scripts change according to the relational database you have chosen.

         After you run the database scripts, Quartz table should be listed like this;

 



Now, configuration is ready for creating jobs and triggers for scheduled tasks



The main Quartz interfaces are listed below:


Job is an interface to be implemented by the classes that contain the business logic that we wish to have executed


JobDetails defines Job instances and data that are related to it


Trigger describes the schedule of job execution


Scheduler is the main Quartz interface that provides all manipulation and searching operations for jobs and triggers



ยท  Scheduling Mail Rest Api


 
@Path("/ws2/mail")
@POST

    @Path("/alert/consolidated")

    @Produces(MediaType.APPLICATION_JSON)

    public @ResponseBody Response emailConsolidatedAlert(final @Context HttpServletRequest httpRequest,

            @NotNull(message = "Invalid amzn account id") @HeaderParam("x-gs-amzn-acc-id") Integer alertId) {

        try {

            alertService.Consolidatedalert(alertId);

            // return Response.status(Status.OK).entity(MAPPER.writeValueAsString("Success")).build();

 

            String responseEntity = MAPPER.writeValueAsString("Success");

            Response response = Response.status(Status.OK).entity(responseEntity).build();

            log.info("Saved email {}", responseEntity);

            log.debug("Saved email {}", responseEntity);

            System.out.println("Saved email " + responseEntity);

            return response;

 

        } catch (JsonProcessingException e) {

            e.printStackTrace();

            log.error("error sending consolidated email alert", e);

            return Response.status(Status.INTERNAL_SERVER_ERROR).build();

        }

    }

 

}

 


   Creating the Alert Request


    AlertSchedulerRequest alertRequest = new AlertSchedulerRequest(

    gsAccount.getAccountID(), alertRuleSettings.getAmazonAccountId(),

    gsAccount.getAwsCustomerID(),

    settings.getConsolidatedAlertReportSchedule(),

    alertRuleSettings.getId(),

    alertRuleSettings.getServiceTag(),

    alertRuleSettings.getPercentageTag()

);

try {

    alertResourceScheduler.createSchedule(alertRequest);

    System.out.println("Consolidated alert report schedule created successfully for account ID: " + gsAccount.getAccountID());

} catch (SchedulerException e) {

    log.error("Error scheduling consolidated alert report email request for account " + gsAccount.getAccountID(), e);

}



ยท  Schedule Request:

 

                                          This class is used to encapsulate the details needed to schedule an alert.

   Above alertscheduler details encapsulate into below classโ€ฆ.


  package com.gs.ci.ciengine.scheduler;

import org.hibernate.validator.constraints.NotEmpty;

 

public class AlertSchedulerRequest {

    @NotEmpty

    private Integer gsAccountID;

 

    @NotEmpty

    private Integer amznAccountID;

 

    @NotEmpty

    private String amznCustomerID;

 

    @NotEmpty

    private String cronExpression;

 

    @NotEmpty

    private Integer alertId;

 

    @NotEmpty

    private String serviveTag;

 

    @NotEmpty

    private String percentageTag;

 

    public AlertSchedulerRequest() {

 

    }โ€ฆโ€ฆโ€ฆโ€ฆโ€ฆ

 

    public AlertSchedulerRequest(Integer gsAccountID, Integer amznAccountID,

            String amznCustomerID,

            String cronExpression,

            Integer alertId, String serviveTag, String percentageTag) {

        super();

        this.gsAccountID = gsAccountID;

        this.amznAccountID = amznAccountID;

        this.amznCustomerID = amznCustomerID;

        this.cronExpression = cronExpression;

        this.alertId = alertId;

        this.serviveTag = serviveTag;

        this.percentageTag = percentageTag;

    }

 

    public Integer getGsAccountID() {

        return gsAccountID;

    }

 

    public void setGsAccountID(Integer gsAccountID) {

        this.gsAccountID = gsAccountID;

    }

 

    public Integer getAmznAccountID() {

        return amznAccountID;

    }

 

    public void setAmznAccountID(Integer amznAccountID) {

        this.amznAccountID = amznAccountID;

    }

 

    public String getAmznCustomerID() {

        return amznCustomerID;

    }

 

    public void setAmznCustomerID(String amznCustomerID) {

        this.amznCustomerID = amznCustomerID;

    }

 

    public String getCronExpression() {

        return cronExpression;

    }

 

    public void setCronExpression(String cronExpression) {

        this.cronExpression = cronExpression;

    }

 

    public Integer getAlertId() {

        return alertId;

    }

 

    public void setAlertId(Integer alertId) {

        this.alertId = alertId;

    }

 

    public String getServiveTag() {

        return serviveTag;

    }

 

    public void setServiveTag(String serviveTag) {

        this.serviveTag = serviveTag;

    }

 

    public String getPercentageTag() {

        return percentageTag;

    }

 

    public void setPercentageTag(String percentageTag) {

        this.percentageTag = percentageTag;

    }

 

}

 



ยท  Schedular Response

                                           

This class is used to encapsulate the response after attempting to schedule an alert. It contains fields like success, jobId, jobGroup, and message.


        package com.gs.ci.ciengine.scheduler;

 

public class AlertSchedulerResponse {

 

    private boolean success;

    private String jobId;

    private String jobGroup;

    private String message;

 

    public AlertSchedulerResponse() {

 

    }

 

    public boolean isSuccess() {

        return success;

    }

 

    public void setSuccess(boolean success) {

        this.success = success;

    }

 

    public String getJobId() {

        return jobId;

    }

 

    public void setJobId(String jobId) {

        this.jobId = jobId;

    }

 

    public String getJobGroup() {

        return jobGroup;

    }

 

    public void setJobGroup(String jobGroup) {

        this.jobGroup = jobGroup;

    }

 

    public String getMessage() {

        return message;

    }

 

    public void setMessage(String message) {

        this.message = message;

    }

 

}

 



ยท  Define the job


                 The job to be scheduled should implement the org.quartz.Job interface..

                 The interface to be implemented by classes that represent a โ€˜jobโ€™ in Quartz. It has a single method called execute() where you write the work that needs to be performed by the Job.


         

@Slf4j

@PropertySources({ @PropertySource("classpath:${env}-application.properties")

})

public class AlertResourcejob extends QuartzJobBean {

 

    @Override

    protected void executeInternal(JobExecutionContext jobExecutionContext)

            throws JobExecutionException {

 

                System.out.println("print");

 

        log.info("Executing Job with key {}",

                jobExecutionContext.getJobDetail().getKey());

 

        JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();

        if (jobDataMap != null) {

            Integer alertId = (Integer) jobDataMap.get("alertId");

            if (alertId != null) {

                postEmailTrigger(alertId);

                // alertService.Consolidatedalert(alertId);

            }

        }

    }



                To implement Job interface, you need to implement only one execute method that accepts a parameter of JobExecutionContext type. JobExecutionContext contains information about the job instance, trigger, scheduler, and other information about the job execution

 

 

ยท Create job and Trigger:

 

In AlertResourceschedular,


                   It is time to create job and trigger to schedule. โ€œSchedulerโ€ interface can be used by just adding โ€œAutowiredโ€ annotation


  @Autowired
  private Scheduler scheduler;


                 Below code sample shows how to create โ€œJobDetailโ€ object. As you saw earlier, you should store data to โ€œJobDataMapโ€ and use this map when creating the JobDetail object. AlertResourcejob class which implements โ€œJobโ€ interface, should be used here. There is also โ€œidentityโ€ for the job, like primary key for a job and will be used to call the created job. Samples about how to use will be shown in the next tutorial


        public AlertSchedulerResponse createSchedule(AlertSchedulerRequest alertRequest)

                        throws SchedulerException {

                boolean newTrigger = false;

                JobDetail jobDetail = buildJobDetail(alertRequest);

                ScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(alertRequest.getCronExpression())

                                .withMisfireHandlingInstructionDoNothing();

                System.out.println("ScheduleBuilder created with cron expression: " + alertRequest.getCronExpression());

 


After creating Job, you must create โ€œTriggerโ€, in order to define the schedule of the job. As seen in the below sample code, when creating the Trigger object, you can specify when to start for running the job, period and how many times you want to run the job. Like in the Job, there is also identity to specify unique trigger


Trigger trigger = buildJobTrigger(jobDetail, scheduleBuilder, alertRequest);

                CronTrigger ctrigger = (CronTrigger) scheduler.getTrigger(trigger.getKey());

 

                if (null == ctrigger) {

                        newTrigger = true;

                        System.out.println("New trigger created for job: " + jobDetail.getKey());

                } else {

                        System.out.println("Trigger already exists for job: " + jobDetail.getKey());

                }

if (scheduler.getTriggerState(trigger.getKey()) == Trigger.TriggerState.PAUSED) {

                        scheduler.resumeJob(jobDetail.getKey());

                }

 

                if (newTrigger) {

                        scheduler.scheduleJob(jobDetail, trigger);

                        System.out.println("New trigger scheduled for job: " + jobDetail.getKey());

 

                } else {

                        scheduler.rescheduleJob(trigger.getKey(), trigger);

                        System.out.println("Trigger rescheduled for job: " + jobDetail.getKey());

 

                }

 

                AlertSchedulerResponse response = buildSchedulerResponse(jobDetail,

                                alertRequest);

                return response;

        }


Now, you have Job and Trigger objects, and as seen above sample, you schedule by just โ€œscheduler.scheduleJob(job,trigger)โ€. After that, job and trigger objects were saved to โ€œQuartz tablesโ€, and job will be fired in the scheduled times.


 if (newTrigger) {

                        scheduler.scheduleJob(jobDetail, trigger);

                        System.out.println("New trigger scheduled for job: " + jobDetail.getKey());

 

                } else {

                        scheduler.rescheduleJob(trigger.getKey(), trigger);

                        System.out.println("Trigger rescheduled for job: " + jobDetail.getKey());

 

                }


 



ยท  Sending email:

   

Pass the data ,


  modal.put("variance", variancefordaily);
  
  modal.put("VariancePercent", VariancePercentfordaily);
  
  modal.put("result", result);
  
  modal.put("hostname", ciConsoleURL);
  
  modal.put("currentMonth", DateUtils.getCurrentMonth());
  
  modal.put("serviceTag", trimmedServiceTag);
  
  modal.put("username", amazonAccount.getGsAccountName());
  
  modal.put("name", amazonAccount.getAmazonAccountName());
  
   
  
  emailAlertService.emailConsolidatedAlert(modal, alertRuleSettings);



A Map named modal is populated with various values, including variance, VariancePercent, result, etc.

The emailConsolidatedAlert method of emailAlertService is called with modal and alertRuleSettings


ยท  Email alert service:



Injects an instance of EmailAlertSender, which handles sending emails

Injects a VelocityEngine instance for template rendering


@Service

@PropertySources({ @PropertySource("classpath:${env}-application.properties")

})

 

public class EmailAlertServiceImpl implements EmailAlertService {

 

    @Autowired

    EmailAlertSender emailalertsender;

 

    @Value("${ci.support.email}")

    String adminEmail;

 

    @Autowired

    VelocityEngine velocityEngine;

 

    @Override

    public void emailConsolidatedAlert(Map<String, Object> modal, AlertRuleSettings alertRuleSettings) {

        try {

            String mailsubject = "Test Email Subject";

            String mailContent = getContentFromTemplate(modal, alertRuleSettings.getServiceTag());

 

            String recipientEmail = alertRuleSettings.getEmailAlert();

            System.out.println("recipientEmail: " + recipientEmail);

 

            String[] serviceNames = alertRuleSettings.getServiceName();

 

            if (StringUtils.isNoneEmpty(mailContent) && serviceNames != null) {

 

                // String[] serviceTags = alertRuleSettings.getServiceTag().split(",");

                List<String> serviceNamesList = Arrays.asList(serviceNames);

                Object serviceTagObj = modal.get("serviceTag");

 

                if (serviceTagObj != null && serviceTagObj instanceof String) {

                    String serviceTag = ((String) serviceTagObj).trim();

 

                    if (serviceNamesList.contains(serviceTag.trim())) {

                        mailsubject = "Alert servicename Report - Cloud Insider";

 

                        double percentageTag = alertRuleSettings.getPercentageForService(serviceTag);

                        System.out.println("Service tag: " + serviceTag + ", Percentage tag: " + percentageTag);

 

                        boolean sendEmail = false;

 

                        for (Map.Entry<String, Object> entry : modal.entrySet()) {

                            String key = entry.getKey();

                            Object value = entry.getValue();

 

                            if (value instanceof Double && "result".equals(key)) {

                                Double resultValue = (Double) value;

                                if (resultValue >= percentageTag) {

                                    sendEmail = true;

                                    break;

                                }

                            }

                        }

                        if (sendEmail) {

                            emailalertsender.sendEmail(recipientEmail, mailsubject, mailContent);

                        } else {

                            System.out

                                    .println("-----------------------------------------------------------------------");

                            System.out.println("Variance value for '" + serviceTag + "' is less than 10...");

                            System.out

                                    .println("-----------------------------------------------------------------------");

 

                        }

                    } else {

                        System.out.println("servicenamelist has no servicetag");

                    }

                } else {

                    System.out.println("serviceTagObj is null");

                }

            } else {

                System.out.println("Mail content is empty or service names array is null");

 

            }

 

            // Send the email

        } catch (Exception e) {

            e.printStackTrace(); // Handle exception appropriately

        }

 

    }

 

    private String getContentFromTemplate(Map<String, Object> model, String servicetype) {

        StringWriter mergedContent = new StringWriter();

        VelocityContext velocityContext = new VelocityContext();

        String template = null;

 

        if (servicetype != null) {

            template = "templates/EC2 others-report.vm";

        } else {

            System.out.println("it is not ec2-other");

        }

 

        for (Map.Entry<String, Object> entry : model.entrySet()) {

            String key = entry.getKey();

            Object value = entry.getValue();

            velocityContext.put(key, value);

        }

        velocityContext.put("date", new DateTool());

        velocityContext.put("number", new NumberTool());

        velocityEngine.mergeTemplate(template, "UTF-8", velocityContext, mergedContent);

 

        return mergedContent.toString();

    }

 

}



This method generates an email alert based on conditions and template content:

Retrieves email content from a Velocity template using getContentFromTemplate.

Checks conditions based on service tag and result value to decide whether to send the email using emailalertsender.sendEmail.

Handles various cases with print statements if conditions are not met..


     This method retrieves the content of an email template using Apache Velocity:

      โ€ข        Determines the template file based on servicetype.

      โ€ข        Populates Velocity context with data from model.

โ€ข        Merges data into the template using velocityEngine.mergeTemplate



ยท  Email alert sender:


                           This method constructs and sends an email using email-builder-lib:

Constructs an Email object using EmailBuilder.

Sends the email using MailerBuilder with SMTP server details.


package com.gs.ci.ciengine.alertmail;

 

import org.simplejavamail.email.Email;

import org.simplejavamail.email.EmailBuilder;

import org.simplejavamail.email.EmailPopulatingBuilder;

import org.simplejavamail.mailer.MailerBuilder;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.PropertySource;

import org.springframework.context.annotation.PropertySources;

import org.springframework.stereotype.Service;

 

@Service

@PropertySources({ @PropertySource("classpath:${env}-application.properties")

})

public class EmailAlertSender {

 

    @Value("${smtp.host}")

    String smtpHost;

 

    @Value("${smtp.port}")

    String smtpPort;

 

    @Value("${smtp.user}")

    String smtpUser;

 

    @Value("${smtp.password}")

    String smtpPasswd;

 

    @Value("${smtp.from.name}")

    String smtpFromName;

 

    @Value("${smtp.from.email}")

    String smtpFromEmail;

 

    @Value("${ci.support.email}")

    String adminEmail;

 

    public boolean sendEmail(String tolist, String subject, String body) {

        // log.trace("Sending email to " + tolist);

        // log.trace("Email body = " + body);

 

        String[] to = tolist.split(",");

        if (to.length > 0) {

            EmailPopulatingBuilder emailPopulatingBuilder = EmailBuilder.startingBlank()

                    .from(smtpFromName, smtpFromEmail).withSubject(subject).withHTMLText(body);

 

            for (int i = 0; i < to.length; i++) {

                emailPopulatingBuilder.to(to[i]);

            }

 

            Email email = emailPopulatingBuilder.buildEmail();

 

            System.out.println("Printing Email Content:");

            System.out.println("From: " + email.getFromRecipient());

            System.out.println("To: " + email.getRecipients());

            System.out.println("Subject: " + email.getSubject());

            System.out.println("Body:\n" + email.getPlainText());

            MailerBuilder.withSMTPServer(smtpHost, Integer.parseInt(smtpPort), smtpUser,

                    smtpPasswd).buildMailer()

                    .sendMail(email, true);

 

            return true;

 

        }

        return false;}

}




 

Open postman check mail api,


This is the api http://localhost:8085/ws2/mail/alert/consolidated




Mail successfully sentโ€ฆ

























 

 

 

 

17/3/2025

Self-Improvement Blog


1.   Description of the Application:

   what is cron job

                     A cron job is a scheduled task that runs at specified intervals, often used for repetitive tasks like backups,maintenance, or sending emails..

   what is springboot

                      Spring Boot is a project that is built on the top of the Spring Framework. It provides an easier and faster way to set up, configure, and run both simple and web-based applications.


2.   How to write cron expression:

ยท        There are 6 Asterisks(******) by default in cron expression as shown below. Further each asterisk has some meaning as they denote a value. These values can be assigned as Second, Minute, Hours, Day, Month, WeekDay respectively in sequence as shown below.

 

 

ยท        A Cron Expression can accept symbols : * โ€“ , / ?

ยท        Comma denotes possible values 0 0 4,6 * * *

Above expression denotes execute given task every day 4:00:00AM and 6:00:00 AM

ยท        Dash (-) denotes a range, which means consider all possible values between the range 0 0 4-6 * * *

To illustrate, above expression just denotes โ€˜execute given task every day 4:00:00AM, 5:00:00AM and 6:00:00 AMโ€™

ยท        Asterisk(*) denotes any/every/all value

ยท        Forward slash(/) denotes a period of time

ยท        Question mark(?) denotes any value, but it is applied only at Day & WeekDay when month value is given.

English names can also be used for the day-of-month and day-of-week fields. Use the first three letters of the particular day or month (case does not matter).


3.  Cron expression exercise with examples using springboot schedular:


Examples using pointof time...

ยท     Write a cron expression that executes a task everyday at 8 AM

 0 0 8 * * *       

ยท     Write a cron expression that executes a task at 9AM and 9PM every day

 0 0 9,21 * * *        


Examples using pointof time continuedโ€ฆ.

ยท        Write a cron expression that executes a task every year on Aug 25th 9AM

 0 0 9 25 8 *

ยท        How to write a cron expression that executes a task on the hour 9AM to 6PM weekdays.

 0 0 8-18 * * MON-FRI  


Examples using period of timeโ€ฆ.

a.   Use slash(/) for period of time at all positions except week days.

ยท       How to write a cron expression that executes a task for every 15 sec gap

  */15 * * * * *       


ยท      At what time the task will be executed by cron expression : 0  0/30  8-10  *  *  *

               Ans:   8:00, 8:30, 9:00, 9:30, 10:00 and 10:30 every day


ยท      At what time the task will be executed by cron expression : 0/20  30/10  10  *  *  *

      Ans:  Every Day

      Start at โ€“ 10:30:00 AM

      Next at โ€“ 10:40:20 AM, 10:50:40 AM

      Next โ€“ Next Day at 10:30:00 AM and so onโ€ฆ                                       

.

 4.  How to Schedule Cron Jobs for email alerts Using Quartz Scheduler in Java springboot?


Create springboot project and then,

Java version 17

Maven version 3.9.8


1.      Add dependency:

          
<<dependency>

                <groupId>mysql</groupId>

                <artifactId>mysql-connector-java</artifactId>

                <version>8.0.28</version> <!-- Use the latest version available -->

 </dependency>

  <dependency>

                <groupId>org.springframework.boot</groupId>

                <artifactId>spring-boot-starter-web</artifactId>

  </dependency>

<dependency>

            <groupId>org.simplejavamail</groupId>

            <artifactId>simple-java-mail</artifactId>

            <version>5.1.3</version>
 </dependency>
 
<dependency>

            <groupId>org.quartz-scheduler</groupId>

            <artifactId>quartz</artifactId>

            <version>2.3.0</version>

</dependency>
 

 

 in Alert controller file,set cron time...


        String time = "18:02";

        String cronexpression = CronUtil.createCronExpressionforalert(time);

        log.debug("cronexpression{}",cronexpression);

        alertRuleSettings.setConsolidatedAlertReportSchedule(cronexpression);

 

This will create Cron time

in cron util,we have method for cron expression


      public static String createCronExpressionforalert(String time) {

        String cronExpression = null;

        if (!StringUtils.isEmpty(time)) {

            String[] timeParts = time.split(":");

            if (timeParts.length == 2) {

                String hour = timeParts[0];

                String minute = timeParts[1];

                // cronExpression = generateCronExpression("0","26/10", hour, "*", "*", "?", "*");

                cronExpression = generateCronExpression("0", minute, hour, "*", "*", "?", "*");
            }

        }

        return cronExpression;

    } 

    public static String generateCronExpression(final String seconds, final String minutes, final String hours,

            final String dayOfMonth, final String month, final String dayOfWeek, final String year) {

        return String.format("%1$s %2$s %3$s %4$s %5$s %6$s %7$s", seconds, minutes, hours, dayOfMonth, month, dayOfWeek, year);

    }
}


5.   Configuring MySQL database, Quartz Scheduler, and Mail Sender

                         

Letโ€™s configure Quartz Scheduler, MySQL database, and Spring Mail. MySQL database will be used for storing Quartz Jobs, and Spring Mail will be used to send emails.


Open src/main/resources/application.properties file and add the following properties -


         

  ## Spring DATASOURCE (DataSourceAutoConfiguration & DataSourceProperties)
  
  spring.datasource.url = jdbc:mysql://localhost:3306/quartz_demo?useSSL=false
  
  spring.datasource.username = root
  
  spring.datasource.password =
  
   
  
  ## QuartzProperties
  
  spring.quartz.job-store-type = jdbc
  
  spring.quartz.properties.org.quartz.threadPool.threadCount = 5
  
  Readmore
  
   
  
  ## MailProperties
  
  spring.mail.host=smtp.gmail.com
  
  spring.mail.port=587
  
  spring.mail.username=test@gmail.com
  
  spring.mail.password=
  
  spring.mail.properties.mail.smtp.auth=true
  
  spring.mail.properties.mail.smtp.starttls.enable=true
  


Youโ€™ll need to create a MySQL database named quartz_demo. Also, donโ€™t forget to change the spring.datasource.username and spring.datasource.password properties as per your MySQL installation.


Weโ€™ll be using Gmailโ€™s SMTP server for sending emails. Please add your password in the spring.mail.password property. You may also pass this property at runtime as command line argument or set it in the environment variable.



Create Quartz Tables


Quartz is an open source job scheduling framework that can be integrated within Java applications. It has powerful features and provides these features with simple usage and integration


         
  BLOB_DATA BLOB NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_CALENDARS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  CALENDAR_NAME VARCHAR(190) NOT NULL,
  
  CALENDAR BLOB NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_FIRED_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  ENTRY_ID VARCHAR(95) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  INSTANCE_NAME VARCHAR(190) NOT NULL,
  
  FIRED_TIME BIGINT(13) NOT NULL,
  
  SCHED_TIME BIGINT(13) NOT NULL,
  
  PRIORITY INTEGER NOT NULL,
  
  STATE VARCHAR(16) NOT NULL,
  
  JOB_NAME VARCHAR(190) NULL,
  
  JOB_GROUP VARCHAR(190) NULL,
  
  IS_NONCONCURRENT VARCHAR(1) NULL,
  
  REQUESTS_RECOVERY VARCHAR(1) NULL,
  
  PRIMARY KEY (SCHED_NAME,ENTRY_ID))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_SCHEDULER_STATE (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  INSTANCE_NAME VARCHAR(190) NOT NULL,
  
  LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
  
  CHECKIN_INTERVAL BIGINT(13) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_LOCKS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  LOCK_NAME VARCHAR(40) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,LOCK_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
  
  CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
  
   
  
  CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
  
  CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
  
   
  
  CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
  
  CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
  
  CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  
   
  
  commit;
  
  CREATE TABLE QRTZ_JOB_DETAILS(
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  JOB_NAME VARCHAR(190) NOT NULL,
  
  JOB_GROUP VARCHAR(190) NOT NULL,
  
  DESCRIPTION VARCHAR(250) NULL,
  
  JOB_CLASS_NAME VARCHAR(250) NOT NULL,
  
  IS_DURABLE VARCHAR(1) NOT NULL,                  
  
  IS_NONCONCURRENT VARCHAR(1) NOT NULL,
  
  IS_UPDATE_DATA VARCHAR(1) NOT NULL,
  
  REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
  
  JOB_DATA BLOB NULL,
  
  PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  JOB_NAME VARCHAR(190) NOT NULL,
  
  JOB_GROUP VARCHAR(190) NOT NULL,
  
  DESCRIPTION VARCHAR(250) NULL,
  
  NEXT_FIRE_TIME BIGINT(13) NULL,
  
  PREV_FIRE_TIME BIGINT(13) NULL,
  
  PRIORITY INTEGER NULL,
  
  TRIGGER_STATE VARCHAR(16) NOT NULL,
  
  TRIGGER_TYPE VARCHAR(8) NOT NULL,
  
  START_TIME BIGINT(13) NOT NULL,
  
  END_TIME BIGINT(13) NULL,
  
  CALENDAR_NAME VARCHAR(190) NULL,
  
  MISFIRE_INSTR SMALLINT(2) NULL,
  
  JOB_DATA BLOB NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
  
  REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_SIMPLE_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  REPEAT_COUNT BIGINT(7) NOT NULL,
  
  REPEAT_INTERVAL BIGINT(12) NOT NULL,
  
  TIMES_TRIGGERED BIGINT(10) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_CRON_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  CRON_EXPRESSION VARCHAR(120) NOT NULL,
  
  TIME_ZONE_ID VARCHAR(80),
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_SIMPROP_TRIGGERS
  
    (
  
      SCHED_NAME VARCHAR(120) NOT NULL,
  
      TRIGGER_NAME VARCHAR(190) NOT NULL,
  
      TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
      STR_PROP_1 VARCHAR(512) NULL,
  
      STR_PROP_2 VARCHAR(512) NULL,
  
      STR_PROP_3 VARCHAR(512) NULL,
  
      INT_PROP_1 INT NULL,
  
      INT_PROP_2 INT NULL,
  
      LONG_PROP_1 BIGINT NULL,
  
      LONG_PROP_2 BIGINT NULL,
  
      DEC_PROP_1 NUMERIC(13,4) NULL,
  
      DEC_PROP_2 NUMERIC(13,4) NULL,
  
      BOOL_PROP_1 VARCHAR(1) NULL,
  
      BOOL_PROP_2 VARCHAR(1) NULL,
  
      PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
      FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
      REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_BLOB_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  BLOB_DATA BLOB NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
  
  INDEX (SCHED_NAME,TRIGGER_NAME, TRIGGER_GROUP),
  
  FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
  
  REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_CALENDARS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  CALENDAR_NAME VARCHAR(190) NOT NULL,
  
  CALENDAR BLOB NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,CALENDAR_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_FIRED_TRIGGERS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  ENTRY_ID VARCHAR(95) NOT NULL,
  
  TRIGGER_NAME VARCHAR(190) NOT NULL,
  
  TRIGGER_GROUP VARCHAR(190) NOT NULL,
  
  INSTANCE_NAME VARCHAR(190) NOT NULL,
  
  FIRED_TIME BIGINT(13) NOT NULL,
  
  SCHED_TIME BIGINT(13) NOT NULL,
  
  PRIORITY INTEGER NOT NULL,
  
  STATE VARCHAR(16) NOT NULL,
  
  JOB_NAME VARCHAR(190) NULL,
  
  JOB_GROUP VARCHAR(190) NULL,
  
  IS_NONCONCURRENT VARCHAR(1) NULL,
  
  REQUESTS_RECOVERY VARCHAR(1) NULL,
  
  PRIMARY KEY (SCHED_NAME,ENTRY_ID))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_SCHEDULER_STATE (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  INSTANCE_NAME VARCHAR(190) NOT NULL,
  
  LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
  
  CHECKIN_INTERVAL BIGINT(13) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,INSTANCE_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE TABLE QRTZ_LOCKS (
  
  SCHED_NAME VARCHAR(120) NOT NULL,
  
  LOCK_NAME VARCHAR(40) NOT NULL,
  
  PRIMARY KEY (SCHED_NAME,LOCK_NAME))
  
  ENGINE=InnoDB;
  
   
  
  CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY ON QRTZ_JOB_DETAILS(SCHED_NAME,REQUESTS_RECOVERY);
  
  CREATE INDEX IDX_QRTZ_J_GRP ON QRTZ_JOB_DETAILS(SCHED_NAME,JOB_GROUP);
  
   
  
  CREATE INDEX IDX_QRTZ_T_J ON QRTZ_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_JG ON QRTZ_TRIGGERS(SCHED_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_C ON QRTZ_TRIGGERS(SCHED_NAME,CALENDAR_NAME);
  
  CREATE INDEX IDX_QRTZ_T_G ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  
  CREATE INDEX IDX_QRTZ_T_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_N_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_N_G_STATE ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME ON QRTZ_TRIGGERS(SCHED_NAME,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST ON QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);
  
  CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP ON QRTZ_TRIGGERS(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);
  
   
  
  CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME);
  
  CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);
  
  CREATE INDEX IDX_QRTZ_FT_J_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_JG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,JOB_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_T_G ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);
  
  CREATE INDEX IDX_QRTZ_FT_TG ON QRTZ_FIRED_TRIGGERS(SCHED_NAME,TRIGGER_GROUP);
  
   
  
  commit;
  
   



We should create quartz table manually,

 

                             we must run your database schema scripts, as seen one example above. You can find scripts in the below link. Scripts change according to the relational database you have chosen.

         After you run the database scripts, Quartz table should be listed like this;

 



Now, configuration is ready for creating jobs and triggers for scheduled tasks



The main Quartz interfaces are listed below:


Job is an interface to be implemented by the classes that contain the business logic that we wish to have executed


JobDetails defines Job instances and data that are related to it


Trigger describes the schedule of job execution


Scheduler is the main Quartz interface that provides all manipulation and searching operations for jobs and triggers



ยท  Scheduling Mail Rest Api


 
@Path("/ws2/mail")
@POST

    @Path("/alert/consolidated")

    @Produces(MediaType.APPLICATION_JSON)

    public @ResponseBody Response emailConsolidatedAlert(final @Context HttpServletRequest httpRequest,

            @NotNull(message = "Invalid amzn account id") @HeaderParam("x-gs-amzn-acc-id") Integer alertId) {

        try {

            alertService.Consolidatedalert(alertId);

            // return Response.status(Status.OK).entity(MAPPER.writeValueAsString("Success")).build();

 

            String responseEntity = MAPPER.writeValueAsString("Success");

            Response response = Response.status(Status.OK).entity(responseEntity).build();

            log.info("Saved email {}", responseEntity);

            log.debug("Saved email {}", responseEntity);

            System.out.println("Saved email " + responseEntity);

            return response;

 

        } catch (JsonProcessingException e) {

            e.printStackTrace();

            log.error("error sending consolidated email alert", e);

            return Response.status(Status.INTERNAL_SERVER_ERROR).build();

        }

    }

 

}

 


   Creating the Alert Request


    AlertSchedulerRequest alertRequest = new AlertSchedulerRequest(

    gsAccount.getAccountID(), alertRuleSettings.getAmazonAccountId(),

    gsAccount.getAwsCustomerID(),

    settings.getConsolidatedAlertReportSchedule(),

    alertRuleSettings.getId(),

    alertRuleSettings.getServiceTag(),

    alertRuleSettings.getPercentageTag()

);

try {

    alertResourceScheduler.createSchedule(alertRequest);

    System.out.println("Consolidated alert report schedule created successfully for account ID: " + gsAccount.getAccountID());

} catch (SchedulerException e) {

    log.error("Error scheduling consolidated alert report email request for account " + gsAccount.getAccountID(), e);

}



ยท  Schedule Request:

 

                                          This class is used to encapsulate the details needed to schedule an alert.

   Above alertscheduler details encapsulate into below classโ€ฆ.


  package com.gs.ci.ciengine.scheduler;

import org.hibernate.validator.constraints.NotEmpty;

 

public class AlertSchedulerRequest {

    @NotEmpty

    private Integer gsAccountID;

 

    @NotEmpty

    private Integer amznAccountID;

 

    @NotEmpty

    private String amznCustomerID;

 

    @NotEmpty

    private String cronExpression;

 

    @NotEmpty

    private Integer alertId;

 

    @NotEmpty

    private String serviveTag;

 

    @NotEmpty

    private String percentageTag;

 

    public AlertSchedulerRequest() {

 

    }โ€ฆโ€ฆโ€ฆโ€ฆโ€ฆ

 

    public AlertSchedulerRequest(Integer gsAccountID, Integer amznAccountID,

            String amznCustomerID,

            String cronExpression,

            Integer alertId, String serviveTag, String percentageTag) {

        super();

        this.gsAccountID = gsAccountID;

        this.amznAccountID = amznAccountID;

        this.amznCustomerID = amznCustomerID;

        this.cronExpression = cronExpression;

        this.alertId = alertId;

        this.serviveTag = serviveTag;

        this.percentageTag = percentageTag;

    }

 

    public Integer getGsAccountID() {

        return gsAccountID;

    }

 

    public void setGsAccountID(Integer gsAccountID) {

        this.gsAccountID = gsAccountID;

    }

 

    public Integer getAmznAccountID() {

        return amznAccountID;

    }

 

    public void setAmznAccountID(Integer amznAccountID) {

        this.amznAccountID = amznAccountID;

    }

 

    public String getAmznCustomerID() {

        return amznCustomerID;

    }

 

    public void setAmznCustomerID(String amznCustomerID) {

        this.amznCustomerID = amznCustomerID;

    }

 

    public String getCronExpression() {

        return cronExpression;

    }

 

    public void setCronExpression(String cronExpression) {

        this.cronExpression = cronExpression;

    }

 

    public Integer getAlertId() {

        return alertId;

    }

 

    public void setAlertId(Integer alertId) {

        this.alertId = alertId;

    }

 

    public String getServiveTag() {

        return serviveTag;

    }

 

    public void setServiveTag(String serviveTag) {

        this.serviveTag = serviveTag;

    }

 

    public String getPercentageTag() {

        return percentageTag;

    }

 

    public void setPercentageTag(String percentageTag) {

        this.percentageTag = percentageTag;

    }

 

}

 



ยท  Schedular Response

                                           

This class is used to encapsulate the response after attempting to schedule an alert. It contains fields like success, jobId, jobGroup, and message.


        package com.gs.ci.ciengine.scheduler;

 

public class AlertSchedulerResponse {

 

    private boolean success;

    private String jobId;

    private String jobGroup;

    private String message;

 

    public AlertSchedulerResponse() {

 

    }

 

    public boolean isSuccess() {

        return success;

    }

 

    public void setSuccess(boolean success) {

        this.success = success;

    }

 

    public String getJobId() {

        return jobId;

    }

 

    public void setJobId(String jobId) {

        this.jobId = jobId;

    }

 

    public String getJobGroup() {

        return jobGroup;

    }

 

    public void setJobGroup(String jobGroup) {

        this.jobGroup = jobGroup;

    }

 

    public String getMessage() {

        return message;

    }

 

    public void setMessage(String message) {

        this.message = message;

    }

 

}

 



ยท  Define the job


                 The job to be scheduled should implement the org.quartz.Job interface..

                 The interface to be implemented by classes that represent a โ€˜jobโ€™ in Quartz. It has a single method called execute() where you write the work that needs to be performed by the Job.


         

@Slf4j

@PropertySources({ @PropertySource("classpath:${env}-application.properties")

})

public class AlertResourcejob extends QuartzJobBean {

 

    @Override

    protected void executeInternal(JobExecutionContext jobExecutionContext)

            throws JobExecutionException {

 

                System.out.println("print");

 

        log.info("Executing Job with key {}",

                jobExecutionContext.getJobDetail().getKey());

 

        JobDataMap jobDataMap = jobExecutionContext.getMergedJobDataMap();

        if (jobDataMap != null) {

            Integer alertId = (Integer) jobDataMap.get("alertId");

            if (alertId != null) {

                postEmailTrigger(alertId);

                // alertService.Consolidatedalert(alertId);

            }

        }

    }



                To implement Job interface, you need to implement only one execute method that accepts a parameter of JobExecutionContext type. JobExecutionContext contains information about the job instance, trigger, scheduler, and other information about the job execution

 

 

ยท Create job and Trigger:

 

In AlertResourceschedular,


                   It is time to create job and trigger to schedule. โ€œSchedulerโ€ interface can be used by just adding โ€œAutowiredโ€ annotation


  @Autowired
  private Scheduler scheduler;


                 Below code sample shows how to create โ€œJobDetailโ€ object. As you saw earlier, you should store data to โ€œJobDataMapโ€ and use this map when creating the JobDetail object. AlertResourcejob class which implements โ€œJobโ€ interface, should be used here. There is also โ€œidentityโ€ for the job, like primary key for a job and will be used to call the created job. Samples about how to use will be shown in the next tutorial


        public AlertSchedulerResponse createSchedule(AlertSchedulerRequest alertRequest)

                        throws SchedulerException {

                boolean newTrigger = false;

                JobDetail jobDetail = buildJobDetail(alertRequest);

                ScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(alertRequest.getCronExpression())

                                .withMisfireHandlingInstructionDoNothing();

                System.out.println("ScheduleBuilder created with cron expression: " + alertRequest.getCronExpression());

 


After creating Job, you must create โ€œTriggerโ€, in order to define the schedule of the job. As seen in the below sample code, when creating the Trigger object, you can specify when to start for running the job, period and how many times you want to run the job. Like in the Job, there is also identity to specify unique trigger


Trigger trigger = buildJobTrigger(jobDetail, scheduleBuilder, alertRequest);

                CronTrigger ctrigger = (CronTrigger) scheduler.getTrigger(trigger.getKey());

 

                if (null == ctrigger) {

                        newTrigger = true;

                        System.out.println("New trigger created for job: " + jobDetail.getKey());

                } else {

                        System.out.println("Trigger already exists for job: " + jobDetail.getKey());

                }

if (scheduler.getTriggerState(trigger.getKey()) == Trigger.TriggerState.PAUSED) {

                        scheduler.resumeJob(jobDetail.getKey());

                }

 

                if (newTrigger) {

                        scheduler.scheduleJob(jobDetail, trigger);

                        System.out.println("New trigger scheduled for job: " + jobDetail.getKey());

 

                } else {

                        scheduler.rescheduleJob(trigger.getKey(), trigger);

                        System.out.println("Trigger rescheduled for job: " + jobDetail.getKey());

 

                }

 

                AlertSchedulerResponse response = buildSchedulerResponse(jobDetail,

                                alertRequest);

                return response;

        }


Now, you have Job and Trigger objects, and as seen above sample, you schedule by just โ€œscheduler.scheduleJob(job,trigger)โ€. After that, job and trigger objects were saved to โ€œQuartz tablesโ€, and job will be fired in the scheduled times.


 if (newTrigger) {

                        scheduler.scheduleJob(jobDetail, trigger);

                        System.out.println("New trigger scheduled for job: " + jobDetail.getKey());

 

                } else {

                        scheduler.rescheduleJob(trigger.getKey(), trigger);

                        System.out.println("Trigger rescheduled for job: " + jobDetail.getKey());

 

                }


 



ยท  Sending email:

   

Pass the data ,


  modal.put("variance", variancefordaily);
  
  modal.put("VariancePercent", VariancePercentfordaily);
  
  modal.put("result", result);
  
  modal.put("hostname", ciConsoleURL);
  
  modal.put("currentMonth", DateUtils.getCurrentMonth());
  
  modal.put("serviceTag", trimmedServiceTag);
  
  modal.put("username", amazonAccount.getGsAccountName());
  
  modal.put("name", amazonAccount.getAmazonAccountName());
  
   
  
  emailAlertService.emailConsolidatedAlert(modal, alertRuleSettings);



A Map named modal is populated with various values, including variance, VariancePercent, result, etc.

The emailConsolidatedAlert method of emailAlertService is called with modal and alertRuleSettings


ยท  Email alert service:



Injects an instance of EmailAlertSender, which handles sending emails

Injects a VelocityEngine instance for template rendering


@Service

@PropertySources({ @PropertySource("classpath:${env}-application.properties")

})

 

public class EmailAlertServiceImpl implements EmailAlertService {

 

    @Autowired

    EmailAlertSender emailalertsender;

 

    @Value("${ci.support.email}")

    String adminEmail;

 

    @Autowired

    VelocityEngine velocityEngine;

 

    @Override

    public void emailConsolidatedAlert(Map<String, Object> modal, AlertRuleSettings alertRuleSettings) {

        try {

            String mailsubject = "Test Email Subject";

            String mailContent = getContentFromTemplate(modal, alertRuleSettings.getServiceTag());

 

            String recipientEmail = alertRuleSettings.getEmailAlert();

            System.out.println("recipientEmail: " + recipientEmail);

 

            String[] serviceNames = alertRuleSettings.getServiceName();

 

            if (StringUtils.isNoneEmpty(mailContent) && serviceNames != null) {

 

                // String[] serviceTags = alertRuleSettings.getServiceTag().split(",");

                List<String> serviceNamesList = Arrays.asList(serviceNames);

                Object serviceTagObj = modal.get("serviceTag");

 

                if (serviceTagObj != null && serviceTagObj instanceof String) {

                    String serviceTag = ((String) serviceTagObj).trim();

 

                    if (serviceNamesList.contains(serviceTag.trim())) {

                        mailsubject = "Alert servicename Report - Cloud Insider";

 

                        double percentageTag = alertRuleSettings.getPercentageForService(serviceTag);

                        System.out.println("Service tag: " + serviceTag + ", Percentage tag: " + percentageTag);

 

                        boolean sendEmail = false;

 

                        for (Map.Entry<String, Object> entry : modal.entrySet()) {

                            String key = entry.getKey();

                            Object value = entry.getValue();

 

                            if (value instanceof Double && "result".equals(key)) {

                                Double resultValue = (Double) value;

                                if (resultValue >= percentageTag) {

                                    sendEmail = true;

                                    break;

                                }

                            }

                        }

                        if (sendEmail) {

                            emailalertsender.sendEmail(recipientEmail, mailsubject, mailContent);

                        } else {

                            System.out

                                    .println("-----------------------------------------------------------------------");

                            System.out.println("Variance value for '" + serviceTag + "' is less than 10...");

                            System.out

                                    .println("-----------------------------------------------------------------------");

 

                        }

                    } else {

                        System.out.println("servicenamelist has no servicetag");

                    }

                } else {

                    System.out.println("serviceTagObj is null");

                }

            } else {

                System.out.println("Mail content is empty or service names array is null");

 

            }

 

            // Send the email

        } catch (Exception e) {

            e.printStackTrace(); // Handle exception appropriately

        }

 

    }

 

    private String getContentFromTemplate(Map<String, Object> model, String servicetype) {

        StringWriter mergedContent = new StringWriter();

        VelocityContext velocityContext = new VelocityContext();

        String template = null;

 

        if (servicetype != null) {

            template = "templates/EC2 others-report.vm";

        } else {

            System.out.println("it is not ec2-other");

        }

 

        for (Map.Entry<String, Object> entry : model.entrySet()) {

            String key = entry.getKey();

            Object value = entry.getValue();

            velocityContext.put(key, value);

        }

        velocityContext.put("date", new DateTool());

        velocityContext.put("number", new NumberTool());

        velocityEngine.mergeTemplate(template, "UTF-8", velocityContext, mergedContent);

 

        return mergedContent.toString();

    }

 

}



This method generates an email alert based on conditions and template content:

Retrieves email content from a Velocity template using getContentFromTemplate.

Checks conditions based on service tag and result value to decide whether to send the email using emailalertsender.sendEmail.

Handles various cases with print statements if conditions are not met..


     This method retrieves the content of an email template using Apache Velocity:

      โ€ข        Determines the template file based on servicetype.

      โ€ข        Populates Velocity context with data from model.

โ€ข        Merges data into the template using velocityEngine.mergeTemplate



ยท  Email alert sender:


                           This method constructs and sends an email using email-builder-lib:

Constructs an Email object using EmailBuilder.

Sends the email using MailerBuilder with SMTP server details.


package com.gs.ci.ciengine.alertmail;

 

import org.simplejavamail.email.Email;

import org.simplejavamail.email.EmailBuilder;

import org.simplejavamail.email.EmailPopulatingBuilder;

import org.simplejavamail.mailer.MailerBuilder;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.context.annotation.PropertySource;

import org.springframework.context.annotation.PropertySources;

import org.springframework.stereotype.Service;

 

@Service

@PropertySources({ @PropertySource("classpath:${env}-application.properties")

})

public class EmailAlertSender {

 

    @Value("${smtp.host}")

    String smtpHost;

 

    @Value("${smtp.port}")

    String smtpPort;

 

    @Value("${smtp.user}")

    String smtpUser;

 

    @Value("${smtp.password}")

    String smtpPasswd;

 

    @Value("${smtp.from.name}")

    String smtpFromName;

 

    @Value("${smtp.from.email}")

    String smtpFromEmail;

 

    @Value("${ci.support.email}")

    String adminEmail;

 

    public boolean sendEmail(String tolist, String subject, String body) {

        // log.trace("Sending email to " + tolist);

        // log.trace("Email body = " + body);

 

        String[] to = tolist.split(",");

        if (to.length > 0) {

            EmailPopulatingBuilder emailPopulatingBuilder = EmailBuilder.startingBlank()

                    .from(smtpFromName, smtpFromEmail).withSubject(subject).withHTMLText(body);

 

            for (int i = 0; i < to.length; i++) {

                emailPopulatingBuilder.to(to[i]);

            }

 

            Email email = emailPopulatingBuilder.buildEmail();

 

            System.out.println("Printing Email Content:");

            System.out.println("From: " + email.getFromRecipient());

            System.out.println("To: " + email.getRecipients());

            System.out.println("Subject: " + email.getSubject());

            System.out.println("Body:\n" + email.getPlainText());

            MailerBuilder.withSMTPServer(smtpHost, Integer.parseInt(smtpPort), smtpUser,

                    smtpPasswd).buildMailer()

                    .sendMail(email, true);

 

            return true;

 

        }

        return false;}

}




 

Open postman check mail api,


This is the api http://localhost:8085/ws2/mail/alert/consolidated




Mail successfully sentโ€ฆ