BaseFunctionResolver implements FunctionResolver, Serializable { @Override public void close() throws IOException { if (!closed) { LOG.info("Calling close() on Stellar functions."); Map<String, Throwable> errors = new HashMap<>(); for (StellarFunctionInfo info : getFunctionInfo()) { try { info.getFunction().close(); } catch (Throwable t) { errors.put(info.getName(), t); } } if (!errors.isEmpty()) { StringBuilder sb = new StringBuilder(); sb.append("Unable to close Stellar functions:"); for (Map.Entry<String, Throwable> e : errors.entrySet()) { Throwable throwable = e.getValue(); String eText = String .format("Exception - Function: %s; Message: %s; Cause: %s", e.getKey(), throwable.getMessage(), throwable.getCause()); sb.append(System.lineSeparator()); sb.append(eText); } closed = true; throw new IOException(sb.toString()); } closed = true; } else { LOG.info("close() already called on Stellar functions - skipping."); } } BaseFunctionResolver(); abstract Set<Class<? extends StellarFunction>> resolvables(); @Override Iterable<StellarFunctionInfo> getFunctionInfo(); @Override Iterable<String> getFunctions(); @Override void initialize(Context context); @Override void close(); @Override StellarFunction apply(String functionName); static StellarFunctionInfo resolveFunction(Class<? extends StellarFunction> clazz); static String getNameFromAnnotation(Stellar annotation); static StellarFunction createFunction(Class<? extends StellarFunction> clazz);  }
@Test public void close_calls_all_loaded_function_close_methods() throws IOException { resolver.withClass(IAmAFunction.class); resolver.withClass(IAmAnotherFunction.class); resolver.close(); assertThat(IAmAFunction.closeCallCount, equalTo(1)); assertThat(IAmAnotherFunction.closeCallCount, equalTo(1)); }
@Test public void close_collects_all_exceptions_thrown_on_loaded_function_close_methods() { IAmAFunction.throwException = true; IAmAnotherFunction.throwException = true; resolver.withClass(IAmAFunction.class); resolver.withClass(IAmAnotherFunction.class); assertThrows(IOException.class, () -> resolver.close()); }
@Test public void close_only_throws_exceptions_on_first_invocation() throws IOException { IAmAFunction.throwException = true; IAmAnotherFunction.throwException = true; resolver.withClass(IAmAFunction.class); resolver.withClass(IAmAnotherFunction.class); assertThrows(IOException.class, () -> resolver.close()); assertThat(IAmAFunction.closeCallCount, equalTo(1)); assertThat(IAmAnotherFunction.closeCallCount, equalTo(1)); resolver.close(); resolver.close(); resolver.close(); assertThat(IAmAFunction.closeCallCount, equalTo(1)); assertThat(IAmAnotherFunction.closeCallCount, equalTo(1)); }