Spring Boot - application creating open, orphan DB connections - spring-boot

In our Spring boot application, we have set the following properties in application.properties
server.port=xxxx
server.servlet.context-path=/
#datasource
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://<IP:Port>/<DB Name>
spring.datasource.username=<username>
spring.datasource.password=<pwd>
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.connection.release_mode=after_statement
.....
//Interface using JpaRepository
#Repository
public interface UserlicensesRepo extends JpaRepository<Userlicenses, Integer> {
Optional<Userlicenses> findById(Integer us);
Optional<Userlicenses> findByUsernameAndUserToken(String user, String token);
}
.....
//Using the repo instance to make DB call
Optional<Userlicenses> ul=userlicensesRepo.findByUsernameAndUserToken(userName, userTokenEncrypted);
The application is functionally working well but over a period of 4-5 days it is creating a lot of orphan DB connections leading to memory leak. We tried setting the "release_mode", please check if we have missed anything or made a mistake in the above configuration. Appreciate your help.

Related

I am not able to connect to Google Cloud Memory Store from Spring Boot

I am developing a module with spring boot in my backend where i need to use Redis through GCP Memory Store. I have been searching in forum and even the "oficial documentation" about memory store but i cannot understand how to connect to memory store with my spring boot app.
I found a google code lab but they use a Compute Engine VM to install spring boot and then save and retrieve information from memory store. So i tried to do it like that in my local spring boot but it didnt work because throws an error saying:
Unable to connect to Redis; nested exception is io.lettuce.core.RedisConnectionException: Unable to connect to 10.1.3.4
the codelab i mentioned earlier says that you only have to add this line to your application.properties:
spring.redis.host=10.1.3.4
as well as the annotation #EnableCaching in the main class and #Cachable annotation in the controller method where you try to do something with redis.
the method looks like this:
#RequestMapping("/hello/{name}")
#Cacheable("hello")
public String hello(#PathVariable String name) throws InterruptedException {
Thread.sleep(5000);
return "Hello " + name;
}
i dont know what else to do. Notice that i am new on this topic of redis and memory store.
Anyone can give me some guidance on this please?
thanks in advance
codelab url: https://codelabs.developers.google.com/codelabs/cloud-spring-cache-memorystore#0
See this documentation on how to setup Memorystore Redis instance.
Included in the documentation is how you can connect and test your Memorystore instance from different computing environments.
There's also a step by step guide on how SpringBoot can use Redis to cache with annonations.
Add the Spring Data Redis starter in your pom.xml if you're using Maven for your project setup.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Add this configuration in your application.properties file:
spring.redis.host=<MEMORYSTORE_REDIS_IP>
# Configure default TTL, e.g., 10 minutes
spring.cache.redis.time-to-live=600000
Turn on caching capability explicitly with the #EnableCaching annotation:
#SpringBootApplication
#EnableCaching
class DemoApplication {
...
}
Once you configured the Spring Boot with Redis and enabled caching, you can use the #Cacheable annotation to cache return values.
#Service
class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
#Cacheable("order")
public Order getOrder(Long id) {
orderRepository.findById(id);
}
}

SpringBoot 1.5 : #SpringBootTest and memory Database

I have a SpringBoot application with spring data/jpa to connect for database.
And a propertie file yml where defined the database connection.
Everything works very well.
I create a test like that :
#ActiveProfiles("dev")
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyMicroServiceApp.class, webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyMicroServiceAppTest {
#Test
public <T> void postConnex() {
//Create Object connexCreate
...
// Create POST
ResponseEntity<Udsaconnex> result1 = this.restTemplate().postForEntity("http://localhost:" + port + "/v1/connex",
connexCreate, Udsaconnex.class);
id = result1.getBody().getIdconnex();
assertEquals(result1.getBody().toString().isEmpty(), false);
}
}
For my test, i have not configured properties for database connection but the test work and i view in console that :
Hibernate: drop table connex if exists
I don't understand why, #SpringBootTest mock database like #DataJpaTest automatically ??
It's possible but i don't find anything about that in spring boot documentation.
Thanks for your help.
If you have application.yml file specifying DB location, then SpringBootTest will obviously use the same configuration and will use your configured DB.
From the title of your question I guess you have an in-memory database in your build dependencies. Spring-boot has some autoconfiguration for certain database (H2, HSQL, Derby) if they are found on the classpath. See this link for a list of the supported databases:
Spring Boot Embedded Database Support

springboot + JDBTemplate (No datasource specified error even though specified in application.properties

Application.properties
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=
i placed this application.properties in resources folder.
Java Class
#Component
public class data{
#Autowired
private JdbcTemplate jdbcTemplate;
public void queryData(){
String sql = "select * from DEPOSIT";
jdbcTemplate = new JdbcTemplate();
jdbcTemplate.execute(sql);
}
}
I am getting
java.lang.Illegal Argument Exception:No Data Source Specified
I am getting this error message even though i specified data source in application.properties
I am using Spring Boot for this task. I Have added almost all the dependencies required in POM.
Not sure why i am not able to access data source. basically trying to access data from DB using Spring boot, MySQL, jdbcTemplate.
Not sure whats wrong here.
Do i have to add anything in the code so that data source can be specified in java class?
Add below properties to your application.properties file. This specifies the data source for your application. Do check if mysql is running on your machine before starting your application.
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=yourusername
spring.datasource.password=yourpassword
For additional information refer to below link:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html

Reload property value when external property file changes ,spring boot

I am using spring boot, and I have two external properties files, so that I can easily change its value.
But I hope spring app will reload the changed value when it is updated, just like reading from files. Since property file is easy enough to meet my need, I hope I don' nessarily need a db or file.
I use two different ways to load property value, code sample will like:
#RestController
public class Prop1Controller{
#Value("${prop1}")
private String prop1;
#RequestMapping(value="/prop1",method = RequestMethod.GET)
public String getProp() {
return prop1;
}
}
#RestController
public class Prop2Controller{
#Autowired
private Environment env;
#RequestMapping(value="/prop2/{sysId}",method = RequestMethod.GET)
public String prop2(#PathVariable String sysId) {
return env.getProperty("prop2."+sysId);
}
}
I will boot my application with
-Dspring.config.location=conf/my.properties
I'm afraid you will need to restart Spring context.
I think the only way to achieve your need is to enable spring-cloud. There is a refresh endpoint /refresh which refreshes the context and beans.
I'm not quite sure if you need a spring-cloud-config-server (its a microservice and very easy to build) where your config is stored(Git or svn). Or if its also useable just by the application.properties file in the application.
Here you can find the doc to the refresh scope and spring cloud.
You should be able to use Spring Cloud for that
Add this as a dependency
compile group: 'org.springframework.cloud', name: 'spring-cloud-starter', version: '1.1.2.RELEASE'
And then use #RefreshScope annotation
A Spring #Bean that is marked as #RefreshScope will get special treatment when there is a configuration change. This addresses the problem of stateful beans that only get their configuration injected when they are initialized. For instance if a DataSource has open connections when the database URL is changed via the Environment, we probably want the holders of those connections to be able to complete what they are doing. Then the next time someone borrows a connection from the pool he gets one with the new URL.
Also relevant if you have Spring Actuator
For a Spring Boot Actuator application there are some additional management endpoints:
POST to
/env to update the Environment and rebind #ConfigurationProperties and log levels
/refresh for re-loading the boot strap context and refreshing the #RefreshScope beans
Spring Cloud Doc
(1) Spring Cloud's RestartEndPoint
You may use the RestartEndPoint: Programatically restart Spring Boot application / Refresh Spring Context
RestartEndPoint is an Actuator EndPoint, bundled with spring-cloud-context.
However, RestartEndPoint will not monitor for file changes, you'll have to handle that yourself.
(2) devtools
I don't know if this is for a production application or not. You may hack devtools a little to do what you want.
Take a look at this other answer I wrote for another question: Force enable spring-boot DevTools when running Jar
Devtools monitors for file changes:
Applications that use spring-boot-devtools will automatically restart
whenever files on the classpath change.
Technically, devtools is built to only work within an IDE. With the hack, it also works when launched from a jar. However, I may not do that for a real production application, you decide if it fits your needs.
I know this is a old thread, but it will help someone in future.
You can use a scheduler to periodically refresh properties.
//MyApplication.java
#EnableScheduling
//application.properties
management.endpoint.refresh.enabled = true
//ContextRefreshConfig.java
#Autowired
private RefreshEndpoint refreshEndpoint;
#Scheduled(fixedDelay = 60000, initialDelay = 10000)
public Collection<String> refreshContext() {
final Collection<String> properties = refreshEndpoint.refresh();
LOGGER.log(Level.INFO, "Refreshed Properties {0}", properties);
return properties;
}
//add spring-cloud-starter to the pom file.
Attribues annotated with #Value is refreshed if the bean is annotated with #RefreshScope.
Configurations annotated with #ConfigurationProperties is refreshed without #RefreshScope.
Hope this will help.
You can follow the ContextRefresher.refresh() code implements.
public synchronized Set<String> refresh() {
Map<String, Object> before = extract(
this.context.getEnvironment().getPropertySources());
addConfigFilesToEnvironment();
Set<String> keys = changes(before,
extract(this.context.getEnvironment().getPropertySources())).keySet();
this.context.publishEvent(new EnvironmentChangeEvent(context, keys));
this.scope.refreshAll();
return keys;
}

How to disable H2's DATABASE_TO_UPPER in Spring Boot, without explicit connection URL

I'm aware that H2 has a boolean property/setting called DATABASE_TO_UPPER, which you can set at least in the connection URL, as in: ;DATABASE_TO_UPPER=false
I’d like to set this to false, but in my Spring Boot app, I don’t explicitly have a H2 connection URL anywhere. Implicitly there sure is a connection URL though, as I can see in the logs:
o.s.j.d.e.EmbeddedDatabaseFactory: Shutting down embedded database:
url='jdbc:h2:mem:2fb4805b-f927-49b3-a786-2a2cac440f44;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false'
So the question is, what's the easiest way to tell H2 to disable DATABASE_TO_UPPER in this scenario? Can I do it in code when creating the H2 datasource with EmbeddedDatabaseBuilder (see below)? Or in application properties maybe?
This is how the H2 database is explicitly initialised in code:
#Configuration
#EnableTransactionManagement
public class DataSourceConfig {
#Bean
public DataSource devDataSource() {
return new EmbeddedDatabaseBuilder()
.generateUniqueName(true)
.setType(EmbeddedDatabaseType.H2)
.setScriptEncoding("UTF-8")
.ignoreFailedDrops(true)
.addScripts("db/init.sql", "db/schema.sql", "db/test_data.sql")
.build();
}
}
Also, I'm telling JPA/Hibernate not to auto-generate embedded database (without this there was an issue that two in-memory databases were launched):
spring.jpa.generate-ddl=false
spring.jpa.hibernate.ddl-auto=none
You can't w\ the generateUniqueName, but if you call setName("testdb;DATABASE_TO_UPPER=false") you can add parameters. I doubt this is officially supported, but it worked for me.
The spring code that generates the connection url is like this:
String.format("jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false", databaseName)
You may want abandon using explicit creation via EmbeddedDatabaseBuilder. Spring Boot creates H2 instance automatically based on configuration. So I would try this in application.properties:
spring.datasource.url=jdbc:h2:file:~/testdb;DATABASE_TO_UPPER=false

Resources