Category Archives: Spring Boot

Quartz reuse existing data source connection pool.

Quartz is a de facto scheduling system for java which has enterprise scale functionality and scales very well. This tutorial will explain how to reuse existing datasource using sprint boot application and quartz. Most real world application has datasource as singleton scope and wanted to share the same object with Quartz.

Step 1 – Data Source configuration

First, we have configured data source with hostname, port, username, password..etc. This DataSource will be a singleton scope and make sure it has enough connections to support your application load and quartz – usually, it will be equal to a total number of quartz worker threads.

package quartz;

import com.mysql.cj.jdbc.MysqlDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * @author CandidJava.com
 */
@Configuration
public class DataSourceFactory {
   @Bean
   public DataSource getDataSource() {
      MysqlDataSource dataSource = new MysqlDataSource();
      dataSource.setServerName("localhost");
      dataSource.setPort(3306);
      dataSource.setDatabaseName("database1");
      dataSource.setUser("user1");
      dataSource.setPassword("password1");
      return dataSource;
   }
}

 

Step 2-  Configure Connnection Provider

Here, we inject the data source from step 1 and implement ConnectionProvider interface from Quartz.

package quartz;

import org.quartz.utils.ConnectionProvider;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

import static java.util.Objects.requireNonNull;

/**
 * Implement ConnectionProvider from quartz library.
 */
public final class ConnectionProviderImpl implements ConnectionProvider {

   private DataSource dataSource;

   ConnectionProviderImpl(DataSource dataSource) {
      this.dataSource = dataSource;
   }

   @Override
   public Connection getConnection() throws SQLException {
      return dataSource.getConnection();
   }

   @Override
   public void shutdown() throws SQLException {
      // No-op
   }

   @Override
   public void initialize() throws SQLException {
      requireNonNull(dataSource, "DataSource initialization failed");
   }
}

 

Step 3 - Configure Quartz Scheduler.

Configure Scheduler system and start the service.

package quartz;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.DirectSchedulerFactory;
import org.quartz.impl.jdbcjobstore.JobStoreTX;
import org.quartz.simpl.SimpleThreadPool;
import org.quartz.utils.DBConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

/**
 * @author CandidJava.com
 * */
@Configuration
public class QuartzSchedulerFactory {

   public static final String INSTANCE_NAME = "Candid-Java-Scheduler";
   public static final String INSTANCE_ID = INSTANCE_NAME + "1"; // Use UUID if running as cluster.
   public static final String DATA_SOURCE = "sharedDataSource";
   private final DataSource dataSource;
   private Scheduler scheduler;

   @Autowired
   public QuartzSchedulerFactory(DataSource dataSource) {
      this.dataSource = dataSource;
   }

   @Bean
   public Scheduler getScheduler() throws SchedulerException {

      DBConnectionManager.getInstance().addConnectionProvider(DATA_SOURCE, new ConnectionProviderImpl(dataSource)); 
      
      // Configure jdbc store
      JobStoreTX jdbcJobStore = new JobStoreTX();
      jdbcJobStore.setInstanceName(INSTANCE_NAME);
      jdbcJobStore.setDataSource(DATA_SOURCE);
      jdbcJobStore.setClusterCheckinInterval(20000L);
      jdbcJobStore.setDbRetryInterval(15000L);
      jdbcJobStore.setIsClustered(true);

      // Create a scheduler.
      DirectSchedulerFactory.getInstance().createScheduler(INSTANCE_NAME, INSTANCE_ID,
            new SimpleThreadPool(5, Thread.NORM_PRIORITY), jdbcJobStore);
      this.scheduler = DirectSchedulerFactory.getInstance().getScheduler(INSTANCE_NAME);

      // Start the scheduler.
      scheduler.start();

      return this.scheduler;
   }


}

 

Step 4 - Expose Scheduler using Controller in spring boot style.

package quartz;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author CandidJava.com
 * */
@Controller
public class QuartzTester {
   private final Scheduler scheduler;

   @Autowired
   public QuartzTester(Scheduler scheduler) {
      this.scheduler = scheduler;
   }

   @RequestMapping("/")
   @ResponseBody
   String getSchedulerDetails() throws SchedulerException {
      return String.format("Scheduler name %s started ?. %s", 
            scheduler.getSchedulerName(), String.valueOf(scheduler.isStarted()).toUpperCase());
   }
}

 

Step 5 - Start the application as Spring boot app.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;


@Configuration
@EnableAutoConfiguration
@ComponentScan("quartz")
public class ApplicationBoot { 
   public static void main(String[] args) {
      SpringApplication.run(ApplicationBoot.class, args);
   }
}

Once you start the application(main method), and hit localhost:8080 in the browser, you will see the scheduler is running by sharing the existing data-source for database connection.

"Scheduler name Candid-Java-Scheduler started ?. TRUE"

Spring boot maven plugin and starter for web application

Spring-boot-starter maven

Spring Boot starters makes deveroper easyer to add jars to classpath

Spring boot maven plugin

The Spring Boot Maven Plugin provides Spring Boot support in Maven, letting you package executable jar or war archives and run an application “in-place”. To use it, you must use Maven 3.2 (or later).

<plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
 </plugin>

spring-boot-starter-parent maven

The spring-boot-starter-parent provides Maven and spring default configuration and dependency-management section so that you can omit version tags for “blessed” dependencies.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.6.RELEASE</version>
</parent>

Note : We can also declare our own parent if needed refer :

spring-boot-starter-web maven

Other “Starters” simply provide dependencies that you are likely to need when developing a specific type of application. Since we are developing a web application, we will add a spring-boot-starter-web dependency to our opm.xml file

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

spring boot dependencies – Spring-boot-starter maven for Web application

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.candidjava.spring.boot</groupId>
    <artifactId>helloworld</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>helloworld</name>
    <url>http://maven.apache.org</url>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

 

Try Spring boot hello word example

Reference

Spring boot maven plugin — official site

 

 

 

 

Spring boot Spring System Requirements and compatibility

Spring boot 1.5.6 Spring System Requirements and compatibility

Java compatibility

Spring boot is compatible with Java 1.6, but consider using latest version

Maven or Gradle

Spring Boot is compatible with Apache Maven 3.2 or above, Gradle 2.9 or above

Container

Any servlet 3.0+ compatible container

Example : Tomcat 7 or above , Jetty 8 or above

Spring Framework

Spring Framework 4.3.10.RELEASE or above

Note:

If you are using tomcat 7 then servlet version should by 3.0 and java 6 or above

If you are using tomcat 8 then servlet version should by 3.1 and java 7 or above

Spring boot tutorial

learn spring boot

Why spring boot :

Spring boot was developed by the pivotal team for the purpose of creates micro services for java based applications. With comprehensive infrastructure spring boot helps you to create standalone application.all you need to do is just run.

Spring boot system requirement

Spring boot starter with maven dependency

Spring boot getting started example

Spring boot Creating executable jar

Spring boot war tomcat – creating a deployable war file

Spring boot devtools eclipse

 

Spring boot JPA curd example using mysql database

 

Spring boot web application example xml configuration using @ImportResource

Spring boot web application Java based configuration – @Import

Spring boot jetty as embedded server example

 

Spring boot quartz scheduler

Spring boot mongodb example

 

Spring boot rabbitmq example

profiles

accuator

Metrics

Logger