Skip to content

Commit

Permalink
implemented a sync version of the jdbc component, fixed some minor er…
Browse files Browse the repository at this point in the history
…ror reporting issues in the black/white list policies
  • Loading branch information
EricWittmann committed Nov 10, 2015
1 parent 4c7d436 commit 615ed0d
Show file tree
Hide file tree
Showing 34 changed files with 1,035 additions and 145 deletions.
Expand Up @@ -169,3 +169,8 @@ apiman-gateway.components.ICacheStoreComponent.client.initialize=true
apiman-gateway.components.ICacheStoreComponent.client.username=${apiman.es.username}
apiman-gateway.components.ICacheStoreComponent.client.password=${apiman.es.password}
apiman-gateway.components.ICacheStoreComponent.client.timeout=${apiman.es.timeout}

# ---------------------------------------------------------------------
# JDBC Component Settings
# ---------------------------------------------------------------------
apiman-gateway.components.IJdbcComponent=io.apiman.gateway.engine.impl.DefaultJdbcComponent
21 changes: 21 additions & 0 deletions gateway/engine/core/pom.xml
Expand Up @@ -34,6 +34,27 @@
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>

<!-- Test Only Dependencies -->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
Expand Up @@ -15,14 +15,16 @@
*/
package io.apiman.gateway.engine.components.jdbc;

import io.apiman.gateway.engine.IComponent;

import javax.sql.DataSource;

/**
* A simple async JDBC component interface
*
* @author Marc Savy {@literal <msavy@redhat.com>}
*/
public interface IJdbcComponent {
public interface IJdbcComponent extends IComponent {

/**
* Create a shared data source.
Expand Down
Expand Up @@ -29,50 +29,56 @@
*/
public interface IJdbcConnection extends AutoCloseable {

// TODO: there are no begintx/endtx statements seemingly?
/**
* Run a query, get the results back to iterate through.
*
* @param query the query
* @param result the result
* @param handler the result handler
* @param sql the sql query (with ?'s for params)
* @param params the parameter values
*/
void query(String query, IAsyncResultHandler<IJdbcResultSet> result);
void query(IAsyncResultHandler<IJdbcResultSet> handler, String sql, Object ... params);

/**
* Run a query, but don't need a result-set. For instance, DROP, CREATE.
*
* @param query the query
* @param result the result set
* @param handler the handler
* @param sql the sql statement (with ?'s for params)
* @param params the parameter values
*/
void execute(String query, IAsyncResultHandler<Void> result);
void execute(IAsyncResultHandler<Void> handler, String sql, Object ... params);

/**
* Set auto-commit status (probably best to explicitly set this?). TODO Should we have a default?
*
* @param autoCommit the auto-commit status
* @param result the result
*/
void setAutoCommit(boolean autoCommit, IAsyncResultHandler<Void> result);
void setAutoCommit(boolean autoCommit, IAsyncResultHandler<Void> handler);

/**
* Commit transaction
*
* @param result the result
* @param handler the handler
*/
void commit(IAsyncResultHandler<Void> result);
void commit(IAsyncResultHandler<Void> handler);

/**
* Abort transaction
*
* @param result the result
* @param handler the handler
*/
void rollback(IAsyncResultHandler<Void> result);
void rollback(IAsyncResultHandler<Void> handler);

/**
* In addition to AutoCloseable we can have a version that provides a result.
* In addition to AutoCloseable we can have a version that provides a handler.
* Closes any associated connection(s).
*
* @param result the result
* @param handler the handler
*/
void close(IAsyncResultHandler<Void> handler);

/**
* Returns true iff the connection has been closed.
*/
void close(IAsyncResultHandler<Void> result);
boolean isClosed() throws Exception;
}
Expand Up @@ -39,7 +39,7 @@ public interface IJdbcResultSet {
*
* @return the number of columns
*/
int getColumnSize();
int getNumColumns();

/**
* Indicates which row presently pointed at
Expand All @@ -48,13 +48,6 @@ public interface IJdbcResultSet {
*/
int getRow();

/**
* Get number of rows in set
*
* @return the number of rows
*/
int getRowSize();

/**
* Point at next row in result set
*/
Expand All @@ -67,20 +60,6 @@ public interface IJdbcResultSet {
*/
boolean hasNext();

/**
* Move to the first row of the result set
*
* @return whether any row exists
*/
boolean first();

/**
* Move to final row of the result set
*
* @return whether any rows exist
*/
boolean last();

/**
* Get result as string
*
Expand Down Expand Up @@ -161,6 +140,8 @@ public interface IJdbcResultSet {
* @throws IndexOutOfBoundsException when index is invalid
*/
DateTime getDateTime(int index);

void close();

// These might be problematic, i.e. not implemented in Vert.x etc
//Object getObject(int index);
Expand Down
Expand Up @@ -22,6 +22,7 @@
import io.apiman.gateway.engine.components.IPolicyFailureFactoryComponent;
import io.apiman.gateway.engine.components.IRateLimiterComponent;
import io.apiman.gateway.engine.components.ISharedStateComponent;
import io.apiman.gateway.engine.components.jdbc.IJdbcComponent;

import java.util.Collection;
import java.util.HashMap;
Expand Down Expand Up @@ -81,6 +82,10 @@ protected void registerCacheStoreComponent() {
addComponent(ICacheStoreComponent.class, new InMemoryCacheStoreComponent());
}

protected void registerJdbcComponent() {
addComponent(IJdbcComponent.class, new DefaultJdbcComponent());
}

/**
* Adds a component to the registry.
* @param componentType
Expand Down
@@ -0,0 +1,160 @@
/*
* Copyright 2015 JBoss Inc
*
* 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 io.apiman.gateway.engine.impl;

import io.apiman.gateway.engine.async.AsyncResultImpl;
import io.apiman.gateway.engine.async.IAsyncResultHandler;
import io.apiman.gateway.engine.components.jdbc.IJdbcClient;
import io.apiman.gateway.engine.components.jdbc.IJdbcComponent;
import io.apiman.gateway.engine.components.jdbc.IJdbcConnection;
import io.apiman.gateway.engine.components.jdbc.JdbcOptionsBean;

import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

/**
* A default implementation of the JDBC Component {@link IJdbcComponent}.
*
* @author eric.wittmann@redhat.com
*/
public class DefaultJdbcComponent implements IJdbcComponent {

private Map<String, IJdbcClient> clients = new HashMap<>();

/**
* Constructor.
*/
public DefaultJdbcComponent() {
}

/**
* @see io.apiman.gateway.engine.components.jdbc.IJdbcComponent#createShared(java.lang.String, io.apiman.gateway.engine.components.jdbc.JdbcOptionsBean)
*/
@Override
public synchronized IJdbcClient createShared(String dsName, JdbcOptionsBean config) {
if (clients.containsKey(dsName)) {
return clients.get(dsName);
} else {
DataSource ds = datasourceFromConfig(config);
DefaultJdbcClient client = new DefaultJdbcClient(ds);
clients.put(dsName, client);
return client;
}
}

/**
* @see io.apiman.gateway.engine.components.jdbc.IJdbcComponent#createStandalone(io.apiman.gateway.engine.components.jdbc.JdbcOptionsBean)
*/
@Override
public IJdbcClient createStandalone(JdbcOptionsBean config) {
DataSource ds = datasourceFromConfig(config);
return new DefaultJdbcClient(ds);
}

/**
* @see io.apiman.gateway.engine.components.jdbc.IJdbcComponent#create(javax.sql.DataSource)
*/
@Override
public IJdbcClient create(DataSource ds) {
return new DefaultJdbcClient(ds);
}

/**
* Creates a datasource from the given jdbc config info.
* @param config
*/
@SuppressWarnings("nls")
protected DataSource datasourceFromConfig(JdbcOptionsBean config) {
Properties props = new Properties();
props.putAll(config.getDsProperties());
setConfigProperty(props, "jdbcUrl", config.getJdbcUrl());
setConfigProperty(props, "username", config.getUsername());
setConfigProperty(props, "password", config.getPassword());

setConfigProperty(props, "connectionTimeout", config.getConnectionTimeout());
setConfigProperty(props, "idleTimeout", config.getIdleTimeout());
setConfigProperty(props, "maxPoolSize", config.getMaximumPoolSize());
setConfigProperty(props, "maxLifetime", config.getMaxLifetime());
setConfigProperty(props, "minIdle", config.getMinimumIdle());
setConfigProperty(props, "poolName", config.getPoolName());
setConfigProperty(props, "autoCommit", config.isAutoCommit());

HikariConfig hikariConfig = new HikariConfig(props);
return new HikariDataSource(hikariConfig);
}

/**
* Sets a configuration property, but only if it's not null.
* @param props
* @param propName
* @param value
*/
private void setConfigProperty(Properties props, String propName, Object value) {
if (value != null) {
props.setProperty(propName, String.valueOf(value));
}
}

/**
* JDBC client impl.
* @author eric.wittmann@redhat.com
*/
private static class DefaultJdbcClient implements IJdbcClient {

protected DataSource ds;

/**
* Constructor.
* @param ds
*/
public DefaultJdbcClient(DataSource ds) {
this.ds = ds;
}

/**
* @see io.apiman.gateway.engine.components.jdbc.IJdbcClient#connect(io.apiman.gateway.engine.async.IAsyncResultHandler)
*/
@Override
public void connect(IAsyncResultHandler<IJdbcConnection> handler) {
IJdbcConnection jdbcConnection = null;
try {
Connection connection = ds.getConnection();
jdbcConnection = new DefaultJdbcConnection(connection);
handler.handle(AsyncResultImpl.create(jdbcConnection));
} catch (Exception e) {
handler.handle(AsyncResultImpl.create(e));
} finally {
try {
if (!jdbcConnection.isClosed()) {
jdbcConnection.close();
}
} catch (Exception e) {
// eat it
}
}
}

}

}

0 comments on commit 615ed0d

Please sign in to comment.