Tomcat Restart required after war file deployment for database connection - spring

While deploying a war file (Spring Boot App) on external Tomcat server, I am getting the exception:
com.zaxxer.hikari.HikariConfig - HikariPool-5 - dataSource or dataSourceClassName or jdbcUrl is required
It gets resolved after server restart and application gets started.
Edit:
Datasource configuration is done as follows:
#Bean(name = "datasource")
#ConfigurationProperties(prefix = "app.datasource")
public DataSource appDataSource() {
return DataSourceBuilder.create().build();
}
Properties used:
app.datasource.jdbc-url
app.datasource.username
app.datasource.password
app.datasource.driverClassName
Not getting the reason for this behavior

Related

JDBC not registering metrics on spring boot 2 when #RefreshScope is on DataSource Bean

I have an application that uses spring boot 2 and logs metrics from micrometer. I want to log jdbc (mysql) min, max, and active connections periodically. I also want to use #RefreshScope on my datasource bean to prevent hikari binding exceptions when injecting configs on the fly from spring admin. I find that when I use #RefreshScope on config class/datasource bean JDBC does not register itself with the MeterRegistry.
Is it possible to have JDBC register itself with the MeterRegistry with #RefreshScope?
Is there a way to progammatically register JDBC with the MeterRegistry in my bean definition?
#Configuration
#EnableAutoConfiguration
#EnableTransactionManagement
#RefreshScope
public class DbConfig {
#Primary
#Bean(name = "dataSource")
#RefreshScope
#ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
Removing #RefreshScope allows JDBC to automatically register with the MeterRegistry but causes the below exception on config change:
org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'dataSource': Could not bind properties to 'HikariDataSource' : prefix=spring.datasource, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.datasource' to javax.sql.DataSource
Add javax.sql.DataSource as an extra refreshable. application.yml file example:
spring:
cloud:
refresh.extra-refreshable:
- javax.sql.DataSource
and remove #RefreshScope from your class.
Other solution would be cast the DataSource to HikariDataSource.
I use the first solution because of DataSource creation is done by external library in my application.
Reference: https://github.com/spring-cloud/spring-cloud-commons/issues/318

Spring jdbctemplate working on tomcat but gives error on WAS server

I am trying to connect to db2 using spring jdbc template. Everything is working fine when deployed on tomcat server. But the same application when I am trying to deploy on WAS server is not working and giving me the below exception.
com.ibm.db2.jcc.am.DisconnectNonTransientConnectionException: [jcc][t4][2030][11211][3.69.66] A communication error occurred during operations on the connection's underlying socket, socket input stream,
or socket output stream. Error location: Reply.fill() - socketInputStream.read (-1). Message: Received fatal alert: handshake_failure. ERRORCODE=-4499, SQLSTATE=08001
My datasource bean configuration is given below
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource=new DriverManagerDataSource();
dataSource.setDriverClassName("com.ibm.db2.jcc.DB2Driver");
dataSource.setUrl("url");
dataSource.setUsername("username");
dataSource.setPassword("password");
Properties connectionProperties=new Properties();
connectionProperties.setProperty("sslConnection", "true");
connectionProperties.setProperty("sslTrustStoreLocation", "pathToFile");
connectionProperties.setProperty("sslTrustStorePassword", "pass");
dataSource.setConnectionProperties(connectionProperties);
return dataSource;
}

Failed to get driver instance for oracle

I’m trying to connect to my oracle database, I’m using a spring boot configuration together with YAML file, I’ve configured jdbc in pom and jpa, but it still fails to connect.
I’ve tried many different configuration for the url:
1) jdbcUrl=jdbc:oracle:thin://test.test.test:1521
2) jdbcUrl=jdbc:oracle:thin#test.test.test:1521
3) jdbcUrl=jdbc:oracle://test.test.test:1521
4) jdbcUrl=jdbc:oracle#test.test.test:1521
here my application.yml
spring:
profiles: test
datasource:
onlineterminierung:
url: jdbc:oracle: jdbc:oracle:thin://test.test.test:1521
database: test
username: test
password: test
driverClassName: oracle.jdbc.driver.OracleDriver
defaultSchema:
maxPoolSize: 20
hibernate:
hbm2ddl.method: update
show_sql: false
format_sql: true
dialect: org.hibernate.dialect.Oracle10gDialect
and here the DataSource bean:
/*
* Configure HikariCP pooled DataSource.
*/
#Bean
public DataSource dataSource() {
DataSourceProperties dataSourceProperties = dataSourceProperties();
HikariDataSource dataSource = (HikariDataSource) DataSourceBuilder.create(dataSourceProperties.getClassLoader())
.driverClassName(dataSourceProperties.getDriverClassName()).url(dataSourceProperties.getUrl()).username(dataSourceProperties.getUsername())
.password(dataSourceProperties.getPassword()).type(HikariDataSource.class).build();
dataSource.setMaximumPoolSize(maxPoolSize);
return dataSource;
}
here the pom:
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.3.0</version>
<scope>test</scope>
</dependency>
here the stack:
HHH000342: Could not obtain connection to query metadata : Failed to get driver instance for jdbcUrl=jdbc:oracle:thin://test.test.test:1521
Unable to build Hibernate SessionFactory
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
Caused by: java.lang.RuntimeException: Failed to get driver instance for jdbcUrl=jdbc:oracle:thin://test.test.test:1521
Caused by: java.sql.SQLException: No suitable driver
Some idea?
Syntax:
jdbc:oracle:thin:#host:port:db","usname","pwd"
#Autowired
DataSource dataSource;
#Bean(name = "dataSource")
public DriverManagerDataSource dataSource() {
DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
driverManagerDataSource.setDriverClassName("oracle.jdbc.OracleDriver");
driverManagerDataSource.setUrl("jdbc:oracle:thin:#hostname:1521/dbname");
driverManagerDataSource.setUsername("uname");
driverManagerDataSource.setConnectionProperties(getadditionalJpaProperties());
driverManagerDataSource.setPassword("password");
return driverManagerDataSource;
}
Properties getadditionalJpaProperties() {
Properties properties = new Properties();
// properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
properties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
properties.setProperty("hibernate.show_sql", "true");
return properties;
}
Always use the long form of the connection URL that gives you the flexibility to pass various connection level parameters. A code sample DataSourceSample on GitHub has a sample URL for reference.
jdbc:oracle:thin:#(DESCRIPTION=(ADDRESS=(HOST=myhost)(PORT=1521)(PROTOCOL=tcp))(CONNECT_DATA=(SERVICE_NAME=myorcldbservicename)))";
I ran into this problem. and I was mistakenly ignoring a line of code
driverManagerDataSource.setDriverClassName("oracle.jdbc.OracleDriver");
or in bean config
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
I am using Oracle 11G and Jersey + Boot server running on Websphere

Weblogic jndi NameNotFoundException occur with java config

I been searching again for this issue where I cannot locate the jndi database by using java config. Before this I use xml and its work perfectly but in java config it cause an issue;
Xml code:
<!-- Jndi database connection -->
<jee:jndi-lookup id="dbDataSource" jndi-name="${db.jndi}"
resource-ref="true" />
<beans:bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate" >
<beans:property name="dataSource" ref="dbDataSource"></beans:property>
</beans:bean>
Java config now:
#Bean(name = "dbDataSource")
public DataSource dataSource(#Value("${db.jndi}") String jndiName)
{
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiName);
}
#Bean
public JdbcTemplate jdbcTemplate(DataSource ds) {
return new JdbcTemplate(ds);
}
Properties file:
db.jndi=jndi/myData
JNDI name in weblogic:
jndi/myData
After change to java config, sometimes the system can read the database but rarely occur, until I clean and restart my computer then it can find the database, but usually its always trigger:
javax.naming.NameNotFoundException: Unable to resolve 'jndi.myData'. Resolved 'jndi'; remaining name 'myData'
Why the application cannot find the database correctly?
Thanks!!!
I've had the same issue. If you're using 4.x version of spring that's probably the cause.
You should also check Weblogic's JNDI Tree. If your data source disapears from the tree after rebuilding the project, that's another symptom
If that's the case, what's happening is:
Your Datasource implements Closeable (and therefore AutoCloseable) and the context will always invoke the shutdown method regardless of your Bean definition
as seen here : SPR-12551: Document how to prevent a JNDI DataSource retrieved using JavaConfig to be removed on shutdown of the context
It's been marked as a documentation issue as this is the "expected" behaviour:
This issue was solely about documentation since we decided not to implement anything at the framework level
the solution, is to define the destroy method of the bean as empty, such as:
#Bean(name = "dbDataSource", destroyMethod="")
public DataSource dataSource(#Value("${db.jndi}") String jndiName)
{
JndiDataSourceLookup lookup = new JndiDataSourceLookup();
return lookup.getDataSource(jndiName);
}
#Bean
public JdbcTemplate jdbcTemplate(DataSource ds) {
return new JdbcTemplate(ds);
}
This is described in this issue (SPR-13022:Destroy callback cannot be disabled for AutoCloseable beans) .
PS: By the way, it seems like on early 4.x version of spring you couldn't override this behaviour by assingning destroyMethod. It apears that this bug was fixed on version 4.2 RC1.
I've had the same issue and I solved problem. I used to jndi datasource on weblogic. After I restart application, I notice my jndi datasource remove from Weblogic's JNDI Tree. Xml configuration works successfuly but java configuration don't work.
My old spring version: 4.1.6.RELEASE Upgrade to 4.3.9.RELEASE
Xml configuration like this;
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>${db-jndi.name}</value>
</property>
</bean>
Java configuration like this;
#Bean(name = "dataSource")
public DataSource dataSource() throws IllegalArgumentException, NamingException
{
JndiTemplate jndiTemplate = new JndiTemplate();
DataSource dataSource = (DataSource) jndiTemplate.lookup(env.getProperty("db-jndi.name"));
logger.info("DataSource initialized in jndi ");
return dataSource;
}
Then i changed
#Bean(name = "dataSource")
to
#Bean(name = "dataSource", destroyMethod = "")
And it's works successfuly.
It looks like your datasource hasn't been deployed. You should look for JNDI tree for the server you tried to deploy datasource. (https://docs.oracle.com/cd/E12839_01/apirefs.1111/e13952/taskhelp/jndi/ViewObjectsInTheJNDITree.html) If you don't see "jndi.myData" on JNDI tree, you can assume that your datasource haven't been deployed. So you can go to your datasource monitoring tab and test the datasource. (https://docs.oracle.com/cd/E17904_01/apirefs.1111/e13952/taskhelp/jdbc/jdbc_datasources/TestDataSources.html)

Using Spring Cloud Connectors together with HikariCP

I would like to use HikariCP from the Spring Cloud Connectors. I am not sure how to proceed...
I have updated my Spring Cloud Connectors to 1.2.0.RC1.
Here is my current config:
#Configuration
#Profile({ Profiles.CLOUD })
public class CloudDataSourceConfiguration extends AbstractCloudConfig {
#Bean
public DataSource dataSource() {
int dbcpMaxActive = 10;
int dbcpMaxWait = 200;
PoolConfig poolConfig = new PoolConfig(dbcpMaxActive, dbcpMaxWait);
ConnectionConfig connectionConfig = new ConnectionConfig("sessionVariables=sql_mode='ANSI';characterEncoding=UTF-8");
DataSourceConfig serviceConfig = new DataSourceConfig(poolConfig, connectionConfig);
return connectionFactory().dataSource("CLEARDB_DATABASE", serviceConfig);
}
}
Can someone please advise?
edit: When I start the app with the cloud profile, I can read
2015-05-23 22:46:56,029 [localhost-startStop-1] INFO org.springframework.cloud.service.relational.PooledDataSourceCreator - Found Tomcat high-performance connection pool on the classpath. Using it for DataSource connection pooling.
from the log output.
edit 2: HikariCP is in the classpath and it seems that tomcat high performance connection pool is also in the classpath.
As stated in my second edit, both tomcat jdbc & HikariCP were on the classpath. By removing tomcat jdbc as follows (in my gradle script):
compile("org.springframework.boot:spring-boot-starter-data-jpa"){
exclude group: 'org.apache.tomcat', module: 'tomcat-jdbc'
}
only HikariCP remained on the classpath and it was picked up properly as shown by the log output below:
INFO org.springframework.cloud.service.relational.PooledDataSourceCreator - Found HikariCP on the classpath. Using it for DataSource connection pooling.

Resources