I've developed a Spring Boot Application based on Heroku's "Getting Started on Heroku with Java". After that I've started configuring mysql as the database. This is the tutorial I've followed throughout this approach. Everything works great when I run the application locally with heroku local web
. I can make GET requests and get data stored in database. I can make POST requests and add new data to database. But if I deploy it to production, I see exceptions thrown in the logs. Below is the related part of the log that I see when I start the application running on url Heroku provided me, in this case: https://danef-dictionary-api.herokuapp.com/
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
Jan 04 02:24:27 danef-dictionary-api app/web.1
Jan 04 02:24:27 danef-dictionary-api app/web.1 The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-java-8.0.18.jar:8.0.18]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-java-8.0.18.jar:8.0.18]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:836) ~[mysql-connector-java-8.0.18.jar:8.0.18]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:456) ~[mysql-connector-java-8.0.18.jar:8.0.18]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246) ~[mysql-connector-java-8.0.18.jar:8.0.18]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:199) ~[mysql-connector-java-8.0.18.jar:8.0.18]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-3.4.1.jar:na]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:353) ~[HikariCP-3.4.1.jar:na]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201) ~[HikariCP-3.4.1.jar:na]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:473) [HikariCP-3.4.1.jar:na]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:562) [HikariCP-3.4.1.jar:na]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:115) [HikariCP-3.4.1.jar:na]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) [HikariCP-3.4.1.jar:na]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:180) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:68) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:101) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:175) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:118) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:1202) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1233) [hibernate-core-5.4.9.Final.jar:5.4.9.Final]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) [spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) [spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391) [spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378) [spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) [spring-orm-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) [spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) [spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595) [spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517) [spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323) [spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321) [spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) [spring-beans-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1108) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:868) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.2.2.RELEASE.jar:5.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.2.RELEASE.jar:2.2.2.RELEASE]
Jan 04 02:24:27 danef-dictionary-api app/web.1 at net.danef.DanefDictionaryApiApplication.main(DanefDictionaryApiApplication.java:12) ~[classes/:na]
From the exceptions, I've picked up the first one, "Common link failure" and used it in the title of this question. I've probably tried everthing I can find as a solution so feel free to redirect me if you know a blog post or answer you think that is helpful.
My application.properties file:
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.generate-ddl=true
spring.datasource.url=jdbc:mysql://localhost:3306/db_words?useSSL=false
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=myusername
spring.datasource.password=mypassword
"myusername" and "mypassword" are just placeholders. I'm using my credentials on my code.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>net.danef</groupId>
<artifactId>danef-dictionary-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>danef-dictionary-api</name>
<description>Danef Dictionary API</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Refer to this link if you want to see the full version of logs: https://paste.ubuntu.com/p/wqZPXqyYFM/
I solved my problem by setting up ClearDB addon in Heroku. After adding the addon, I've had a remote database URL. Setting the remote URL as datasource.url solved the problem. My application.properties file looks like this now.
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
spring.jpa.generate-ddl=true
spring.datasource.url=jdbc:mysql://`remote_database_url`
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=samet
spring.datasource.password=password
Set your remote database URL without backticks.