I have a springboot 3 application, pretty standard, which has a Controller, a service that is called by the controller and a repository that the service uses to fetch and save data.
I had configured my application to work with a postgresql DB, and it was actually working quite well. Then I decided to do some refactoring (originally, all logic was in the controller, I introduced the service mentioned above and moved it there). I didn’t change anything to the Application launcher, the application.properties or anything else.
Now when I try to start I get the following error:
APPLICATION FAILED TO START
Description:
Failed to configure a DataSource: ‘url’ attribute is not specified and no embedded datasource could be configured.
Reason: Failed to determine a suitable driver class
Action:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
While the actual runtimeException where my debug point occurs says:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘dataSourceScriptDatabaseInitializer’ defined in class path resource [org/springframework/boot/autoconfigure/sql/init/DataSourceInitializationConfiguration.class]: Unsatisfied dependency expressed through method ‘dataSourceScriptDatabaseInitializer’ parameter 0: Error creating bean with name ‘dataSource’ defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method ‘dataSource’ threw exception with message: Failed to determine a suitable driver class
I found some threads saying to (exclude = DataSourceAutoConfiguration.class) to my SpringBootApplication annotation, but this just results in another error saying UnsatisfiedDependencyException where my Repository is not available for injection into my controller.
I’ve tried undoing all of my refactoring but still it’s not working, and I’m quite stuck on this.
Application:
Application
Repository:
Repository
Controller:
Controller
Service:
Service
Application.properties:
Properties
pom.xml:
Pom
Tried excluding DataSourceAutoConfiguration from the SpringBootApplication annotation, but this resulted in the TranslationRepository not being available in my TranslationService.
Tried reverting my changes but that didn’t help.
Tried adding explicit postgres driver property to application.properties, also didn’t help.
As suggested by Mox:
TranslationApplication:
package com.projectbluegames.tbd;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class TranslationApplication {
public static void main(String[] args) {
SpringApplication.run(TranslationApplication.class, args);
}
}
properties:
spring.datasource.url=jdbc:postgresql://localhost:5432/TBD
spring.datasource.username=postgres
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.driver-class-name=org.postgresql.Driver
Repository:
package com.projectbluegames.tbd.repository;
import org.springframework.data.repository.CrudRepository;
import com.projectbluegames.tbd.entities.Translation;
public interface TranslationRepository extends CrudRepository<Translation, Integer> {}
Controller:
@RestController
public class TranslationController {
private final ITranslationService translationService;
public TranslationController(ITranslationService translationService) {
this.translationService = translationService;
}
@PostMapping("/refresh")
private ResponseEntity<String> refreshTranslationCache() {
translationService.refreshTranslationCache();
return ResponseEntity.ok("Translation cache reloaded successfully");
}
}
IService:
package com.projectbluegames.tbd.services;
import java.util.List;
import com.projectbluegames.tbd.dtos.TranslationDto;
public interface ITranslationService {
public void refreshTranslationCache();
}
Service:
package com.projectbluegames.tbd.services;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.projectbluegames.tbd.entities.Translation;
import com.projectbluegames.tbd.repository.TranslationRepository;
public class TranslationService implements ITranslationService {
private final TranslationRepository translationRepository;
private Map<String, Translation> translationCache = new HashMap<String, Translation>();
public TranslationService(TranslationRepository translationRepository) {
this.translationRepository = translationRepository;
refreshTranslationCache();
}
@Override
public void refreshTranslationCache() {
translationCache.clear();
Iterable<Translation> translations = translationRepository.findAll();
translations.forEach(t -> translationCache.put(t.getLanguage() + "_" + t.getKey(), t));
}
}
Translation Entity:
package com.projectbluegames.tbd.entities;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name="translations")
public class Translation {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String key;
private String language;
private String value;
private Translation() { }
public Translation(String key, String language, String value) {
this.key = key;
this.language = language;
this.value = value;
}
public String getKey() {
return key;
}
public String getLanguage() {
return language;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
pom:
<?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>3.1.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.pb</groupId>
<artifactId>core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>tbd</name>
<description>Core</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2
Answers
As part of my refactoring, I had added to the pom.xml
Which I had forgotten to remove.
After removing this, it works.
Include the following property in your properties file
This should mostly resolve.