From ec02d42b2eaa8b4807d4e6c0dcd11297305bb27c Mon Sep 17 00:00:00 2001 From: "Matteo Franci a.k.a. Fugerit" Date: Fri, 8 Sep 2023 17:39:28 +0200 Subject: [PATCH 1/2] dao connect test coverage --- fj-core/pom.xml | 7 ++ .../connect/ConnectionFactoryCloseable.java | 5 ++ .../db/connect/ConnectionFactoryImpl.java | 21 +++++ .../db/connect/SingleConnectionFactory.java | 7 +- .../java/core/db/dao/DAOException.java | 9 ++ .../db/connect/TestConnectionFactory.java | 89 +++++++++++++++++++ .../java/core/db/dao/TestDAOException.java | 16 ++++ .../core/db/connct-properties-mem.xml | 25 ++++++ fj-core/src/test/resources/jndi.properties | 5 ++ .../test/resources/jndi/datasource.properties | 5 ++ 10 files changed, 183 insertions(+), 6 deletions(-) create mode 100644 fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryCloseable.java create mode 100644 fj-core/src/test/java/test/org/fugerit/java/core/db/connect/TestConnectionFactory.java create mode 100644 fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAOException.java create mode 100644 fj-core/src/test/resources/core/db/connct-properties-mem.xml create mode 100644 fj-core/src/test/resources/jndi.properties create mode 100644 fj-core/src/test/resources/jndi/datasource.properties diff --git a/fj-core/pom.xml b/fj-core/pom.xml index f907bd1f..3bb6880c 100644 --- a/fj-core/pom.xml +++ b/fj-core/pom.xml @@ -78,6 +78,13 @@ + + com.github.h-thurow + simple-jndi + 0.23.0 + test + + diff --git a/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryCloseable.java b/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryCloseable.java new file mode 100644 index 00000000..4b6ab17f --- /dev/null +++ b/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryCloseable.java @@ -0,0 +1,5 @@ +package org.fugerit.java.core.db.connect; + +public interface ConnectionFactoryCloseable extends ConnectionFactory, AutoCloseable { + +} diff --git a/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryImpl.java b/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryImpl.java index e8dae594..0e124569 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryImpl.java +++ b/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryImpl.java @@ -152,6 +152,27 @@ public DataBaseInfo getDataBaseInfo() throws DAOException { */ public static final String PROP_CF_EXT_POOLED_MC = "db-ext-pooled-mc"; + public static ConnectionFactoryCloseable wrap( ConnectionFactory cf ) { + return new ConnectionFactoryCloseable() { + @Override + public void close() throws Exception { + this.release(); + } + @Override + public void release() throws DAOException { + cf.release(); + } + @Override + public DataBaseInfo getDataBaseInfo() throws DAOException { + return cf.getDataBaseInfo(); + } + @Override + public Connection getConnection() throws DAOException { + return cf.getConnection(); + } + }; + } + /** * Parse a configuration Element looking for ConnectionFactory configuration * diff --git a/fj-core/src/main/java/org/fugerit/java/core/db/connect/SingleConnectionFactory.java b/fj-core/src/main/java/org/fugerit/java/core/db/connect/SingleConnectionFactory.java index a10d6336..494d0fc2 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/db/connect/SingleConnectionFactory.java +++ b/fj-core/src/main/java/org/fugerit/java/core/db/connect/SingleConnectionFactory.java @@ -1,7 +1,6 @@ package org.fugerit.java.core.db.connect; import java.sql.Connection; -import java.sql.SQLException; import org.fugerit.java.core.db.dao.DAOException; import org.fugerit.java.core.db.metadata.DataBaseInfo; @@ -24,11 +23,7 @@ public DataBaseInfo getDataBaseInfo() throws DAOException { @Override public void release() throws DAOException { - try { - this.getConnection().close(); - } catch (SQLException e) { - throw new DAOException( "Error closing connection "+this.conn, e ); - } + DAOException.apply( () -> this.getConnection().close() ); } @Override diff --git a/fj-core/src/main/java/org/fugerit/java/core/db/dao/DAOException.java b/fj-core/src/main/java/org/fugerit/java/core/db/dao/DAOException.java index e2f18a63..2b350676 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/db/dao/DAOException.java +++ b/fj-core/src/main/java/org/fugerit/java/core/db/dao/DAOException.java @@ -20,6 +20,7 @@ */ package org.fugerit.java.core.db.dao; +import org.fugerit.java.core.function.UnsafeVoid; import org.fugerit.java.core.lang.ex.ExConverUtils; /* @@ -69,4 +70,12 @@ public static DAOException convertEx( Exception e ) { return convertEx( ExConverUtils.DEFAULT_CAUSE_MESSAGE, e ); } + public static void apply( UnsafeVoid fun ) throws DAOException { + try { + fun.apply(); + } catch (Exception e) { + throw new DAOException( e ); + } + } + } diff --git a/fj-core/src/test/java/test/org/fugerit/java/core/db/connect/TestConnectionFactory.java b/fj-core/src/test/java/test/org/fugerit/java/core/db/connect/TestConnectionFactory.java new file mode 100644 index 00000000..87e7f8ae --- /dev/null +++ b/fj-core/src/test/java/test/org/fugerit/java/core/db/connect/TestConnectionFactory.java @@ -0,0 +1,89 @@ +package test.org.fugerit.java.core.db.connect; + +import java.io.InputStream; +import java.sql.Connection; + +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; + +import org.fugerit.java.core.db.connect.CfConfig; +import org.fugerit.java.core.db.connect.ConnectionFacadeWrapper; +import org.fugerit.java.core.db.connect.ConnectionFactory; +import org.fugerit.java.core.db.connect.ConnectionFactoryCloseable; +import org.fugerit.java.core.db.connect.ConnectionFactoryImpl; +import org.fugerit.java.core.db.connect.SingleConnectionFactory; +import org.fugerit.java.core.lang.helpers.ClassHelper; +import org.fugerit.java.core.util.PropsIO; +import org.fugerit.java.core.xml.dom.DOMIO; +import org.junit.Assert; +import org.junit.Test; +import org.w3c.dom.Document; + +import lombok.extern.slf4j.Slf4j; +import test.org.fugerit.java.BasicTest; +import test.org.fugerit.java.core.db.BasicDBHelper; + +@Slf4j +public class TestConnectionFactory extends BasicTest { + + private static final String JNDI_DS_NAME = "java:/comp/env/datasource/ds"; + + private boolean worker( ConnectionFactory wrapped ) throws Exception { + boolean ok = false; + try ( ConnectionFactoryCloseable cf = ConnectionFactoryImpl.wrap( wrapped ); + Connection conn = cf.getConnection() ) { + log.info( "db info : {}", cf.getDataBaseInfo() ); + log.info( "driver info : {}", ConnectionFactoryImpl.getDriverInfo( cf ) ); + } + ok = (wrapped != null); + return ok; + } + + @Test + public void testCFProps() throws Exception { + ConnectionFactory wrapped = ConnectionFactoryImpl.newInstance( PropsIO.loadFromClassLoaderSafe( BasicDBHelper.DEFAULT_DB_CONN_PATH ) ); + boolean ok = this.worker(wrapped); + Assert.assertTrue(ok); + } + + + @Test + public void testCFXml() throws Exception { + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( "core/db/connct-properties-mem.xml" ) ) { + Document doc = DOMIO.loadDOMDoc( is ); + CfConfig cfConfig = ConnectionFactoryImpl.parseCfConfig( doc.getDocumentElement() ); + boolean ok = this.worker( cfConfig.getCfMap().get( "mem-db" ) ); + Assert.assertTrue(ok); + ok = this.worker( cfConfig.getCfMap().get( "mem-db-pooled" ) ); + Assert.assertTrue(ok); + } + } + + private DataSource createDS() throws NamingException { + InitialContext initialContext = new InitialContext(); + return (DataSource)initialContext.lookup( JNDI_DS_NAME ); + } + + @Test + public void testCFDS() throws Exception { + boolean ok = this.worker( new ConnectionFacadeWrapper( ConnectionFactoryImpl.newInstance( this.createDS() ) ) ); + Assert.assertTrue(ok); + } + + @Test + public void testCFSingle() throws Exception { + DataSource ds = this.createDS(); + try ( Connection conn = ds.getConnection() ) { + boolean ok = this.worker( new SingleConnectionFactory(conn) ); + Assert.assertTrue(ok); + } + } + + @Test + public void testCFJndi() throws Exception { + boolean ok = this.worker( ConnectionFactoryImpl.newInstance( JNDI_DS_NAME ) ); + Assert.assertTrue(ok); + } + +} diff --git a/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAOException.java b/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAOException.java new file mode 100644 index 00000000..be97fe7b --- /dev/null +++ b/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAOException.java @@ -0,0 +1,16 @@ +package test.org.fugerit.java.core.db.dao; + +import java.sql.SQLException; + +import org.fugerit.java.core.db.dao.DAOException; +import org.junit.Assert; +import org.junit.Test; + +public class TestDAOException { + + @Test + public void testApply() { + Assert.assertThrows( DAOException.class ,() -> DAOException.apply( () -> { throw new SQLException( "junit test scenario" ); } ) ); + } + +} diff --git a/fj-core/src/test/resources/core/db/connct-properties-mem.xml b/fj-core/src/test/resources/core/db/connct-properties-mem.xml new file mode 100644 index 00000000..0d69758d --- /dev/null +++ b/fj-core/src/test/resources/core/db/connct-properties-mem.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + diff --git a/fj-core/src/test/resources/jndi.properties b/fj-core/src/test/resources/jndi.properties new file mode 100644 index 00000000..dd665679 --- /dev/null +++ b/fj-core/src/test/resources/jndi.properties @@ -0,0 +1,5 @@ +java.naming.factory.initial=org.osjava.sj.SimpleContextFactory +org.osjava.sj.jndi.shared=true +jndi.syntax.separator=/ +org.osjava.sj.space=java:/comp/env +org.osjava.sj.root=src/test/resources/jndi \ No newline at end of file diff --git a/fj-core/src/test/resources/jndi/datasource.properties b/fj-core/src/test/resources/jndi/datasource.properties new file mode 100644 index 00000000..a0c31bb6 --- /dev/null +++ b/fj-core/src/test/resources/jndi/datasource.properties @@ -0,0 +1,5 @@ +ds.type=javax.sql.DataSource +ds.driver=org.hsqldb.jdbcDriver +ds.url=jdbc:hsqldb:mem:base_db_jndi +ds.user=test-db +ds.password=test-db \ No newline at end of file From 6254c26eb2fba3961ce4af5ffd4cdfde889e9198 Mon Sep 17 00:00:00 2001 From: "Matteo Franci a.k.a. Fugerit" Date: Fri, 8 Sep 2023 21:04:17 +0200 Subject: [PATCH 2/2] ConnectionFactory coverage --- .../core/db/connect/ConnectionFacade.java | 4 +- .../db/connect/ConnectionFactoryImpl.java | 170 ++++-------------- .../db/connect/DbcpConnectionFactory.java | 16 +- .../java/core/db/dao/DAOException.java | 13 +- .../db/connect/TestConnectionFactory.java | 95 +++++++++- .../java/core/db/dao/TestDAOException.java | 40 +++++ .../core/db/dao/TestDAORuntimeException.java | 46 +++++ .../fugerit/java/core/db/dao/rse/TestRSE.java | 30 ++++ .../resources/core/db/base-db-conn.properties | 9 + .../core/db/connct-properties-mem-fail1.xml | 11 ++ .../core/db/connct-properties-mem-fail2.xml | 19 ++ 11 files changed, 295 insertions(+), 158 deletions(-) create mode 100644 fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAORuntimeException.java create mode 100644 fj-core/src/test/resources/core/db/base-db-conn.properties create mode 100644 fj-core/src/test/resources/core/db/connct-properties-mem-fail1.xml create mode 100644 fj-core/src/test/resources/core/db/connct-properties-mem-fail2.xml diff --git a/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFacade.java b/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFacade.java index 00103a3a..1b8cf90e 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFacade.java +++ b/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFacade.java @@ -73,7 +73,7 @@ public static ConnectionFactory getFactory( String name ) { * @return true if everything was closed with no errors */ public static boolean closeLoose( Connection conn, Statement stm, ResultSet rs ) { - return closeLoose( conn ) && closeLoose( stm ) && closeLoose( rs ); + return closeLoose( conn ) & closeLoose( stm ) & closeLoose( rs ); } /** @@ -84,7 +84,7 @@ public static boolean closeLoose( Connection conn, Statement stm, ResultSet rs ) * @return true if everything was closed with no errors */ public static boolean closeLoose( Connection conn, Statement stm ) { - return closeLoose( conn ) && closeLoose( stm ); + return closeLoose( conn ) & closeLoose( stm ); } /** diff --git a/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryImpl.java b/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryImpl.java index 0e124569..123a37e4 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryImpl.java +++ b/fj-core/src/main/java/org/fugerit/java/core/db/connect/ConnectionFactoryImpl.java @@ -23,19 +23,18 @@ import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.Driver; -import java.sql.SQLException; import java.util.Iterator; import java.util.List; import java.util.Properties; -import javax.naming.Context; import javax.naming.InitialContext; -import javax.naming.NamingException; import javax.sql.DataSource; import org.fugerit.java.core.cfg.ConfigRuntimeException; import org.fugerit.java.core.db.dao.DAOException; import org.fugerit.java.core.db.metadata.DataBaseInfo; +import org.fugerit.java.core.function.UnsafeSupplier; +import org.fugerit.java.core.lang.helpers.StringUtils; import org.fugerit.java.core.log.BasicLogObject; import org.fugerit.java.core.xml.dom.DOMUtils; import org.fugerit.java.core.xml.dom.SearchDOM; @@ -189,7 +188,7 @@ public static CfConfig parseCfConfig( Element cfConfig ) throws Exception { Element currentEntryTag = (Element) cfConfigEntryIt.next(); Properties props = DOMUtils.attributesToProperties( currentEntryTag ); String id = props.getProperty( "id" ); - if ( id == null || id.trim().length() == 0 ) { + if ( StringUtils.isEmpty( id ) ) { throw new ConfigRuntimeException( "Connection factory id must be defined." ); } else if ( config.getCfMap().containsKey( id ) ) { throw new ConfigRuntimeException( "Connection factory id already used : '"+id+"'" ); @@ -208,15 +207,12 @@ public static CfConfig parseCfConfig( Element cfConfig ) throws Exception { * @throws DAOException in case of issues */ public static String getDriverInfo( ConnectionFactory cf ) throws DAOException { - String result = ""; - try (Connection conn = cf.getConnection()) { - DatabaseMetaData databaseMetaData = conn.getMetaData(); - result = databaseMetaData.getDriverName()+" "+databaseMetaData.getDriverVersion(); - } catch (Exception e) { - throw DAOException.convertExMethod( "getDriverInfo", e ); - } - - return result; + return DAOException.get( () -> { + try (Connection conn = cf.getConnection()) { + DatabaseMetaData databaseMetaData = conn.getMetaData(); + return databaseMetaData.getDriverName()+" "+databaseMetaData.getDriverVersion(); + } + }); } /** @@ -228,7 +224,7 @@ public static String getDriverInfo( ConnectionFactory cf ) throws DAOException { */ private static String getParamName( String prefix, String name ) { String res = name; - if ( prefix != null && !prefix.equals( "" ) ) { + if ( StringUtils.isNotEmpty( prefix ) ) { res = prefix+"-"+name; } return res; @@ -277,17 +273,10 @@ public static ConnectionFactory newInstance( Properties props, String propsPrefi props.getProperty( getParamName( prefix, PROP_CF_MODE_DC_USR ) ), props.getProperty( getParamName( prefix, PROP_CF_MODE_DC_PWD ) ), cl ); } - } else if ( PROP_CF_MODE_DS.equalsIgnoreCase( mode ) ) { - cf = newInstance( props.getProperty( PROP_CF_MODE_DS_NAME ) ); - } else if ( PROP_CF_MODE_DS2.equalsIgnoreCase( mode ) ) { + } else if ( PROP_CF_MODE_DS.equalsIgnoreCase( mode ) || PROP_CF_MODE_DS2.equalsIgnoreCase( mode ) ) { String dsName = props.getProperty( PROP_CF_MODE_DS_NAME ); - try { - javax.naming.InitialContext ctx = new javax.naming.InitialContext(); - DataSource dataSource = ( DataSource ) ctx.lookup( dsName ); - cf = newInstance( dataSource ); - } catch (Exception e) { - throw ( new DAOException( e ) ); - } + log.info( "dsName -> {}", dsName ); + cf = newInstance( dsName ); } else { throw ( new DAOException( "Unsupported factory mode ( valid values ar 'dc', 'ds', 'ds2' )" ) ); } @@ -305,7 +294,10 @@ public static ConnectionFactory newInstance( Properties props, String propsPrefi * @throws DAOException in case of issues */ public static ConnectionFactory newInstance(Driver drv, String url, String usr, String pwd) throws DAOException { - return new DirectConnectionFactory( drv, url , usr, pwd ); + Properties info = new Properties(); + info.setProperty( "user", usr ); + info.setProperty( "password", pwd ); + return new SupplierConnectionFactory( "directConnectionSupplier" , () -> drv.connect( url, info ) ); } /** @@ -334,23 +326,19 @@ public static ConnectionFactory newInstance(String drv, String url, String usr, * @throws DAOException in case of issues */ public static ConnectionFactory newInstance(String drv, String url, String usr, String pwd, ClassLoader cl) throws DAOException { - ConnectionFactory connectionFactory = null; - try { - log.info( "ConnectionFactoryImpl.newInstance() direct connection driver : {}", drv ); - log.info( "ConnectionFactoryImpl.newInstance() direct connection url : {}", url ); - log.info( "ConnectionFactoryImpl.newInstance() direct connection username : {}", usr ); - log.info( "ConnectionFactoryImpl.newInstance() direct connection password : ******" ); + log.info( "ConnectionFactoryImpl.newInstance() direct connection driver : {}", drv ); + log.info( "ConnectionFactoryImpl.newInstance() direct connection url : {}", url ); + log.info( "ConnectionFactoryImpl.newInstance() direct connection username : {}", usr ); + log.info( "ConnectionFactoryImpl.newInstance() direct connection password : ******" ); + return DAOException.get( () -> { Driver driver = null; if ( cl != null ) { driver = (Driver)cl.loadClass( drv ).getDeclaredConstructor().newInstance(); } else { driver= (Driver)Class.forName( drv ).asSubclass( Driver.class ).getDeclaredConstructor().newInstance(); } - connectionFactory = ( new DirectConnectionFactory( driver, url, usr, pwd ) ); - } catch (Exception e) { - throw ( new DAOException( e ) ); - } - return connectionFactory; + return newInstance(driver, url, usr, pwd); + }); } /** @@ -362,7 +350,7 @@ public static ConnectionFactory newInstance(String drv, String url, String usr, */ public static ConnectionFactoryImpl newInstance(String dsName) throws DAOException { log.info( "ConnectionFactoryImpl.newInstance() data source name : {}", dsName ); - return (new DSConnectionFactory(dsName)); + return newInstance( DAOException.get( () -> (DataSource)new InitialContext().lookup( dsName ) ) ); } /** @@ -374,7 +362,7 @@ public static ConnectionFactoryImpl newInstance(String dsName) throws DAOExcepti */ public static ConnectionFactoryImpl newInstance(DataSource ds) throws DAOException { log.info( "ConnectionFactoryImpl.newInstance() data source : {}", ds ); - return (new DS2ConnectionFactory(ds)); + return new SupplierConnectionFactory( "dataSourceSupplier" , () -> ds.getConnection() ); } /* @@ -395,112 +383,26 @@ public void release() throws DAOException { } -/** - * ConnectionFactory implementations based on DriverManager - * - * @author Fugerit - * - */ -class DirectConnectionFactory extends ConnectionFactoryImpl { - - private String url; - private Driver driver; - private Properties info; +class SupplierConnectionFactory extends ConnectionFactoryImpl { - public DirectConnectionFactory( Driver drv, String url, String usr, String pwd ) { - this.driver = drv; - this.url = url; - this.info = new Properties(); - this.info.setProperty( "user", usr ); - this.info.setProperty( "password", pwd ); - } + private String description; - @Override - public Connection getConnection() throws DAOException { - Connection conn = null; - try { - conn = this.driver.connect( this.url, this.info ); - } catch (Exception e) { - throw DAOException.convertExMethod( "getConnection", e ); - } - return conn; + private UnsafeSupplier supplier; + + public SupplierConnectionFactory(String description, UnsafeSupplier supplier) { + super(); + this.description = description; + this.supplier = supplier; } - -} -/** - * ConnectionFactory implementation based on a Data Source - * - * @author Fugerit - * - */ -@Slf4j -class DSConnectionFactory extends ConnectionFactoryImpl { - - @Override - public String toString() { - return this.getClass().getName()+"[dsName:"+this.dsName+",source:"+this.source+"]"; - } - @Override public Connection getConnection() throws DAOException { - Connection conn = null; - try { - conn = this.source.getConnection(); - } catch (SQLException se) { - throw (new DAOException("Cannot create connection", se)); - } - return conn; + return DAOException.get( supplier ); } - - private String dsName; - - private DataSource source; - - public DSConnectionFactory(String dsName) throws DAOException { - log.info( "INIT START, dsName={}", dsName ); - this.dsName = dsName; - try { - Context ctx = new InitialContext(); - source = (DataSource) ctx.lookup(dsName); - } catch (NamingException ne) { - throw (new DAOException("Cannot create ConnectionFactory", ne)); - } catch (Exception e) { - throw (new DAOException("Fatal Error", e)); - } - log.info( "INIT END, source={}", source ); - } - -} - -/** - * ConnectionFactory implementation based on a Data Source (v2) - * - * @author Fugerit - * - */ -class DS2ConnectionFactory extends ConnectionFactoryImpl { @Override public String toString() { - return this.getClass().getName()+"[source:"+this.source+"]"; - } - - @Override - public Connection getConnection() throws DAOException { - Connection conn = null; - try { - conn = this.source.getConnection(); - } catch (SQLException se) { - throw (new DAOException("Cannot create Connection", se)); - } - return conn; + return "SupplierConnectionFactory["+this.description+"]"; } - private DataSource source; - - public DS2ConnectionFactory(DataSource ds) throws DAOException { - this.source = ds; - } - } diff --git a/fj-core/src/main/java/org/fugerit/java/core/db/connect/DbcpConnectionFactory.java b/fj-core/src/main/java/org/fugerit/java/core/db/connect/DbcpConnectionFactory.java index d95126da..6e11b75b 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/db/connect/DbcpConnectionFactory.java +++ b/fj-core/src/main/java/org/fugerit/java/core/db/connect/DbcpConnectionFactory.java @@ -21,7 +21,6 @@ package org.fugerit.java.core.db.connect; import java.sql.Connection; -import java.sql.SQLException; import org.apache.commons.dbcp2.BasicDataSource; import org.fugerit.java.core.db.dao.DAOException; @@ -66,7 +65,7 @@ public DbcpConnectionFactory( String drv, String url, String usr, String pwd, in * @throws DAOException in case of issues */ public DbcpConnectionFactory( String drv, String url, String usr, String pwd, int init, int min, int max, ClassLoader cl ) throws DAOException { - try { + DAOException.apply( () -> { this.dataSource = new BasicDataSource(); this.dataSource.setDriverClassName( drv ); this.dataSource.setUrl( url ); @@ -78,21 +77,12 @@ public DbcpConnectionFactory( String drv, String url, String usr, String pwd, in if ( cl != null ) { this.dataSource.setDriverClassLoader( cl ); } - } catch (Exception e) { - throw new DAOException( e ); - } + }); } @Override public Connection getConnection() throws DAOException { - Connection conn = null; - try { - conn = this.dataSource.getConnection(); - } catch (SQLException e) { - throw new DAOException( e ); - } - return conn; + return DAOException.get( () -> this.dataSource.getConnection() ); } - } diff --git a/fj-core/src/main/java/org/fugerit/java/core/db/dao/DAOException.java b/fj-core/src/main/java/org/fugerit/java/core/db/dao/DAOException.java index 2b350676..289028e5 100644 --- a/fj-core/src/main/java/org/fugerit/java/core/db/dao/DAOException.java +++ b/fj-core/src/main/java/org/fugerit/java/core/db/dao/DAOException.java @@ -20,6 +20,7 @@ */ package org.fugerit.java.core.db.dao; +import org.fugerit.java.core.function.UnsafeSupplier; import org.fugerit.java.core.function.UnsafeVoid; import org.fugerit.java.core.lang.ex.ExConverUtils; @@ -69,12 +70,22 @@ public static DAOException convertExMethod( String method, Exception e ) { public static DAOException convertEx( Exception e ) { return convertEx( ExConverUtils.DEFAULT_CAUSE_MESSAGE, e ); } + + public static T get( UnsafeSupplier fun ) throws DAOException { + T res = null; + try { + res = fun.get(); + } catch (Exception e) { + throw convertEx( e ); + } + return res; + } public static void apply( UnsafeVoid fun ) throws DAOException { try { fun.apply(); } catch (Exception e) { - throw new DAOException( e ); + throw convertEx( e ); } } diff --git a/fj-core/src/test/java/test/org/fugerit/java/core/db/connect/TestConnectionFactory.java b/fj-core/src/test/java/test/org/fugerit/java/core/db/connect/TestConnectionFactory.java index 87e7f8ae..fa73f81f 100644 --- a/fj-core/src/test/java/test/org/fugerit/java/core/db/connect/TestConnectionFactory.java +++ b/fj-core/src/test/java/test/org/fugerit/java/core/db/connect/TestConnectionFactory.java @@ -2,17 +2,22 @@ import java.io.InputStream; import java.sql.Connection; +import java.util.Properties; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.sql.DataSource; +import org.fugerit.java.core.cfg.ConfigRuntimeException; import org.fugerit.java.core.db.connect.CfConfig; +import org.fugerit.java.core.db.connect.ConnectionFacade; import org.fugerit.java.core.db.connect.ConnectionFacadeWrapper; import org.fugerit.java.core.db.connect.ConnectionFactory; import org.fugerit.java.core.db.connect.ConnectionFactoryCloseable; import org.fugerit.java.core.db.connect.ConnectionFactoryImpl; +import org.fugerit.java.core.db.connect.DbcpConnectionFactory; import org.fugerit.java.core.db.connect.SingleConnectionFactory; +import org.fugerit.java.core.db.dao.DAOException; import org.fugerit.java.core.lang.helpers.ClassHelper; import org.fugerit.java.core.util.PropsIO; import org.fugerit.java.core.xml.dom.DOMIO; @@ -31,6 +36,7 @@ public class TestConnectionFactory extends BasicTest { private boolean worker( ConnectionFactory wrapped ) throws Exception { boolean ok = false; + log.info( "cf -> {}", wrapped ); try ( ConnectionFactoryCloseable cf = ConnectionFactoryImpl.wrap( wrapped ); Connection conn = cf.getConnection() ) { log.info( "db info : {}", cf.getDataBaseInfo() ); @@ -42,22 +48,64 @@ private boolean worker( ConnectionFactory wrapped ) throws Exception { @Test public void testCFProps() throws Exception { - ConnectionFactory wrapped = ConnectionFactoryImpl.newInstance( PropsIO.loadFromClassLoaderSafe( BasicDBHelper.DEFAULT_DB_CONN_PATH ) ); - boolean ok = this.worker(wrapped); + String name = "wrapped"; + Properties props= PropsIO.loadFromClassLoaderSafe( BasicDBHelper.DEFAULT_DB_CONN_PATH ); + ConnectionFactory wrapped = ConnectionFactoryImpl.newInstance( props ); + ConnectionFacade.registerFactory( name , wrapped ); + boolean ok = this.worker( ConnectionFacade.getFactory( name ) ); + Assert.assertTrue(ok); + // pooled + ok = this.worker( new DbcpConnectionFactory( props.getProperty( ConnectionFactoryImpl.PROP_CF_MODE_DC_DRV ), + props.getProperty( ConnectionFactoryImpl.PROP_CF_MODE_DC_URL ), + props.getProperty( ConnectionFactoryImpl.PROP_CF_MODE_DC_USR ), + props.getProperty( ConnectionFactoryImpl.PROP_CF_MODE_DC_PWD ), 1, 1, 3 ) ); Assert.assertTrue(ok); } - @Test - public void testCFXml() throws Exception { - try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( "core/db/connct-properties-mem.xml" ) ) { + public void testCFPropsPrefix() throws Exception { + boolean ok = this.worker( + ConnectionFactoryImpl.newInstance( + PropsIO.loadFromClassLoaderSafe( "core/db/base-db-conn.properties" ), + "prefixtest", TestConnectionFactory.class.getClassLoader() ) ); + Assert.assertTrue(ok); + } + + private boolean loadXmlHelper( String path ) throws Exception { + boolean ok = false; + try ( InputStream is = ClassHelper.loadFromDefaultClassLoader( path ) ) { Document doc = DOMIO.loadDOMDoc( is ); CfConfig cfConfig = ConnectionFactoryImpl.parseCfConfig( doc.getDocumentElement() ); - boolean ok = this.worker( cfConfig.getCfMap().get( "mem-db" ) ); + ok = this.worker( cfConfig.getCfMap().get( "mem-db" ) ); Assert.assertTrue(ok); ok = this.worker( cfConfig.getCfMap().get( "mem-db-pooled" ) ); Assert.assertTrue(ok); } + return ok; + } + + @Test + public void testCFXml() throws Exception { + boolean ok = this.loadXmlHelper( "core/db/connct-properties-mem.xml" ); + Assert.assertTrue(ok); + } + + @Test + public void testCFXmlFail1() throws Exception { + Assert.assertThrows( ConfigRuntimeException.class , () -> this.loadXmlHelper( "core/db/connct-properties-mem-fail1.xml" ) ); + } + + @Test + public void testCFXmlFail2() throws Exception { + Assert.assertThrows( ConfigRuntimeException.class , () -> this.loadXmlHelper( "core/db/connct-properties-mem-fail2.xml" ) ); + } + + + @Test + public void testCFUnsupportedMode() throws Exception { + Properties props = new Properties(); + props.setProperty( ConnectionFactoryImpl.PROP_CF_MODE , "mode-not-exists" ); + Assert.assertThrows( DAOException.class , () ->ConnectionFactoryImpl.newInstance(props) ); } private DataSource createDS() throws NamingException { @@ -81,8 +129,39 @@ public void testCFSingle() throws Exception { } @Test - public void testCFJndi() throws Exception { - boolean ok = this.worker( ConnectionFactoryImpl.newInstance( JNDI_DS_NAME ) ); + public void testCFJndi1() throws Exception { + Properties props = new Properties(); + props.setProperty( ConnectionFactoryImpl.PROP_CF_MODE , ConnectionFactoryImpl.PROP_CF_MODE_DS ); + props.setProperty( ConnectionFactoryImpl.PROP_CF_MODE_DS_NAME , JNDI_DS_NAME ); + boolean ok = this.worker( ConnectionFactoryImpl.newInstance( props ) ); + Assert.assertTrue(ok); + } + + @Test + public void testCFJndi2() throws Exception { + Properties props = new Properties(); + props.setProperty( ConnectionFactoryImpl.PROP_CF_MODE , ConnectionFactoryImpl.PROP_CF_MODE_DS2 ); + props.setProperty( ConnectionFactoryImpl.PROP_CF_MODE_DS_NAME , JNDI_DS_NAME ); + boolean ok = this.worker( ConnectionFactoryImpl.newInstance( props ) ); + Assert.assertTrue(ok); + } + + @Test + public void testCFDirect1() throws Exception { + boolean ok = this.worker( ConnectionFactoryImpl.newInstance( "org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:base_db_direct1", "testuser", "testp" ) ); + Assert.assertTrue(ok); + } + + + @Test + public void testCFDirect2() throws Exception { + boolean ok = this.worker( ConnectionFactoryImpl.newInstance( "org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:base_db_direct2", "testuser", "testp", TestConnectionFactory.class.getClassLoader() ) ); + Assert.assertTrue(ok); + } + + @Test + public void testCFDirect3() throws Exception { + boolean ok = this.worker( ConnectionFactoryImpl.newInstance( new org.hsqldb.jdbcDriver(), "jdbc:hsqldb:mem:base_db_direct3", "testuser", "testp" ) ); Assert.assertTrue(ok); } diff --git a/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAOException.java b/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAOException.java index be97fe7b..f8e03d48 100644 --- a/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAOException.java +++ b/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAOException.java @@ -12,5 +12,45 @@ public class TestDAOException { public void testApply() { Assert.assertThrows( DAOException.class ,() -> DAOException.apply( () -> { throw new SQLException( "junit test scenario" ); } ) ); } + + @Test + public void testGet() { + Assert.assertThrows( DAOException.class ,() -> DAOException.get( () -> { throw new SQLException( "junit test scenario" ); } ) ); + } + + @Test + public void testEx1() { + Assert.assertNotNull( new DAOException() ); + } + + @Test + public void testEx2() { + Assert.assertNotNull( new DAOException( "a" ) ); + } + + @Test + public void testEx3() { + Assert.assertNotNull( new DAOException( new SQLException( "b" ) ) ); + } + + @Test + public void testEx4() { + Assert.assertNotNull( new DAOException( "c", new SQLException( "d" ) ) ); + } + + @Test + public void testEx5() { + Assert.assertNotNull( DAOException.convertEx( "e" , new SQLException( "f" ) ) ); + } + + @Test + public void testEx6() { + Assert.assertNotNull( DAOException.convertEx( "g" , new DAOException( "g" ) ) ); + } + + @Test + public void testEx7() { + Assert.assertNotNull( DAOException.convertExMethod( "e" , new SQLException( "f" ) ) ); + } } diff --git a/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAORuntimeException.java b/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAORuntimeException.java new file mode 100644 index 00000000..5635c75c --- /dev/null +++ b/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/TestDAORuntimeException.java @@ -0,0 +1,46 @@ +package test.org.fugerit.java.core.db.dao; + +import java.sql.SQLException; + +import org.fugerit.java.core.db.dao.DAORuntimeException; +import org.junit.Assert; +import org.junit.Test; + +public class TestDAORuntimeException { + + @Test + public void testEx1() { + Assert.assertNotNull( new DAORuntimeException() ); + } + + @Test + public void testEx2() { + Assert.assertNotNull( new DAORuntimeException( "a" ) ); + } + + @Test + public void testEx3() { + Assert.assertNotNull( new DAORuntimeException( new SQLException( "b" ) ) ); + } + + @Test + public void testEx4() { + Assert.assertNotNull( new DAORuntimeException( "c", new SQLException( "d" ) ) ); + } + + @Test + public void testEx5() { + Assert.assertNotNull( DAORuntimeException.convertEx( "e" , new SQLException( "f" ) ) ); + } + + @Test + public void testEx6() { + Assert.assertNotNull( DAORuntimeException.convertEx( "g" , new DAORuntimeException( "g" ) ) ); + } + + @Test + public void testEx7() { + Assert.assertNotNull( DAORuntimeException.convertExMethod( "e" , new SQLException( "f" ) ) ); + } + +} diff --git a/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/rse/TestRSE.java b/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/rse/TestRSE.java index c3a0bca6..a1c4c3db 100644 --- a/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/rse/TestRSE.java +++ b/fj-core/src/test/java/test/org/fugerit/java/core/db/dao/rse/TestRSE.java @@ -2,9 +2,14 @@ import java.math.BigDecimal; import java.sql.Connection; +import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.Properties; +import org.fugerit.java.core.db.connect.ConnectionFacade; +import org.fugerit.java.core.db.connect.ConnectionFactoryCloseable; +import org.fugerit.java.core.db.connect.ConnectionFactoryImpl; import org.fugerit.java.core.db.dao.DAORuntimeException; import org.fugerit.java.core.db.dao.DAOUtilsNG; import org.fugerit.java.core.db.dao.RSExtractor; @@ -17,6 +22,7 @@ import org.fugerit.java.core.db.dao.rse.SingleColumnRSE; import org.fugerit.java.core.db.dao.rse.StringRSE; import org.fugerit.java.core.function.SafeFunction; +import org.fugerit.java.core.util.PropsIO; import org.fugerit.java.core.util.collection.OptionItem; import org.junit.Assert; import org.junit.Test; @@ -142,5 +148,29 @@ public void testPropertyCachingRSE() throws SQLException { Properties result = this.worker( "SELECT username, state FROM fugerit.user WHERE username = ?" , TEST_USERNAME, rse, null ); Assert.assertEquals( TEST_USERNAME , result.getProperty( "USERNAME" ) ); } + + @Test + public void tesConnectionFacade() throws Exception { + try ( ConnectionFactoryCloseable cf = ConnectionFactoryImpl.wrap( + ConnectionFactoryImpl.newInstance( PropsIO.loadFromClassLoaderSafe( BasicDBHelper.DEFAULT_DB_CONN_PATH ) ) ) ) { + try ( Connection conn = cf.getConnection(); + Statement stm = conn.createStatement(); + ResultSet rs = stm.executeQuery( "SELECT * FROM fugerit.user" ) ) { + ConnectionFacade.closeLoose( rs ); + ConnectionFacade.closeLoose( stm ); + ConnectionFacade.closeLoose( conn ); + } + try ( Connection conn = cf.getConnection(); + Statement stm = conn.createStatement(); + ResultSet rs = stm.executeQuery( "SELECT * FROM fugerit.user" ) ) { + ConnectionFacade.closeLoose(conn, stm, rs); + } + try ( Connection conn = cf.getConnection(); + Statement stm = conn.createStatement(); + ResultSet rs = stm.executeQuery( "SELECT * FROM fugerit.user" ) ) { + ConnectionFacade.closeLoose(conn, stm); + } + } + } } diff --git a/fj-core/src/test/resources/core/db/base-db-conn.properties b/fj-core/src/test/resources/core/db/base-db-conn.properties new file mode 100644 index 00000000..f4c61f25 --- /dev/null +++ b/fj-core/src/test/resources/core/db/base-db-conn.properties @@ -0,0 +1,9 @@ +prefixtest-db-cf-mode=DC +prefixtest-db-mode-dc-drv=org.hsqldb.jdbcDriver +prefixtest-db-mode-dc-url=jdbc:hsqldb:mem:base_db_pre +prefixtest-db-mode-dc-usr=test_db +prefixtest-db-mode-dc-pwd=test_db +prefixtest-db-db-ext-pooled=true +prefixtest-db-db-ext-pooled-sc=1 +prefixtest-db-db-ext-pooled-ic=1 +prefixtest-db-db-ext-pooled-mc=3 \ No newline at end of file diff --git a/fj-core/src/test/resources/core/db/connct-properties-mem-fail1.xml b/fj-core/src/test/resources/core/db/connct-properties-mem-fail1.xml new file mode 100644 index 00000000..4bd646f2 --- /dev/null +++ b/fj-core/src/test/resources/core/db/connct-properties-mem-fail1.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/fj-core/src/test/resources/core/db/connct-properties-mem-fail2.xml b/fj-core/src/test/resources/core/db/connct-properties-mem-fail2.xml new file mode 100644 index 00000000..46eb6b06 --- /dev/null +++ b/fj-core/src/test/resources/core/db/connct-properties-mem-fail2.xml @@ -0,0 +1,19 @@ + + + + + + + + +