Skip to content
Snippets Groups Projects
Commit 11de3429 authored by Christian Wulf's avatar Christian Wulf
Browse files

Merge branch 'collectedExceptions' into 'master'

Collected exceptions

fixes #221
This branch introduces techniques which allow to log exceptions and collect them afterwards

See merge request !55
parents 071bf905 ef126d8e
No related branches found
No related tags found
No related merge requests found
Showing
with 90 additions and 39 deletions
...@@ -46,7 +46,7 @@ class A4StageAttributeSetter { ...@@ -46,7 +46,7 @@ class A4StageAttributeSetter {
} }
private void setAttributes(final Stage threadableStage, final Set<Stage> intraStages) { private void setAttributes(final Stage threadableStage, final Set<Stage> intraStages) {
threadableStage.setExceptionHandler(configuration.getFactory().createInstance()); threadableStage.setExceptionHandler(configuration.getFactory().createInstance(threadableStage.getOwningThread()));
// threadableStage.setOwningThread(owningThread); // threadableStage.setOwningThread(owningThread);
threadableStage.setOwningContext(configuration.getContext()); threadableStage.setOwningContext(configuration.getContext());
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
*/ */
package teetime.framework; package teetime.framework;
import teetime.framework.exceptionHandling.IExceptionListenerFactory; import teetime.framework.exceptionHandling.AbstractExceptionListenerFactory;
import teetime.framework.exceptionHandling.TerminatingExceptionListenerFactory; import teetime.framework.exceptionHandling.TerminatingExceptionListenerFactory;
/** /**
...@@ -28,7 +28,7 @@ import teetime.framework.exceptionHandling.TerminatingExceptionListenerFactory; ...@@ -28,7 +28,7 @@ import teetime.framework.exceptionHandling.TerminatingExceptionListenerFactory;
*/ */
public abstract class Configuration extends AbstractCompositeStage { public abstract class Configuration extends AbstractCompositeStage {
private final IExceptionListenerFactory<?> factory; private final AbstractExceptionListenerFactory<?> factory;
private final ConfigurationContext context; private final ConfigurationContext context;
private boolean initialized; private boolean initialized;
...@@ -39,7 +39,7 @@ public abstract class Configuration extends AbstractCompositeStage { ...@@ -39,7 +39,7 @@ public abstract class Configuration extends AbstractCompositeStage {
this(new TerminatingExceptionListenerFactory()); this(new TerminatingExceptionListenerFactory());
} }
protected Configuration(final IExceptionListenerFactory<?> factory) { protected Configuration(final AbstractExceptionListenerFactory<?> factory) {
this.factory = factory; this.factory = factory;
this.context = new ConfigurationContext(this); this.context = new ConfigurationContext(this);
} }
...@@ -60,7 +60,7 @@ public abstract class Configuration extends AbstractCompositeStage { ...@@ -60,7 +60,7 @@ public abstract class Configuration extends AbstractCompositeStage {
this.executed = executed; this.executed = executed;
} }
public IExceptionListenerFactory<?> getFactory() { public AbstractExceptionListenerFactory<?> getFactory() {
return factory; return factory;
} }
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
package teetime.framework; package teetime.framework;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import teetime.framework.signal.ValidatingSignal; import teetime.framework.signal.ValidatingSignal;
...@@ -104,7 +106,14 @@ public final class Execution<T extends Configuration> { ...@@ -104,7 +106,14 @@ public final class Execution<T extends Configuration> {
* @since 2.0 * @since 2.0
*/ */
public void waitForTermination() { public void waitForTermination() {
int numExceptions = 0;
configurationContext.waitForConfigurationToTerminate(); configurationContext.waitForConfigurationToTerminate();
for (Entry<Thread, List<Exception>> entry : configuration.getFactory().getThreadExceptionsMap().entrySet()) {
numExceptions += entry.getValue().size();
}
if (numExceptions != 0) {
throw new ExecutionException(configuration.getFactory().getThreadExceptionsMap());
}
} }
// TODO: implement // TODO: implement
......
...@@ -15,24 +15,23 @@ ...@@ -15,24 +15,23 @@
*/ */
package teetime.framework; package teetime.framework;
import java.util.Collection; import java.util.List;
import java.util.Map;
import teetime.util.ThreadThrowableContainer;
/** /**
* Represents a exception, which is thrown by an analysis, if any problems occured within its execution. * Represents a exception, which is thrown by an analysis, if any problems occured within its execution.
* A collection of thrown exceptions within the analysis can be retrieved with {@link #getThrownExceptions()}. * A collection of thrown exceptions within the analysis can be retrieved with {@link #getThrownExceptions()}.
* *
* @since 1.1 * @since 2.0
*/ */
public class ExecutionException extends RuntimeException { public class ExecutionException extends RuntimeException {
private static final long serialVersionUID = 7486086437171884298L; private static final long serialVersionUID = 7486086437171884298L;
private final Collection<ThreadThrowableContainer> exceptions; private final Map<Thread, List<Exception>> exceptions;
public ExecutionException(final Collection<ThreadThrowableContainer> exceptions) { public ExecutionException(final Map<Thread, List<Exception>> exceptions) {
super((exceptions.size() == 1) ? exceptions.toString() : "Error(s) while execution. Check thrown exception(s)."); super((exceptions.size() == 1) ? exceptions.toString() : exceptions.size() + " error(s) while execution. Check thrown exception(s).");
this.exceptions = exceptions; this.exceptions = exceptions;
} }
...@@ -40,9 +39,9 @@ public class ExecutionException extends RuntimeException { ...@@ -40,9 +39,9 @@ public class ExecutionException extends RuntimeException {
* Returns all exceptions thrown within the execution. * Returns all exceptions thrown within the execution.
* These are passed on as pairs of threads and throwables, to indicate a exception's context. * These are passed on as pairs of threads and throwables, to indicate a exception's context.
* *
* @return a collection of pairs * @return a thread-exceptionlist-map
*/ */
public Collection<ThreadThrowableContainer> getThrownExceptions() { public Map<Thread, List<Exception>> getThrownExceptions() {
return exceptions; return exceptions;
} }
......
...@@ -121,7 +121,7 @@ public abstract class Stage { ...@@ -121,7 +121,7 @@ public abstract class Stage {
} catch (TerminateException e) { } catch (TerminateException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
final FurtherExecution furtherExecution = this.exceptionListener.onStageException(e, this); final FurtherExecution furtherExecution = this.exceptionListener.reportException(e, this);
if (furtherExecution == FurtherExecution.TERMINATE) { if (furtherExecution == FurtherExecution.TERMINATE) {
throw TerminateException.INSTANCE; throw TerminateException.INSTANCE;
} }
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
*/ */
package teetime.framework.exceptionHandling; package teetime.framework.exceptionHandling;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -27,6 +30,9 @@ import teetime.framework.Stage; ...@@ -27,6 +30,9 @@ import teetime.framework.Stage;
*/ */
public abstract class AbstractExceptionListener { public abstract class AbstractExceptionListener {
private final List<Exception> exceptionsList = new ArrayList<Exception>();
private final boolean logExceptions;
public enum FurtherExecution { public enum FurtherExecution {
CONTINUE, TERMINATE CONTINUE, TERMINATE
} }
...@@ -36,8 +42,9 @@ public abstract class AbstractExceptionListener { ...@@ -36,8 +42,9 @@ public abstract class AbstractExceptionListener {
*/ */
protected final Logger logger; protected final Logger logger;
public AbstractExceptionListener() { protected AbstractExceptionListener(final boolean shouldLogExceptions) {
this.logger = LoggerFactory.getLogger(this.getClass().getCanonicalName()); this.logger = LoggerFactory.getLogger(this.getClass().getCanonicalName());
this.logExceptions = shouldLogExceptions;
} }
/** /**
...@@ -52,4 +59,15 @@ public abstract class AbstractExceptionListener { ...@@ -52,4 +59,15 @@ public abstract class AbstractExceptionListener {
*/ */
public abstract FurtherExecution onStageException(Exception e, Stage throwingStage); public abstract FurtherExecution onStageException(Exception e, Stage throwingStage);
public List<Exception> getLoggedExceptions() {
return exceptionsList;
}
public FurtherExecution reportException(final Exception e, final Stage stage) {
if (logExceptions) {
exceptionsList.add(e);
}
return onStageException(e, stage);
}
} }
...@@ -15,8 +15,24 @@ ...@@ -15,8 +15,24 @@
*/ */
package teetime.framework.exceptionHandling; package teetime.framework.exceptionHandling;
public interface IExceptionListenerFactory<T extends AbstractExceptionListener> { import java.util.HashMap;
import java.util.List;
import java.util.Map;
public T createInstance(); public abstract class AbstractExceptionListenerFactory<T extends AbstractExceptionListener> {
private final Map<Thread, List<Exception>> threadExceptionsMap = new HashMap<Thread, List<Exception>>();
protected abstract T createInstance();
public T createInstance(final Thread thread) {
T instance = createInstance();
threadExceptionsMap.put(thread, instance.getLoggedExceptions());
return instance;
}
public Map<Thread, List<Exception>> getThreadExceptionsMap() {
return threadExceptionsMap;
}
} }
...@@ -19,6 +19,10 @@ import teetime.framework.Stage; ...@@ -19,6 +19,10 @@ import teetime.framework.Stage;
class IgnoringExceptionListener extends AbstractExceptionListener { class IgnoringExceptionListener extends AbstractExceptionListener {
IgnoringExceptionListener() {
super(false);
}
@Override @Override
public FurtherExecution onStageException(final Exception e, final Stage throwingStage) { public FurtherExecution onStageException(final Exception e, final Stage throwingStage) {
return FurtherExecution.CONTINUE; return FurtherExecution.CONTINUE;
......
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
*/ */
package teetime.framework.exceptionHandling; package teetime.framework.exceptionHandling;
public class IgnoringExceptionListenerFactory implements IExceptionListenerFactory { public class IgnoringExceptionListenerFactory extends AbstractExceptionListenerFactory<IgnoringExceptionListener> {
@Override @Override
public AbstractExceptionListener createInstance() { protected final IgnoringExceptionListener createInstance() {
return new IgnoringExceptionListener(); return new IgnoringExceptionListener();
} }
......
...@@ -19,6 +19,10 @@ import teetime.framework.Stage; ...@@ -19,6 +19,10 @@ import teetime.framework.Stage;
class LoggingExceptionListener extends AbstractExceptionListener { class LoggingExceptionListener extends AbstractExceptionListener {
LoggingExceptionListener() {
super(true);
}
@Override @Override
public FurtherExecution onStageException(final Exception e, final Stage throwingStage) { public FurtherExecution onStageException(final Exception e, final Stage throwingStage) {
logger.warn("Exception occurred in " + throwingStage.getId(), e); logger.warn("Exception occurred in " + throwingStage.getId(), e);
......
...@@ -15,10 +15,10 @@ ...@@ -15,10 +15,10 @@
*/ */
package teetime.framework.exceptionHandling; package teetime.framework.exceptionHandling;
public class LoggingExceptionListenerFactory implements IExceptionListenerFactory { public class LoggingExceptionListenerFactory extends AbstractExceptionListenerFactory<LoggingExceptionListener> {
@Override @Override
public AbstractExceptionListener createInstance() { protected final LoggingExceptionListener createInstance() {
return new LoggingExceptionListener(); return new LoggingExceptionListener();
} }
......
...@@ -25,7 +25,7 @@ class TerminatingExceptionListener extends AbstractExceptionListener { ...@@ -25,7 +25,7 @@ class TerminatingExceptionListener extends AbstractExceptionListener {
private final List<Exception> exceptions = new ArrayList<Exception>(); private final List<Exception> exceptions = new ArrayList<Exception>();
TerminatingExceptionListener() { TerminatingExceptionListener() {
// should only be instantiated by its factory super(true);
} }
@Override @Override
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
*/ */
package teetime.framework.exceptionHandling; package teetime.framework.exceptionHandling;
public class TerminatingExceptionListenerFactory implements IExceptionListenerFactory<TerminatingExceptionListener> { public class TerminatingExceptionListenerFactory extends AbstractExceptionListenerFactory<TerminatingExceptionListener> {
@Override @Override
public TerminatingExceptionListener createInstance() { public TerminatingExceptionListener createInstance() {
......
wiki @ 709c839c
Subproject commit 2c3239a10d4bac6e0b97ecbf114cc67a1d04b2be Subproject commit 709c839c447a50c93b37fcc633a01297115d4823
...@@ -18,16 +18,13 @@ package teetime.framework; ...@@ -18,16 +18,13 @@ package teetime.framework;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.lang.Thread.State; import java.lang.Thread.State;
import java.util.ArrayList; import java.util.HashMap;
import java.util.Collection; import java.util.List;
import java.util.Map;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import teetime.util.ThreadThrowableContainer;
import com.google.common.base.Joiner;
public class RunnableConsumerStageTest { public class RunnableConsumerStageTest {
@Test @Test
...@@ -118,17 +115,17 @@ public class RunnableConsumerStageTest { ...@@ -118,17 +115,17 @@ public class RunnableConsumerStageTest {
} }
private void start(final Execution<?> execution) { private void start(final Execution<?> execution) {
Collection<ThreadThrowableContainer> exceptions = new ArrayList<ThreadThrowableContainer>(); Map<Thread, List<Exception>> exceptions = new HashMap<Thread, List<Exception>>();
try { try {
execution.executeBlocking(); execution.executeBlocking();
} catch (ExecutionException e) { } catch (ExecutionException e) {
exceptions = e.getThrownExceptions(); exceptions = e.getThrownExceptions();
} }
for (ThreadThrowableContainer pair : exceptions) { // for (ThreadThrowableContainer pair : exceptions) {
System.err.println(pair.getThrowable()); // System.err.println(pair.getThrowable());
System.err.println(Joiner.on("\n").join(pair.getThrowable().getStackTrace())); // System.err.println(Joiner.on("\n").join(pair.getThrowable().getStackTrace()));
throw new AssertionError(pair.getThrowable()); // throw new AssertionError(pair.getThrowable());
} // }
assertEquals(0, exceptions.size()); assertEquals(0, exceptions.size());
} }
} }
...@@ -19,6 +19,10 @@ import teetime.framework.Stage; ...@@ -19,6 +19,10 @@ import teetime.framework.Stage;
public class TestListener extends AbstractExceptionListener { public class TestListener extends AbstractExceptionListener {
protected TestListener() {
super(false);
}
private int numExceptionsInvoked; private int numExceptionsInvoked;
@Override @Override
......
...@@ -18,12 +18,12 @@ package teetime.framework.exceptionHandling; ...@@ -18,12 +18,12 @@ package teetime.framework.exceptionHandling;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class TestListenerFactory implements IExceptionListenerFactory { public class TestListenerFactory extends AbstractExceptionListenerFactory<TestListener> {
private final List<TestListener> instances = new ArrayList<TestListener>(); private final List<TestListener> instances = new ArrayList<TestListener>();
@Override @Override
public AbstractExceptionListener createInstance() { public TestListener createInstance() {
TestListener listener = new TestListener(); TestListener listener = new TestListener();
instances.add(listener); instances.add(listener);
return listener; return listener;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment