Saturday, September 17, 2022

Clean Shutdown of Spring Boot Applications

For the last 3-4 years, I have been working on Spring Boot and its associations like Spring Cloud, Spring Data and Spring Security. I have always been tempted to use the combination of [Ctrl+C] and [taskkill] for the purpose of killing spring boot applications or processes. It can be automated by a batch script, but usually i was quite lazy to do this myself, as the combination of actions used to serve the purpose! :-) Almost always on the command line, the [Ctrl+C] kills the Spring Boot application process, but the outcome is very different on Eclipse (IDE). The process outlives the [Ctrl+C] termination of spring boot application in the case of the IDE. Anyways, this unreliable and inconsistent outcomes across platforms requires us to find out standard or clean ways to shutdown Spring Boot applications and processes. Please note that this article is oriented toward the windows operating system.



GitHub Link to Clone Repository / Fork Code
https://github.com/sumithpuri/skp-spring-boot-shutdown

 

Remember, This article will explain ways to shutdown a spring boot application 'cleanly' - This means the terminating a spring boot application will also lead to its process being terminated, immediately. It is different from a graceful shutdown at the application level, where application may need to perform certain actions or wait for a certain period of time to gracefully respond to current requests or to end current processing. 

1. Terminate the Application, Kill the Process (Command Line) - IDE

The most simple method used by most developers. Click on the [Terminate - Red Square in Eclipse on the Console Tab] button. You will observer that the application immediately shuts down. But infact at the background, the tomcat server is still running on the port that it was started!

You can verify this fact by issuing this command on the command-line

 netstat -ao  


You will get one such screen - Locate the port on which you had started the Tomcat Server.



Go ahead and locate the PID and kill the task (Windows/MS-DOS)

 taskkill /F /PID 14836  


Note that if you were running the application from the command-line, You can just press [Ctrl+C] to terminate the application. In most cases, it will also kill the process. But if it does not kill the process, you should proceed with the above mentioned steps. 
 
[1a] Automate the writing of Process Id to a File
[The above mentioned task of finding out the process id associated with the application can be automated or programmed using the 'ApplicationPidFileWriter' as shown below. In the below example, when the server starts it will write the PID to the file name 'sbshutdownwin.pid'. Later, the same steps as described above can be followed to kill the process. Note that the steps can also be automated via Batch Scripting in Windows/MS-DOS]

 SpringApplication springBootapplication = new SpringApplication(SpringBootDockerApplication.class);  
 springBootapplication.addListeners(new ApplicationPidFileWriter("sbshutdownwin.pid"));  
 springBootapplication.run();  


2. Terminate the Application, Kill the Process (TCPView)

There is one another way to immediately kill the process via the TCPView tool that is made available by Microsoft. It is available at this link to download.



The next simple method is proposed by me. Beginby clicking on the [Terminate - Red Square in Eclipse on the Console Tab] button. You will observer that the application immediately shuts down. But infact at the background, the tomcat server will still be running on the port that it was started!

Use the above TCPView tool to locate the process based on the port on which you started the Tomcat Server/Spring Boot Application. Right Click on the process/row item and click on [Kill Process...] and then again Click on [OK] to confirm the killing of the operating system process. 

This is a very convenient way especially if you are a Software Architect or an Engineer who has lots of Microservices to develop/manage/maintain. It will be useful when you are in depths of testing/debugging/fixing.


3. Shutdown using Actuator Endpoint

The most 'cleanest' way among the ones I described until now is the usage of Actuator to shutdown the spring boot applications. You will begin this by making sure to the include the following in your pom.xml


Next make sure that you have enabled the shutdown endpoint via actuator using the properties as shown below.


Once you have to shutdown the application, the actuator endpoint /shutdown will also kill the associated process. This is a very clean way to shutdown the Spring Boot applications. You have to make sure that you invoke the actuator endpoint /shutdown via a [POST] request only.


 

If Spring Boot is the root context of your spring boot application, then the invocation will look like the following. The above diagram shows the response from the request sent via Postman.

 http://localhost:8080/springbootdocker/actuator/shutdown  


4. Close the Spring Boot ApplicationContext

The application context needs to be stored when you start/run the spring boot application in your spring boot application class.

 public class SpringBootDockerApplication {  
      // Clean Shutdown Method 2 - Actuator Shutdown Endpoint - Store the Context  
      // Not a Recommended Way to Use public static - Only for the Demo Purposes..  
      public static ConfigurableApplicationContext ctx;  
      public static void main(String[] args) {  
           // Clean Shutdown Method 2 - Actuator Shutdown Endpoint - Store the Context  
           ctx = SpringApplication.run(SpringBootDockerApplication.class, args);  
      }  
 }  

You may then use the following controller method to close the context asynchronously. Also, note that a PreDestroy method has been added to do any cleanup.

      // Starting Threads using Runnable is Not Always the Best Way..  
      // Do Explore Other Integrated Approaches such as Async Servlet  
      @RequestMapping(value = "/shutdown2", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)  
      public ResponseEntity<Object> rule() {  
           System.out.println("Entry Thread Id (Debug): " + Thread.currentThread().getName());  
           Runnable runnable= () -> {  
                try {  
                     Thread.sleep(2000);  
                } catch (InterruptedException e) {  
                       
                     System.out.println("Thread was Interrupted! Error in Thread Sleep (2 Seconds!)");  
                }  
                System.out.println("Callable Thread Id: " + Thread.currentThread().getName());  
                SpringBootDockerApplication.ctx.close();            
           };  
             
           new Thread(runnable).start();  
           System.out.println("Exit Thread Id (Debug): " + Thread.currentThread().getName());  
           return new ResponseEntity<>("Shutdown Requested - Will Shutdown in Next 2 Seconds!", HttpStatus.OK);  
      }  
   
        
   
      @PreDestroy  
      public void requestShutdown2PreDestroy() {  
   
           System.out.println("Requested Shutdown (via Context) of the Spring Boot Container");  
      }  

Once the above has been done, built and deployed. You may then close the spring boot using the following browser request.


You will notice that the application has been shutdown when you see the console and also the process has been removed from the operating system processes.




5. Exit using SpringApplication.exit()

The other way is use the exit() method of the SpringApplication class, it will also require to use System.exit() for ending the process. 

 -  
    // Clean Shutdown Method 2 - Actuator Shutdown Endpoint - Store the Context   
    // Not a Recommended Way to Use public static - Only for the Demo Purposes..   
    private static ConfigurableApplicationContext ctx;   
     
    public static void main(String[] args) {   
     
       // Clean Shutdown Method 2 - Actuator Shutdown Endpoint - Store the Context   
       ctx = SpringApplication.run(SpringBootDockerApplication.class, args);   
    }   
       
    public static void exitApplication() {   
       int staticExitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {   
            
        @Override   
        public int getExitCode() {   
        // no errors   
        return 0;   
        }   
       });   
       
       System.exit(staticExitCode );   
    }   
    

The controller will look similar to what we had written previously. Once your application is running and you want to shutdown the application 'cleanly', then you may use the following:


You will notice that the application has been shutdown when you see the console and also the process has been removed from the operating system processes.


Friday, September 16, 2022

Starting Docker Desktop with Spring Boot

I came across Docker Desktop for the first time about 3 years ago, when I was working as a Principal Architect (Strategic R & D) on the Microservices Reference Architecture for a product development organization. At the time, when I was working on my corporate laptop - It became a tedious task to configure virtualization and settings to get it to work. Once I got it running smoothly, I realized that the memory requirements required to run it is quite high. At times, I found it tough to use my laptop for daily development with it running. It was also because I was working on microservices and had almost 6+ spring boot applications running.  

Again, In the last month I used Docker Desktop and found it be smoother and running without any issues. This was on my personal laptop. Also, It is attributed to the fact that I was running only one Microservice.

I will take you through step-by-step to install docker desktop and to create a docker image, push it to docker and then to create/start it in a docker container. 


Requirements

1. Knowledge of Spring Boot
2. Basics of Docker Container
3. Windows 10 (Updated)
4. Docker for Windows Desktop
5. Eclipse (Spring Boot Project)



Spring Boot + Docker Desktop Example



GitHub Link to Clone Repository / Fork Code
https://github.com/sumithpuri/skp-spring-boot-docker-desktop


⦿ Install Windows Subsystem for Linux

We will first begin by installing the Windows Subsytem for Linux (WSL2). You have to make sure that your Windows 10 has got all the latest updates. Else, you will not be able to locate the features explained.

Press ÿ+I to get to Windows Settings. Search/Click on [Apps & Features] > Click on [Optional Features] > Click on [More Windows Features] > Make Sure that the [Virtual Platform/Virtualization] is already selected. If you do not see any such option, you will have to make sure that you have enabled [Virtualization] in your BIOS.

Once you have made sure that [Virtual Platform/Virtualization] is already installed, Click on [Windows Subsystem for Linux] to install it on your system. You may optionally install the [Hyper-V/Windows Hypervisor Platform]. 

More details are available at the following link.  


⦿ Install Docker for Windows Desktop

The next step is to download the Docker for Windows Desktop installable. You may download it from the official site, from this link. Please go through the installation process as it is pretty straightforward once you have all the pre-requisites. Also, make sure to create an account on [Docker Hub] using your e-mail. This can be used to push images to internet with public or private visibility.

 

⦿ Create a Spring Boot Application

The next step is to create a spring boot application. You may also update/edit your existing application to include the dockerfile and build via docker maven plugin. The example Spring Boot application can be cloned/forked from this link.


⦿ Include Maven Docker Plugin

    <properties>  
         <java.version>1.8</java.version>  
         <docker.image.prefix>spring-boot-docker</docker.image.prefix>  
         <docker.image.exposed.port>8080</docker.image.exposed.port>  
         <docker.image.dockerfile.dir>${basedir}</docker.image.dockerfile.dir>  
         <docker.image.dockerize.version>v0.6.1</docker.image.dockerize.version>  
         <docker.plugin.version>1.2.0</docker.plugin.version>  
    </properties>  

Make sure that your maven pom.xml that will be used to build the project has the following entries under <properties>. 

The below is the snippet for the [dockerfile-maven-plugin] to be added to the <plugins> section of your maven pom.xml

     <!-- dockerfile maven plugin -->  
     <plugin>  
         <groupId>com.spotify</groupId>  
         <artifactId>dockerfile-maven-plugin</artifactId>  
         <version>1.4.12</version>  
         <configuration>  
             <repository>${docker.image.prefix}/${project.artifactId}</repository>  
             <buildArgs>  
                 <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>  
             </buildArgs>  
         </configuration>  
     </plugin>  
     <!-- dockerfile maven plugin -->  


⦿ Create a Dockerfile 

 FROM openjdk:8-jdk-alpine   
 VOLUME /tmp  
 ARG JAR_FILE  
 COPY ${JAR_FILE} spring-boot-docker.jar  
 ENTRYPOINT ["java","-jar","/spring-boot-docker.jar"]  

The typical dockerfile for a spring boot application will look like the above. It contains the image of the jdk, the volume in the container for the data that is generated by container and the other line items for the binary/jar file and the command for  running this application in the container. 


⦿ Create/Push Image to Docker 

Use the following options while running maven. The plugin is the dockerfile and the goal is build. It will create and push an image to the docker for desktop that is running on port 2376.

 mvn clean install dockerfile:build  


⦿ Create/Start the Docker Container

 docker run -p 9090:8080 -t spring-boot-docker/skp-spring-boot-docker  

Next, Move to the folder where you have installed [docker]. It is a good practice to include that in the [PATH] environment variable, if you are going to frequently use docker. Then you can use the following command to create/start your docker container.


⦿ Test the Spring Boot Application 

 http://localhost:9090/springbootdocker/quote  

For this sample application, you will see that the spring boot applications gives the following output on the browser! 




The next part of this article will focus on taking this to AWS Beanstalk/EC2, so that we can deploy this container on the AWS Cloud  





Wednesday, July 27, 2022

Obelix - Microservices Reference Implementation

Guys, After much delay - Finally, I have Obelix - Microservices Reference Implementation available for use by all. Even though, It is still a work-in-progress activity and will go through possibly 5 to 10 versions before it reaches to an absolute [Gold Standard Release].

Obelix is highly recommended for all organizations adopting Microservices. The implementation is based on Spring Boot/Spring Cloud. You may base your MSA Reference Implementation in your organization on Obelix.
 

Kindly Like, Star and Fork my Repository
GitHub Linkhttps://github.com/sumithpuri/skp-msa-ri-obelix
 

Obelix - Microservices Infrastructure Components
► Messaging – RabbitMQ
► Config Server – Spring Cloud
► Config Server Refresh – Spring Cloud Bus Refresh
► API Gateway – Spring Cloud 
► Circuit Breaker – Netflix Hystrix 
► Circuit Breaker Dashboard – Spring Cloud Turbine
► Circuit Breaker Dashboard – Netflix Hystrix
► Web Services Client – SpringCloud Feign 
► Client Side Load Balancer – Ribbon
► Discovery Server – Netflix Eureka


Obelix - Microservices Demo/Test Bed (Microservices)
 Demo Service - Inventory Service
► Demo Service - Inventory Service Client
► Demo Service - SaleOrder Service 
► Demo Service - SaleOrder Service Client 





STEPS TO DEMO OBELIX – REFERENCE IMPLEMENTATION

 [Options to Shutdown a Spring Boot Application in Eclipse/Windows]

W. Simply Use the Red or Stop Button in Eclipse (May Lead to Unclean Shutdown)

X. To Kill Sys Tasks - taskkill /F /PID ?????

Y. TCP View -- https://www.rebrand.ly/tcpview

Z. Enable Spring Boot Shutdown Hook /shutdown

 

 [ Steps of Config Server Repository - Local ]

£. Create a Local GitHub Repo in Eclipse

£. Add .properties File as per Pattern > [service-name]-[profile].properties

£. Commit the Files to the Local Repo In [Eclipse]

  

[Steps to Start all Infrastructural Services]

0. rabbitmq-plugins enable rabbitmq_management

0. rabbitmq-server -detached (to start server)

1. Start the RabbitMQ Server on Port 15672

2. Start the [Discovery Server] Port 8761

3. Start the [Config Server] on Port 8888

4. Start the [Circuit Breaker]: Port 8081

5. Start the [ API Gateway ] on Port 8087

 

[Demo Services – Inventory Service and SaleOrder Service ]

A' Start the Obelix Demo Service 1 Port 8082 - Inventory Service Instance 1

A" Start the Obelix Demo Service 1 Port 8083 - Inventory Service Instance 1

B. Start the Obelix Demo Service 2 Port 8084 - SaleOrder Service

C. Demo Load Balanced Client Access to Hosted Service 1 Port 8085

D. Demo Single Node Client Access to Hosted Service 2 : Port 8086


For an even more effective Microservices Implementation, make sure to buy a copy of my book to build your thoughts on the following topics:

  1. Pains of Monolithic Architecture
  2. Needs and Motivations for Microservices
  3. Moving from Monolithic to Microservices
  4. DevOps, Planning, Testing, Agile in MSA
  5. Failurs, Pitfalls & Disadvantage of [MSA]

By the way, I really like Obelix (The Character) - Who is your favourite cartoon character?


[Update Log]
Obelix v0.1 : 20/07/2022
Obelix v0.2 : 27/07/2022

Saturday, April 23, 2022

AWS Step Functions - Integration, Logs & Docs - Part #03

 [AWS SF : Image Showing AWS Step Functions Logo]


Refer to Part-01 (AWS Step Functions - Features & Usage) of this Article 
Refer to Part-02 (AWS Step Functions - Features & Usage) of this Article
 


This series of articles will cover the Features and Usage of Step Functions. These are from the point of view of Integration with AWS API Gateway and REST Endpoints (Spring Boot) hosted on Elastic Beanstalk/EC2. Also, The discussion is from a purview of Data Management in Microservices, Transaction Management, Service Orchestration and Saga Design Pattern. 
 
 
[Important Information: The article is based on the experience of the author working on the PoC/Prototype/Pilot of AWS Step Functions, Elastic Beanstalk* (EC2), AWS API Gateway* for a Neo Bank Startup of Philippines/Singapore. It contains knowledge collated, referenced from various manuals, blogs and tutorials on the internet. The transaction shown below is a mock use-case or a mock business transaction. Any Images are copyright of their respective owners and only used for non-commercial purposes. I have verified and certify that it contains no copyright or confidential business information.]
 

 The topics covered in this specific article are :

    • API Gateway Integration   
    • Postman Invocation - SF API   
    • AWS Step Functions:Vast API*   
    • Invoking Step Functions from SF   
    • ‘Known’ Integration Issues   
    • Cloudwatch Logs
    • X-Ray Tracing   
    • EC2/Beanstalk (Optional)

[API Gateway Integration]
To understand how to perform API Gateway Integration with Step Functions, please refer to the following link: https://www.antstack.io/blog/integrating-rest-api-to-synchronous-step-functions/ It is a pretty straightforward and requires a simple understanding of REST to create the API Gateway façade over the Step Functions. It allows to invoke the Step Functions from the outside world.
 
 
 
Fig.12 : Creating AWS API Gateway Facade Over Step Functions 
(For Purposes of External Invocation via a REST API)
 
 
[Postman Invocation - SF API]
In the above explanation, once we have completed creating the API Gateway over the Step Function, we will be able to invoke the Step Function via REST API (AWS API Gateway) using SOAPUI, Postman or even the Browser. Typical Endpoint (POST) for Invocation will be as Follows:
 
[Typical Step Functions URL - REST Endpoint on AWS API Gateway]
 
 Request Body (POST)  
 {  
 "input": "{}",  
 "name": "DemoExecution-99",  
 "stateMachineArn": "arn:aws:states:us-east-1:683993062563:stateMachine:uno-state-machine-poc"  
 }  
Typical Response { "executionArn": "arn:aws:states:us-east-1:683993062563:execution:uno-state-machine- poc:DemoExecution-99", "startDate": 1.649873197406E9 }
Typical Request and Response (Mock Use-Case using Step Function)

 
If you go the ‘Executions’ UI/Screen in AWS Console for Step Functions, you can find the visual execution results and details of the given Step Function instance that was started using Postman/SOAPUI.
 
 
AWS Step Functions:Vast API*
AWS has a very vast and deep API for the purposes of integration using any of our own services. This allows us to design our UI or Monitoring or Façade API services on the basis of the Step Functions API. The documentation for the usage of AWS Step Functions API is provided at:
 
 
 
Invoking Another Step Function from a SF
Another interesting aspect is that we can chain Step Functions and invoke one Step Function from another Step Function. Even though it falls under the category of calling any AWS Service from AWS Step Functions – It can allow us to differentiate concerns of business use-case flows and allows for a cleaner integration. There is an option to either just invoke the step function and return back or to wait for it synchronously to complete its execution.
 
 
 
Fig.13 : Invoking Another Step Function from a Step Function
 
 
‘Known’ Integration Issues
  • One of the Most Common Issue when IAM Rights are Correctly Not Provided, You may get No Message with a Red Cross when Saving the Workflow – Contact DevOps for Rights
  • Another Issue is that you may not be able to Invoke/Execute the Step Function from API Gateway – In this case also, you have to contact DevOps for Rights.
  • Your Workflow will not be Saved with Blank Error or Error with a Message. It usually means that your ASL or Workflow ‘Syntax’ is not correct. Please check online manual or reference to understand the correct usage of constructs.
  • EC2/Beanstalk fails to respond to the request citing Server Error. Make sure that you add the configuration parameter SERVER_PORT=5000
 
Cloudwatch Logs
You may use cloudwatch logs to get the details on all steps including input, output. Also, you may get finer details when an exception occurs. If you have given any console print or log statements (via cloudwatch appender in log4j) in your Java/Java EE code then you will find them in this console.
 
 
 
Fig.14 : Access Logs on Cloudwatch 
(Enable Logs while Creating Step Functions)
 
 
X-Ray Tracing
X-Ray Tracing is used to track the performance of each step as well as of the the entire step function and then compare it with their historical execution. You may enable X-Ray Tracing at the time of creating the Step Function.
 
 
 
Fig.15 : X-Ray Tracing (Performance & Statistics)
 
 
EC2/Beanstalk (Optional)
You may use the EC2 or Elastic Beanstalk to host your service. Especially, while trying to Deploy for the purposes of Learning or Prototyping anything on Step Functions – Elastic Beanstalk is very easy and elegant in case of Spring Boot/REST Deployments. For a step by step example to understand on Elastic Beanstalk, please refer to: https://rebrand.ly/skp-ts-aws-eb-02 Also, You will find a very basic step by step example for AWS Step Functions over here: https://rebrand.ly/skp-ts-aws-sf-01  


Thanks and Hope you learnt the Features, Usage, Integration and Invocation of AWS Step Functions in the context of AWS API Gateway and Elastic Beanstalk/EC2. Wishing Happy and Productive Times on the Amazon Web Services Ecosystem!