Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Spring-Boot, How can we connect to two databases (Mysql database and MongoDB) in the same project?

I am trying to create a "Spring-Boot" project in which I have a requirement where I want to connect to to different databases "MySql" and "MongoDB".

Do I need to do something special to connect to both the databases or spring-boot will figure automatically to connect to both the databases by itself. Do I need to define datasource for "mongodb" as well?

MySQL specific "YML" file is like below

# Default DB parameter definitions for the URL parameters in the spring.datasource.url property below
database:
  host: localhost
  port: 3306
  schema: subscriptions
  username: root
  password: root
  autoconnect:
    maxReconnects: 3
    initialTimeout: 2
  timeout:
    connectTimeout: 0
    socketTimeout: 0
  failover:
    host: localhost 
    port: 3306
    queriesBeforeRetryMaster: 50
    secondsBeforeRetryMaster: 30
  properties: useTimezone=true&serverTimezone=UTC&useLegacyDatetimeCode=false&failOverReadOnly=false&autoReconnect=true&maxReconnects=${database.autoconnect.maxReconnects}&initialTimeout=${database.autoconnect.initialTimeout}&connectTimeout=${database.timeout.connectTimeout}&socketTimeout=${database.timeout.socketTimeout}&queriesBeforeRetryMaster=${database.failover.queriesBeforeRetryMaster}&secondsBeforeRetryMaster=${database.failover.secondsBeforeRetryMaster}

spring:
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://${database.host}:${database.port},${database.failover.host}:${database.failover.port}/${database.schema}?${database.properties}
    username: ${database.username}
    password: ${database.password}
    continueOnError: true
    initialize: false
    initialSize: 0
    timeBetweenEvictionRunsMillis: 5000
    minEvictableIdleTimeMillis: 5000
    removeAbandonedTimeout: 60
    removeAbandoned: true
    minIdle: 0

  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
      naming_strategy: org.hibernate.cfg.DefaultNamingStrategy
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
        hbm2ddl:
          auto: none
        temp:
          use_jdbc_metadata_defaults: false 

My MongoDB "YML" looks like below

spring:
  data:
    mongodb.host: localhost
    mongodb.port: 27017
    mongodb.database: eventsarchive
    mongodb.username: root
    mongodb.password: root
    mongodb.repositories.enabled: true

Application.java file below

@Configuration
@EnableAutoConfiguration
@EnableConfigurationProperties
@EntityScan(basePackages = { "persistence.mysql.domain" })
@EnableJpaRepositories("persistence.mysql.dao")
@EnableMongoRepositories("persistence.mongodb.dao")
@ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
value = ApiAuthenticationFilter.class) },
basePackages = {
                "admin",
                "common",
                "mqclient",
"scheduler" })
public class Application {

  @Value("${service.name}")
  private String serviceName;
  @Value("${service.namespace}")
  private String serviceNamespace;
  @Value("${webservice.namespace}")
  private String webserviceNamespace;
  @Value("${webservice.port}")
  private int webservicePort;
  @Value("${jersey.request-filters}")
  private String requestFilters;
  @Value("${jersey.response-filters}")
  private String responseFilters;

  private static final String MAPPING_URL = "/%s/*";

  static {
    System.setProperty(USER_TIMEZONE, "UTC");
  }

  /**
   * Java main method.
   */
  public static void main(String[] args) {
    /*
     * Defines which Spring Boot Profiles should be active on startup. Please see
     * http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-profiles for details.
     */
    final SpringApplicationBuilder appBuilder = new SpringApplicationBuilder(Application.class);
    appBuilder.profiles("common", "common_mongo_db", "common_mysql_db", "common_rabbitmq", "admin").application()
    .run(args);
  }

  /**
   * Registers Jersey with Spring Boot.
   */
  @Bean
  public ServletRegistrationBean registerJersey() {
    final ServletRegistrationBean registration = new ServletRegistrationBean(new SpringServlet(),
                                                                             String.format(MAPPING_URL,
                                                                                           this.serviceNamespace));

    registration.addInitParameter(JERSEY_MAPPING_FEATURE, Boolean.toString(true));
    registration.addInitParameter(PROPERTY_CONTAINER_REQUEST_FILTERS, this.requestFilters);
    registration.addInitParameter(PROPERTY_CONTAINER_RESPONSE_FILTERS, this.responseFilters);
    registration.addInitParameter(PROPERTY_RESOURCE_FILTER_FACTORIES, ValidationResourceFilterFactory.class.getName());

    return registration;
  }

  /**
   * This method initializes SimpleHttpServerJaxWsServiceExporter bean which reads all @Webservice annotated components
   * and hosts web service for them.
   *
   * @return SimpleHttpServerJaxWsServiceExporter
   */
  @Bean
  public SimpleHttpServerJaxWsServiceExporter exportJaxwsService() {
    final SimpleHttpServerJaxWsServiceExporter jaxWsServiceExporter = new SimpleHttpServerJaxWsServiceExporter();
    jaxWsServiceExporter.setPort(this.webservicePort);
    jaxWsServiceExporter.setBasePath("/" + this.serviceNamespace + "/" + this.webserviceNamespace + "/");
    return jaxWsServiceExporter;
  }

  @Bean
  @Primary
  @ConfigurationProperties(prefix = "spring.datasource")
  public DataSource primaryDataSource() {
    return DataSourceBuilder.create().build();
  }

  @Bean
  public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
    factory.setTomcatContextCustomizers(Arrays.asList(new CustomCustomizer()));
    return factory;
  }

  static class CustomCustomizer implements TomcatContextCustomizer {

    @Override
    public void customize(Context context) {
      context.setUseHttpOnly(false);
      context.setCookies(false);
    }
  }
}
like image 939
Ripu Daman Avatar asked Sep 28 '15 10:09

Ripu Daman


People also ask

What is the relationship between Spring Boot and MongoDB?

Data that is viewed together stays together. Spring also provides connectors like MongoTemplate and MongoRepository to perform all the database operations in MongoDB. What is Spring Boot used for?

How do I configure multiple databases in Spring Boot?

Multiple Database Configurations in Spring Boot Following is the application.properties file that contains configurations for multiple databases. You can notice that properties starting from spring.user.datasource has user database configuration and properties starting from spring.booking.datasource has booking datasource configurations.

What is the best NoSQL database for Spring Boot?

MongoDB is the most popular NoSQL database because of the ease with which data can be stored and retrieved. Combining Spring Boot and MongoDB results in applications that are fast, secure, reliable, and require minimum development time.

How to connect to multiple datasources with Spring Boot?

However, if you need to connect to multiple datasources with Spring Boot, additional configuration is needed. You need to provide configuration data to Spring Boot, customized for each data source. The source code of our sample application is available on GitHub .


1 Answers

There were no questions in this forum which talks about the connecting the two different databases (Mysql database and MongoDB) in the same spring-boot project.

I have done the work to do that hence I am posting it as answer here.

Use below given configurations and the repositories as, either JpaRepository or MongoRepository, depending on the DB particular repository belongs to.

MySQL specific "YML" file is like below

# Default DB parameter definitions for the URL parameters in the spring.datasource.url property below
database:
  host: localhost
  port: 3306
  schema: subscriptions
  username: root
  password: root
  autoconnect:
    maxReconnects: 3
    initialTimeout: 2
  timeout:
    connectTimeout: 0
    socketTimeout: 0
  failover:
    host: localhost 
    port: 3306
    queriesBeforeRetryMaster: 50
    secondsBeforeRetryMaster: 30
  properties: useTimezone=true&serverTimezone=UTC&useLegacyDatetimeCode=false&failOverReadOnly=false&autoReconnect=true&maxReconnects=${database.autoconnect.maxReconnects}&initialTimeout=${database.autoconnect.initialTimeout}&connectTimeout=${database.timeout.connectTimeout}&socketTimeout=${database.timeout.socketTimeout}&queriesBeforeRetryMaster=${database.failover.queriesBeforeRetryMaster}&secondsBeforeRetryMaster=${database.failover.secondsBeforeRetryMaster}

spring:
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://${database.host}:${database.port},${database.failover.host}:${database.failover.port}/${database.schema}?${database.properties}
    username: ${database.username}
    password: ${database.password}
    continueOnError: true
    initialize: false
    initialSize: 0
    timeBetweenEvictionRunsMillis: 5000
    minEvictableIdleTimeMillis: 5000
    removeAbandonedTimeout: 60
    removeAbandoned: true
    minIdle: 0
  
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
      naming_strategy: org.hibernate.cfg.DefaultNamingStrategy
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
        hbm2ddl:
          auto: none
        temp:
          use_jdbc_metadata_defaults: false 

My MongoDB "YML" looks like below

spring:
  data:
    mongodb.host: localhost
    mongodb.port: 27017
    mongodb.database: eventsarchive
    mongodb.username: root
    mongodb.password: root
    mongodb.repositories.enabled: true

Application.java file below

@Configuration
@EnableAutoConfiguration
@EnableConfigurationProperties
@EntityScan(basePackages = { "persistence.mysql.domain" })
@EnableJpaRepositories("persistence.mysql.dao")
@EnableMongoRepositories("persistence.mongodb.dao")
@ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
value = ApiAuthenticationFilter.class) },
basePackages = {
                "admin",
                "common",
                "mqclient",
"scheduler" })
public class Application {

  @Value("${service.name}")
  private String serviceName;
  @Value("${service.namespace}")
  private String serviceNamespace;
  @Value("${webservice.namespace}")
  private String webserviceNamespace;
  @Value("${webservice.port}")
  private int webservicePort;
  @Value("${jersey.request-filters}")
  private String requestFilters;
  @Value("${jersey.response-filters}")
  private String responseFilters;

  private static final String MAPPING_URL = "/%s/*";

  static {
    System.setProperty(USER_TIMEZONE, "UTC");
  }

  /**
   * Java main method.
   */
  public static void main(String[] args) {
    /*
     * Defines which Spring Boot Profiles should be active on startup. Please see
     * http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-profiles for details.
     */
    final SpringApplicationBuilder appBuilder = new SpringApplicationBuilder(Application.class);
    appBuilder.profiles("common", "common_mongo_db", "common_mysql_db", "common_rabbitmq", "admin").application()
    .run(args);
  }

  /**
   * Registers Jersey with Spring Boot.
   */
  @Bean
  public ServletRegistrationBean registerJersey() {
    final ServletRegistrationBean registration = new ServletRegistrationBean(new SpringServlet(),
                                                                             String.format(MAPPING_URL,
                                                                                           this.serviceNamespace));

    registration.addInitParameter(JERSEY_MAPPING_FEATURE, Boolean.toString(true));
    registration.addInitParameter(PROPERTY_CONTAINER_REQUEST_FILTERS, this.requestFilters);
    registration.addInitParameter(PROPERTY_CONTAINER_RESPONSE_FILTERS, this.responseFilters);
    registration.addInitParameter(PROPERTY_RESOURCE_FILTER_FACTORIES, ValidationResourceFilterFactory.class.getName());

    return registration;
  }

  /**
   * This method initializes SimpleHttpServerJaxWsServiceExporter bean which reads all @Webservice annotated components
   * and hosts web service for them.
   *
   * @return SimpleHttpServerJaxWsServiceExporter
   */
  @Bean
  public SimpleHttpServerJaxWsServiceExporter exportJaxwsService() {
    final SimpleHttpServerJaxWsServiceExporter jaxWsServiceExporter = new SimpleHttpServerJaxWsServiceExporter();
    jaxWsServiceExporter.setPort(this.webservicePort);
    jaxWsServiceExporter.setBasePath("/" + this.serviceNamespace + "/" + this.webserviceNamespace + "/");
    return jaxWsServiceExporter;
  }

  @Bean
  @Primary
  @ConfigurationProperties(prefix = "spring.datasource")
  public DataSource primaryDataSource() {
    return DataSourceBuilder.create().build();
  }

  @Bean
  public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
    factory.setTomcatContextCustomizers(Arrays.asList(new CustomCustomizer()));
    return factory;
  }

  static class CustomCustomizer implements TomcatContextCustomizer {

    @Override
    public void customize(Context context) {
      context.setUseHttpOnly(false);
      context.setCookies(false);
    }
  }
}
like image 98
Ripu Daman Avatar answered Oct 04 '22 09:10

Ripu Daman