We are using spring boot 1.5.9.RELEASE. We have spring-boot-starter-data-jpa and mysql-connector-java in our maven dependency to connect to MySQL db. We have not configured any connection pool. According to the documentation since we are using spring-boot-starter-data-jpa tomcat connection pool is used as default connection pool. But when we try setting connection pool properties as spring.datasource.tomcat.* it is not working. But the same is working when spring.datasource.* format is used.
i.e spring.datasource.max-active=50 is working where as spring.datasource.tomcat.max-active=50 is not working. I confirmed this by printing Datasource in main class for which I'm getting org.apache.tomcat.jdbc.pool.DataSource#<objecthash>{key1=value1; key2=value2; ....} as output.
Why is this happening? Is it because we are using mysql-connector-java it's not reading tomcat connection pool properties? if that's the case then when I print Datasource how am I getting org.apache.tomcat.jdbc.pool.DataSource#a1f72f5 as data source with configured values? Or did I miss out something from the documentation? or JPA is not working properly?
pom.xml:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath />
</parent>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
Mainclass.java
import javax.sql.DataSource;
#SpringBootApplication
public class MainClass implements CommandLineRunner {
#Autowired
DataSource dataSource;
public static void main(String[] args) {
SpringApplication.run(MainClassChild.class, args);
}
#Override
public void run(String... args) throws Exception {
System.out.println("DATASOURCE = " + dataSource);
}
}
Application.properties
spring.datasource.url=jdbc:mysql://1.2.3.4/dbname?useSSL=false
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#Working
spring.datasource.max-active=30
spring.datasource.max-idle=20
spring.datasource.min-idle=10
#Not Working
spring.datasource.tomcat.max-active=30
spring.datasource.tomcat.max-idle=20
spring.datasource.tomcat.min-idle=10
Note: We autowire jdbctemplate and use it in DAO.
Related
Spring cloud-config server started with application.properties :
server.port:8888
spring.application.name=test-config-server
spring.cloud.config.server.git.uri=https://gitlab.com/pearsontechnology/gpt/sms/sms-micro-services/config-server.git
spring.cloud.config.server.git.default-label=develop
#Private repo. access credentials
spring.cloud.config.server.git.username=xxx
spring.cloud.config.server.git.password=xxxx
spring.cloud.config.server.git.clone-on-start=true
spring.cloud.config.profile=dev
On starting the config-client,
Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
My version of spring boot, spring-cloud and dependencies are as follows from pom.xml :
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<java.version>17</java.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<scope>runtime</scope>
</dependency>
application.prop of config-client :
spring.application.name=systems-lookup-service
spring.cloud.config.profile=dev
spring.config.import=optional:configserver:
server.port=8081
Properties related to Datasource like url etc. need to be taken from
systems-lookup-service-dev.properties hosted on Git.
custom.url=jdbc:oracle:thin:#localhost:1998/smscert
custom.username=smscert
custom.password=go#salt
custom.driverClassName=
And the DAO class in config-client accessing the db :
public class XXDaoImpl implements XXDao {
private JdbcTemplate jdbcTemplate;
#Autowired(required=false)
private DataSourceConfig config;
#Autowired
public SystemDaoImpl(JdbcTemplate jdbcTemplateIn){
final DataSource dataSource = DataSourceBuilder.create()
.driverClassName(config.getDriverClassName())
.url(config.getUrl())
.username(config.getUsername())
.password(config.getPassword())
.build();
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
...............
}
#Component
#ConfigurationProperties("custom")
public class DataSourceConfig {
private String url;
private String username;
private String password;
//#Value("${greeting.message}")
private String driverClassName;
....
}
I believe you follow the first boot-strapping for your central cloud registration to do so you need following artifact with in your client service pom file.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
Add the following properties to you client service property file application.prop
spring.application.name=systems-lookup-service
spring.cloud.config.uri=http://localhost:"cloud-config-port"
spring.profiles.active=dev
spring.config.import=optional:configserver:
With in main class on central cloud config add the annotation #EnableConfigServer and within it pom file add following artifact
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
append following properties to your central cloud config property file
spring.application.name=configuration-server
server.port=8780
management.endpoints.web.exposure.include=*
spring.cloud.config.server.git.uri=file:absoluthe-path
spring.cloud.config.server.git.clone-on-start=true
spring.cloud.config.allowOverride=true
Finally add your client service properties in your gitrepo with naming servicename-profile convention.
Extra point
You may consider to use spring cloud boss, for hot reloading the configs and not restarting services to handshake again, find out more in here.
Disabled auto-configuration of the data source by annotating client main with #SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
I created a springboot application that uses Spring Boot and Apache Camel JDBC Component for inserting a record in postgreSQL. For this purpose I am using the following dependencies:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jdbc</artifactId>
<version>${camel.version}</version>
<!-- use the same version as your Camel core version -->
</dependency>
As for the database configuration, I created the following java class with an application.properties file:
Database Configuration java class:
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
import org.apache.camel.support.SimpleRegistry;
import org.apache.commons.dbcp2.BasicDataSource;
public class DatabaseConfiguration {
public static SimpleRegistry createDatabaseConfiguration() throws IOException {
Properties properties = new Properties();
properties.load(new FileInputStream("src/main/resources/application.properties"));
BasicDataSource basic = new BasicDataSource();
basic.setDriverClassName(properties.getProperty("PostgresDBClassname"));
basic.setUsername(properties.getProperty("PostgresDBUsername"));
basic.setPassword(properties.getProperty("PostgresDBPassword"));
basic.setUrl(properties.getProperty("PostgresDBUrl"));
SimpleRegistry registry = new SimpleRegistry();
registry.bind("myDataSource", basic);
return registry;
}
}
application.properties file:
PostgresDBUsername = username
PostgresDBPassword = password
PostgresDBClassname = org.postgresql.Driver
PostgresDBUrl = jdbc:postgresql://localhost:5432/postgres
I wrote the router in the following way, noting that I tried to replace dataSource with myDataSource:
#Component
public class InsertRestService extends RouteBuilder {
#Override
public void configure() throws Exception {
rest("/").produces("text/plain")
.get("insert")
.to("direct:hello");
from("direct:hello")
.transform().simple("INSERT INTO person (name, country) VALUES (DANY, LB)")
.to("jdbc:dataSource") //spring boot starter jdbc creates the bean in the registry
.transform().simple("Data inserted in Postgres successfully");
}
}
I got the following error:
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
I provided the URL in the application.properties file PostgresDBUrl
Also note that I downloaded the jdbc driver jar file and added it to the module path, after a right click on the package, build path, configure build path
So what can I do to solve this issue?
Thank you!!
I removed the configuration file (DatabaseConfiguration) and replaced the content of the application.properties file with:
spring.datasource.url=jdbc:postgresql://localhost:5432/test
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.platform=postgres
spring.jpa.hibernate.ddl-auto=none
and it worked!
Check your pom.xml file and switch its packaging into war. It worked for me.
<packaging>war</packaging>
I have a Spring application that's trying to connect to a database. In order to connect, an SSH tunnel must first be established (using Jsch). How do I delay HibernateJpaAutoConfiguration until after the bean that's establishing the Jsch SSH session has returned? Currently the application is failing to start because the tunnel hasn't been opened yet. When I try to exclude this autoconfiguration class, and then instantiate it explicitly predicated on the session bean already having been created, I get the following error:
Caused by: java.lang.IllegalArgumentException: At least one JPA metamodel must be present!
I don't understand why I suddenly have to provide this myself when, if I rely on the auto-configuration, I don't have to provide it. If someone can show me a way to achieve this, that would be great.
POM:
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- Spring data JPA, default tomcat pool, exclude it -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</exclusion>
</exclusions>
</dependency>
...
Main application:
#SpringBootApplication(exclude = HibernateJpaAutoConfiguration.class)
public class Application {
public static void main(String... args) {
SpringApplication.run(Application.class, args);
}
#Configuration
static class SshTunnelConfiguration {
#Bean
public com.jcraft.jsch.Session sshTunnel() {
...
}
}
#Configuration
#ConditionalOnBean(com.jcraft.jsch.Session.class)
static class DelayedJpaConfiguration extends HibernateJpaAutoConfiguration {
public JpaConfiguration(DataSource dataSource, JpaProperties jpaProperties, ObjectProvider<JtaTransactionManager> jtaTransactionManager, ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
super(dataSource, jpaProperties, jtaTransactionManager, transactionManagerCustomizers);
}
}
}
You would have to implement your own data source (by extending the one you use) and implementing the InitializingBean interface and in the 'afterPropertiesSet' method initialize your jsch tunnel.
Please refer to this: Spring Data JPA with ssh tunnel to a remote MySQL server
I am experiencing some problems using Spring Boot and MongoDB external driver. I can't use the project Spring Data MongoDB, because I need to use the ufficial async driver given by Mongo. However, I need to use Spring Boot, because the module I am developing is part of a bigger project using this library.
Here is my pom.xml file.
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>tx-view</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- omissis -->
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-async</artifactId>
<version>${mongodb.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
In detail, I am using Spring Boot 1.4.1 and Mongo Async Driver 3.2.2.
Here is my application.
#SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
public class TxViewApplication {
public static void main(String[] args) {
SpringApplication.run(TxViewApplication.class, args);
}
#Value("${mongo.uri}")
private String mongoUri;
#Bean
public MongoClient mongoClient() {
return MongoClients.create(mongoUri);
}
}
It follows the only (empty) test I have at the moment.
#SpringBootTest
#RunWith(SpringRunner.class)
public class ApplicationTest {
#Test
public void loadContext() throws Exception {}
}
I have no other code in this project. When I run the test, I have the following error:
2016-11-22 15:43:58.597 INFO 4572 --- [null'}-db:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server db:27017
com.mongodb.MongoException: java.io.IOException: Il computer remoto ha rifiutato la connessione di rete.
at com.mongodb.connection.InternalStreamConnection.open(InternalStreamConnection.java:125) ~[mongodb-driver-core-3.2.2.jar:na]
at com.mongodb.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:128) ~[mongodb-driver-core-3.2.2.jar:na]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_101]
Caused by: java.io.IOException: Il computer remoto ha rifiutato la connessione di rete.
at sun.nio.ch.Iocp.translateErrorToIOException(Iocp.java:309) ~[na:1.8.0_101]
at sun.nio.ch.Iocp.access$700(Iocp.java:46) ~[na:1.8.0_101]
at sun.nio.ch.Iocp$EventHandlerTask.run(Iocp.java:399) ~[na:1.8.0_101]
at sun.nio.ch.AsynchronousChannelGroupImpl$1.run(AsynchronousChannelGroupImpl.java:112) ~[na:1.8.0_101]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_101]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_101]
... 1 common frames omitted
As you can see, I have properly inserted the exclude clause in the SpringBootApplication annotation in order to stop Spring Boot to try handle its own the connection to Mongo, as suggested in Mongo tries to connect automatically to port 27017(localhost).
I have also noticed that I started to have the error after the addition to the pom.xml of the dependency to spring-boot-starter-web.
How can I inhibit Spring Boot to try to connect automatically to Mongo at startup? The same problem is present with the synchronous version of MongoDB driver.
--- EDIT ---
I have also try to build a wrapper around the async.MongoClient object, in this way:
public class MongoWrapper {
private final MongoClient mongo;
public MongoWrapper() {
mongo = MongoClients.create();
}
public MongoClient getMongo() {
return mongo;
}
}
The configuration was changed accordingly.
#Bean
public MongoWrapper mongo() {
return new MongoWrapper();
}
Unfortunately, nothing had changed. Spring Boot seems to intercept the MongoClient object also in this way :(
Thanks a lot.
You have a MongoClient bean in your own configuration which does not make any sense to me if you've excluded the auto-configuration.
I've commented out the #Bean definition in your own config and no attempt to connect to Mongo is performed now. I am not sure I answer to your question and you're probably looking for something else but if you don't want to use mongo, don't define a MongoClient in your own config!
This helped us to disable async java driver of MongoDB to use default configuration:
#EnableAutoConfiguration(exclude = {MongoReactiveAutoConfiguration.class})
Spring Boot application fails to launch after upgrade from 1.3.3 to 1.3.5.
Spring is unable to start embedded container (Tomcat 8) and following error message is displayed:
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'embeddedServletContainerFactory': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [wad.config.HttpsConfiguration$1]: No default constructor found; nested exception is java.lang.NoSuchMethodException: wad.config.HttpsConfiguration$1.()
Basically this error message says it can't create the embeddedServletContainerFactory, but it's not clear to me what [wad.config.HttpsConfiguration$1] refers to. The Java configuration class itself is in package wad.config and named HttpsConfiguration.
I tried to add empty constructor to my HttpsConfiguration.java but it didn't help.
Here are the relevant parts of my POM:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.5.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
...
</dependencies>
My Application class:
#EntityScan(
basePackageClasses = {Application.class, Jsr310JpaConverters.class}
)
#SpringBootApplication
#Import({DevProfile.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And here is my configuration for port redirect from 8080 -> 8443 (configurable via application.properties):
#Configuration
public class HttpsConfiguration {
#Value("${server.port}")
private int httpsPort;
#Value("${server.port.http}")
private int httpPort;
#Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {
#Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
return tomcat;
}
// redirect from (http) port to (https) if https is enabled.
private Connector initiateHttpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(httpPort);
connector.setSecure(false);
connector.setRedirectPort(httpsPort);
return connector;
}
application.properties config:
...
#Actuator port
management.port = 9001
#HTTPS port
server.port=8443
#HTTP port
server.port.http=8080
#Enable SSL
server.ssl.enabled=true
...
Update:
Issue can be reproduced with Spring Boot 1.3.5 project configured with the above POM, application.properties and HttpSecurity & Application classes.
The usage of spring-boot-starter-actuator dependency together with management.port
being defined in application.properties causes starting the embedded tomcat container to fail.
Removing the management.port property definition from application.properties makes the application to start up again.
It is worth noting that while removing the property fixed the issue it's not clear why.
The solution this problem can be found here:
https://github.com/spring-projects/spring-boot/issues/6193
and creating a separate class extending TomcatEmbeddedServletContainerFactory and in that class have a public constructor that class super. The class extending TomcatEmbeddedServletContainerFactory can't be an inner class, it must be in it's own file and public in the package, otherwise the error will not go away.