@Bean
 public CommandBus commandBus() {
   SimpleCommandBus commandBus = new SimpleCommandBus();
   commandBus.setHandlerInterceptors(Arrays.asList(new BeanValidationInterceptor()));
   //		commandBus.setTransactionManager(new SpringTransactionManager(transactionManager));
   return commandBus;
 }
  /**
   * Tests that exceptions thrown by dispatch interceptors on another thread are handled properly.
   *
   * <p>Documentation states,
   *
   * <blockquote>
   *
   * Exceptions have the following effect:<br>
   * Any declared checked exception will be thrown if the Command Handler (or an interceptor) threw
   * an exceptions of that type. If a checked exception is thrown that has not been declared, it is
   * wrapped in a CommandExecutionException, which is a RuntimeException.<br>
   * &hellip;
   *
   * </blockquote>
   */
  @Test(
      expected =
          SecurityException.class, // per documentation, an unchecked exception (theoretically
      // the only kind throwable by an interceptor) is returned unwrapped
      timeout =
          10000) // bug is that the caller waits forever for a CommandCallback.onFailure that never
                 // comes...
  public void testCommandDipatchInterceptorExceptionOnRetryThreadIsThrownToCaller() {
    commandGateway = new DefaultCommandGateway(commandBus, retryScheduler);

    // trigger retry
    commandBus.subscribe(
        String.class.getName(),
        new CommandHandler<String>() {
          @Override
          public Object handle(CommandMessage<String> commandMessage, UnitOfWork unitOfWork)
              throws Throwable {
            throw new ConcurrencyException("some retryable exception");
          }
        });

    // say we have a dispatch interceptor that expects to get the user's session from a
    // ThreadLocal...
    // yes, this should be configured on the gateway instead of the command bus, but still...
    final Thread testThread = Thread.currentThread();
    commandBus.setDispatchInterceptors(
        Collections.singletonList(
            new CommandDispatchInterceptor() {
              @Override
              public CommandMessage<?> handle(CommandMessage<?> commandMessage) {
                if (Thread.currentThread() == testThread) {
                  return commandMessage; // ok
                } else {
                  // also, nothing is logged!
                  LoggerFactory.getLogger(getClass()).info("throwing exception from dispatcher...");
                  throw new SecurityException("test dispatch interceptor exception");
                }
              }
            }));

    // wait, but hopefully not forever...
    commandGateway.sendAndWait("command");
  }
  /**
   * It'd be nice if metadata added by a {@linkplain SimpleCommandBus#setDispatchInterceptors(List)
   * command bus's dispatch interceptors} could be preserved, too, but that doesn't seem to be
   * possible given how {@link RetryingCallback} works, so verify that it behaves as designed (if
   * not as "expected").
   */
  @Test(timeout = 10000)
  public void testCommandBusDispatchInterceptorMetaDataIsNotPreservedOnRetry() {
    final Thread testThread = Thread.currentThread();
    commandGateway = new DefaultCommandGateway(commandBus, retryScheduler);

    // trigger retry, then return metadata for verification
    commandBus.subscribe(
        String.class.getName(),
        new CommandHandler<String>() {
          @Override
          public MetaData handle(CommandMessage<String> commandMessage, UnitOfWork unitOfWork)
              throws Throwable {
            if (Thread.currentThread() == testThread) {
              throw new ConcurrencyException("some retryable exception");
            } else {
              return commandMessage.getMetaData();
            }
          }
        });

    commandBus.setDispatchInterceptors(
        Collections.singletonList(
            new CommandDispatchInterceptor() {
              @Override
              public CommandMessage<?> handle(CommandMessage<?> commandMessage) {
                if (Thread.currentThread() == testThread) {
                  return commandMessage.andMetaData(
                      Collections.singletonMap("commandBusMetaData", "myUserSession"));
                } else {
                  // say the security interceptor example
                  // from #testCommandDipatchInterceptorExceptionOnRetryThreadIsThrownToCaller
                  // has been "fixed" -- on the retry thread, there's no security context
                  return commandMessage.andMetaData(
                      Collections.singletonMap("commandBusMetaData", "noUserSession"));
                }
              }
            }));

    assertEquals(
        "noUserSession",
        ((MetaData) commandGateway.sendAndWait("command")).get("commandBusMetaData"));
  }
  /** This test should make sure the problem described in issue #91 does not occur anymore */
  @Test
  public void testCallbackCalled() {
    SimpleCommandBus scb = new SimpleCommandBus();
    AnnotationCommandHandlerAdapter.subscribe(this, scb);

    scb.dispatch(
        GenericCommandMessage.asCommandMessage("Hello"),
        new VoidCallback() {
          @Override
          protected void onSuccess() {
            // what I expected
          }

          @Override
          public void onFailure(Throwable cause) {
            cause.printStackTrace();
            fail("Did not expect a failure");
          }
        });
  }
  /**
   * Tests that metadata added by a {@linkplain
   * AbstractCommandGateway#AbstractCommandGateway(CommandBus,RetryScheduler,List) command gateway's
   * dispatch interceptors} is preserved on retry.
   *
   * <p>It'd be nice if metadata added by a {@linkplain
   * SimpleCommandBus#setDispatchInterceptors(List) command bus's dispatch interceptors} could be
   * preserved, too, but that doesn't seem to be possible given how {@link RetryingCallback} works,
   * so verify that it is not preserved.
   */
  @Test(timeout = 10000)
  public void testCommandGatewayDispatchInterceptorMetaDataIsPreservedOnRetry() {
    final Thread testThread = Thread.currentThread();
    commandGateway =
        new DefaultCommandGateway(
            commandBus,
            retryScheduler,
            new CommandDispatchInterceptor() {
              @Override
              public CommandMessage<?> handle(CommandMessage<?> commandMessage) {
                if (Thread.currentThread() == testThread) {
                  return commandMessage.andMetaData(
                      Collections.singletonMap("gatewayMetaData", "myUserSession"));
                } else {
                  // gateway interceptor should only be called from the caller's thread
                  throw new SecurityException("test dispatch interceptor exception");
                }
              }
            });

    // trigger retry, then return metadata for verification
    commandBus.subscribe(
        String.class.getName(),
        new CommandHandler<String>() {
          @Override
          public MetaData handle(CommandMessage<String> commandMessage, UnitOfWork unitOfWork)
              throws Throwable {
            if (Thread.currentThread() == testThread) {
              throw new ConcurrencyException("some retryable exception");
            } else {
              return commandMessage.getMetaData();
            }
          }
        });

    assertEquals(
        "myUserSession", ((MetaData) commandGateway.sendAndWait("command")).get("gatewayMetaData"));
  }