ConnectionFactory doesn't recognize application.properties properties - java

I have a ConnectionFactory class in order to use in my Jdbc Appender to save logs in a mysql database, but, I want to use properties in ConnectionFactory class to avoid leaving sensitive data exposed in the code, but, it is a singleton class, so its never get the values of my properties, the properties are always null. Can someone help me, is there any way to bring the application.properties properties into the ConnectionFactory?
I have this ConnectionFactory class:
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnection;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.springframework.beans.factory.annotation.Value;
public class ConnectionFactory {
private static interface Singleton {
final ConnectionFactory INSTANCE = new ConnectionFactory();
}
private final DataSource dataSource;
#Value("${spring.datasource.user}")
private String user;
#Value("${spring.datasource.password}")
private String password;
#Value("${spring.datasource.url}")
private String url;
private ConnectionFactory() {
Properties properties = new Properties();
properties.setProperty("user", user);
properties.setProperty("password", password); // or get properties from some configuration file
GenericObjectPool<PoolableConnection> pool = new GenericObjectPool<PoolableConnection>();
DriverManagerConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
url, properties
);
new PoolableConnectionFactory(
connectionFactory, pool, null, "SELECT 1", 3, false, false, Connection.TRANSACTION_READ_COMMITTED
);
this.dataSource = new PoolingDataSource(pool);
}
public static Connection getDatabaseConnection() throws SQLException {
return Singleton.INSTANCE.dataSource.getConnection();
}
And, my application.properties:
spring.cloud.compatibility-verifier.enabled=false
# database configs
spring.datasource.url=jdbc:mysql://localhost:3306/myDatabase
spring.datasource.username=root
spring.datasource.password=
spring.datasource.testWhileIdle=true
spring.datasource.validationQuery=SELECT 1
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
Is there any way to bring the properties into the ConnectionFactory class?

I found a response, you can add the environment variables in a singleton class using this code:
System.getenv("MY_ENV_VARIABLE");
This way, you get the environment variables.
If you really need to get the properties of applications.properties, you need to create a Properties properties variable, and then you can use this code:
try (InputStream input = YourSingletonClass.class.getClassLoader().getResourceAsStream("application.properties")) {
properties.load(input);
} catch (IOException e) {
e.printStackTrace();
}
To get the value of any propertie, use properties.getProperty(key); where the 'key' is the name of your propertie.

Related

How to provide DataSource properties in spring boot application after deployment of the application

I am developing a server that is configured to a PostgreSQL database, I want that application takes data source properties ( username, password, port, hostname etc.) from the client specific to his database so how can I take input from the client and pass that configuration after deployment because I want to distribute only WAR file of the server
Yes You can Add configuration Dynamically from the Client side. We can achieve this concept by spring-boot hibernate.
--> You have to create an class to Auto congifure the propertise.
I am sharing my sample code to configure the propertise.
package com.spring.hibernate.config;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;
#Configuration
#EnableTransactionManagement
public class Configurations {
#Value("${db.url}")
private String URL;
#Value("${db.username}")
private String USERNAME;
#Value("${db.password}")
private String PASSWORD;
#Value("${hibernate.hbm2ddl.auto}")
private String HBM2DDL;
#Value("${hibernate.show_sql}")
private String SHOW_SQL;
#Value("${hibernate.dialect}")
private String DIALECT;
#Value("${spring.entitymanager.packagestoscan}")
private String packagesToscan;
#Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setUrl(URL);
dataSource.setUsername(USERNAME);
dataSource.setPassword(PASSWORD);
return dataSource;
}
#Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan(packagesToscan);
Properties hibernatePropertise = new Properties();
hibernatePropertise.put("hibernate.dialect", DIALECT);
hibernatePropertise.put("hibernate.hbm2ddl.auto", HBM2DDL);
hibernatePropertise.put("hibernate.show_sql", SHOW_SQL);
sessionFactory.setHibernateProperties(hibernatePropertise);
return sessionFactory;
}
}
Have a configuration class in the above structure to configure the application Properties file.
And have your application properties file as follow.
db.url: jdbc:mysql://localhost:3306/data_db
db.username: root
db.password: 8452
hibernate.hbm2ddl.auto=update
hibernate.show_sql=true
hibernate.dialect: org.hibernate.dialect.MySQL5InnoDBDialect
spring.entitymanager.packagestoscan: com.spring.hibernate
Use the above sample code. Still any logics needed have a command for me...Thank You..

Spring authentication with Oracle JDBC10

I'm following a Spring Course that the teacher makes an example of Spring Security (loging page with spring mvc) ... he's using mysql and i'm trying to do it but with Oracle Database 19c, width ojdbc10, but i'm missing something.
I have the same tables (user and password), with the same data in it, but when i try to log in, i failed in the authentication, like the user name or password is wrong.
Properties file
#
#JDBC connection properties
#
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:#192.168.240.11:1521:orcl
jdbc.user=jcataldo
jdbc.password=Pola1095
App config .java
ort org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import com.mchange.v2.c3p0.ComboPooledDataSource;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages="com.luv2code.springsecurity.demo")
#PropertySource("classpath:persistence-oracle.properties")
public class DemoAppConfig {
// define a bean for ViewResolver ==> Indica que es lo que debería mostrar, en este caso todo los
// .jsp ubicados en /WEB-INF/view
#Autowired
private Environment env; //hold data read from properties file
// set up a logger for diagnostics
private Logger logger = Logger.getLogger(getClass().getName());
// define a bean for ViewResolver
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
// define a bean for our security datasource
#Bean
public DataSource securityDataSource() {
// create a connection pool
ComboPooledDataSource securityDataSource
= new ComboPooledDataSource();
// set the jdbc driver class
try {
securityDataSource.setDriverClass(env.getProperty("jdbc.driver"));
} catch (PropertyVetoException exc) {
throw new RuntimeException(exc);
}
// log the connection props
// check if we are really reading data from properties file
logger.info(">>>>> jdbc.url=" + env.getProperty("jdbc.url"));
logger.info(">>>>> jdbc.user=" + env.getProperty("jdbc.user"));
// set database connection props
securityDataSource.setJdbcUrl(env.getProperty("jdbc.url"));
securityDataSource.setUser(env.getProperty("jdbc.user"));
securityDataSource.setPassword(env.getProperty("jdbc.password"));
// set connection pool props
securityDataSource.setInitialPoolSize(
getIntProperty("connection.pool.initialPoolSize"));
securityDataSource.setMinPoolSize(
getIntProperty("connection.pool.minPoolSize"));
securityDataSource.setMaxPoolSize(
getIntProperty("connection.pool.maxPoolSize"));
securityDataSource.setMaxIdleTime(
getIntProperty("connection.pool.maxIdleTime"));
return securityDataSource;
}
private int getIntProperty(String propName) {
String propVal = env.getProperty(propName);
// convert to int
int intPropVal = Integer.parseInt(propVal);
return intPropVal;
}
}
I have NO CONNECTION ERRORS, but its like the data in the table user and password is not matching with my input in the mvc login page.
Hope someone can help me.
thanks in advance and sorry if i misslead something, i'm new in this.
Well, i messed up with the table's database, didn't follow the right schema, wich is:
CREATE TABLE USERS (
USERNAME NVARCHAR2(128) PRIMARY KEY,
PASSWORD NVARCHAR2(128) NOT NULL,
ENABLED CHAR(1) CHECK (ENABLED IN ('Y','N') ) NOT NULL);
CREATE TABLE AUTHORITIES (
USERNAME NVARCHAR2(128) NOT NULL,
AUTHORITY NVARCHAR2(128) NOT NULL);
ALTER TABLE AUTHORITIES ADD CONSTRAINT AUTHORITIES_UNIQUE UNIQUE (USERNAME, AUTHORITY);
ALTER TABLE AUTHORITIES ADD CONSTRAINT AUTHORITIES_FK1 FOREIGN KEY (USERNAME) REFERENCES USERS (USERNAME) ENABLE;

Check if H2 db file exists

I have been using a real simple H2 DB on a file. I had my setup like this:
Class.forName("org.h2.Driver");
Connection conn = DriverManager.getConnection("jdbc:h2:"+dbFileName);
Statement stat = conn.createStatement();
and on application startup, I would simply do:
File dbFile = new File("~/mydb.db");
if(!dbFile.exists()) {
String sql = -create my table here, etc...
}
But I am now trying to do this in a "correct" Spring Boot way. So I have my application.properties file to contain this:
# H2
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.datasource.url=jdbc:h2:file:~/mydb.db
spring.datasource.username=sa
spring.datasource.password=
spring.datasource.driver-class-name=org.h2.Driver
And I am trying to use the JdbcTemplate / Dao way of doing things. But I need to check if the DB is there at startup. So I want to do my previous check in the Application classes event listener for ApplicationReadyEvent. But how do I get a reference to the datasource url? I had is a a configuration property before and was automatically loaded, and I could still do that, but it would be in to places and that would be bad.
So what's the essayist / correct way to ensure this DB file is there when the application starts up. (and I want this in a JDBC way, no JPA please)
You can use ApplicationListener then parse the spring.datasource.url value:
import java.io.File;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
#Component
public class MyApplicationListener implements ApplicationListener<ApplicationStartedEvent> {
#Value("${spring.datasource.url}")
private String databaseUrl;
#Override
public void onApplicationEvent(ApplicationStartedEvent event) {
System.out.println("Application started");
String path = databaseUrl.replace("jdbc:h2:file:", "");
System.out.println(path);
File dbFile = new File(path);
if (!dbFile.exists()) {
String sql = "etc";
}
}
}

Correct JNDI #Resource(name)

I have the following class for obtaining a JDBC connection:
package util;
import java.sql.Connection;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
public class OracleConnection implements AutoCloseable{
private final String oracle_DS_CTX = "java:jboss/oracleDS";
// #Resource(name="java:jboss/oracleDS")
// private DataSource ds; //doesn't work
private Connection _conn;
public OracleConnection() throws SQLException, NamingException{
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup(oracle_DS_CTX);
_conn = ds.getConnection();
}
#Override
public void close() throws Exception {
if(_conn != null){
_conn.close();
}
}
public Connection getConnection() throws SQLException {
return _conn;
}
}
I have a problem using the #Resource annotation. Datasource obtained via InitialContext works without any problems but I am not sure what string should I put into resource name (commented out in my code).
I have tried:
#Resource(name="java:jboss/oracleDS")
#Resource(name="oracleDS")
AS is JBOSS AS7
What name did you define in your standalone.xml?
That is the name you need to define in your #Resource
But there's a little trick, you need to set it in the lookup property instead of name.
Here's an example, let's assume my DS jndi is java:jboss/ExampleDS.
#Resource(lookup = "java:jboss/ExampleDS")
private DataSource dataSource;

Getting Database Connection using Quartz

I have a requirement where i need to insert data and retrieve the same during my scheduling process.Though i can create my own connection class and can do the work but i am wondering is there a way to obtain a data base connection using Quartz API.
Since Quartz is efficiently doing data base connection and handling so my intention was to use a well defined structure in stead of creating my own.
I saw the following code in the Quartz
conn = DBConnectionManager.getInstance().getConnection(
getDataSource());
but i am not sure how good this approach is to obtain the connection.Or is there any good example/resource to create an efficient database connection class.
Quartz Property File
org.quartz.scheduler.instanceName=QuartzScheduler
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.threadPool.threadCount=7
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.MSSQLDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.dataSource = myDS
org.quartz.dataSource.myDS.driver=com.mysql.jdbc.Driver
org.quartz.dataSource.myDS.URL=jdbc:mysql://localhost:3306/quartz
org.quartz.dataSource.myDS.user=root
org.quartz.dataSource.myDS.password=root
org.quartz.dataSource.myDS.maxConnections=5
You can get connection utilizing Quartz by naming the data-source you have defined in your property file like
conn = DBConnectionManager.getInstance().getConnection("myDS");
here myDS is the name of the data source you have defined in your property file
but since you are using the underlying data pool of quartz make sure that you close the connection so that it should get back to the pool.
This is just an outline based on my knowledge of Quartz and how it get connection.
If you want to get DataSource:
import java.io.InputStream;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.quartz.SchedulerException;
import org.quartz.utils.PoolingConnectionProvider;
import org.quartz.utils.PropertiesParser;
/**
* This class just exposes the underlying data source backed by C3PO
* (http://www.mchange.com/projects/c3p0/index.html).
*/
class MyDataSource extends PoolingConnectionProvider {
public MyDataSource(Properties config) throws SchedulerException, SQLException {
super(config);
}
public DataSource dataSource() {
return getDataSource();
}
}
/** This class exposes the data store configured in quartz.properties. */
public class MyDataSourceLoader {
private static final String DATA_SOURCE_CONFIG = "quartz.properties";
private static final String DATA_SOURCE_PREFIX = "org.quartz.dataSource.myDS";
private static final DataSource dataSource;
static {
try {
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(DATA_SOURCE_CONFIG);
Properties quartzConfig = new Properties();
quartzConfig.load(in);
in.close();
PropertiesParser pp = new PropertiesParser(quartzConfig);
Properties dataSourceConfig = pp.getPropertyGroup(DATA_SOURCE_PREFIX, true);
MyDataSource mds = new MyDataSource(dataSourceConfig);
dataSource = mds.dataSource();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static DataSource dataSource() {
return dataSource;
}
}

Categories