# Automatically Injecting Robustness Statements into Distributed Applications
## 4 Dependency Analysis and Code Transformation
### Code Transformation  
After performing the data dependency analysis described above, the found RMIs can be automatically refactored to ensure failure handling and asynchronous execution. The transformation employs the Failsafe library, which has been available since Java 8. Failsafe is instrumental in managing failure cases with various patterns and policies, as it offers multiple policies handling specific exceptions encountered during network communication. The appropriate response to exceptions depends on the selected policy. To enhance the client application, we implemented a Wait and Retry policy with exponential backoff. This approach entails that when an exception occurs during communication, the RMI call is retried after an exponentially increasing interval. As the number of consecutive exceptions grows, the waiting period before each entry increases. This strategy significantly enhances the robustness of the application by allowing it to overcome intermittent communication issues. Moreover, Failsafe enables the asynchronous execution of RMI by integrating the CompletableFuture library. CompletableFuture represents a future result of an asynchronous computation and provides a rich set of methods for creating, chaining, and combining asynchronous tasks. This integration can result in significant performance enhancements in Java applications [39]. By leveraging CompletableFuture within Failsafe, we notably improve the robustness and efficiency of applications, ensuring the proper handling of RMIs. The code shown in Listing 1 has been automatically transformed into the one shown in Listing 2. For the latter code, lines 7 and 8 are the refactored version of the RMI (in line 5 of the former code) using the CompletableFuture and the FailSafe libraries. The data dependency analysis has identified the instruction at line 13 as data-dependent; hence, the synchronization was inserted just before, at line 11, using the f.get() method, which returns the result obtained by the previous call to getAuthors() method once it is available, hence blocking execution when needed. The instructions were encapsulated within a try/catch statement (lines 6 and 18) to enhance the robustness and guarantee that a missed answer of the server will be handled properly. Similarly to the previous remote call at line 5 in the original code, line 6 of the original code has been refactored using the Failsafe library and is in line 9 of the transformed code. This refactoring aims at achieving robustness but without introducing asynchronous execution, given the subsequent data dependency. The integration of the Failsafe library enhances the RMI's resilience against failures, particularly network instability or transient errors, thereby maintaining operational integrity. ```
1 publicclassClient{
2 privatestaticDataInterfaceservice=newServiceProxy();
3....
4
5 publicstaticOptional<Author>extractMostReviewedAuthorParallel(){
6 try{
7 CompletableFuture<HashMap<String,Author>f=
8 Failsafe.with(retryPolicy).getAsync(()->service.getAuthors());
9 Bookbook=Failsafe.with(retryPolicy)
10.get(()->service.getMostReviewedBook());
11 HashMap<String,Author>authors=f.get();
12
13 returnauthors.values().stream()
14.filter(auth->auth.getBooks().stream()
15.anyMatch(b->b.getTitle().equals(book.get().getTitle())))
16.findFirst();
17}
18 catch(Exceptione){
19e.printStackTrace();
20 returnOptional.empty();
21}
22}
23}
```  
Listing 2: An example of the transformed code for the origin code shown in Listing 1. The getAuthors() RMI (lines 7 and 8) now uses CompletableFuture to achieve asynchronous execution and FailSafe to achieve robustness, whereas the getMostReviewedBook() RMI only uses FailSafe to achieve robustness. The synchronization instruction is inserted at line 11.