com.bloidonia.vertx.mods.JdbcProcessor Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mod-jdbc-persistor Show documentation
Show all versions of mod-jdbc-persistor Show documentation
JDBC Persistor Module for Vert.x
The newest version!
/*
* Copyright 2012-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bloidonia.vertx.mods ;
import com.mchange.v2.c3p0.* ;
import java.sql.Connection ;
import java.sql.Driver ;
import java.sql.DriverManager ;
import java.sql.PreparedStatement ;
import java.sql.ResultSet ;
import java.sql.SQLException ;
import java.sql.Statement ;
import java.util.ArrayList ;
import java.util.concurrent.ConcurrentHashMap ;
import java.util.Iterator ;
import java.util.List ;
import java.util.Map ;
import java.util.UUID ;
import org.apache.commons.dbutils.QueryRunner ;
import org.apache.commons.dbutils.ResultSetHandler ;
import org.apache.commons.dbutils.handlers.MapListHandler ;
import org.apache.commons.dbutils.handlers.LimitedMapListHandler ;
import org.vertx.java.busmods.BusModBase ;
import org.vertx.java.core.Handler ;
import org.vertx.java.core.eventbus.Message ;
import org.vertx.java.core.json.JsonArray ;
import org.vertx.java.core.json.JsonObject ;
public class JdbcProcessor extends BusModBase implements Handler> {
private String address ;
private String uid ;
private String driver ;
private String url ;
private String username ;
private String password ;
private String pmdKnownBroken ;
private boolean ignoreAutoGeneratedKeys;
private StatementFiller statementFiller ;
private int minpool ;
private int maxpool ;
private int acquire ;
private int batchTimeout ;
private int transTimeout ;
private volatile static ConcurrentHashMap poolMap = new ConcurrentHashMap( 8, 0.9f, 1 ) ;
private static boolean setupPool( String address,
String driver,
String url,
String username,
String password,
int minPool,
int maxPool,
int acquire,
String automaticTestTable,
int idleConnectionTestPeriod,
String preferredTestQuery,
boolean testConnectionOnCheckin,
boolean testConnectionOnCheckout,
int acquireRetryAttempts,
int acquireRetryDelay ) throws Exception {
if( poolMap.get( address ) == null ) {
synchronized( poolMap ) {
if( poolMap.get( address ) == null ) {
DriverManager.registerDriver( (Driver)Class.forName( driver ).newInstance() ) ;
ComboPooledDataSource pool = new ComboPooledDataSource() ;
pool.setDriverClass( driver ) ;
pool.setJdbcUrl( url ) ;
pool.setUser( username ) ;
pool.setPassword( password ) ;
pool.setMinPoolSize( minPool ) ;
pool.setMaxPoolSize( maxPool ) ;
pool.setAcquireIncrement( acquire ) ;
pool.setAutomaticTestTable( automaticTestTable ) ;
pool.setIdleConnectionTestPeriod( idleConnectionTestPeriod ) ;
pool.setPreferredTestQuery( preferredTestQuery ) ;
pool.setTestConnectionOnCheckin( testConnectionOnCheckin ) ;
pool.setTestConnectionOnCheckout( testConnectionOnCheckout ) ;
pool.setAcquireRetryAttempts( acquireRetryAttempts ) ;
pool.setAcquireRetryDelay( acquireRetryDelay ) ;
if( poolMap.putIfAbsent( address, pool ) != null ) {
pool.close() ;
}
}
}
}
return false ;
}
private static void closePool( String address, String url ) throws SQLException {
if( poolMap.get( address ) != null ) {
synchronized( poolMap ) {
ComboPooledDataSource pool = poolMap.get( address ) ;
if( pool != null ) {
pool = poolMap.remove( address ) ;
if( pool != null ) {
pool.close() ;
DriverManager.deregisterDriver( DriverManager.getDriver( url ) ) ;
}
}
}
}
}
public void start() {
super.start() ;
address = getOptionalStringConfig( "address", "com.bloidonia.jdbcpersistor" ) ;
uid = String.format( "%s-%s", address, UUID.randomUUID().toString() ) ;
driver = getOptionalStringConfig( "driver", "org.hsqldb.jdbcDriver" ) ;
url = getOptionalStringConfig( "url", "jdbc:hsqldb:mem:test?shutdown=true" ) ;
username = getOptionalStringConfig( "username", "" ) ;
password = getOptionalStringConfig( "password", "" ) ;
String automaticTestTable = getOptionalStringConfig( "c3p0.automaticTestTable", null ) ;
int idleConnectionTestPeriod = getOptionalIntConfig( "c3p0.idleConnectionTestPeriod", 0 ) ;
String preferredTestQuery = getOptionalStringConfig( "c3p0.preferredTestQuery", null ) ;
boolean testConnectionOnCheckin = getOptionalBooleanConfig( "c3p0.testConnectionOnCheckin", false ) ;
boolean testConnectionOnCheckout = getOptionalBooleanConfig( "c3p0.testConnectionOnCheckout", false ) ;
int acquireRetryAttempts = getOptionalIntConfig( "c3p0.acquireRetryAttempts", 30 ) ;
int acquireRetryDelay = getOptionalIntConfig( "c3p0.acquireRetryDelay", 1000 ) ;
minpool = getOptionalIntConfig( "minpool", 5 ) ;
maxpool = getOptionalIntConfig( "maxpool", 20 ) ;
acquire = getOptionalIntConfig( "acquire", 5 ) ;
ignoreAutoGeneratedKeys = getOptionalBooleanConfig("ignoreAutoGeneratedKeys", false);
pmdKnownBroken = getOptionalStringConfig( "pmdKnownBroken", "no" ) ;
switch( pmdKnownBroken ) {
case "yes" :
statementFiller = new BrokenPMDStatementFiller() ;
break ;
case "maybe" :
statementFiller = new MaybeBrokenPMDStatementFiller() ;
break ;
default :
statementFiller = new NonBrokenPMDStatementFiller() ;
}
batchTimeout = getOptionalIntConfig( "batchtimeout", 5000 ) ;
transTimeout = getOptionalIntConfig( "transactiontimeout", 10000 ) ;
try {
if( setupPool( address, driver, url, username, password, minpool, maxpool, acquire,
automaticTestTable, idleConnectionTestPeriod, preferredTestQuery,
testConnectionOnCheckin, testConnectionOnCheckout, acquireRetryAttempts,
acquireRetryDelay ) ) {
logger.debug( "Pool created" ) ;
}
else {
logger.debug( "Pool already exists" ) ;
}
eb.registerHandler( address, this ) ;
eb.send( String.format( "%s.ready", address ), new JsonObject() {{
putString( "status", "ok" ) ;
}} ) ;
}
catch( Exception ex ) {
logger.fatal( "Error when starting JdbcBusMod", ex ) ;
}
}
public void stop() {
eb.send( address + ".unregister", new JsonObject() {{
putString( "processor", uid ) ;
}} ) ;
eb.unregisterHandler( uid, this ) ;
try {
closePool( address, url ) ;
}
catch( SQLException ex ) {
logger.error( String.format( "Error closing pool: %s", ex.getMessage() ), ex ) ;
}
}
public void handle( final Message message ) {
String action = message.body().getString( "action" ) ;
if ( logger.isDebugEnabled() ) {
logger.debug( "** HANDLE ** " + this.toString() + " (main handler) RECEIVED CALL " + action ) ;
}
if( action == null ) {
sendError( message, "action must be specified" ) ;
}
switch( action ) {
case "select" :
doSelect( message ) ;
break ;
case "execute" :
doExecute( message ) ;
break ;
case "update" :
doUpdate( message, false ) ;
break ;
case "insert" :
doUpdate( message, true ) ;
break ;
case "transaction" :
doTransaction( message ) ;
break ;
case "pool-status" :
final ComboPooledDataSource pool = poolMap.get( address ) ;
if( pool != null ) {
try {
sendOK( message, new JsonObject() {{
putNumber( "connections", pool.getNumConnections() ) ;
putNumber( "idle", pool.getNumIdleConnections() ) ;
putNumber( "busy", pool.getNumBusyConnections() ) ;
putNumber( "orphans", pool.getNumUnclosedOrphanedConnections() ) ;
}} ) ;
}
catch( SQLException ex ) {
sendError( message, "Cannot get pool info", ex ) ;
}
}
else {
sendError( message, "No pool found!" ) ;
}
break ;
default:
sendError( message, "Invalid action : " + action ) ;
}
}
/****************************************************************************
**
** Select handling
**
****************************************************************************/
private void doSelect( Message message ) {
Connection connection = null ;
try {
connection = poolMap.get( address ).getConnection() ;
doSelect( message, connection, null ) ;
}
catch( Exception ex ) {
SilentCloser.close( connection ) ;
sendError( message, String.format( "Caught error with SELECT: %s", ex.getMessage() ), ex ) ;
}
}
private void doSelect( Message message,
Connection connection,
TransactionalHandler transaction ) throws SQLException {
new BatchHandler( connection, message, transaction ) {
public JsonObject process() throws SQLException {
JsonObject reply = new JsonObject() ;
ArrayList