You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by df...@apache.org on 2009/02/24 18:31:00 UTC
svn commit: r747449 - in /commons/sandbox/dbutils/bugfixing/src:
java/org/apache/commons/dbutils/QueryRunner.java
test/org/apache/commons/dbutils/QueryRunnerTest.java
Author: dfabulich
Date: Tue Feb 24 17:30:59 2009
New Revision: 747449
URL: http://svn.apache.org/viewvc?rev=747449&view=rev
Log:
fillStatementWithBean: tweaked exception handling, added unit test
Added:
commons/sandbox/dbutils/bugfixing/src/test/org/apache/commons/dbutils/QueryRunnerTest.java
Modified:
commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java
Modified: commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java
URL: http://svn.apache.org/viewvc/commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java?rev=747449&r1=747448&r2=747449&view=diff
==============================================================================
--- commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java (original)
+++ commons/sandbox/dbutils/bugfixing/src/java/org/apache/commons/dbutils/QueryRunner.java Tue Feb 24 17:30:59 2009
@@ -19,6 +19,8 @@
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
@@ -212,16 +214,19 @@
for (int i = 0; i < properties.length; i++) {
PropertyDescriptor property = properties[i];
Object value = null;
+ Method method = property.getReadMethod();
+ if (method == null)
+ throw new RuntimeException("No read method for bean property "
+ + bean.getClass() + " " + property.getName());
try {
- if (property.getReadMethod().getParameterTypes().length > 0) {
- throw new SQLException(
- "Can't use an indexed bean property as a SQL parameter: "
- + property.getName());
- }
- value = property.getReadMethod().invoke(bean, new Object[0]);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ value = method.invoke(bean, new Object[0]);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException("Couldn't invoke method: " + method, e);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Couldn't invoke method with 0 arguments: " + method, e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Couldn't invoke method: " + method, e);
+ }
params[i] = value;
}
fillStatement(stmt, params);
@@ -249,14 +254,13 @@
descriptors = Introspector.getBeanInfo(bean.getClass())
.getPropertyDescriptors();
} catch (IntrospectionException e) {
- throw new RuntimeException(e);
+ throw new RuntimeException("Couldn't introspect bean " + bean.getClass().toString(), e);
}
PropertyDescriptor[] sorted = new PropertyDescriptor[propertyNames.length];
for (int i = 0; i < propertyNames.length; i++) {
String propertyName = propertyNames[i];
if (propertyName == null)
- throw new NullPointerException("propertyName can't be null: "
- + i);
+ throw new NullPointerException("propertyName can't be null: " + i);
boolean found = false;
for (int j = 0; j < descriptors.length; j++) {
PropertyDescriptor descriptor = descriptors[j];
Added: commons/sandbox/dbutils/bugfixing/src/test/org/apache/commons/dbutils/QueryRunnerTest.java
URL: http://svn.apache.org/viewvc/commons/sandbox/dbutils/bugfixing/src/test/org/apache/commons/dbutils/QueryRunnerTest.java?rev=747449&view=auto
==============================================================================
--- commons/sandbox/dbutils/bugfixing/src/test/org/apache/commons/dbutils/QueryRunnerTest.java (added)
+++ commons/sandbox/dbutils/bugfixing/src/test/org/apache/commons/dbutils/QueryRunnerTest.java Tue Feb 24 17:30:59 2009
@@ -0,0 +1,124 @@
+package org.apache.commons.dbutils;
+
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+public class QueryRunnerTest extends TestCase {
+ QueryRunner runner;
+ PreparedStatement stmt;
+
+ public void setUp() {
+ runner = new QueryRunner();
+ stmt = fakePreparedStatement();
+ }
+
+ public void testFillStatementWithBean() throws SQLException {
+ TestBean tb = new TestBean();
+ tb.setOne("uno");
+ tb.setTwo("dos");
+ tb.setThree("tres");
+ NoOpFillStatement fakeQueryRunner = new NoOpFillStatement();
+ fakeQueryRunner.fillStatementWithBean(stmt, tb, new String[] {"three", "two", "one"});
+ String[] expected = new String[] {"tres", "dos", "uno"};
+ assertArrayEquals("Statement filled with incorrect parameters", expected, fakeQueryRunner.params);
+ }
+
+ private PreparedStatement fakePreparedStatement() {
+ InvocationHandler noOpHandler = new InvocationHandler() {
+ public Object invoke(Object proxy, Method method, Object[] args)
+ throws Throwable {
+ return null;
+ }
+ };
+ PreparedStatement stmt = ProxyFactory.instance().createPreparedStatement(noOpHandler);
+ return stmt;
+ }
+
+ public void testFillStatementWithBeanErrorNoReadMethod() throws Exception {
+ TestBean tb = new TestBean();
+ PropertyDescriptor noReadMethod = new PropertyDescriptor("one", TestBean.class, null, "setOne");
+
+ PropertyDescriptor properties[] = new PropertyDescriptor[] { noReadMethod };
+ try {
+ runner.fillStatementWithBean(stmt, tb, properties);
+ fail("Expected RuntimeException: tried to use a property with no read method");
+ } catch (RuntimeException expected) {}
+ }
+
+ public void testFillStatementWithBeanErrorBadReadMethod() throws Exception {
+ PropertyDescriptor badReadMethod = new IndexedPropertyDescriptor("indexed", getClass(), null, null, "getIndexed", null) {
+ public synchronized Method getReadMethod() {
+ return super.getIndexedReadMethod();
+ }
+ };
+ PropertyDescriptor properties[] = new PropertyDescriptor[] { badReadMethod };
+ try {
+ runner.fillStatementWithBean(stmt, this, properties);
+ fail("Expected RuntimeException: tried to use a property with no no-arg read method");
+ } catch (RuntimeException expected) {}
+ }
+
+ public void testFillStatementWithBeanErrorReadMethodThrows() throws Exception {
+ PropertyDescriptor badReadMethod = new PropertyDescriptor("throwsException", getClass(), "getThrowsException", null);
+ PropertyDescriptor properties[] = new PropertyDescriptor[] { badReadMethod };
+ try {
+ runner.fillStatementWithBean(stmt, this, properties);
+ fail("Expected RuntimeException: tried to call a method that throws");
+ } catch (RuntimeException expected) {}
+ }
+
+ public void testFillStatementWithBeanErrorReadMethodPrivate() throws Exception {
+ getPrivate();
+ Method getPrivate = getClass().getDeclaredMethod("getPrivate", new Class[0]);
+ PropertyDescriptor badReadMethod = new PropertyDescriptor("throwsException", getPrivate, null);
+ PropertyDescriptor properties[] = new PropertyDescriptor[] { badReadMethod };
+ try {
+ runner.fillStatementWithBean(stmt, this, properties);
+ fail("Expected RuntimeException: tried to call a private method");
+ } catch (RuntimeException expected) {}
+ }
+
+ public void testRethrowNullMessage() throws SQLException {
+ // DBUTILS-40
+ SQLException sqe = new SQLException((String)null);
+ QueryRunner qr = new QueryRunner();
+ try {
+ qr.rethrow(sqe, "foo", new Object[] {"bar"});
+ fail("rethrow didn't throw");
+ } catch (SQLException expected) {};
+ }
+
+ // indexed bean property
+ public String getIndexed(int index) {
+ return null;
+ }
+
+ public String getThrowsException() {
+ throw new RuntimeException("this getter always throws an exception");
+ }
+
+ private String getPrivate() {
+ return null;
+ }
+
+ private void assertArrayEquals(String message, Object[] expected, Object[] actual) {
+ assertEquals(message, Arrays.asList(expected).toString(), Arrays.asList(actual).toString());
+ assertEquals(message, expected.length, actual.length);
+ }
+
+
+ private class NoOpFillStatement extends QueryRunner {
+ Object[] params;
+ public void fillStatement(PreparedStatement stmt, Object[] params)
+ throws SQLException {
+ this.params = params;
+ }
+ }
+}