Ripu Daman Bhadoria
Ripu Daman Bhadoria

Reputation: 2572

How to start spring-boot app without depending on Database?

I am using "Spring-boot + Hibernate4 + mysql" for my application. As part of which I have a requirement where my sprint-boot app should be able to start even when database is down. Currently it gives the below exception when I try to start my spring boot app without DB being up.

I researched a lot and found out that this exception has to do with hibernate.temp.use_jdbc_metadata_defaults property.

I tried setting this in "application.yml" of spring boot but this property's value is not being reflected at runtime.

Exception Stack Trace:

2014-05-25 04:09:43.193  INFO 59755 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
2014-05-25 04:09:43.250  WARN 59755 --- [           main] o.h.e.jdbc.internal.JdbcServicesImpl     : HHH000342: Could not obtain connection to query metadata : Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
2014-05-25 04:09:43.263  INFO 59755 --- [           main] o.apache.catalina.core.StandardService   : Stopping service Tomcat

Error starting ApplicationContext. To display the auto-configuration report enabled debug logging (start with --debug)


Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:973)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:750)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:120)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:648)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:311)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:909)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:898)
    at admin.Application.main(Application.java:36)
Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set
    at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.determineDialect(DialectFactoryImpl.java:104)
    at org.hibernate.engine.jdbc.dialect.internal.DialectFactoryImpl.buildDialect(DialectFactoryImpl.java:71)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:205)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:89)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:178)
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:843)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:399)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
    at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:150)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:336)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
    ... 15 more

application.yml:

spring:   
  jpa:
show-sql: true
hibernate:
  ddl-auto: none
  naming_strategy: org.hibernate.cfg.DefaultNamingStrategy
  temp:
    use_jdbc_metadata_defaults: false

Upvotes: 38

Views: 46744

Answers (5)

selami tastan
selami tastan

Reputation: 92

The solution is really useful for me. Thanks i used file "application.properties" includes following lines:

    app.sqlhost=192.168.10.11
    app.sqlport=3306
    app.sqldatabase=logs

    spring.main.web-application-type=none

    # Datasource
    spring.datasource.url=jdbc:mysql://${app.sqlhost}:${app.sqlport}/${app.sqldatabase}
    spring.datasource.username=user
    spring.datasource.password=password
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
    spring.jpa.properties.hibernate.hbm2dll.auto = none
    spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false

    spring.datasource.continue-on-error=true
    spring.datasource.initialization-mode=never

    spring.datasource.hikari.connection-timeout=5000
    spring.datasource.hikari.idle-timeout=600000
    spring.datasource.hikari.max-lifetime=1800000
    spring.datasource.hikari.initialization-fail-timeout= -1

    spring.jpa.hibernate.use-new-id-generator-mappings=true
    spring.jpa.hibernate.ddl-auto=none

    spring.jpa.show-sql=true

    spring.output.ansi.enabled=always

But, you can not use @Transactional annotation at class level

@Service
//@Transactional  //do not use to touch the Repository
@EnableAsync
@Scope( proxyMode = ScopedProxyMode.TARGET_CLASS )
public class LogService {
.... }

@Async
@Transactional  // you can use at function level
public void deleteLogs(){
    logRepository.deleteAllBy ...
}

Upvotes: 0

vr3C
vr3C

Reputation: 1774

Add following config should be work:

spring.jpa.database-platform: org.hibernate.dialect.MySQL5Dialect

Upvotes: -1

Percy Vega
Percy Vega

Reputation: 1450

Adding this alone worked for me:

spring.jpa.properties.hibernate.dialect: org.hibernate.dialect.Oracle10gDialect

Just replace the last part with your database dialect.

Upvotes: 5

Ripu Daman Bhadoria
Ripu Daman Bhadoria

Reputation: 2572

It was indeed a tough nut to crack.

After lot and lot of research and actually debugging the spring-boot, spring, hibernate, tomcat pool, etc to get it done.

I do think that it will save lot of time for people trying to achieve this type of requirement.

Below are the settings required to achieve the following requirement

  1. Spring boot apps will start fine even if DB is down or there is no DB.
  2. Apps will pick up the connections on the fly as DB comes up which means there is no need to restart the web server or redeploy the apps.
  3. There is no need to start the tomcat or redeploy the apps, if DB goes down from running state and comes up again.

application.yml :

spring:
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/schema
    username: root
    password: root
    continueOnError: true
    initialize: false
    initialSize: 0
    timeBetweenEvictionRunsMillis: 5000
    minEvictableIdleTimeMillis: 5000
    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

Upvotes: 63

Stephane Nicoll
Stephane Nicoll

Reputation: 33091

I am answering here and will close the issue that you have cross-posted

Any "native" property of the JPA implementation (Hibernate) can be set using the spring.jpa.properties prefix as explained here

I haven't looked much further in the actual issue here but to answer this particular question, you can set that hibernate key as follows

spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults

Upvotes: 10

Related Questions