Saturday 2 May 2020

Spring Retry Mechanism

Distributed this mechanism into 3 parts and configurations are as follows-

1. Simple retry :


  • Add dependency in pom.xml 

                <dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
 <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.2</version>
</dependency>


  • Add annotation in spring boot application along with @SpringBootApplication

            @EnableRetry

  • Add retry annotation on any method 
            @Retryable(value = { CustomException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))



2. Retry and recover :

  • Add dependency in pom.xml 

                <dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
 <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.2</version>
</dependency>


  • Add annotation in spring boot application along with @SpringBootApplication

            @EnableRetry

  • Add retry annotation on any method 



            @Retryable(value = { CustomException.class }, maxAttempts = 3, backoff = @Backoff(delay = 1000))
                   public String doService(String module) { }
  • Add recover annotation along with method, This method will call when all retry completed with failure. 
            @Recover
       public String getRecover(RuntimeException e) {}

3. Retry with recover and Listener:

  • Add dependency in pom.xml 

                <dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
<version>1.2.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjtools -->
 <dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.2</version>
</dependency>


  • Add annotation in spring boot application along with @SpringBootApplication

            @EnableRetry

  • Add retry annotation on any method having listener key and array of string as value



            @Retryable(listeners= {"deepRetryListener"},value = { CustomException.class }, maxAttempts = 3, backoff =                                           @Backoff(delay = 1000))
                   public String doService(String module) { }
  • Add recover annotation along with method, This method will call when all retry completed with failure. 
  •             @Recover
           public String getRecover(RuntimeException e) {}

  • Add a new class having extend RetryListenerSupport 
                    @Component
                      public class DeepRetryListener extends RetryListenerSupport {}








Friday 22 May 2015

Reloadable Configuration Files by observing any change


Some time there is need to reload config files when you change it, without restarting server. For this there is not so good example you can find on internet, So following code will help you to achieve this. This API developed using multi threading and Observable Design Pattern. First Create those class which will affected when a configuration file is change.

Two Observer class that will change as the config file change CronChangeObserver

 package com.bharat.observers;  
 import java.util.Observable;  
 import java.util.Observer;  
 public class CronChangeObserver implements Observer {  
      public void update(Observable o, Object arg) {  
           System.out.println("Cron reschedule started....since renewal property file changed");  
           //TODO call change method from here  
           System.out.println("Cron rescheduled successfully....since renewal property file changed");  
      }  
 }  
RenewalPropertyChangeObserver
 package com.bharat.observers;  
 import java.util.Observable;  
 import java.util.Observer;  
 public class RenewalPropertyChangeObserver implements Observer {  
      public void update(Observable o, Object arg) {  
           System.out.println("RenewalPropertyChangeObserver change started....since renewal property file changed");  
           //TODO call change method from here  
           System.out.println("RenewalPropertyChangeObserver change conpleted....since renewal property file changed");  
      }  
 }  

Now write a Observer that will notify all observables. PropertyChangeObservable
 package com.bharat.observable;  
 import java.text.SimpleDateFormat;  
 import java.util.Date;  
 import java.util.Locale;  
 import java.util.Observable;  
 
 public class PropertyChangeObservable extends Observable{  
      public void notifyObservers(Object arg)  
   {  
     setChanged();  
     super.notifyObservers(arg);  
   }  
   public void notifyObservers()  
   {  
     setChanged();  
     super.notifyObservers(null);  
   }  
Now a Watch Service of nio package and ChangeListener that catch changes in file. Just Instantiate it by passing Observer and File path that we have to watch, for any changes.
 package com.bharat.customer.services;  
 import java.io.IOException;  
 import java.nio.file.FileSystems;  
 import java.nio.file.Path;  
 import java.nio.file.Paths;  
 import java.nio.file.StandardWatchEventKinds;  
 import java.nio.file.WatchEvent;  
 import java.nio.file.WatchKey;  
 import java.nio.file.WatchService;  
 import java.util.Observable;  
 public class ConfigurationChangeListner implements Runnable{  
       private String configFileName = null;  
        private String fullFilePath = null;  
        private Observable observable=null;  
        public ConfigurationChangeListner(final String filePath, Observable observable) {  
          this.fullFilePath = filePath;  
          this.observable=observable;  
        }  
        public void run() {  
          try {  
               watchFile(this.fullFilePath);  
          } catch (IOException e) {  
            e.printStackTrace();  
          }  
        }  
        private void watchFile(final String file) throws IOException {  
          final int lastIndex = file.lastIndexOf("/");  
          String dirPath = file.substring(0, lastIndex + 1);  
          String fileName = file.substring(lastIndex + 1, file.length());  
          this.configFileName = fileName;           
          startWatchService(dirPath, fileName);  
        }  
        private void startWatchService(String dirPath, String file) throws IOException {  
          final WatchService watchService = FileSystems.getDefault()  
              .newWatchService();  
          Path path = Paths.get(dirPath);  
          path.register(watchService, StandardWatchEventKinds.ENTRY_MODIFY);          
          WatchKey key = null;  
          while (true) {  
            try {  
              key = watchService.take();  
              for (WatchEvent< ?> event : key.pollEvents()) {  
                if (event.context().toString().equals(configFileName)) {  
                  configurationChanged(dirPath + file);  
                }  
              }  
              boolean reset = key.reset();  
              if (!reset) {  
                System.out.println("unable to reset watch key..........");  
                break;  
              }  
            } catch (Exception e) {  
              e.printStackTrace();  
            }  
          }  
          Runtime.getRuntime().addShutdownHook(new Thread() {  
            public void run() {  
              try {  
                watchService.close();  
              } catch (IOException e) {  
                e.printStackTrace();  
              }  
            }  
          });  
        }  
        public void configurationChanged(final String file) {  
          System.out.println("Configuration Changed Notifing all observers..................");  
          observable.notifyObservers();           
        }  
 }  
A threading program that will cause to run all to observers and hat start all functionality without restart
 package com.bharat.common;  
 import java.io.File;  
 import java.net.URISyntaxException;  
 import java.text.SimpleDateFormat;  
 import java.util.Date;  
 import java.util.Locale;  
 import java.util.Observable;  
 import org.springframework.context.ApplicationContext;  
 import org.springframework.context.support.ClassPathXmlApplicationContext;  
 import com.bharat.customer.services.ConfigurationChangeListner;  
 import com.bharat.observable.PropertyChangeObservable;  
 import com.bharat.observers.CronChangeObserver;  
 import com.bharat.observers.RenewalPropertyChangeObserver;  
 public class LoadChangeResource {  
      public static void main(String args[]){  
           ApplicationContext context = new ClassPathXmlApplicationContext(  
                     new String[] { "locale.xml", "Spring-Customer.xml" });  
           File f1 =null;  
           try {  
                f1 = new File(LoadChangeResource.class.getResource("/locale/customer/messages_en_US.properties").toURI());  
           } catch (URISyntaxException e) {  
                // TODO Auto-generated catch block  
                e.printStackTrace();  
           }  
           RenewalPropertyChangeObserver renewalObs = new RenewalPropertyChangeObserver();  
           CronChangeObserver cronObs = new CronChangeObserver();  
           PropertyChangeObservable observable = new PropertyChangeObservable();  
           observable.addObserver(renewalObs);  
           observable.addObserver(cronObs);  
           String filePath=f1.getPath();       
         propertyChange(filePath,observable);  
      }  
      private static boolean propertyChange(String filePath, Observable observable) {  
           ConfigurationChangeListner listner = new ConfigurationChangeListner(filePath,observable);  
     try {  
       new Thread(listner).start();  
       while (true) {  
         Thread.sleep(2000l);          
       }  
     } catch (Exception e) {  
       e.printStackTrace();  
     }  
     return false;  
   }  
          
      public static String getCurrentTimeStamp() {  
           SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");//dd/MM/yyyy  
        Date now = new Date();  
        String strDate = sdf.format(now);  
        return strDate;  
      }  
 }  
Run this and enjoy.......