Skip to content
This repository has been archived by the owner on Sep 20, 2022. It is now read-only.

Execute callables within Gumshoe managed context #27

Merged
merged 1 commit into from
Aug 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions java/src/main/java/com/bazaarvoice/gumshoe/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.Callable;

/**
* A data context for events. Contexts can be stacked. Data can be stored
Expand Down Expand Up @@ -139,6 +140,44 @@ public Context start() {
return this;
}

/**
* Starts a context and calls the Callable within it and returns the result. The context will
* be finished or failed as appropriate. If an exception bubbles out of the Callable, an
* InContextException runtime exception will be thrown.
*
* @param callable
* @return
*/
public <V> V start(Callable<V> callable) {
try {
start();
V result = callable.call();
finish();
return result;
} catch (Exception exception) {
fail(exception);
throw new InContextException(exception);
}
}

/**
* Starts a context and calls the VoidCallable within it. The context will be finished or
* failed as appropriate. If an exception bubbles out of the Callable, an InContextException
* runtime exception will be thrown.
*
* @param callable
*/
public void start(VoidCallable callable) {
try {
start();
callable.call();
finish();
} catch (Exception exception) {
fail(exception);
throw new InContextException(exception);
}
}

/**
* Emits an event within the current context
*
Expand Down
13 changes: 13 additions & 0 deletions java/src/main/java/com/bazaarvoice/gumshoe/InContextException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.bazaarvoice.gumshoe;

/**
* Exception raised when an exception happens within a context.
*
* @author lance.woodson
*
*/
public class InContextException extends RuntimeException {
public InContextException(Exception cause) {
super(cause);
}
}
11 changes: 11 additions & 0 deletions java/src/main/java/com/bazaarvoice/gumshoe/VoidCallable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.bazaarvoice.gumshoe;

/**
* Interface of objects that can be invoked within a context
*
* @author lance.woodson
*
*/
public interface VoidCallable {
void call() throws Exception;
}
80 changes: 80 additions & 0 deletions java/src/test/java/com/bazaarvoice/gumshoe/ContextTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

public class ContextTest extends Assert {
private EventFactory eventFactory;
Expand Down Expand Up @@ -97,6 +98,85 @@ public void ensureStartLoadsEventFactorysDataStack() {
assertEquals(eventFactory.getDataStack().get("foo"), "bar");
}

@Test
public void ensureStartWithCallableReturnsCallableResult() {
String result = context.start(new Callable<String>() {
@Override
public String call() {
return "test";
}
});
assertEquals(result, "test");
}

@Test
public void ensureStartWithCallableFinishesStatus() {
context.start(new Callable<String>() {
@Override
public String call() {
return "test";
}
});
assertEquals(Context.Status.FINISHED, context.getStatus());
}

@Test(expectedExceptions={InContextException.class})
public void ensureStartWithCallableThrowingExceptionPropagatesException() {
context.start(new Callable<String>() {
@Override
public String call() {
throw new RuntimeException("Ooops, I did it again");
}
});
}

@Test
public void ensureStartWithCallableThrowingExceptionFinishesContext() {
try {
context.start(new Callable<String>() {
@Override
public String call() {
throw new RuntimeException("Ooops, I did it again");
}
});
} catch (Exception e) { }
assertEquals(Context.Status.FINISHED, context.getStatus());
}

@Test
public void ensureStartWithVoidCallableFinishesContext() {
context.start(new VoidCallable() {
@Override
public void call() {
// do something
}
});
assertEquals(Context.Status.FINISHED, context.getStatus());
}

@Test(expectedExceptions={InContextException.class})
public void ensureStartWithVoidCallableThrowingExceptionPropagatesException() {
context.start(new VoidCallable() {
@Override
public void call() {
throw new RuntimeException("Ooops, I did it again");
}
});
}

@Test
public void ensureStartWithVoidCallableThrowingExceptionFinishesContext() {
try {
context.start(new VoidCallable() {
@Override
public void call() {
throw new RuntimeException("Ooops, I did it again");
}
});
} catch (Exception e) { }
assertEquals(Context.Status.FINISHED, context.getStatus());
}

@Test(expectedExceptions={IllegalStateException.class})
public void ensureEmitFailsIfContextNotStarted() {
context.emit("test");
Expand Down