我试图在调用REST模板的方法上使用@retryable
。如果由于通信错误而返回错误,我希望重试,否则我希望在调用上引发异常。
当ApiException发生时,我得到的不是@Retryable抛出并忽略它,而是EXTUSTEDRETRYException
和一个关于没有找到足够的“可恢复”的抱怨,即@recover
方法。
我想我会看看是否只有可恢复的方法存在可能使它高兴,并仍然按照希望的执行。没那么多。它没有引发异常,而是调用了可恢复方法。
@Retryable(exclude = ApiException include = ConnectionException, maxAttempts = 5, backoff = @Backoff(multiplier = 2.5d, maxDelay = 1000000L, delay = 150000L))
Object call(String domainUri, ParameterizedTypeReference type, Optional<?> domain = Optional.empty(), HttpMethod httpMethod = HttpMethod.POST) throws RestClientException {
RequestEntity request = apiRequestFactory.createRequest(domainUri, domain, httpMethod)
log.info "************************** Request Entity **************************"
log.info "${request.toString()}"
ResponseEntity response
try {
response = restTemplate.exchange(request, type)
log.info "************************** Response Entity **************************"
log.info "${response.toString()}"
} catch (HttpStatusCodeException | HttpMessageNotWritableException httpException) {
String errorMessage
String exceptionClass = httpException.class.name.concat("-")
if(httpException instanceof HttpStatusCodeException) {
log.info "************************** API Error **************************"
log.error("API responded with errors: ${httpException.responseBodyAsString}")
ApiError apiError = buildErrorResponse(httpException.responseBodyAsString)
errorMessage = extractErrorMessage(apiError)
if(isHttpCommunicationError(httpException.getStatusCode().value())) {
throw new ConnectionException(exceptionClass.concat(errorMessage))
}
}
errorMessage = StringUtils.isBlank(errorMessage) ? exceptionClass.concat(httpException.message) : exceptionClass.concat(errorMessage)
throw new ApiException(httpMethod, domainUri, errorMessage)
}
if (type.type == ResponseEntity) {
response
}
else response.body
}
@Recover
Object connectionException(ConnectionException connEx) {
log.error("Retry failure - communicaiton error")
throw new ConnectionException(connEx.class.name + " - " + connEx.message)
}
任何见解都将不胜感激。是bug还是操作员错误?这是使用Spring Boot 1.3.6和Spring-Retry 1.1.3。
您的include/exclude语法看起来很糟糕--甚至无法编译。
我刚刚编写了一个快速测试,如果您有零个@recovere
方法,它的工作完全符合预期...
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.retry.annotation.EnableRetry;
import org.springframework.retry.annotation.Retryable;
@SpringBootApplication
@EnableRetry
public class So38601998Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(So38601998Application.class, args);
Foo bean = context.getBean(Foo.class);
try {
bean.out("foo");
}
catch (Exception e) {
System.out.println(e);
}
try {
bean.out("bar");
}
catch (Exception e) {
System.out.println(e);
}
}
@Bean
public Foo foo() {
return new Foo();
}
public static class Foo {
@Retryable(include = IllegalArgumentException.class, exclude = IllegalStateException.class,
maxAttempts = 5)
public void out(String foo) {
System.out.println(foo);
if (foo.equals("foo")) {
throw new IllegalArgumentException();
}
else {
throw new IllegalStateException();
}
}
}
}
结果:
foo
foo
foo
foo
foo
java.lang.IllegalArgumentException
bar
java.lang.IllegalStateException
@Recover
public void connectionException(IllegalArgumentException e) {
System.out.println("Retry failure");
}
foo
foo
foo
foo
foo
Retry failure
bar
org.springframework.retry.ExhaustedRetryException: Cannot locate recovery method; nested exception is java.lang.IllegalStateException
@Recover
public void connectionException(Exception e) throws Exception {
System.out.println("Retry failure");
throw e;
}
foo
foo
foo
foo
foo
Retry failure
bar
Retry failure
java.lang.IllegalStateException
我用Spock测试Java代码。我测试这段代码: 我写了一个测试: 它失败是因为抛出了另一个CustomException。但是在块中,我捕获这个异常并抛出一个,因此我希望我的方法将抛出,而不是。如何测试它?
抛出异常的行为是否可能抛出不同的异常? 为了抛出异常,必须(可选地)分配新对象,并调用其构造函数(隐式调用fillinstacktrace)。在某些情况下,听起来像addSupressed也被称为。那么如果没有足够的内存会发生什么呢?JVM是否需要预分配内置异常?例如,(1/0)会抛出OutOfMemoryError而不是ArithmeticException吗? 此外,构造函数是一个方法调用,因
我正试图为一个方法编写一个测试用例,该方法基于特定的逻辑抛出异常。然而,测试用例失败了,因为预期的异常和获得的异常是不同的。 我如何解决这个问题?
问题内容: 包含多个有关将检查的异常与混合使用的问题。 虽然一些答案暗示使用其方法会导致难以阅读的用户代码。 我将使用此空间来提供可提高可读性的替代解决方案。 请注意,此问题特定于CompletableFuture。 这使我们能够提供更广泛地不扩展到lambda表达式的解决方案。 问题答案: 给定实用程序类(下面提供),用户可以无缝地抛出检查异常: 由lambda引发的任何异常(是否经过检查)都将
以下操作会在运行时导致异常: java.lang.VerifyError:操作数堆栈上的类型错误异常详细信息:location:com/sun/net/httpserver/spi/httpserverprovider$1.run()ljava/lang/object;@27:invokestatic原因:类型“sun/net/httpserver/defaulthttpserverprovide
问题内容: 考虑以下代码: 无需添加方法签名即可编译该代码。(它与同样表现到位,太)。 我理解为什么 可以 安全地运行它,因为实际上不能将其引发在块中,因此不能引发已检查的异常。我有兴趣知道在何处指定此行为。 并非永远都不会达到目标:以下代码也会编译: 但是,如果抛出一个检查的异常,它不会像我期望的那样编译: 在JLS Sec 11.2.2中 ,它说: 一,其抛出的表达式语句(§14.18)具有静