Skip to content

Commit

Permalink
feat: Allow disabling of datasources by excluding packages (#1323)
Browse files Browse the repository at this point in the history
This allows the testing of non-db beans without requiring the connection pools to be fully configured.

Does not cover r2dbc as that is defined elsewhere.

micronaut-projects/micronaut-data#2893

It is done this way (with package requirements) as there is no way currently to allow EachBean to skip factory creation based on a property of the bean (ie Toggleable#isEnabled).
  • Loading branch information
timyates authored Apr 26, 2024
1 parent 54dc469 commit b1bad14
Show file tree
Hide file tree
Showing 14 changed files with 272 additions and 20 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2020 original authors
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,8 +18,11 @@
*/
@Configuration
@Requires(classes = BasicDataSource.class)
@Requires(property = BasicJdbcConfiguration.PREFIX + ".enabled", value = StringUtils.TRUE, defaultValue = StringUtils.TRUE)
package io.micronaut.configuration.jdbc.dbcp;

import io.micronaut.context.annotation.Configuration;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.util.StringUtils;
import io.micronaut.jdbc.BasicJdbcConfiguration;
import org.apache.commons.dbcp2.BasicDataSource;
Original file line number Diff line number Diff line change
@@ -1,18 +1,3 @@
/*
* Copyright 2017-2020 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.configuration.jdbc.dbcp

import io.micronaut.jdbc.DataSourceResolver
Expand Down Expand Up @@ -69,6 +54,27 @@ class DatasourceConfigurationSpec extends Specification {
applicationContext.close()
}

void "test datasource can be disabled"() {
given:
ApplicationContext applicationContext = new DefaultApplicationContext("test")
applicationContext.environment.addPropertySource(MapPropertySource.of(
"test",
[
'datasources.default': [:],
'datasources.enabled': false
]
))
applicationContext.start()

expect:
!applicationContext.containsBean(DataSource)
!applicationContext.containsBean(BasicDataSource)
!applicationContext.containsBean(DatasourceConfiguration)

cleanup:
applicationContext.close()
}

void "test operations with a blank connection"() {
given:
ApplicationContext applicationContext = new DefaultApplicationContext("test")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2020 original authors
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,8 +18,11 @@
*/
@Configuration
@Requires(classes = HikariDataSource.class)
@Requires(property = BasicJdbcConfiguration.PREFIX + ".enabled", value = StringUtils.TRUE, defaultValue = StringUtils.TRUE)
package io.micronaut.configuration.jdbc.hikari;

import com.zaxxer.hikari.HikariDataSource;
import io.micronaut.context.annotation.Configuration;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.util.StringUtils;
import io.micronaut.jdbc.BasicJdbcConfiguration;
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,27 @@ class DatasourceConfigurationSpec extends Specification {
applicationContext.close()
}

void "test datasource can be disabled"() {
given:
ApplicationContext applicationContext = new DefaultApplicationContext("test")
applicationContext.environment.addPropertySource(MapPropertySource.of(
'test',
[
'datasources.default': [:],
'datasources.enabled' : false
]
))
applicationContext.start()

expect:
!applicationContext.containsBean(DataSource)
!applicationContext.containsBean(HikariDataSource)
!applicationContext.containsBean(DatasourceConfiguration)

cleanup:
applicationContext.close()
}

void "test operations with a blank connection"() {
given:
ApplicationContext applicationContext = new DefaultApplicationContext("test")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2020 original authors
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,8 +18,11 @@
*/
@Configuration
@Requires(classes = DataSource.class)
@Requires(property = BasicJdbcConfiguration.PREFIX + ".enabled", value = StringUtils.TRUE, defaultValue = StringUtils.TRUE)
package io.micronaut.configuration.jdbc.tomcat;

import io.micronaut.context.annotation.Configuration;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.util.StringUtils;
import io.micronaut.jdbc.BasicJdbcConfiguration;
import org.apache.tomcat.jdbc.pool.DataSource;
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,27 @@ class DatasourceConfigurationSpec extends Specification {
applicationContext.close()
}

void "test datasource can be disabled"() {
given:
ApplicationContext applicationContext = new DefaultApplicationContext("test")
applicationContext.environment.addPropertySource(MapPropertySource.of(
'test',
[
'datasources.default': [:],
'datasources.enabled' : false
]
))
applicationContext.start()

expect:
!applicationContext.containsBean(DataSource)
!applicationContext.containsBean(DatasourceConfiguration)
!applicationContext.containsBean(TomcatDataSourcePoolMetadata)

cleanup:
applicationContext.close()
}

void "test operations with a blank connection"() {
given:
ApplicationContext applicationContext = new DefaultApplicationContext("test")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2020 original authors
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -18,8 +18,11 @@
*/
@Configuration
@Requires(classes = PoolDataSource.class)
@Requires(property = BasicJdbcConfiguration.PREFIX + ".enabled", value = StringUtils.TRUE, defaultValue = StringUtils.TRUE)
package io.micronaut.configuration.jdbc.ucp;

import io.micronaut.context.annotation.Configuration;
import io.micronaut.context.annotation.Requires;
import io.micronaut.core.util.StringUtils;
import io.micronaut.jdbc.BasicJdbcConfiguration;
import oracle.ucp.jdbc.PoolDataSource;
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package io.micronaut.configuration.jdbc.ucp
import io.micronaut.context.ApplicationContext
import io.micronaut.context.DefaultApplicationContext
import io.micronaut.context.env.MapPropertySource
import io.micronaut.context.exceptions.NoSuchBeanException
import io.micronaut.inject.qualifiers.Qualifiers
import io.micronaut.jdbc.DataSourceResolver
import oracle.ucp.jdbc.PoolDataSource
Expand Down Expand Up @@ -101,6 +102,35 @@ class DatasourceConfigurationSpec extends Specification {
applicationContext.close()
}

void "test datasource can be disabled"() {
given:
ApplicationContext applicationContext = new DefaultApplicationContext("test")
applicationContext.environment.addPropertySource(MapPropertySource.of(
'test',
[
"datasources.default.url": "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE",
"datasources.default.username": "sa",
"datasources.default.password": "",
"datasources.enabled": false
]
))
applicationContext.start()

expect:
!applicationContext.containsBean(PoolDataSource)
!applicationContext.containsBean(DatasourceConfiguration)

when:
applicationContext.getBean(DataSource)

then:
def ex = thrown(NoSuchBeanException)
ex.message.startsWith("No bean of type [javax.sql.DataSource] exists.")

cleanup:
applicationContext.close()
}

void "test properties are bindable"() {
given:
String context = UUID.randomUUID().toString()
Expand Down
2 changes: 1 addition & 1 deletion src/main/docs/guide/jdbc.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Java data sources can be configured for one of three currently provided implementations. Apache DBCP2, Hikari, and Tomcat are supported by default.
Java data sources can be configured for one of four currently provided implementations. Apache DBCP2, Hikari, Tomcat, and Oracle Universal Connection Pool are supported by default.

[TIP]
.Using the CLI
Expand Down
1 change: 1 addition & 0 deletions src/main/docs/guide/jdbc/jdbc-disable.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
You can disable Micronaut Data Sources, for example in a test, by setting `datasources.enabled` to `false`.
1 change: 1 addition & 0 deletions src/main/docs/guide/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ introduction: Introduction
releaseHistory: Release History
jdbc:
title: Configuring JDBC
jdbc-disable: Disable Micronaut JDBC Data Sources
jdbc-connection-pools: Configuring JDBC Connection Pools
jdbc-multiple-datasources: Configuring Multiple Data Sources
jdbc-healthchecks: JDBC Health Checks
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.hibernate6.sync;

import io.micronaut.context.annotation.Property;
import io.micronaut.context.exceptions.NoSuchBeanException;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.runtime.server.EmbeddedServer;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;

import javax.sql.DataSource;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

@MicronautTest
@Property(name = "datasources.enabled", value = "false")
@Property(name = "datasources.default.db-type", value = "mysql")
@Property(name = "jpa.default.properties.hibernate.dialect", value = "org.hibernate.dialect.MySQLDialect")
class DisabledDbAppTest {

@Test
void serverRunning(EmbeddedServer embeddedServer) {
assertTrue(embeddedServer.isRunning());
}

@Test
void canTestNonDbBeans(EmbeddedServer embeddedServer) {
Integer i = embeddedServer.getApplicationContext().getBean(ConversionService.class).convert("10", Integer.class).orElse(999);
assertEquals(10, i);
}

@Test
void noDatasourceDefined(EmbeddedServer embeddedServer) {
assertThrows(NoSuchBeanException.class, () -> embeddedServer.getApplicationContext().getBean(DataSource.class));
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package example.jdbc.ucp.sync;

import io.micronaut.context.annotation.Property;
import io.micronaut.context.exceptions.NoSuchBeanException;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.runtime.server.EmbeddedServer;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.Test;

import javax.sql.DataSource;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;

@MicronautTest
@Property(name = "datasources.enabled", value = "false")
@Property(name = "datasources.default.db-type", value = "oracle")
@Property(name = "datasources.default.connection-factory-class-name", value = "oracle.jdbc.pool.OracleDataSource")
@Property(name = "test-resources.containers.oracle.startup-timeout", value = "600s")
class DisabledDbAppTest {

@Test
void serverRunning(EmbeddedServer embeddedServer) {
assertTrue(embeddedServer.isRunning());
}

@Test
void canTestNonDbBeans(EmbeddedServer embeddedServer) {
Integer i = embeddedServer.getApplicationContext().getBean(ConversionService.class).convert("10", Integer.class).orElse(999);
assertEquals(10, i);
}

@Test
void noDatasourceDefined(EmbeddedServer embeddedServer) {
assertThrows(NoSuchBeanException.class, () -> embeddedServer.getApplicationContext().getBean(DataSource.class));
}
}

Loading

0 comments on commit b1bad14

Please sign in to comment.