├── pom.xml
└── src
└── main
└── java
└── info
└── maigo
└── lab
└── sample
└── retry
└── exhausted
├── HogeApplication.java
├── HogeController.java
├── HogeException.java
├── HogeHogeException.java
└── HogeService.java
Cette fois, exécutez la compilation avec Maven. pom.xml est basé sur celui généré par Spring Initializr. Ajoutez spring-retry aux dépendances pour utiliser Spring Retry. Ajoutez également spring-boot-starter-aop car la classe AOP est requise lors de l'exécution.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.M4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>info.maigo.lab</groupId>
<artifactId>sample.retry.exhausted</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sample.retry.exhausted</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.retry/spring-retry -->
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</pluginRepository>
</pluginRepositories>
</project>
Générez un fichier JAR avec la commande mvn package.
$ mvn package
Démarrez le serveur en spécifiant le fichier JAR avec la commande java.
$ java -jar target/sample.retry.exhausted-0.0.1-SNAPSHOT.jar
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.2.0.M4)
HogeApplication.java
Classe d'entrée de démarrage par Spring Boot. L'annotation @EnableRetry est spécifiée pour utiliser Spring Retry.
package info.maigo.lab.sample.retry.exhausted;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.retry.annotation.EnableRetry;
@SpringBootApplication
@EnableRetry
public class HogeApplication {
public static void main(String[] args) {
SpringApplication.run(HogeApplication.class, args);
}
}
HogeController.java
Classe de contrôleur qui reçoit une requête HTTP et renvoie une réponse. Lorsqu'une exception se produit, gérez-la avec la méthode qui spécifie l'annotation @ExceptionHandler.
package info.maigo.lab.sample.retry.exhausted;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HogeController {
@Autowired
private HogeService hogeService;
@RequestMapping("/")
public Map<String, Object> index(@RequestParam(name = "name", defaultValue = "java.lang.RuntimeException") String name) throws Exception {
return new HashMap<String, Object>() {
{
put("result", hogeService.invoke(name));
}
};
}
@ExceptionHandler(Exception.class)
public Map<String, Object> handleException(HttpServletRequest req, Exception e) {
return new HashMap<String, Object>() {
{
put("handleException", e.getClass().getName() + " / " + e.getMessage());
}
};
}
}
HogeException.java
Une classe d'exception qui hérite uniquement d'Exception.
package info.maigo.lab.sample.retry.exhausted;
public class HogeException extends Exception {
}
HogeHogeException.java
Une classe d'exception qui hérite de HogeException.
package info.maigo.lab.sample.retry.exhausted;
public class HogeHogeException extends HogeException {
}
HogeService.java
Classe de service. La méthode invoke crée un objet d'exception basé sur la chaîne spécifiée et le lève. L'annotation @Retryable est spécifiée dans la méthode invoke. Inclure spécifie le type d'exception à réessayer et exclure spécifie le type d'exception à ne pas réessayer. Spécifiez le nombre de tentatives avec maxAttempts. Spécifiez le temps d'attente avant une nouvelle tentative avec interruption. La méthode avec l'annotation @Recover est appelée lorsqu'une exception se produit même après avoir essayé le nombre de fois spécifié (même si l'exception n'est pas la cible de la nouvelle tentative, cette méthode est appelée si elle correspond au type).
package info.maigo.lab.sample.retry.exhausted;
import java.lang.reflect.Constructor;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Service;
import org.springframework.retry.annotation.Recover;
@Service
public class HogeService {
@Retryable(
include = {HogeException.class},
exclude = {HogeHogeException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 1000))
public String invoke(String name) throws Exception {
System.out.println("HogeService#invoke: " + name);
Class cls = Class.forName(name);
Constructor cnst = cls.getDeclaredConstructor();
Exception e = (Exception) cnst.newInstance();
throw e;
}
@Recover
public String recover(HogeException e, String name) {
System.out.println("HogeService#recover: " + name);
return "HogeService#recover: " + e.getClass().getName();
}
}
Lorsque vous accédez au serveur démarré avec curl, JSON est généré. Spécifie qu'une HogeException doit se produire. La méthode recover renvoie une représentation sous forme de chaîne de HogeException.
$ curl http://localhost:8080/?name=info.maigo.lab.sample.retry.exhausted.HogeException
{"result":"HogeService#recover: info.maigo.lab.sample.retry.exhausted.HogeException"}
Affichez le journal de sortie standard côté serveur. Vous pouvez voir que la méthode de récupération est appelée après l'exécution de la nouvelle tentative et que la méthode d'invocation est appelée trois fois.
HogeService#invoke: info.maigo.lab.sample.retry.exhausted.HogeException
HogeService#invoke: info.maigo.lab.sample.retry.exhausted.HogeException
HogeService#invoke: info.maigo.lab.sample.retry.exhausted.HogeException
HogeService#recover: info.maigo.lab.sample.retry.exhausted.HogeException
Étant donné que HogeException est spécifié dans l'annotation include of @Retryable, le traitement de nouvelle tentative est exécuté. Si une exception se produit lors de la dernière tentative, la méthode avec l'annotation @Recover est appelée.
Accédez avec curl en spécifiant que HogeHogeException se produira. La méthode recover renvoie une représentation sous forme de chaîne de HogeHogeException.
$ curl http://localhost:8080/?name=info.maigo.lab.sample.retry.exhausted.HogeHogeException
{"result":"HogeService#recover: info.maigo.lab.sample.retry.exhausted.HogeHogeException"}
Affichez le journal de sortie standard côté serveur. Vous pouvez voir que la méthode de récupération est appelée après que la méthode invoke a été appelée une seule fois.
HogeService#invoke: info.maigo.lab.sample.retry.exhausted.HogeHogeException
HogeService#recover: info.maigo.lab.sample.retry.exhausted.HogeHogeException
HogeHogeException est spécifié dans l'exclusion de l'annotation @Retryable, le traitement de nouvelle tentative n'est donc pas effectué. J'ai appelé la méthode invoke une fois et j'ai obtenu une HogeHogeException, et la méthode recover a été appelée et la chaîne résultante a été renvoyée. De plus, HogeHogeException est une sous-classe de HogeException spécifiée dans include of @Retryable annotation, donc si HogeHogeException n'est pas spécifié dans exclude, il sera retenté.
Accédez avec curl en spécifiant que java.lang.Exception se produira. Une exception org.springframework.retry.ExhaustedRetryException est levée sans être interceptée par la méthode de récupération.
$ curl http://localhost:8080/?name=java.lang.Exception
{"handleException":"org.springframework.retry.ExhaustedRetryException / Cannot locate recovery method; nested exception is java.lang.Exception"}
Affichez le journal de sortie standard côté serveur. Vous pouvez voir que la méthode invoke n'est appelée qu'une seule fois. La méthode de récupération n'a pas été appelée.
HogeService#invoke: java.lang.Exception
Étant donné que java.lang.Exception n'est pas spécifié dans l'annotation include of @Retryable, le traitement des nouvelles tentatives n'est pas effectué. En outre, ExhaustedRetryException est levée car l'annotation @Recover n'est pas le type d'exception qui peut être interceptée par la méthode spécifiée. Dans ce cas, la méthode getCause de la classe ExhaustedRetryException peut être utilisée pour obtenir l'objet de l'exception java.lang.Exception qui l'a provoquée.
Recommended Posts