Sending Bulk SMS using Sprint Boot Batch


You must use Spring Boot Batch Jobs to send the bulk SMS's.  It's very flexible to schedule these jobs using Cron expression, so you can send the SMS as per the requirement. e.g. daily, weekly or at a particular time. 


We need to integrate our job with the SMS provider like - msg91

Following is the Job configuration - This class has reader which will read the data for SMS content and job defination


@Configuration
@EnableBatchProcessing
public class SmsBatchConfiguration {
	
	@Autowired
	@Qualifier("smsContentReader")
    
	public ItemReader> itemReader;
	
	@Autowired
	@Qualifier("nenewalNotificationSMSProcessor")
	RenewalNotificationSMSProcessor renewalNotificationSMSProcessor;
	
	@Autowired
	@Qualifier("smsSender")
	SmsSender SmsSender;
	
	@Autowired
	public JobBuilderFactory jobBuilderFactory;
	
	@Autowired
	public StepBuilderFactory stepBuilderFactory;
	
	@Value("${renewal.batch.notifications.email}")
	private String email;
	
	@Bean
    public JobExecutionListener listener1() {
        return new JobCompletionNotificationListener(email, "SMS_JOB");
    }
	
	@Bean("smsReminderJob")
    public Job renewalSMSNotificationJob() {
		return jobBuilderFactory.get("renewalSMSNotificationJob")
                .incrementer(new RunIdIncrementer())
                .start(getSmsRenewalPolicyData())
				.listener(listener1())
                .build();
    }

    @Bean
    public Step getSmsRenewalPolicyData() {
        return stepBuilderFactory.get("renewal-policy-sms-n")
                ., SmsFlowModel>chunk(1)
                .reader(itemReader)
                .processor(renewalNotificationSMSProcessor)
                .writer(SmsSender)
                .build();
    }
    
}

Following class is the item processor which will get the data from reader and pass it to writter


@StepScope
@Component("nenewalNotificationSMSProcessor")
public class RenewalNotificationSMSProcessor implements ItemProcessor, SmsFlowModel> {

    private static final Logger log = LoggerFactory.getLogger(RenewalNotificationSMSProcessor.class);

    @Value("${renewal.batch.notifications.sms.template_id}")
    private String template_id;

    @Value("${renewal.batch.notifications.sms.sender}")
    private String sender;

    @Override
    public SmsFlowModel process(List renewals) throws Exception {
        log.info("started - processing renewal policy details - SMS");
        List recipientsList = null;
        SmsFlowModel smsFlowModel = null;

        if (renewals != null && !renewals.isEmpty()) {
            recipientsList = new ArrayList<>();
            for (Renewal renewal : renewals) {
                if (renewal.getContactNumber() != null) {   // You will get the mobile number of recipient
                    MessageParameters msgParam = new MessageParameters();
                    msgParam.setPolicyno(renewal.getPolicyNo());
                    msgParam.setPremiumamount(String.valueOf(renewal.getPremium()));
                    msgParam.setMobiles("91".concat(renewal.getContactNumber().trim()));
                    recipientsList.add(msgParam);
                }
            }
            if (!recipientsList.isEmpty()) {
                smsFlowModel = new SmsFlowModel();
                smsFlowModel.setTemplate_id(this.template_id);
                smsFlowModel.setSender(this.sender);
                smsFlowModel.getRecipients().addAll(recipientsList);
            }
            return smsFlowModel;
        }
        return null;
    }

}

Following class will send the SMS, will are invoking the msg91 api to send the SMS to mobile numbers


@StepScope
@Component("smsSender")
public class SmsSender implements ItemWriter {
    private static final Logger LOGGER = LoggerFactory.getLogger(SmsSender.class);

    @Value("${renewal.batch.notifications.sms.auth}")
    private String authKey;

    @Value("${renewal.batch.notifications.sms.url}")
    private String apiUrl;

    @Override
    public void write(List bulkSMS) throws Exception {
        LOGGER.info("about to start sending SMS---");
        StringBuilder msg = (StringBuilder) CommonConstant.getDaysMap().get("sms-job-message");

        if (bulkSMS != null && bulkSMS.size() > 0) {
            SmsFlowModel sms = bulkSMS.get(0);
            ObjectMapper mapper = new ObjectMapper();
            String jsonString = mapper.writeValueAsString(sms);
            msg.append("\n").append("SMS request json : ").append(jsonString);

			HttpResponse response = null;

            try {
                response = Unirest.post(apiUrl)
                        .header("authkey", authKey)
                        .header("content-type", "application/json")
                        .body(jsonString)
                        .asJson();
            } catch (UnirestException e) {
                LOGGER.error("Error occured while sending sms : {}", e.getMessage());
                e.printStackTrace();
            }

			msg.append("\n").append("------------------------------------------------------------------------------------");
			if (response != null) {
                JSONObject myObj = response.getBody().getObject();
                LOGGER.info("SMS server response : " + myObj);
                msg.append("\n").append("SMS server response : ").append(myObj);
            } else {
                LOGGER.info("SMS server response response is null");
                msg.append("\n").append("SMS server response response is null");
            }

        } else {
            LOGGER.info("--sms sender object is null ---");
            msg.append("\n").append("sms sender object is null");
        }
        CommonConstant.getDaysMap().put("sms-job-message", msg);
    }
}

Properties file

This job will send the SMS on daily basis at 12 PM (as per the cron expression value)



##Batch properties##
spring.profiles.active=prod
spring.batch.job.enabled=false
spring.first.initialization=false

##Database##
spring.datasource.url=jdbc:mysql://localhost:3306/test_db
spring.datasource.username=uname
spring.datasource.password=passwd
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.initialization-mode=ALWAYS
spring.datasource.continue-on-error=false
spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

spring.jpa.properties.hibernate.format_sql=false
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=false

#sms-server
renewal.batch.notifications.sms.auth=
renewal.batch.notifications.sms.url=http://api.msg91.com/api/v5/flow/?response=json
renewal.batch.notifications.sms.template_id=
renewal.batch.notifications.sms.sender=SHRI

#cron-expression
sms.job.launch.cronExpression=0 0 12 * * *

POM file link https://github.com/shrikantar/bulksms/blob/main/pom.xml

Comments

Popular posts from this blog

Right way to close HttpsURLConnetion using try with resources in java 8

Spring Boot Batch - Parallel Processing (Running Multiple Jobs Concurrently)

Git Quick Card