Reputation: 165
I'm trying to use two data sources for my Micronaut web application written in Kotlin: the one with a mysql database, and one in memory H2 database to be used when executing the tests.
I've tried using only the h2
database as the default production data source, so the configuration fields regarding it should be correct.
The application runs as expected with the mysql data source by executing ./gradlew run
application.yml
and application-test.yml
in src/main/resources/
directory and also placing only application-test.yml
in src/test/resources/
, without result.@MicronautTest
annotation declaring there the test
environment and application = BookieSparaerverApplication
params didn't work.@TypeHint(Genre::class, Book::class, DefaultGenreRepository::class)
annotation to BookieServerApplication
didn't work.These are the relevant fields of the src/main/resources/application.yml
configuration file
datasources:
default:
url: 'jdbc:mysql://localhost:3306/bookie-server?useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false'
dbCreate: create-update
driverClassName: com.mysql.cj.jdbc.Driver
dialect: org.hibernate.dialect.MySQL5InnoDBDialect
username: root
password: root
jpa:
default:
entity-scan:
packages:
- 'com.transgressoft.bookieserver.domain'
properties:
hibernate:
hbm2ddl:
auto: update
show_sql: true
And this is the src/test/resources/application-test.yml
file:
datasources:
default:
url: ${JDBC_URL:`jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE`}
username: ${JDBC_USER:sa}
password: ${JDBC_PASSWORD:""}
driverClassName: ${JDBC_DRIVER:org.h2.Driver}
jpa:
default:
entity-scan:
packages:
- 'com.transgressoft.bookieserver.domain'
properties:
hibernate:
hbm2ddl:
auto: update
show_sql: true
When I execute the test (GenreControllerSpec
in the code), looks like the EntityManager
bean is not created and therefore the DAO class cannot be instantiated (in my code is the GenreRepository
class).
This is the full log message:
Internal Server Error: Failed to inject value for parameter [entityManager] of class: com.transgressoft.bookieserver.domain.$DefaultGenreRepositoryDefinition$Intercepted
Message: No bean of type [javax.persistence.EntityManager] exists. Make sure the bean is not disabled by bean requirements (enable trace logging for 'io.micronaut.context.condition' to check) and if the bean is enabled then ensure the class is declared a bean and annotation processing is enabled (for Java and Kotlin the 'micronaut-inject-java' dependency should be configured as an annotation processor).
Path Taken: new $GenreControllerDefinition$Intercepted([GenreRepository genreRepository],BeanContext beanContext,Interceptor[] interceptors) --> new $DefaultGenreRepositoryDefinition$Intercepted([EntityManager entityManager],ConfigurationProperties applicationConfiguration,BeanContext beanContext,Interceptor[] interceptors)
io.micronaut.http.client.exceptions.HttpClientResponseException: Internal Server Error: Failed to inject value for parameter [entityManager] of class: com.transgressoft.bookieserver.domain.$DefaultGenreRepositoryDefinition$Intercepted
The full project code is accesible here
https://github.com/octaviospain/bookie-server/tree/feature/jpa-and-hibernate and to reproduce above logs just execute ./gradlew test
and open the report, or run it with logs activated.
EDIT: I've updated the description with Ivan Lopez's suggestion, but error and expected result remains the same.
Upvotes: 4
Views: 5471
Reputation: 12228
Your example application is using 1.1.1 of micronaut-hibernate-jpa
which does not support
jpa:
default:
entity-scan:
packages:
- 'com.transgressoft.bookieserver.domain'
You must use jpa.default.packages-to-scan
instead as the documentation states.
Upvotes: 1
Reputation: 944
I think you have missunderstood how defining datasources work. When setting:
datasources:
production:
...
test:
...
jpa:
production:
...
test:
...
You are telling Micronaut: "I want you to create two datasources, one named production
and other named test
at the same time. Both datasources will be available to the application and you can inject them using the names defined (production
and test
) and qualifiers.
What you need to do is define in src/main/resources/application.yml
only one datasource. Micronaut use default
name as the default one:
datasources:
default:
... // your production MySQL database
jpa:
default:
... // configuration for MySQL database
And then you can override anything defined in application.yml
just creating src/test/resources/application-test.yml
with the content:
datasources:
default:
... // your test H2 database
jpa:
default:
... // configuration for H2 database
Hope it makes sense. You can find more information about it here: https://docs.micronaut.io/latest/guide/index.html#config
Upvotes: 4