I'm currently using a pool connection(Hikari) and an abstract factory pattern to implement my MySQL queries in Java like this:
MySqlFactoryDAO.java
public class MySqlFactoryDAO extends FactoryDAO {
private static HikariDataSource connPool_;
public static Connection createConnection() throws SQLException {
if (connPool_ == null) {
// Load database configuration
PropertiesFile props = FactoryConfig.getConfig().getDatabaseProperties();
connPool_ = new HikariDataSource();
connPool_.setJdbcUrl(props.getString(Params.DB_URL,""));
connPool_.setUsername(props.getString(Params.DB_USER,"root"));
connPool_.setPassword(props.getString(Params.DB_PASSWORD,"root"));
}
return connPool_.getConnection();
}
//-------------------------------------------------------------------------
public ProductDAO getProductDAO() {
return new ProductMySQLFactoryDAO();
}
}
ProductMySQLFactoryDAO.java
public class ProductMySQLFactoryDAO implements ProductDAO {
public int insertProduct(String name) {
...
Connection conn = MySqlFactoryDAO.createConnection();
...
}
}
I was wondering if this code is thread safe and I think that there is a problem at the time of initialization of coonPool_. I have read things like "Initialization-on-demand_holder_idiom" in wikipedia but I am not sure about it. Does anyone have a better implementation of this to solve this problem or just a better new one?
No, it's not thread-safe. Two threads might call createConnection() concurrently, both see the pool as null, and both create a new DataSource.
The method needs to be synchronized. Or the pool must be created at class initializing time:
private static final HikariDataSource DATA_SOURCE = createDataSource();
Your connPool_ field should be private, too.
Related
I have created a class in Spring boot to establish a global javers object that can be used by all classes. This is my code.
#Component
public class JaversInstance {
public static final Javers javers;
static
{
ConnectionProvider connectionProvider = new ConnectionProvider() {
#Override
public Connection getConnection() throws SQLException {
String url = "any_url";
Properties props = new Properties();
props.setProperty("user", "test");
props.setProperty("password", "test");
DriverManager.getConnection(url, props);
System.out.println("CONNECTION PROVIDER invoked");
return DriverManager.getConnection(url, props);
}
};
JaversSqlRepository sqlRepository = SqlRepositoryBuilder
.sqlRepository()
.withConnectionProvider(connectionProvider)
.withDialect(DialectName.MYSQL).build();
System.out.println("JAVERS instance creation");
javers = JaversBuilder.javers().registerJaversRepository(sqlRepository).build();
}
private JaversInstance() {
}
}
Output:
JAVERS instance creation
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
CONNECTION PROVIDER invoked
Can someone tell me what has happened here. Why the getConnection() is called so many times? Is this any kind of retry?
It happens as many times as the anonymous class of ConnectionProvider is loaded. The following code will help you understand it better:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
static Comparator<Integer> comparator;
static {
comparator = new Comparator() {
#Override
public int compare(Object o1, Object o2) {
System.out.println("Hello");
return 0;
}
};
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(40);
list.add(20);
list.add(10);
list.add(30);
Collections.sort(list, comparator);
}
}
Output:
Hello
Hello
Hello
Although the ConnectionProvider is instantiated inside a static block, its overridden method is neither static (can't be) nor related to the static block itself but to the instance connectionProvider.
Basically, you implement a method of an anonymous class. I suppose the ConnectionProvider is an interface, then defining a class implementing the very same interface would be effectively the same as your code:
static
{
ConnectionProvider connectionProvider = new MyConnectionProvider();
}
The internals of the getConnection method is not bound to the static block, the instance connectionProvider itself is. There are multiple calls since the method has been invoked multiple times from an instance defined within the static block.
This question already has answers here:
Spring: How to inject a value to static field?
(5 answers)
Closed 4 years ago.
I am a beginner with Spring and I am working on a spring-boot project with Jooq.
I created an application properties
which loads the database access settings,
it's working, but I need a connection class that returns a connection object for me to use when needed.
It would be better if this class had a static getConnection method. I wrote the class as #Component and I put my
#Value but all these attributes are null when I try to use them.
Is there another way to do this?
Thank you so much.
#Component
public class ConnectionFactory {
#Value("${bws.codigo.escola}")
static private String codigoEscola;
#Value("${bws.driver.connection}")
static private String driver;
#Value("${bws.database.name}")
static private String nameDb;
#Value("${bws.database.user}")
static private String user;
#Value("${bws.database.password}")
static private String password;
#Value("${bws.database.server}")
static private String server;
#Value("${bws.string.connection}")
static private String firstUrlPart;
#Value("${bws.string.connectionLast}")
static private String lastPartUrl;
#Value("${bws.database.port}")
static private String port;
static String strConnection = firstUrlPart+server+":"+port+"/"+nameDb+lastPartUrl;
public static Connection getConnection() throws SQLException {
try {
Class.forName(driver);
return DriverManager.getConnection(strConnection,
user,password);
} catch (ClassNotFoundException e) {
throw new SQLException(e.getMessage());
}
}
}
that way I would use it in other classes
try (Connection con = ConnectionFactory.getConnection()) {
DSLContext ctx = DSL.using(con, SQLDialect.MYSQL);
int count = ctx.selectCount()
.from(ALUNO)
.fetchOne(0, int.class);
return count;
}
You could, of course, go ahead and inject all the values required to create a JDBC connection for each of your query on an ad-hoc basis. Or, much better, you inject a pre-configured DSLContext singleton instance that wraps the JDBC connection through a DataSource (ideally implemented by a connection pool).
The Spring Boot manual illustrates how this can be done:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-sql.html#boot-features-jooq
A more complete example can be seen here:
https://github.com/jOOQ/jOOQ/tree/master/jOOQ-examples/jOOQ-spring-boot-example
The goal would be to have:
class SomeClass {
#Autowired
DSLContext ctx;
public int countAluno() {
return ctx.selectCount()
.from(ALUNO)
.fetchOne(0, int.class);
}
}
I'm running a long running web service via Jetty/CometD, and I'm using the Redisson library for connecting to redis. I'm using a Singleton pattern for getting my RedissonClient/connection and I am not sure if that is the best way to go.
Class looks like this:
public class RedisClient {
// singleton instance of our RedisonClient/connection
private static RedissonClient _redissonInstance;
public static String REDIS_HOST = "my.redishost.com:6379";
private static RedissonClient setupRedis() {
org.redisson.Config config = new org.redisson.Config();
config.useSingleServer()
.setAddress(REDIS_HOST)
.setConnectionPoolSize(200);
return Redisson.create(config);
}
public static RedissonClient getRedis() {
if (_redissonInstance == null) {
_redissonInstance = setupRedis();
}
return _redissonInstance;
}
public static void setRedisHost(String redisHost) {
_logger.warn("Setting REDIS_HOST to: " + redisHost);
REDIS_HOST = redisHost;
}
}
I would say that this is a bad idea. I don't think singletons are a good idea in general but even so this is not a good way to do it. Your code is not thread-safe and it seems as if you want to support multiple hosts.
If you really don't want to pass your redis client around to every component and your host is not going to change and want something quick and dirty try this:
public class Redis {
public static final RedissonClient CLIENT;
static {
Config config = new Config();
config.useSingleServer()
.setAddress("my.redishost.com:6379")
.setConnectionPoolSize(200);
CLIENT = Redisson.create(config);
}
}
This has the benefit of being thread-safe without having any synchronization when getting the reference.
I have a question about closing resources (AutoCloseable or not) that are static members of a Java class. In my particular situation I have a class that manages connections to a MongoDB instance using a static MongoClient instance variable. How would I ensure that this client is closed as the documentation recommends when my application terminates? I am using this class as part of the back end to a Java webapp which is run in a container (Tomcat 7). I could not override the Object's finalize() method to close the client because that is called on an instance of the class and would have no effect on static members correct? Here is my example code:
public class MyManager {
//This needs to be closed when the application terminates
private static MongoClient CLIENT;
static {
...
CLIENT = new MongoClient("localhost", 27017);
...
}
public static DB getSomeDB(String dbName) {
return CLIENT.getDB(dbName);
}
//more factory methods
...
//Would this work?
#Override
protected void finalize() throws Throwable {
CLIENT.close();
}
}
Can someone tell me how to best handle this situation and in general with resources such as a database connection or JDBC driver? Thanks!
We are using Spring and simply create a bean which calls the close() method once it's being destroyed:
#Bean(name = "mongoClient", destroyMethod = "close")
public MongoClient mongoClient() throws MongoException, UnknownHostException {
...
I have several DAO objects that are used to retrieve information from a database and I really want to write some automated tests for them but I'm having a hard time figuring out how to do it.
I'm using Spring's JdbcTemplate to run the actual query (via a prepared statement) and map the results to the model object (via the RowMapper class).
If I were to write unit tests, I'm not sure how I would/should mock the objects. For example, since there are only reads, I would use the actual database connection and not mock the jdbcTemplate, but I'm not sure that's right.
Here's the (simplified) code for the simplest DAO of the batch:
/**
* Implementation of the {#link BusinessSegmentDAO} interface using JDBC.
*/
public class GPLBusinessSegmentDAO implements BusinessSegmentDAO {
private JdbcTemplate jdbcTemplate;
private static class BusinessSegmentRowMapper implements RowMapper<BusinessSegment> {
public BusinessSegment mapRow(ResultSet rs, int arg1) throws SQLException {
try {
return new BusinessSegment(rs.getString(...));
} catch (SQLException e) {
return null;
}
}
}
private static class GetBusinessSegmentsPreparedStatementCreator
implements PreparedStatementCreator {
private String region, cc, ll;
private int regionId;
private GetBusinessSegmentsPreparedStatementCreator(String cc, String ll) {
this.cc = cc;
this.ll = ll;
}
public PreparedStatement createPreparedStatement(Connection connection)
throws SQLException {
String sql = "SELECT ...";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, cc);
ps.setString(2, ll);
return ps;
}
}
public GPLBusinessSegmentDAO(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
public Collection<BusinessSegment> getBusinessSegments(String cc, String ll) {
return jdbcTemplate.query(
new GetBusinessSegmentsPreparedStatementCreator(cc, ll),
new BusinessSegmentRowMapper());
}
}
Any idea would be appreciated.
Thanks!
Please have a look at below links:
Testing SQL queries with Spring and DbUnit
MockObjects or DBUnit for testing Code using JdbcTemplate
Hope that helps.
EDIT:
Here is the GitHub version of RowMapperTests for easy reference.
I recommend breaking your dependency on JdbcTemplate class, and using the JdbcOperations interface instead, e.g.
public class GPLBusinessSegmentDAO implements BusinessSegmentDAO {
private final JdbcOperations jdbc;
public GPLBusinessSegmentDAO(DataSource dataSource) {
this(new JdbcTemplate(dataSource));
}
public GPLBusinessSegmentDAO(JdbcOperations jdbc) {
this.jdbc = jdbc;
}
// ... DAO methods here
}
Your unit test can invoke the second constructor, passing in a mock JdbcOperations object. Since all DB operations are performed via the jdbc object, you can mock that easily enough.
Your live code can call the first constructor as before.
To write a true unit test for this, you would not be touching a real database.
You may however find it more practical to pass in a real DataSource to your underlying db, and test the getBusinessSegments() method returns 0, 1 and many results depending on the cc and ll values you pass in.
Another option worth investigating would be to pass in a DataSource of an embedded Java DB that was initialised with your schema in a setUp/#Before method. I guess what you really want to test is that the SELECT... query maps correctly to the schema, so such a test would catch any errors that arise at runtime when the schema, say, changes.