### Question:
SqlAttributesFilter extends GenericHeapObject implements Filter { @Override public Promise<Response, NeverThrowsException> filter(final Context context, final Request request, final Handler next) { final Bindings bindings = bindings(context, request); target.set(bindings, new LazyMap<>(new Factory<Map<String, Object>>() { @Override public Map<String, Object> newInstance() { HashMap<String, Object> result = new HashMap<>(); Connection c = null; try { c = dataSource.getConnection(); PreparedStatement ps = createPreparedStatement(c); ResultSet rs = ps.executeQuery(); if (rs.next()) { ResultSetMetaData rsmd = rs.getMetaData(); int columns = rsmd.getColumnCount(); for (int n = 1; n <= columns; n++) { result.put(rsmd.getColumnLabel(n), rs.getObject(n)); } } if (logger.isLoggable(DEBUG)) { logger.debug("Result: " + result); } rs.close(); ps.close(); } catch (SQLException sqle) { logger.error(sqle); } finally { if (c != null) { try { c.close(); } catch (SQLException sqle) { logger.error(sqle); } } } return result; } private PreparedStatement createPreparedStatement(final Connection connection) throws SQLException { logger.debug(format("PreparedStatement %s", preparedStatement)); PreparedStatement ps = connection.prepareStatement(preparedStatement); ps.clearParameters(); Iterator<Expression<?>> expressions = parameters.iterator(); int count = ps.getParameterMetaData().getParameterCount(); for (int i = 0; i < count; i++) { if (!expressions.hasNext()) { logger.warning(format(" Placeholder %d has no provided value as parameter", i + 1)); continue; } Object eval = expressions.next().eval(bindings); ps.setObject(i + 1, eval); logger.debug(format(" Placeholder #%d -> %s", i + 1, eval)); } if (expressions.hasNext()) { logger.warning(format(" All parameters with index >= %d are ignored because there are " + "no placeholders for them in the configured prepared statement (%s)", count, preparedStatement)); } return ps; } })); return next.handle(context, request); } SqlAttributesFilter(final DataSource dataSource,
                               @SuppressWarnings("rawtypes") final Expression<Map> target,
                               final String preparedStatement); List<Expression<?>> getParameters(); @Override Promise<Response, NeverThrowsException> filter(final Context context,
                                                          final Request request,
                                                          final Handler next);  }### Answer:
@Test public void testSqlResultRowIsStoredInAMapAndInAttributesContextProperty() throws Exception { SqlAttributesFilter filter = new SqlAttributesFilter(source, Expression.valueOf("${attributes.result}", Map.class), null); mockDatabaseInteractions(); AttributesContext context = new AttributesContext(new RootContext()); filter.filter(context, null, terminalHandler); @SuppressWarnings("unchecked") Map<String, Object> result = (Map<String, Object>) context.getAttributes().get("result"); assertThat(result).containsOnly(entry("password", "secret")); }
@Test public void testSomethingBadHappenDuringSqlInteraction() throws Exception { SqlAttributesFilter filter = new SqlAttributesFilter(source, Expression.valueOf("${attributes.result}", Map.class), null); filter.setLogger(spy(filter.getLogger())); when(source.getConnection()).thenThrow(new SQLException("Unexpected")); AttributesContext context = new AttributesContext(new RootContext()); filter.filter(context, null, terminalHandler); @SuppressWarnings("unchecked") Map<String, String> result = (Map<String, String>) context.getAttributes().get("result"); assertThat(result).isEmpty(); verify(filter.getLogger()).error(any(SQLException.class)); }