这是我演员的样子
public final class DiskMonitorActor extends UntypedActor {
private final File assetsDirectory;
private final long thresholdPercentage;
private final LoggingAdapter logging = Logging.getLogger(getContext().system(), this);
public DiskMonitorActor(final File assetsDirectory, final long thresholdPercentage) {
this.assetsDirectory = assetsDirectory;
this.thresholdPercentage = thresholdPercentage;
validateAssetsDirectory();
}
public static Props props(final File assetsDirectory, final long thresholdPercentage) {
return Props.create(new Creator<DiskMonitorActor>() {
private static final long serialVersionUID = 1L;
public DiskMonitorActor create() throws Exception {
return new DiskMonitorActor(assetsDirectory, thresholdPercentage);
}
});
}
private void validateAssetsDirectory() {
if (!assetsDirectory.exists()) {
throw new DiskException(assetsDirectory.getAbsolutePath() + " does not exists");
}
if (!assetsDirectory.isDirectory()) {
throw new DiskException(assetsDirectory.getAbsolutePath() + " is not a directory");
}
if (!assetsDirectory.canRead()) {
throw new DiskException(assetsDirectory.getAbsolutePath() + " does have read permission");
}
}
@Override
public void onReceive(final Object message) throws Exception {
if (message instanceof DiskMonitorMessage) {
logging.info("disk: {}, total space: {}, usable space: {}",
assetsDirectory.getAbsolutePath(),
assetsDirectory.getTotalSpace(),
assetsDirectory.getUsableSpace());
if (isThresholdExceeded()) {
logging.error("Disk full. Available Space {}", assetsDirectory.getFreeSpace());
throw new DiskException("disk capacity reached threshold.");
}
} else {
unhandled(message);
}
}
private boolean isThresholdExceeded() {
final long usedBytes = assetsDirectory.getTotalSpace() - assetsDirectory.getUsableSpace();
final long thresholdBytes = assetsDirectory.getTotalSpace() * thresholdPercentage / 100;
return usedBytes >= thresholdBytes;
}
}
和测试
public class DiskMonitorActorTest {
@Mock
private File assetsDirectory;
@Rule
public TestName testName = new TestName();
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void testDirectoryDoesNotExists() throws Exception {
when(assetsDirectory.exists()).thenReturn(false);
expectedException.expect(DiskException.class);
expectedException.expectMessage("null does not exists");
getDiskMonitorActor(assetsDirectory, 10L);
}
private DiskMonitorActor getDiskMonitorActor(final File assetsDirectory,
final long threshold) {
final Props props = DiskMonitorActor.props(assetsDirectory, threshold);
final ActorSystem system = ActorSystem.create("system");
final TestActorRef<DiskMonitorActor> actorRef =
TestActorRef.create(system, props, testName.getMethodName());
return actorRef.underlyingActor();
}
}
当我运行它时,我看到
[ERROR] [04/26/2015 15:51:35.206] [system-akka.actor.default-dispatcher-2] [akka://system/user/testDirectoryDoesNotExists] null does not exists
akka.actor.ActorInitializationException: exception during creation
at akka.actor.ActorInitializationException$.apply(Actor.scala:164)
at akka.actor.ActorCell.create(ActorCell.scala:596)
at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:456)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:478)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:279)
at akka.testkit.CallingThreadDispatcher.process$1(CallingThreadDispatcher.scala:244)
at akka.testkit.CallingThreadDispatcher.runQueue(CallingThreadDispatcher.scala:284)
at akka.testkit.CallingThreadDispatcher.register(CallingThreadDispatcher.scala:153)
at akka.dispatch.MessageDispatcher.attach(AbstractDispatcher.scala:132)
at akka.actor.dungeon.Dispatch$class.start(Dispatch.scala:87)
at akka.actor.ActorCell.start(ActorCell.scala:369)
at akka.testkit.TestActorRef.<init>(TestActorRef.scala:50)
at akka.testkit.TestActorRef$.apply(TestActorRef.scala:141)
at akka.testkit.TestActorRef$.apply(TestActorRef.scala:137)
at akka.testkit.TestActorRef$.create(TestActorRef.scala:160)
at akka.testkit.TestActorRef.create(TestActorRef.scala)
at com.self.monitoring.tenant.DiskMonitorActorTest.getDiskMonitorActor(DiskMonitorActorTest.java:69)
at com.self.monitoring.tenant.DiskMonitorActorTest.testDirectoryDoesNotExists(DiskMonitorActorTest.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: com.self.monitoring.tenant.exception.DiskException: null does not exists
at com.self.monitoring.tenant.DiskMonitorActor.validateAssetsDirectory(DiskMonitorActor.java:38)
at com.self.monitoring.tenant.DiskMonitorActor.<init>(DiskMonitorActor.java:23)
at com.self.monitoring.tenant.DiskMonitorActor$1.create(DiskMonitorActor.java:31)
at com.self.monitoring.tenant.DiskMonitorActor$1.create(DiskMonitorActor.java:27)
at akka.actor.CreatorConsumer.produce(Props.scala:335)
at akka.actor.Props.newActor(Props.scala:252)
at akka.actor.ActorCell.newActor(ActorCell.scala:552)
at akka.actor.ActorCell.create(ActorCell.scala:578)
... 46 more
[INFO] [04/26/2015 15:51:35.211] [system-akka.actor.default-dispatcher-3] [akka://system/user/testDirectoryDoesNotExists] Message [akka.testkit.TestActorRef$InternalGetActor$] from Actor[akka://system/temp/$a] to TestActor[akka://system/user/testDirectoryDoesNotExists] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
java.lang.AssertionError:
Expected: (an instance of com.self.monitoring.tenant.exception.DiskException and exception with message a string containing "null does not exists")
but: an instance of com.self.monitoring.tenant.exception.DiskException <java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]> is a java.util.concurrent.TimeoutException
Stacktrace was: java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223)
at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:116)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
at scala.concurrent.Await$.result(package.scala:116)
at akka.testkit.TestActorRef.underlyingActor(TestActorRef.scala:93)
at com.self.monitoring.tenant.DiskMonitorActorTest.getDiskMonitorActor(DiskMonitorActorTest.java:71)
at com.self.monitoring.tenant.DiskMonitorActorTest.testDirectoryDoesNotExists(DiskMonitorActorTest.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
java.lang.AssertionError:
Expected: (an instance of com.self.monitoring.tenant.exception.DiskException and exception with message a string containing "null does not exists")
but: an instance of com.self.monitoring.tenant.exception.DiskException <java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]> is a java.util.concurrent.TimeoutException
Stacktrace was: java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]
at scala.concurrent.impl.Promise$DefaultPromise.ready(Promise.scala:219)
at scala.concurrent.impl.Promise$DefaultPromise.result(Promise.scala:223)
at scala.concurrent.Await$$anonfun$result$1.apply(package.scala:116)
at scala.concurrent.BlockContext$DefaultBlockContext$.blockOn(BlockContext.scala:53)
at scala.concurrent.Await$.result(package.scala:116)
at akka.testkit.TestActorRef.underlyingActor(TestActorRef.scala:93)
at com.self.monitoring.tenant.DiskMonitorActorTest.getDiskMonitorActor(DiskMonitorActorTest.java:71)
at com.self.monitoring.tenant.DiskMonitorActorTest.testDirectoryDoesNotExists(DiskMonitorActorTest.java:44)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:239)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20)
at org.junit.Assert.assertThat(Assert.java:956)
at org.junit.Assert.assertThat(Assert.java:923)
at org.junit.rules.ExpectedException.handleException(ExpectedException.java:252)
at org.junit.rules.ExpectedException.access$000(ExpectedException.java:106)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:241)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Process finished with exit code 255
我不明白我怎么看
Stacktrace was: java.util.concurrent.TimeoutException: Futures timed out after [5000 milliseconds]
什么是工作流程?我以为我的构造函数会抛出有效的异常,因此我应该能够轻松捕获
ActorInitializationException
这里发生了什么?
最佳答案
超时是由underlyingActor
方法引起的,该方法在对actor实例进行Await.result
编码时在内部使用ask
。而且由于您的演员永远不会被创建,因此这个ask
将永远不会被满足。
要解决您的问题,您可以在其他actor内创建DiskMonitorActor
actor,从而为DiskMonitorActor
实例创建父对象,然后在创建时将Failure
发送到它的context.parent
(如here),或者您可以重构DiskMonitorActor
逻辑,因此任何人在失败后向DiskMonitorActor
发送消息的用户将收到Failure
消息作为响应(在这种情况下,我建议使用become
模式,例如针对失败和正常状态的不同接收方法)。第二种方法有点复杂,因为您需要确定何时在失败的actor中执行context.stop(self)
。
解决此问题的其他方法是通过消息传递目录,而不是通过构造函数传递目录,因此您可以先使用Failure
然后使用context.stop
对其进行响应。
简而言之,您所做的只是一点点的“akkish”。
关于java - Stacktrace是:java.util.concurrent.TimeoutException: future 在[5000毫秒]之后超时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29884634/