How to create and configure MariaDBDataSource manually - java

I'm having problems with creating unpooled datasource with MariaDBDataSource class.
MariaDbDataSource mysqlDs = new MariaDbDataSource(connectionUrl);
mysqlDs.setPassword(password);
mysqlDs.setUser(username);
return wrapWithPool(mysqlDs);
wrapWithPool simply wraps the given datasource with a pooled one (c3p0 pool).
But I fail to checkout a connection from the pool. Whenever I do
datasource.getConnection()
I get
org.mariadb.jdbc.internal.util.dao.QueryException: Could not connect: Access denied for user 'someuser'#'somehost' (using password: NO)
Not sure why? I do set non empty password. Is there anything else to set on the MariaDbDatasource class to make it use the password?
edit:
Ok, so it seems that when I do not wrap the MariaDbDataSource all works ok.
So c3p0 is breaking up the connection, and from debug I see it fails to get the password...
The wrap method is quite simple
private static DataSource wrapWithPool(DataSource unpooled) throws SQLException {
unpooled.setLoginTimeout(HOST_REACH_TIMEOUT.getValue());
Map<String, Object> poolOverrideProps = new HashMap<>();
poolOverrideProps.put("maxPoolSize", CONNECTION_POOL_SIZE.getValue());
poolOverrideProps.put("minPoolSize", 1);
poolOverrideProps.put("checkoutTimeout", HOST_REACH_TIMEOUT.getValue() * 2);
return DataSources.pooledDataSource(unpooled, poolOverrideProps);
}
And it works perfecly fine with other drivers (oracle, jtds). Why not with mariaDb?

Ok, so I discovered the problem. For some reason, the c3p0 when creating the pool, wraps the given DataSource class within own WrapperConnectionPoolDataSourceBase class. Then it tries to detect the authentication parameters from it using reflection. Since MariaDBDataSource does not provide the getPassword method, the discovered value is null, and thus the error message about not using the password.
So as a workaround I did a simple wrapper
private static class MariaDbDExtender extends MariaDbDataSource {
private String password;
public MariaDbDExtender(String connectionUrl) throws SQLException {
super(connectionUrl);
}
#Override
public void setPassword(String pass) {
this.password = pass;
super.setPassword(pass);
}
//this method is required to allow c3p0 magically use reflection to get correct password for connection
public String getPassword() {
return password;
}
}
and later on
MariaDbDExtender mysqlDs = new MariaDbDExtender(connectionUrl);
mysqlDs.setPassword(password);
mysqlDs.setUser(username);
return wrapWithPool(mysqlDs);
And it magically starts to work. This is some driver specific issue, since oracle datasource does not have the getPassword method, but works. So some very specific implementation details of those 2 libraries just make it incompatible in my use case.

Related

Factory Method vs Constructor with ServletContext as Parameter

To test the health of all our applications we are including a Healthcheck servlet in each application. These healthchecks simply test the dependencies of each application. One of these dependency types are Sql server connections. To test the connections we have a method called HealthCheckRunner.Result run(). (Shown in the code below). The method will take a url, username, and password and attempt to connect to the server.
This method works fine but I have found that across all our apps I am still repeating a lot of code to retrieve the url, username, password, and driver from the context.xml. To save time and repetition I would like to refactor with either another constructor or a factory method, shown below in Options 1 and 2.
Neither method seems very appealing to me though. First the constructor is pretty messy and doesn't seem very user friendly. Second, the static method may be difficult to test. And lastly, they both take a ServletContext as a parameter.
Will unit testing the static method be difficult? For simplicity I'd rather stay away from PowerMock and only use Mockito. And also, will copies of ServletContext be created for every SqlHealthCheck I create? Or will they all use the same reference? And, since I'm only using a few values from the context would it be better to create another class and pass only the values I need? The solutions I have come up with are not great and I know there must be a better way.
public class SqlHealthCheck extends HealthCheck {
private String url;
private String username;
private String password;
private String driver;
// Option 1: Constructor with ServletContext as parameter.
public SqlHealthCheck (ServletContext context, String prefix) {
this.url = context.getInitParameter(prefix + ".db-url");
this.username = context.getInitParameter(prefix + ".db-user");
this.password = context.getInitParameter(prefix + ".db-passwd");
setType("sqlcheck");
setDescription("SQL database check: " + this.url);
this.decodePassword();
this.setDriver(context.getInitParameter(prefix + ".db-driver"));
}
// Option 2: Static factory method with ServletContext as parameter
public static HealthCheck createHealthCheck(ServletContext context, String prefix) {
String dbUrl = context.getInitParameter(prefix + ".db-url");
String username = context.getInitParameter(prefix + ".db-user");
String password = context.getInitParameter(prefix + ".db-passwd");
String sqlDriver = context.getInitParameter(prefix + ".db-driver");
SqlHealthCheck healthCheck = new SqlHealthCheck("SQL database check: " + dbUrl, dbUrl, username, password);
healthCheck.decodePassword();
healthCheck.setDriver(sqlDriver);
return healthCheck;
}
public HealthCheckRunner.Result run() {
Connection connection = null;
Statement statement = null;
try {
if (driver != null) { Class.forName(driver); }
connection = DriverManager.getConnection(this.url, this.username, this.password);
statement = connection.createStatement();
statement.executeQuery("SELECT 1");
return HealthCheckRunner.Result.Pass;
} catch (SQLException | ClassNotFoundException ex) {
setMessage(ex.getMessage());
return getFailureResult();
}
finally {
try {
if (statement != null) {statement.close();}
if (connection != null) {connection.close();}
} catch (SQLException ex) {
setMessage(ex.getMessage());
}
}
}
public void decodePassword() {
// Decode password
try {
if (password != null && !"".equals(password)) {
password = new String(Base64.decode(password.getBytes()));
}
} catch (Exception e) {
if (e.getMessage()!=null) {
this.setMessage(e.getMessage());}
}
}
}
I have found that across all our apps I am still repeating a lot of code to retrieve the url, username, password, and driver from the context.xml
4 lines of code is far, far, far from being a lot of code. But if you're actually copying and pasting this class in all your apps, then you simply shouldn't. Create a separate project containing reusable health checks like this one, producing a jar, and use this jar in each app that needs the health checks.
the constructor is pretty messy and doesn't seem very user friendly
Frankly, it's not that messy. But it could be less messy if you didn't repeat yourself, initialized private fields all the same way, and if you grouped comparable code together:
public SqlHealthCheck (ServletContext context, String prefix) {
this.url = getParam(context, prefix, "db-url");
this.username = getParam(context, prefix, "db-user");
this.password = getParam(context, prefix, "db-password");
this.driver = getParam(context, prefix, "db-driver");
this.decodePassword();
setType("sqlcheck");
setDescription("SQL database check: " + this.url);
}
Will unit testing the static method be difficult?
No. ServletContext is an interface. So you can create your own fake implementation or use a mocking framework to mock it. Then you can just call the constructor of the factory method, run the health check, and see if it returns the correct value.
will copies of ServletContext be created for every SqlHealthCheck I create?
Of course not. Java passes references to objects by value.
would it be better to create another class and pass only the values I need?
You could do that, but then the logic of getting the values from the servlet context will just be elsewhere, and you'll have to test that too, basically in the same way as you would test this class.

ArangoDB java driver on executing AQL sometimes return NULL and other times the correct result

I am unable to wrap my head around this peculiar issue.
I am using arangodb 3.0.10 and arangodb-java-driver 3.0.4.
I am executing a very simple AQL fetch query. (See code below) All my unit tests pass every time and problem never arises when debugging. The problem does not occur all the time (around half the time). It gets even stranger, the most frequent manifestation is NullPointerException at
return cursor.getUniqueResult();
but also got once a ConcurrentModificationException
Questions:
Do I have to manage the database connection? Like closing the driver
connection after each use.
Am i doing something completely wrong
with the ArangoDB query?
Any hint in the right direction is appreciated.
Error 1:
java.lang.NullPointerException
at org.xworx.sincapp.dao.UserDAO.get(UserDAO.java:41)
Error 2:
java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextNode(HashMap.java:1437)
at java.util.HashMap$EntryIterator.next(HashMap.java:1471)
at java.util.HashMap$EntryIterator.next(HashMap.java:1469)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:206)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:145)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:208)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:145)
at com.google.gson.Gson.toJson(Gson.java:593)
at com.google.gson.Gson.toJson(Gson.java:572)
at com.google.gson.Gson.toJson(Gson.java:527)
at com.google.gson.Gson.toJson(Gson.java:507)
at com.arangodb.entity.EntityFactory.toJsonString(EntityFactory.java:201)
at com.arangodb.entity.EntityFactory.toJsonString(EntityFactory.java:165)
at com.arangodb.impl.InternalCursorDriverImpl.getCursor(InternalCursorDriverImpl.java:94)
at com.arangodb.impl.InternalCursorDriverImpl.executeCursorEntityQuery(InternalCursorDriverImpl.java:79)
at com.arangodb.impl.InternalCursorDriverImpl.executeAqlQuery(InternalCursorDriverImpl.java:148)
at com.arangodb.ArangoDriver.executeAqlQuery(ArangoDriver.java:2158)
at org.xworx.sincapp.dao.UserDAO.get(UserDAO.java:41)
ArangoDBConnector
public abstract class ArangoDBConnector {
protected static ArangoDriver driver;
protected static ArangoConfigure configure;
public ArangoDBConnector() {
final ArangoConfigure configure = new ArangoConfigure();
configure.loadProperties(ARANGODB_PROPERTIES);
configure.init();
final ArangoDriver driver = new ArangoDriver(configure);
ArangoDBConnector.configure = configure;
ArangoDBConnector.driver = driver;
}
UserDAO
#Named
public class UserDAO extends ArangoDBConnector{
private Map<String, Object> bindVar = new HashMap();
public UserDAO() {}
public User get(#NotNull String objectId) {
bindVar.clear();
bindVar.put("uuid", objectId);
String fetchUserByObjectId = "FOR user IN User FILTER user.uuid == #uuid RETURN user";
CursorResult<User> cursor = null;
try {
cursor = driver.executeAqlQuery(fetchUserByObjectId, bindVar, driver.getDefaultAqlQueryOptions(), User.class);
} catch (ArangoException e) {
new ArangoDaoException(e.getErrorMessage());
}
return cursor.getUniqueResult();
}
As AntJavaDev said, you access bindVar more than once the same time. When one thread modify bindVar and another tried to build the AQL call at the same time by reading bindVar. This leads to the ConcurrentModificationException.
The NullPointerException results from an AQL call with no result. e.g. when you clear bindVar and directly after that, execute the AQL in another thread with no content in bindVar.
To your questions:
1. No, you do not have to close the driver connection after each call.
2. Beside the shared bindVar, everything looks correct.

UCP PoolDataSourceImpl with ConnectionInitializationCallback

I am attempting to configure a UCP PoolDataSourceImpl with a ConnectionInitializationCallback. Here's my configuration:
private static DataSource createDataSource(Properties properties) throws SQLException, UniversalConnectionPoolException {
UniversalConnectionPoolManager ucpm = UniversalConnectionPoolManagerImpl.getUniversalConnectionPoolManager();
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();
final String editionName = properties.getProperty("jdbc.editionName", "ora$base");
pds.registerConnectionInitializationCallback(new oracle.ucp.jdbc.ConnectionInitializationCallback() {
public void initialize(Connection connection) throws SQLException {
LOG.debug("Attempting to set edition to: {}", editionName);
try (Statement statement = connection.createStatement()) {
statement.executeUpdate("ALTER SESSION SET EDITION = " + editionName);
}
LOG.debug("Edition set to: {}", editionName);
}
});
pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
pds.setUser(properties.getProperty("jdbc.username"));
pds.setPassword(properties.getProperty("jdbc.password"));
pds.setURL(properties.getProperty("jdbc.url"));
pds.setConnectionPoolName("demo-pool");
pds.setInitialPoolSize(3);
pds.setMaxPoolSize(3);
pds.setValidateConnectionOnBorrow(true);
LOG.debug("Created DataSource Pool");
ucpm.createConnectionPool((UniversalConnectionPoolAdapter)pds);
ucpm.startConnectionPool("demo-pool");
return pds;
}
However the initialize method is never called. I'm using java 1.7.0_51 with the following Oracle jars:
ojdbc6.jar - v12.1.0.1.0
ucp.jar - v12.1.0.0.0
I have managed to make this work by removing the call to "registerConnectionInitializationCallback" and replacing it with a call to "registerConnectionLabelingCallback" but from my understanding this will exeute the ALTER SESSION each time a connection is requested from the pool rather then when it is actually created.
Any help with getting the ConnectionInitializationCallback to work would be much appreciated.
Kind Regards
The ConnectionInitializationCallback mechanism appears to be a part of the "Application Continuity" feature released with 12c. Application Continuity requires that you use one of the following DataSource implementations:
oracle.jdbc.replay.OracleDataSourceImpl
oracle.jdbc.replay.OracleConnectionPoolDataSourceImpl
I haven't tried it for myself, but I'm guessing if you use one of these DataSource implementations, your ConnectionInitializationCallback will work.
It would've been nice if this had been included as part of the standard UCP implementation, much like Connection Labeling.

Implementing Connection Pooling : Java

In one of the interviews that I faced,I was asked to implement connection pooling.
So approach was this:
Create a List or HashMap
Create predefined number of connections
Add them to the collection.
Now when the ConnectionImpl getConnection() method of ConnectionPoolingImpl class is invoked return a connection reference.
Now when someone returns the connection (releaseConnection(ConnectionImpl O)) how can I ensure that when the same application again tries to reuse the connection object, my implementation throws an exception?
The same connection object might have been returned to a new application and that should be able to use it.
My point of view would be to maintain a flag variable in another array kind of structure for each Connectionimpl object and set that variable to a valid value. When user returns the connection object I would make that some invalid value. For every operation in my ConnectionImpl, I will have to verify if the user had a valid flag.
What would you say to that approach?
I would not return the "real" connection object from the pool, but a wrapper which gives the pool control of connection life cycle, instead of the client.
Assume you have a really simple connection, which you can read int values from:
interface Connection {
int read(); // reads an int from the connection
void close(); // closes the connection
}
An implementation reading from a stream could look like this (ignoring exceptions, EOF handling, etc):
class StreamConnection implements Connection {
private final InputStream input;
int read(){ return input.read(); }
void close(){ input.close(); }
}
Furthermore, let's assume you have a pool for StreamConnections that looks like this (again, ignoring exceptions, concurrency, etc):
class StreamConnectionPool {
List<StreamConnection> freeConnections = openSomeConnectionsSomehow();
StreamConnection borrowConnection(){
if (freeConnections.isEmpty()) throw new IllegalStateException("No free connections");
return freeConnections.remove(0);
}
void returnConnection(StreamConnection conn){
freeConnections.add(conn);
}
}
The basic idea here is OK, but we can't be sure the connections are returned, and we can't be sure they aren't closed and then returned, or that you don't return a connection which came from another source altogether.
The solution is (of course) another layer of indirection: Make a pool which returns a wrapper Connection which, instead of closing the underlying connection when close() is called, returns it to the pool:
class ConnectionPool {
private final StreamConnectionPool streamPool = ...;
Connection getConnection() {
final StreamConnection realConnection = streamPool.borrowConnection();
return new Connection(){
private boolean closed = false;
int read () {
if (closed) throw new IllegalStateException("Connection closed");
return realConnection.read();
}
void close() {
if (!closed) {
closed = true;
streamPool.returnConnection(realConnection);
}
}
protected void finalize() throws Throwable {
try {
close();
} finally {
super.finalize();
}
}
};
}
}
This ConnectionPool would be the only thing the client code ever sees. Assuming it is the sole owner of the StreamConnectionPool, this approach has several advantages:
Reduced complexity and minimal impact on client code - the only difference between opening connections yourself and using the pool is that you use a factory to get hold of Connections (which you might already do, if you're using dependency injection). Most importantly, you always clean up your resources in the same way, i.e., by calling close(). Just like you don't care what read does, as long as it gives you the data you need, you don't care what close() does, as long as it releases the resources you've claimed. You shouldn't have to think whether this connection is from a pool or not.
Protection against malicious/incorrect usage - clients can only return resources they've retrieved from the pool; they can't close the underlying connections; they can't use connections they've already returned... etc.
"Guaranteed" returning of resources - thanks to our finalize implementation, even if all references to a borrowed Connection is lost, it is still returned to the pool (or does at least stand a chance to be returned). The connection will of course be held longer than necessary this way - possibly indefinitely, since finalization isn't guaranteed to ever run - but it's a small improvement.
I'd just tell them I'd use the JdbcConnectionPool class (here) that comes with H2 (you can probably copy it out). Screw trying to implement one :) It could be a trick question.
ConnectionPool implemenation
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/** A Connection Pool with 5 Available Connections **/
class ConnectionPool {
private List<Connection>availableConnections =
new ArrayList<Connection>();
private List<Connection>usedConnections = new ArrayList<Connection>();
private final int MAX_CONNECTIONS = 5;
private String URL;
private String USERID;
private String PASSWORD;
/** Initialize all 5 Connections and put them in the Pool **/
public ConnectionPool(String Url, String UserId, String password)
throws SQLException {
this.URL = Url;
this.USERID = UserId;
this.PASSWORD = password;
for (int count = 0; count <MAX_CONNECTIONS; count++) {
availableConnections.add(this.createConnection());
}
}
/** Private function,
used by the Pool to create new connection internally **/
private Connection createConnection() throws SQLException {
return DriverManager
.getConnection(this.URL, this.USERID, this.PASSWORD);
}
/** Public function, used by us to get connection from Pool **/
public Connection getConnection() {
if (availableConnections.size() == 0) {
System.out.println("All connections are Used !!");
return null;
} else {
Connection con =
availableConnections.remove(
availableConnections.size() - 1);
usedConnections.add(con);
return con;
}
}
/** Public function, to return connection back to the Pool **/
public boolean releaseConnection(Connection con) {
if (null != con) {
usedConnections.remove(con);
availableConnections.add(con);
return true;
}
return false;
}
/** Utility function to check the number of Available Connections **/
public int getFreeConnectionCount() {
return availableConnections.size();
}
}
OK, so if I understand correctly, your question is basically "how can we can ensure that a thread doesn't return a connection to the pool and then carry on using it?". Provided you don't pass back the "raw" Connection object to the caller, then the answer is essentially "you can put some control in somewhere if you want".
The actual check could involve marking each connection with which Thread "owns" it at a given moment, then making sure this is always Thread.currentThread() during any call to use the connection.
It doesn't matter terribly much what object you do pass back to user of the connection to represent the connection: it could be your own wrapper implementation of Connection, or just some other wrapper object with your methods for executing queries. Whichever you use, you just need to make the abovementioned check before executing any query. Bear in mind that for security you generally shouldn't be allowing "raw" arbitrary SQL to be executed, but that all queries should be based on a well-defined PreparedStatement. So there's no particular compulsion to return an actual implementation of Connection, other than this might in some circumstances help you migrate existing code (and/or if you've decided you really do want to permit execution of arbitrary SQL).
In many circumstances, you could also not bother making this check. You're passing a caller a means to access your database, so it's a bit like trying to stop pilots from crashing planes into buildings by scanning them for explosives at airports: they all ready have a means of messing up your system whether or not you make the additional check.

jdbc mysql connectivity

I want to make a web application by using jsp servlet and bean am using Netbeans IDE.
I want to know where I should place the database connectivity code so that i can use my database code with every servlet, means I do not want to write the connectivity code in everypage where I need to use the database.
Please help me to find and how should I move?
Just put all the JDBC stuff in its own class and import/call/use it in the servlet.
E.g.
public class UserDAO {
public User find(String username, String password) {
User user = new User();
// Put your JDBC code here to fill the user (if found).
return user;
}
}
With
import com.example.dao.UserDAO;
import com.example.model.User;
public class LoginServlet extends HttpServlet {
private UserDAO userDAO;
public void init() throws ServletException {
userDAO = new UserDAO(); // Or obtain by factory.
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userDAO.find(username, password);
if (user != null) {
// Login.
} else {
// Error: unknown user.
}
}
}
Here's one idea how to do it:
Make a class named DBConnection with a static factory method getNewDBConnection
During application startup, verify that your db connection is valid, and using ServletContextListener, set up the DBConnection class so the mentioned method will always return a new connection
Use throughout your code DBConnection.getNewDBConnection().
I'll leave the boilerplate and exception handling up to you. There are more elegant ways to do this, using JPA for example, but this is outside of this answer's scope.
Beware of above idea. I have only written it; but haven't tried it and proven it correct.
Have you tried using the include mechanisms:
<%# include file="filename" %>
Detail here http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/JSPIntro8.html
If you make connection from the servlets, you could create a BaseServlet class that extends HttpServlet, than your actual server have to extends BaseServlet rather then HttpServlet.
Now you can write the connectivity code just in the BaseServlet and just use it in your pseudo-servlets (extending BaseServlet).

Categories

Resources