StatementInvocationHandler implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { checkNotNull(method); if (!method.getName().startsWith("execute")) { try { return method.invoke(statement, args); } catch (InvocationTargetException e) { throw e.getCause(); } } Optional<String> sql; if (method.getParameterTypes().length > 0 && method.getParameterTypes()[0] == String.class) { sql = Optional.fromNullable((String) args[0]); } else if (this.sql.isPresent()) { sql = this.sql; } else { sql = Optional.absent(); } try (TraceService.Span span = traceService.open("JDBC.Statement#" + method.getName())) { if (sql.isPresent()) { span.annotate(Label.SQL_TEXT, traceOptions.sqlScrubber().apply(sql.get())); } try { return method.invoke(statement, args); } catch (InvocationTargetException e) { throw e.getCause(); } } } StatementInvocationHandler(
      Statement statement,
      TraceOptions traceOptions,
      TraceService traceService,
      Optional<String> sql); @Override Object invoke(Object proxy, Method method, Object[] args);  }
@Test public void invoke_Statement_close() throws Throwable { StatementInvocationHandler statementInvocationHandler = new StatementInvocationHandler( mockRealStatement, TRACE_OPTIONS, mockTraceService, Optional.<String>absent()); statementInvocationHandler.invoke( mockProxy, Statement.class.getDeclaredMethod("close"), new Object[0]); verify(mockRealStatement).close(); verifyNoMoreInteractions(mockTraceSpan); }
@Test public void invoke_Statement_close_fails() throws Throwable { StatementInvocationHandler statementInvocationHandler = new StatementInvocationHandler( mockRealStatement, TRACE_OPTIONS, mockTraceService, Optional.<String>absent()); Exception expectedException = new SQLException(); doThrow(expectedException).when(mockRealStatement).close(); try { statementInvocationHandler.invoke( mockProxy, Statement.class.getDeclaredMethod("close"), new Object[0]); fail("expected SQLException"); } catch (Exception actualException) { assertThat(actualException).isSameAs(expectedException); } verify(mockRealStatement).close(); verifyNoMoreInteractions(mockTraceSpan); }
@Test public void invoke_Statement_execute() throws Throwable { StatementInvocationHandler statementInvocationHandler = new StatementInvocationHandler( mockRealStatement, TRACE_OPTIONS, mockTraceService, Optional.<String>absent()); statementInvocationHandler.invoke( mockProxy, Statement.class.getDeclaredMethod("execute", new Class<?>[] {String.class}), new Object[] {"insert some sql text"}); InOrder inOrder = inOrder(mockTraceService, mockTraceSpan, mockRealStatement); inOrder.verify(mockTraceService).open("JDBC.Statement#execute"); inOrder.verify(mockTraceSpan).annotate(Label.SQL_TEXT, Optional.of("#scrubbed SQL#")); inOrder.verify(mockRealStatement).execute("insert some sql text"); inOrder.verify(mockTraceSpan).close(); }
@Test public void invoke_PreparedStatement_execute() throws Throwable { StatementInvocationHandler statementInvocationHandler = new StatementInvocationHandler( mockRealPreparedStatement, TRACE_OPTIONS, mockTraceService, Optional.of("select some sql text")); statementInvocationHandler.invoke( mockProxy, PreparedStatement.class.getDeclaredMethod("execute"), new Object[0]); InOrder inOrder = inOrder(mockTraceService, mockTraceSpan, mockRealPreparedStatement); inOrder.verify(mockTraceService).open("JDBC.Statement#execute"); inOrder.verify(mockTraceSpan).annotate(Label.SQL_TEXT, Optional.of("#scrubbed SQL#")); inOrder.verify(mockRealPreparedStatement).execute(); inOrder.verify(mockTraceSpan).close(); }
@Test public void invoke_CallableStatement_execute() throws Throwable { StatementInvocationHandler statementInvocationHandler = new StatementInvocationHandler( mockRealCallableStatement, TRACE_OPTIONS, mockTraceService, Optional.of("call myproc()")); statementInvocationHandler.invoke( mockProxy, PreparedStatement.class.getDeclaredMethod("execute"), new Object[0]); InOrder inOrder = inOrder(mockTraceService, mockTraceSpan, mockRealCallableStatement); inOrder.verify(mockTraceService).open("JDBC.Statement#execute"); inOrder.verify(mockTraceSpan).annotate(Label.SQL_TEXT, Optional.of("#scrubbed SQL#")); inOrder.verify(mockRealCallableStatement).execute(); inOrder.verify(mockTraceSpan).close(); }
@Test public void invoke_fails() throws Throwable { StatementInvocationHandler statementInvocationHandler = new StatementInvocationHandler( mockRealStatement, TRACE_OPTIONS, mockTraceService, Optional.<String>absent()); Exception expectedException = new SQLException(); when(mockRealStatement.execute("some sql text")).thenThrow(expectedException); try { statementInvocationHandler.invoke( mockProxy, Statement.class.getDeclaredMethod("execute", String.class), new Object[]{"some sql text"}); } catch (Exception actualException) { assertThat(actualException).isSameAs(expectedException); } InOrder inOrder = inOrder(mockTraceService, mockTraceSpan, mockRealStatement); inOrder.verify(mockTraceService).open("JDBC.Statement#execute"); inOrder.verify(mockRealStatement).execute("some sql text"); inOrder.verify(mockTraceSpan).close(); }