Thursday, 19 June 2025

Restfull webservices vs soap services

 

๐ŸŒ What is a RESTful Web Service?

REST (Representational State Transfer) is an architectural style used to design lightweight, scalable, and stateless web services.

✅ Key Characteristics:

  • REST uses HTTP methods like GET, POST, PUT, DELETE

  • REST returns data in the form of JSON, XML, etc. (JSON is most common)

  • REST is Stateless means, each request contains all the info needed

  • REST is easily accessible via web browser, mobile apps, etc.

  • It uses URLs to access resources

๐Ÿ“ฆ Example:

GET https://api.example.com/employees/101

Response:

{
"id": 101, "name": "John", "salary": 50000 }

๐Ÿงผ What is a SOAP Web Service?

SOAP (Simple Object Access Protocol) is a protocol for exchanging structured information using XML messages between systems over a network.

✅ Key Characteristics:

  • Soap always uses XML for both request and response

  • Soap strictly defined with WSDL (Web Services Description Language)

  • Soap Can use HTTP, SMTP, or other protocols

  • Soap supports built-in security, transactions, and reliable messaging

  • Soap is often used in enterprise-level applications (banking, telecom, etc.)

๐Ÿ“ฆ Example:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body> <getEmployee> <id>101</id> </getEmployee> </soapenv:Body> </soapenv:Envelope>

๐Ÿ” RESTful Web Services vs SOAP Web Services (Comparison Table)

Feature๐ŸŒ RESTful Web Services๐Ÿงผ SOAP Web Services
ProtocolREST can be sent over HTTP only SOAP can be sent over HTTP, SMTP, TCP
FormatJSON, XML, Text, etc.XML only
SpeedFaster (lightweight)Slower (heavy XML)
SecurityCustom (HTTPS, JWT, OAuth)Built-in (WS-Security)
StatefulnessStatelessCan be stateless or stateful
StandardsLoosely definedStrict (WSDL, XML Schema)
Error HandlingHTTP codes (404, 500, etc.)SOAP Fault
Best ForMobile apps, MicroservicesEnterprise integrations

✅ In Simple Words
RESTSOAP
Simple, fast, and flexible             Complex, strict, and secure
Mostly used in modern APIsUsed in legacy/enterprise systems
JSON is commonXML is mandatory
Good for web and mobile appsGood for financial/secure systems

Pseudo(Virtual) columns in MS SQL/My SQL/ Oracle and Mongo DB

 Pseudo columns are special types of virtual columns provided by databases to retrieve metadata or special information about a row without being part of the actual schema.

๐Ÿ”ธ 1. Oracle – Rich Pseudo Column Support

Oracle supports several pseudo columns, and they are very commonly used.

Pseudo ColumnDescriptionExample
ROWNUMReturns a number indicating the order in which a row is selected from a table.SELECT * FROM EMP WHERE ROWNUM <= 5;
ROWIDUnique ID for each row in the database (physical location of the row).SELECT ROWID, ENAME FROM EMP;
LEVELUsed with hierarchical queries (CONNECT BY).SELECT ENAME, LEVEL FROM EMP CONNECT BY PRIOR EMPNO = MGR;
SYSDATECurrent date and time.SELECT SYSDATE FROM DUAL;
SYSTIMESTAMPReturns current timestamp with time zone.SELECT SYSTIMESTAMP FROM DUAL;
USERReturns the name of the currently logged-in user.SELECT USER FROM DUAL;
CURRVAL, NEXTVALUsed with sequences to get the current or next value.SELECT SEQ_EMP.NEXTVAL FROM DUAL;

๐Ÿ”ธ 2. MySQL – Limited or Different Behavior

MySQL doesn’t have pseudo columns in the traditional Oracle sense. But some functions or keywords act similarly:

FeatureDescriptionExample
LAST_INSERT_ID()Returns the last AUTO_INCREMENT value inserted.SELECT LAST_INSERT_ID();
ROW_NUMBER() (Window Function)Not a pseudo column but provides similar use.SELECT *, ROW_NUMBER() OVER (ORDER BY id) FROM employees;
UUID()Generates a universal unique identifier (acts like a surrogate key).SELECT UUID();
NOW()Current date and time.SELECT NOW();
USER()Logged-in user info.SELECT USER();

๐Ÿ“ MySQL has virtual/generated columns, but they’re explicitly defined—not implicit pseudo columns.


๐Ÿ”ธ 3. SQL Server (MS SQL)

SQL Server doesn't have pseudo columns like Oracle, but provides similar features via functions and system-defined metadata.

FeatureDescriptionExample
@@IDENTITY, SCOPE_IDENTITY()Last inserted identity value.SELECT SCOPE_IDENTITY();
ROW_NUMBER()Assigns sequential number to rows (like ROWNUM).SELECT ROW_NUMBER() OVER (ORDER BY id) AS RowNum FROM Employees;
GETDATE()Current system date and time.SELECT GETDATE();
SYSDATETIME()Higher precision timestamp.SELECT SYSDATETIME();
SYSTEM_USERReturns the login name of the user.SELECT SYSTEM_USER;
NEWID()Generates a new GUID.SELECT NEWID();

๐Ÿ”ธ 4. MongoDB – Document-Based, No True Pseudo Columns

MongoDB is a NoSQL document store, so it doesn’t have SQL-style pseudo columns. However, you can treat some default fields as pseudo columns:

FieldDescriptionExample
_idUnique ObjectId for each document (like ROWID).db.collection.find({}, { _id: 1 })
ObjectId.getTimestamp()Timestamp from _id value.ObjectId("5f4e8f45...").getTimestamp()
$currentDate, $toDate, $nowAggregation operators for current date/time.db.collection.update({}, { $currentDate: { lastModified: true } })
$$CURRENTIn aggregation, refers to current document.Used inside $map, $filter, etc.

๐Ÿ”ธ Note: MongoDB doesn’t support row numbers or positional references like ROWNUM, but can emulate via aggregation pipelines with $group, $sort, $limit, $skip.

✅ Summary Table

DBCommon Pseudo Columns / Equivalents
OracleROWNUM, ROWID, LEVEL, SYSDATE, SYSTIMESTAMP, USER, NEXTVAL
MySQLLAST_INSERT_ID(), UUID(), NOW(), USER(), ROW_NUMBER() (window)
SQL Server@@IDENTITY, SCOPE_IDENTITY(), ROW_NUMBER(), GETDATE(), NEWID()
MongoDB_id, ObjectId.getTimestamp(), $$CURRENT, $currentDate, $now
----------------------------------------

2. Stored precedure vs function in MS Sql

Stored Procedures and Functions are reusable blocks of SQL code — but they differ significantly in purpose, features, and usage.

Here’s a full comparison of Stored Procedures vs Functions in MS SQL:

✅ 1. Definition

FeatureStored ProcedureFunction
PurposePerform actions (INSERT, UPDATE, DELETE, etc.)Return a value (scalar/table), mainly for calculations
SyntaxCREATE PROCEDURECREATE FUNCTION
Return TypeOptional, use OUTPUT parametersMandatory: must return a value

✅ 2. Syntax Example

๐Ÿ”น Stored Procedure

CREATE PROCEDURE GetUserById @userId INT AS BEGIN SELECT * FROM users WHERE id = @userId; END

๐Ÿ”น Function

CREATE FUNCTION GetUserFullName(@userId INT) RETURNS VARCHAR(200) AS BEGIN DECLARE @fullName VARCHAR(200); SELECT @fullName = first_name + ' ' + last_name FROM users WHERE id = @userId; RETURN @fullName; END

✅ 3. Return Types

FeatureStored ProcedureFunction
Scalar ReturnNo (must use output parameter)Yes (scalar or table)
Table ReturnYes (via SELECT)Yes (via RETURNS TABLE)
Multiple Result SetsYesNo

✅ 4. Usage in SQL Queries

FeatureStored ProcedureFunction
Can be used in SELECT❌ No✅ Yes (must be deterministic)
Can be used in JOIN❌ No✅ Yes (table-valued function)
Called from other SQL codeEXEC GetUserById @idSELECT dbo.GetUserFullName(@id)

✅ 5. Side Effects & DML

FeatureStored ProcedureFunction
Can modify data (DML)✅ Yes (INSERT/UPDATE/DELETE)❌ No (pure function)
Can use TRY...CATCH✅ Yes❌ No
Can use transactions✅ Yes❌ No

✅ 6. Parameters

FeatureStored ProcedureFunction
Input Parameters✅ Yes✅ Yes
Output Parameters✅ Yes (@param OUTPUT)❌ No (use return value only)
Default Values✅ Yes✅ Yes

✅ 7. Execution Context

FeatureStored ProcedureFunction
Can be executed directly✅ Yes (via EXEC)❌ No (must be called inside SQL)
Execution Plan caching✅ Yes✅ Yes

✅ 8. Performance

  • Stored Procedures are generally used for action-based tasks, transaction management, and complex logic.

  • Functions are typically used for calculation or returning data inside queries.

  • Overuse of scalar functions inside large queries may lead to performance issues (e.g., row-by-row execution).


✅ Use Case Summary

Use CaseUse Stored ProcedureUse Function
Modifying data (INSERT/UPDATE)✅ Yes❌ No
Returning single value❌ Use OUTPUT param✅ Yes (scalar function)
Returning table for joins❌ Use temp tables✅ Yes (table-valued)
Used inside SELECT or WHERE❌ Not allowed✅ Yes
Error handling with TRY...CATCH✅ Yes❌ No

✅ Final Recommendation

Use Stored Procedure When…
- You need to perform transactions (insert/update/delete).
- You want to return multiple result sets.
- You need error handling (TRY…CATCH).
- You want procedural logic (e.g., loops, conditionals).

Use Function When…
- You want to use logic inside queries (like SELECT/WHERE).
- You want to return a calculated value or derived table.
- You need deterministic logic without side effects.

Sunday, 15 June 2025

Hibernate, JPA, Microservices and Kafka annotations

 ๐Ÿ”„ Hibernate Annotations 

These annotations are used for Object-Relational Mapping (ORM) in Hibernate and JPA-based applications.


1. @Entity

  • What@Entity is a JPA (Java Persistence API) annotation used to mark a class as a persistent entity, meaning the class is mapped to a table in a relational database. Hibernate uses this annotation to recognize which classes should be stored in the database..

  • Why: Enables Hibernate to persist the object in the DB.

  • Where: On top of POJO class.

  • When: When creating a model mapped to a database table.

import javax.persistence.*; @Entity @Table(name = "employees") // optional: overrides default table name public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "emp_name", nullable = false) private String name; private String department; // Getters and Setters }


2. @Table(name = "table_name")

  • What@Table is a JPA annotation used to explicitly specify the name of the database table that an @Entity class should map to.

    If this annotation is not used, the table name is assumed to be the same as the entity class name by default.

  • Why: To map the class to a specific table.

  • Where: On top of the entity class.

  • When: When table name differs from the class name.

import javax.persistence.*; @Entity @Table(name = "employees") // Maps this class to 'employees' table public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "emp_name", nullable = false) private String name; private String department; // Getters and setters }


3. @Id

  • What: Marks the primary key of the entity.

  • Why: Hibernate requires a unique identifier for persistence.

  • Where: On a field of the entity class.

  • When: For any field acting as a primary key.

@Id
private Long id;

4. @GeneratedValue

  • What: Specifies how the primary key is generated.

  • Why: For auto-increment or sequence-based IDs.

  • Where: Along with @Id.

  • When: When the DB should generate IDs.

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;

5. @Column

  • What: Maps a field to a table column.

  • Why: To customize the column mapping (name, length, nullable).

  • Where: On entity fields.

  • When: For customization or matching different DB column names.

@Column(name = "first_name", nullable = false, length = 100)
private String firstName;

6. @OneToOne, @OneToMany, @ManyToOne, @ManyToMany

๐Ÿ”น What:

These annotations define associations between two entity classes. They instruct Hibernate (and JPA) on how to map object relationships to database relationships, especially foreign keys.


๐Ÿ“Œ Why:

In relational databases:

  • Entities are linked using foreign keys.

  • In Java, we use references or collections.

These annotations bridge the gap between object-oriented programming and relational models (ORM - Object Relational Mapping).


๐Ÿงญ Where:

  • Place on fields inside entity classes.

  • Often combined with @JoinColumn, @JoinTable, mappedBy, cascade, and fetch.


๐Ÿ•’ When to Use:

Use these when your domain model has real-world relationships:

  • Employee belongs to one Department: @ManyToOne

  • Department has many Employees: @OneToMany

  • A User has one Profile: @OneToOne

  • Students can enroll in many Courses: @ManyToMany


๐Ÿ“˜ Detailed Annotations


@OneToOne

➤ Description:

Defines a one-to-one relationship between two entities.

➤ Example:

@Entity public class User { @Id private Long id; @OneToOne @JoinColumn(name = "profile_id") // foreign key in User table private Profile profile; }

➤ Use Case:

  • A User has one Profile.

  • Place @OneToOne on the owning side (where FK exists).


@OneToMany

➤ Description:

Defines a one-to-many relationship — one entity is related to multiple instances of another entity.

➤ Example:

@Entity public class Department { @Id private Long id; @OneToMany(mappedBy = "department", cascade = CascadeType.ALL) private List<Employee> employees; }

Note: mappedBy tells Hibernate that the foreign key resides in the Employee entity.


@ManyToOne

➤ Description:

Defines a many-to-one relationship — many instances relate to one instance of another entity.

➤ Example:

@Entity public class Employee { @Id private Long id; @ManyToOne @JoinColumn(name = "department_id") // FK in Employee table private Department department; }

Typically used in the child or owning side of a bidirectional relationship.


@ManyToMany

➤ Description:

Defines a many-to-many relationship — both sides can relate to multiple instances of the other.

➤ Example:

@Entity public class Student { @Id private Long id; @ManyToMany @JoinTable( name = "student_course", joinColumns = @JoinColumn(name = "student_id"), inverseJoinColumns = @JoinColumn(name = "course_id") ) private List<Course> courses; }

This creates a join table student_course with 2 foreign keys.


๐Ÿ“Œ Additional Attributes

  • mappedBy: Indicates the field that owns the relationship (used in bidirectional mapping).

  • cascade: Enables cascading operations like PERSIST, MERGE, REMOVE.

  • fetch: Defines loading strategy (FetchType.LAZY or FetchType.EAGER).


๐Ÿงช Summary Table

AnnotationCardinalityExample Use Case
@OneToOne1 ↔ 1User ↔ Profile
@OneToMany1 ↔ ManyDepartment ↔ Employees
@ManyToOneMany ↔ 1Employee ↔ Department
@ManyToManyMany ↔ ManyStudent ↔ Course

7. @JoinColumn

  • What: Specifies the foreign key column.

  • Why: For explicitly naming and customizing joins.

  • Where: On relational fields.

  • When: In associations.


@ManyToOne @JoinColumn(name = "dept_id") private Department department;

8. @Lob

  • What: Maps large objects like BLOB or CLOB.

  • Why: For storing large text/images.

  • Where: On entity fields.

  • When: For binary or large content.


9. @Temporal

  • What: Maps java.util.Date or Calendar to SQL date/time.

  • Why: To handle date types properly.

  • Where: On date/time fields.

  • When: When storing time-sensitive data.


@Temporal(TemporalType.DATE) private Date dob;

10. @Transient

  • What: Excludes a field from persistence.

  • Why: For non-persistent calculated or helper fields.

  • Where: On entity fields.

  • When: When field should not be saved to DB.


⚙️ Kafka Annotations in Spring Boot

1.@KafkaListener

What: @KafkaListener is a Spring annotation used to designate a method as a Kafka message consumer.

Why:
  • Automates the message consumption process from a Kafka topic.

  • Eliminates the need to manually poll the topic.

  • Supports batch consumption, filtering, error handling, concurrency, etc.


Where:

  • Applied to a method in a Spring-managed bean (typically a @Service or @Component class).


When:

  • Used when you want to consume messages from a Kafka topic, typically in event-driven microservices.


๐Ÿงฉ Example:

import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Service; @Service public class OrderConsumerService { @KafkaListener(topics = "orders", groupId = "order-service") public void consume(String message) { System.out.println("Received: " + message); } }

2. @KafkaHandler

What

@KafkaHandler is used to handle multiple message types (i.e., method overloading) within a single Kafka consumer class that is annotated with class-level @KafkaListener.


Why

  • Kafka normally maps one listener method to one topic. But when you want to consume different object types from the same topic, @KafkaHandler allows handling them in separate methods.

  • This is useful for polymorphic deserialization — messages are deserialized to different POJOs based on type.


Where

  • Used on multiple methods inside a class that has a class-level @KafkaListener.

  • Each method has a unique parameter type (POJO, String, etc.).


When

Use @KafkaHandler:

  • When you want a single Kafka consumer to process different message types from a single topic.

  • When working with message classes like OrderCreated, OrderCancelled, etc., all published to the same topic.

Example

Suppose you have a topic named "events" that sends different message types:

json

// 1st message { "type": "email", "to": "user@example.com", "subject": "Welcome" } // 2nd message { "type": "sms", "to": "+911234567890", "content": "Your OTP is 1234" }

✅ POJO Classes

java

public class EmailNotification { private String to; private String subject; // getters and setters } public class SMSNotification { private String to; private String content; // getters and setters }

✅ Kafka Consumer with @KafkaHandler

java

@KafkaListener(topics = "events", groupId = "notification-group") public class NotificationHandler { @KafkaHandler public void handleEmail(EmailNotification email) { System.out.println("Received email: " + email.getSubject()); } @KafkaHandler public void handleSMS(SMSNotification sms) { System.out.println("Received SMS: " + sms.getContent()); } // Fallback handler @KafkaHandler(isDefault = true) public void handleUnknown(Object obj) { System.out.println("Unknown message: " + obj); } }

๐Ÿ”ง Required Configuration for Deserialization

You must configure a message converter to automatically convert JSON messages to their respective Java objects:

java

@Bean public RecordMessageConverter messageConverter() { return new StringJsonMessageConverter(); }

3. @SendTo

  • What: Sends reply to another topic.

  • Why: For request-reply patterns.

  • Where: On Kafka consumer methods.

  • When: When response is needed after processing.


@KafkaListener(topics = "request-topic") @SendTo("response-topic") public String handleRequest(String request) { return "Processed: " + request; }

4. @EnableKafka

What

@EnableKafka is a Spring annotation that enables support for Kafka listener annotations like @KafkaListener, @KafkaHandler, etc.


Why

By default, Spring Boot does not scan or activate Kafka listener infrastructure.

  • This annotation registers the Kafka listener container factory and related beans in the Spring context.

  • Without @EnableKafka, your @KafkaListener methods will be ignored and not invoked, even if correctly defined.


Where

  • On a Java configuration class (annotated with @Configuration).

  • Typically, the class where you define Kafka-related beans like ConsumerFactory, ConcurrentKafkaListenerContainerFactory, etc.


When

  • Once per application, typically at startup.

  • Required only if you use annotation-based Kafka listeners, like @KafkaListener.


✅ Example

๐Ÿ“„ Kafka Configuration Class

import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka; @Configuration @EnableKafka public class KafkaConfig { // Optional: Kafka consumer or producer bean definitions }

This is the minimum requirement to allow Spring to detect and activate Kafka listener methods.


๐Ÿง  Behind the Scenes

Internally, @EnableKafka:

  • Registers a KafkaListenerAnnotationBeanPostProcessor.

  • That bean processes all @KafkaListener annotations during application context initialization.

  • It then creates Kafka listener containers for each listener method.

Without this setup, message consumption won't happen even if topics are available and properly configured.


๐Ÿ”ง Typically used alongside

You usually combine @EnableKafka with Kafka consumer configurations like:

@Bean
public ConsumerFactory<String, String> consumerFactory() { Map<String, Object> props = new HashMap<>(); props.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092"); props.put(ConsumerConfig.GROUP_ID_CONFIG, "my-group"); props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class); return new DefaultKafkaConsumerFactory<>(props); } @Bean public ConcurrentKafkaListenerContainerFactory<String, String> kafkaListenerContainerFactory() { ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>(); factory.setConsumerFactory(consumerFactory()); return factory; }

✅ Summary Table

AttributeDescription
WhatEnables Spring to detect and process Kafka-related annotations
WhyRequired to make @KafkaListener, @KafkaHandler work
WhereIn a @Configuration class
WhenOnce per application — at app configuration/startup

๐Ÿงฑ Microservices Related Annotations


1. @EnableDiscoveryClient

  • What@EnableDiscoveryClient is a Spring Cloud annotation that enables service registration and discovery capabilities in a Spring Boot application.

    It tells the application to register itself with a Discovery Server like:

    • Eureka

    • Consul

    • Zookeeper

  • Why: To register microservices with Eureka/Consul.

  • Where: On Spring Boot app class.

  • When: When using service discovery.

@SpringBootApplication
@EnableDiscoveryClient
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

2. @LoadBalanced

  • What@LoadBalanced is a Spring Cloud annotation used to enable client-side load balancing on a RestTemplate or WebClient. Enables client-side load balancing using Ribbon.

It allows the client to resolve service names (like http://order-service) into actual instances using the service discovery registry (like Eureka or Consul).

  • Why: To distribute REST calls across service instances.

In microservices, multiple instances of the same service may be running for scalability and resilience. Instead of hardcoding IPs or ports, you use the service name:

java
restTemplate.getForObject("http://order-service/orders", String.class);
  • Where: On RestTemplate bean.

  • When: In clients calling other microservices.

@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }

3. @EnableFeignClients

  • What: Enables use of Feign declarative REST clients.

@EnableFeignClients is a Spring Cloud annotation that enables the use of Feign, a declarative HTTP client, in your Spring Boot application.

It scans your project for interfaces annotated with @FeignClient and auto-generates implementations that handle HTTP requests to other microservices.

  • Why: To simplify inter-service HTTP calls.

  • Where: On main Spring Boot app or config class.

  • When: When using Feign clients.

@SpringBootApplication
@EnableFeignClients
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

4. @FeignClient(name = "user-service")

What

@FeignClient is a Spring Cloud annotation used to declare an interface as a REST client for another microservice.

It tells Spring to generate a proxy implementation of the interface that:

  • Automatically resolves the service name (user-service) using a discovery client (like Eureka)

  • Sends HTTP requests to the corresponding service

  • Handles serialization and deserialization of request/response data


Why

Using @FeignClient simplifies HTTP communication between microservices by:

  • Eliminating manual RestTemplate setup

  • Avoiding repetitive HTTP call code

  • Supporting fallback mechanisms with Resilience4j or Hystrix

  • Integrating easily with Spring Cloud components (like Eureka, Ribbon/Spring LoadBalancer)


Where

Place @FeignClient(name = "user-service"):

  • On a Java interface

  • That declares methods for calling REST endpoints on the user-service


When

Use @FeignClient:

  • When your service calls another microservice over HTTP

  • When using Eureka/Consul for dynamic service discovery

  • When you want clean, type-safe, declarative HTTP calls


✅ Example Usage

Let’s say your order-service wants to fetch user info from user-service.


1. ๐Ÿ“„ Enable Feign Clients

@SpringBootApplication @EnableFeignClients public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }

2. ๐Ÿ“„ Define Feign Client Interface

@FeignClient(name = "user-service") // name must match the Eureka service ID public interface UserClient { @GetMapping("/users/{id}") User getUser(@PathVariable("id") Long id); 
}

5. @CircuitBreaker, @Retry, @RateLimiter, @Bulkhead

  • What: Provide fault tolerance and resilience.

  • Why: To handle microservice failures gracefully.

  • Where: On service methods.

  • When: For timeout handling, retries, etc.

(from Resilience4j, a lightweight fault tolerance library)

These annotations help microservices stay resilient under failure, load, or latency by offering fault tolerance patterns like circuit breakers, retries, rate limiting, and thread isolation.


✅ A. @CircuitBreaker

๐Ÿ”น What

Monitors the failure rate of a method and opens the circuit if the failure threshold is breached. Prevents further calls until the service is considered healthy again.

๐Ÿ”น Why

To avoid repeated failed calls to a service that’s down or slow, improving system stability and responsiveness.

๐Ÿ”น Where

On service methods that call remote services (e.g., REST APIs via Feign or RestTemplate).

๐Ÿ”น When

Use it when calling unreliable downstream services.

Example:

@CircuitBreaker(name = "userService", fallbackMethod = "fallback")
public String callUserService() { return restTemplate.getForObject("http://user-service/users/1", String.class); } public String fallback(Throwable ex) { return "User service is down. Please try later."; }

๐Ÿ”น Configuration (in application.yml)

yaml
resilience4j.circuitbreaker:
instances: userService: registerHealthIndicator: true slidingWindowSize: 10 failureRateThreshold: 50 waitDurationInOpenState: 5s

✅ B. @Retry

๐Ÿ”น What

Automatically retries a failed method a fixed number of times.

๐Ÿ”น Why

To handle temporary failures (e.g., network issues, service timeouts) without failing immediately.

๐Ÿ”น Where

On methods calling remote services.

๐Ÿ”น When

Use when there’s a high probability of transient failure that can be resolved with a retry.

Example:

@Retry(name = "userService", fallbackMethod = "fallback")
public String callUserService() { return restTemplate.getForObject("http://user-service/users/1", String.class); } public String fallback(Throwable t) { return "Temporary issue. Please try again later."; }

๐Ÿ”น Configuration:

yaml
resilience4j.retry:
instances: userService: maxAttempts: 3 waitDuration: 1s

✅ C. @RateLimiter

๐Ÿ”น What

Limits the rate of method invocations.

๐Ÿ”น Why

To protect your service from being overwhelmed by too many requests in a short period.

๐Ÿ”น Where

On methods that can tolerate throttling, such as public APIs or heavy DB operations.

๐Ÿ”น When

Use when you need to control traffic to prevent overloading the system.

Example:

java
@RateLimiter(name = "userService", fallbackMethod = "fallback") public String callUserService() { return restTemplate.getForObject("http://user-service/users/1", String.class); } public String fallback(RequestNotPermitted ex) { return "Too many requests. Try again later."; }

๐Ÿ”น Configuration:

yaml
resilience4j.ratelimiter: instances: userService: limitForPeriod: 5 limitRefreshPeriod: 1s

✅ D. @Bulkhead

๐Ÿ”น What

Limits the number of concurrent calls to a method, isolating failures.

๐Ÿ”น Why

To prevent resource exhaustion (e.g., thread or memory) by restricting how many requests can be processed in parallel.

๐Ÿ”น Where

On high-latency or high-resource methods.

๐Ÿ”น When

Use when you need to isolate components to contain failure to a specific section of the system.

Example:

@Bulkhead(name = "userService", fallbackMethod = "fallback")
public String callUserService() { return restTemplate.getForObject("http://user-service/users/1", String.class); } public String fallback(Throwable t) { return "Service busy. Please try again later."; }

๐Ÿ”น Configuration:

yaml
resilience4j.bulkhead:
instances: userService: maxConcurrentCalls: 5 maxWaitDuration: 0

๐Ÿ”„ Summary Table

AnnotationPurposeUse Case
@CircuitBreakerPrevents repeated failed callsUnstable or flaky downstream service
@RetryRetries failed calls automaticallyTemporary issues (e.g., timeouts)
@RateLimiterControls number of calls per secondPublic APIs, database-intensive operations
@BulkheadLimits concurrent executionsProtect system from thread starvation

๐Ÿ› ️ Dependencies

To use these annotations, add the following dependency:

xml
<dependency> <groupId>io.github.resilience4j</groupId> <artifactId>resilience4j-spring-boot2</artifactId> </dependency>