Spring Boot Interview Questions
Spring Boot Interview Questions
Spring Boot is a Spring module which provides RAD (Rapid Application Development) feature
to Spring framework.
It is used to create standalone spring based application that you can just run because it
needs very little spring configuration.
In Spring Boot, annotations are used to simplify configuration without extensive XML
configuration.
o Create stand-alone Spring applications that can be started using java -jar.
o Embed Tomcat, Jetty or Undertow directly. You don't need to deploy WAR files.
o It provides opinionated 'starter' POMs to simplify your Maven configuration.
o It automatically configure Spring whenever possible.
Notes:
1. Embedded Servers:
o Traditionally, in a Java EE application, you'd deploy a WAR file to a separate web
server (like Tomcat or Jetty). The web server runs independently, and the WAR file
is deployed to it.
o In Spring Boot, the server is embedded directly into the application. This means
that when you run the application, it automatically starts an embedded server
(e.g., Tomcat, Jetty, or Undertow) to serve the application. You don't need a
separate server running or deployment step.
2. No Need for WAR Deployment:
o In a traditional Spring MVC application, you would build your project as a WAR
file and deploy it to an external web server. With Spring Boot, you can package
the application as a JAR file and it will run with its own embedded web server,
without the need for a WAR file or an external web container.
o This simplifies deployment since you don't need to configure the server
separately.
Benefits:
1. Simplified Deployment: No need to worry about managing separate application servers
or deploying to them. You just run your application with java -jar and it handles
everything.
2. Standalone Applications: With an embedded server, your Spring Boot application is
completely self-contained and can be executed directly as a standalone application.
3. Ease of Use: Spring Boot makes it simple to configure and customize the embedded
server using properties in the application.properties or application.yml.
Cross Questions:
1. What if we want to use Jetty or Undertow instead of Tomcat?
o Answer: "Spring Boot allows you to easily switch between different embedded
servers by adding the corresponding dependency. For example, to use Jetty, you
can add spring-boot-starter-jetty instead of spring-boot-starter-tomcat in your
pom.xml."
2. Can we still deploy a Spring Boot app as a WAR file if needed?
o Answer: "Yes, Spring Boot supports both JAR (with embedded server) and WAR
deployment. If you need to deploy it to an external server, you can package it as a
WAR file and deploy it like a traditional Spring application."
3. What is the difference between using a JAR with an embedded server vs. a WAR file?
o Answer: "A JAR file with an embedded server is self-contained and can be
executed directly, while a WAR file needs to be deployed to an external server like
Tomcat or Jetty. The embedded approach is easier for microservices and cloud-
native applications because it avoids the need for external server setup."
Cross-Questions in Interviews:
1. Can you customize the dependencies in a Spring Boot starter?
o Answer: "Yes, although Spring Boot provides opinionated defaults, you can
always exclude or override the default dependencies in a starter if you need
more control. For example, if you want to use a different version of a library or
a different implementation, you can customize it in your pom.xml file."
2. What would happen if you didn't use a starter POM?
o Answer: "If you don’t use a starter POM, you would need to manually configure
each dependency for the libraries you need in your application. This could make
the configuration much more complex and error-prone, especially as the project
grows."
3. Is it possible to use more than one starter in a Spring Boot application?
o Answer: "Yes, you can include multiple starters in a Spring Boot application. For
example, you might use spring-boot-starter-web for web development and
spring-boot-starter-data-jpa for data persistence. You can combine them to
achieve the desired functionality."
4. What is the difference between spring-boot-starter-web and spring-boot-starter-
webflux?
o Answer: "spring-boot-starter-web is used for building traditional servlet-based
web applications using Spring MVC, whereas spring-boot-starter-webflux is used
for reactive programming with Spring WebFlux, which supports non-blocking,
event-driven applications."
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>spring-boot-war-example</artifactId>
<version>1.0</version>
<packaging>war</packaging> <!-- Change packaging type to WAR -->
<dependencies>
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class SpringBootWarExampleApplication extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringBootWarExampleApplication.class);
}
}
Explanation of Changes:
1. packaging set to war:
o Tells Maven to generate a WAR file instead of the default JAR file.
2. spring-boot-starter-tomcat with provided scope:
o Ensures that the embedded Tomcat is not included in the WAR file since the
external servlet container will provide it.
3. Extending SpringBootServletInitializer:
o Configures the Spring Boot application to work as a traditional WAR that can be
deployed to an external servlet container.
Example Output:
Access URL: Once deployed, you can access the application at:
http://localhost:8080/spring-boot-war-example
1. Core Annotations
@SpringBootApplication
Purpose: Main annotation to bootstrap a Spring Boot application.
Explanation: Combines three annotations:
o @Configuration: Marks the class as a source of bean definitions.
o @EnableAutoConfiguration: Enables Spring Boot’s auto-configuration
mechanism.
o @ComponentScan: Scans the specified package for Spring components.
Example:
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@Service
class MyService {}
@Repository
class MyRepository {}
@Controller
class MyController {}
@GetMapping("/user/{id}")
public String getUser(@PathVariable int id) {
return "User ID: " + id;
}
5. Configuration Annotations
@Configuration
Purpose: Marks a class as a source of bean definitions.
@Bean
Purpose: Declares a Spring-managed bean.
Example:
@Configuration
class MyConfig {
@Bean
public MyService myService() {
return new MyService();
}
}
6. Transaction Management
@Transactional
Purpose: Declares transactional boundaries.
Example:
@Service
@Transactional
public class UserService {
public void saveUser(User user) {
userRepository.save(user);
}
}
7. Testing Annotations
@SpringBootTest
Purpose: Used for integration tests.
@MockBean
Purpose: Creates a mock of a bean for testing.
Example:
@SpringBootTest
public class MyServiceTest {
@MockBean
private MyRepository repository;
@Autowired
private MyService service;
}
Cross Questions
1. What’s the difference between @Component, @Service, and @Repository?
o Answer: Functionally similar, but they are semantically categorized for readability
and use case differentiation.
2. How does @SpringBootApplication differ from @EnableAutoConfiguration?
o Answer: @SpringBootApplication includes @EnableAutoConfiguration but also
enables component scanning and Java-based configuration.
3. Can @RestController be replaced with @Controller?
o Answer: Yes, but you’ll need to use @ResponseBody on each method.
4. How does @Transactional work under the hood?
o Answer: It uses proxies to manage transactions at the method level. On method
entry, a transaction begins, and it commits or rolls back depending on the
outcome.
1. @Controller
Purpose: Used to define a controller in a Spring MVC application that returns views (e.g., JSP,
Thymeleaf) or responses based on view resolvers.
Behavior:
o Methods in a @Controller class typically return view names that map to a template
(e.g., return "home" for home.html).
o If a method needs to return a JSON or XML response, you must annotate it with
@ResponseBody to indicate that the return value is the response body, not a view name.
Example:
@Controller
@GetMapping("/welcome")
@GetMapping("/api/data")
@ResponseBody
2. @RestController
Purpose: A specialized version of @Controller used to create RESTful web services that return
data (like JSON or XML) directly in the HTTP response body.
Behavior:
o Methods in a @RestController return data directly, without the need to annotate each
method with @ResponseBody.
Example:
@RestController
@GetMapping("/api/data")
Key Differences
For rendering views (HTML, JSP, For building REST APIs (JSON/XML
Primary Use
Thymeleaf). responses).
Requires
Yes, for returning response data. No, it's built-in.
@ResponseBody
When to Use @ResponseBody Instead of @RestController
1. If your class primarily serves views but has a few endpoints that return JSON or XML, use
@ResponseBody for those specific methods.
2. If your class is focused on building REST APIs, use @RestController to avoid adding
@ResponseBody to every method.
3. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping
Purpose: Shortcut annotations for HTTP methods like GET, POST, PUT, DELETE.
Use Case: To define specific endpoints for different HTTP operations.
Example:
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users")
public List<User> getUsers() {
return userService.findAll();
}
@PostMapping("/users")
public User createUser(@RequestBody User user) {
return userService.save(user);
}
}
Cross Questions:
o Can @RequestMapping replace these annotations?
o How to handle different HTTP methods on the same endpoint?
4. @RequestMapping
Purpose: General mapping annotation for defining routes. Can handle multiple HTTP
methods.
Use Case: When you need flexible mappings with multiple HTTP methods or complex
URLs.
Example:
@RestController
@RequestMapping("/api")
public class ProductController {
@RequestMapping(value = "/products", method = RequestMethod.GET)
public List<Product> getProducts() {
return productService.findAll();
}
}
In a traditional Spring MVC application (prior to the introduction of the shortcut annotations
like @GetMapping, @PostMapping, @PutMapping, and @DeleteMapping), you would use the
@RequestMapping annotation and explicitly specify the HTTP method using the method
attribute.
Here's how it was done:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class MyController {
@RestController
public class MyRestController {
@GetMapping("/getExample")
public String getExample() {
return "GET request received";
}
@PostMapping("/postExample")
public String postExample() {
return "POST request received";
}
@PutMapping("/putExample")
public String putExample() {
return "PUT request received";
}
@DeleteMapping("/deleteExample")
public String deleteExample() {
return "DELETE request received";
}
}
Key Differences
Shortcut Annotations
Feature @RequestMapping (Traditional)
(@GetMapping, etc.)
Readability More verbose and less intuitive. Cleaner and more readable.
Supports multiple HTTP methods in one Specific to one HTTP method per
Flexibility
annotation. annotation.
5. @Service
Purpose: Marks a class as a service (business logic layer). Internally uses @Component.
Use Case: To separate business logic from the controller layer.
Example:
@Service
public class UserService {
public List<User> findAll() {
// Business logic here
}
}
Cross Questions:
o Difference between @Service and @Component?
o Can we use @Service without @Autowired?
1. @Component
Purpose: A generic stereotype used to denote any Spring-managed component.
Usage:
o Applied to classes that act as general components in the application, such as
utility classes or any custom-defined beans.
o Serves as the parent stereotype for other specific annotations like @Service,
@Controller, and @Repository.
Example:
@Component
public class MyUtility {
public String process() {
return "Utility processing...";
}
}
2. @Service
Purpose: A specialization of @Component, specifically intended for service-layer classes.
Usage:
o Indicates that a class contains business logic or service methods.
o May be used in conjunction with AOP (Aspect-Oriented Programming) features
like transactions.
Example:
@Service
public class MyService {
public String performService() {
return "Service logic executed!";
}
}
Key Differences
@Component
public class MyComponent {
private final MyService myService = new MyService(); // Manual instantiation (not ideal)
6. @Repository
Purpose: Specialization of @Component. Used for the persistence layer, such as
database interaction.
Use Case: To define DAO (Data Access Object) components.
Example:
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
List<User> findByName(String name);
}
Cross Questions:
o Why do we need @Repository when @Component exists?
o What happens if we don't use @Repository on a DAO class?
The @Repository annotation in Spring is a specialization of @Component with additional
semantics and behaviors tailored for Data Access Object (DAO) classes. While both @Repository
and @Component result in a Spring-managed bean, there are specific reasons why @Repository
is preferred for DAO classes.
@Repository
public class UserDao {
7. @Component
Purpose: Marks a class as a Spring-managed component (generic stereotype).
Use Case: When a class doesn’t fit into a specific stereotype like @Service or
@Repository.
Example:
@Component
public class EmailNotificationService {
public void sendEmail(String message) {
// Logic for sending emails
}
}
Cross Questions:
o How does Spring discover classes with @Component?
o Can you replace @Component with other annotations?
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication scans all packages under com.example.demo by default.
1. Specialized Annotations
@Controller: Indicates a web controller in the MVC layer.
@Service: Indicates a service layer component containing business logic.
@Repository: Indicates a persistence layer component (DAO) and enables exception
translation.
These annotations are functionally equivalent to @Component but provide additional semantics
and readability.
@Component
public @interface MyCustomAnnotation {
// Add additional metadata if required
}
Usage:
@MyCustomAnnotation
public class MyBean {
public void doSomething() {
System.out.println("Custom annotation works!");
}
}
Spring treats the custom annotation as a @Component because it is meta-annotated with
@Component.
@Component
public @interface TaskHandler {
// Custom annotation for task-related beans
}
Usage:
@TaskHandler
public class TaskManager {
public void manageTask() {
System.out.println("Managing tasks...");
}
}
8. @Autowired
Purpose: Used to inject dependencies into a class.
Use Case: To achieve dependency injection without manually creating objects.
Example:
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
Constructor Injection:
Definition: Dependencies are injected through the constructor of the class.
Example:
@Service
public class OrderService {
private final OrderRepository orderRepository;
Key Differences:
Cross Questions:
Which type of injection is recommended in Spring?
o Constructor injection is recommended because it promotes immutability and
makes dependencies explicit.
Can you mix field and constructor injection in the same class?
o Yes, but it's generally discouraged as it can lead to inconsistent and harder-to-
maintain code.
Scenarios:
1. Using @Autowired:
o By default, @Autowired is required. If the bean is not found, Spring throws:
UnsatisfiedDependencyException: Error creating bean with name [...]
o Solution: Use @Autowired(required = false) if the dependency is optional:
@Autowired(required = false)
private SomeService someService;
2. Using @Qualifier:
o If multiple beans of the same type exist but no specific bean is qualified, Spring
throws:
NoUniqueBeanDefinitionException
o Solution: Specify the desired bean explicitly using @Qualifier:
@Autowired
@Qualifier("specificBeanName")
private SomeService someService;
3. Using Constructor Injection:
o If a required constructor dependency is missing, the application fails to start with:
UnsatisfiedDependencyException
o Solution: Ensure all required beans are defined in the context.
4. Using Optional:
o Mark the dependency as optional to handle cases where the bean might not be
present:
@Autowired
private Optional<SomeService> someService;
Cross Questions:
What happens if two beans of the same type are present?
o Spring throws a NoUniqueBeanDefinitionException.
o Solution: Use @Primary or @Qualifier.
What is the use of @Primary in Spring?
o @Primary marks a bean as the default choice when multiple candidates are
available:
@Primary
@Bean
public SomeService someServiceImpl() {
return new SomeServiceImpl();
}
What are the alternatives to @Autowired?
o Alternatives include @Inject (from JSR-330) and XML-based configuration.
9. @Configuration
Purpose: Indicates that a class contains bean definitions and configuration settings.
Use Case: To define application-specific beans.
Example:
@Configuration
public class AppConfig {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Cross Questions:
o Difference between @Configuration and @Component?
o Can a class annotated with @Configuration contain @ComponentScan?
Bean Typically used to declare multiple beans Generally used for components like
Declaration using @Bean annotated methods. services, controllers, or repositories.
Feature @Configuration @Component
10. @Bean
Purpose: Used to define a bean within @Configuration classes.
Use Case: To manually define and control bean lifecycles.
Example:
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
Cross Questions:
o What is the default scope of a bean?
o Can a bean method have parameters?
Example:
@Component
public class MySingletonBean {
public void doSomething() {
System.out.println("Singleton instance invoked!");
}
}
@RestController
public class TestController {
@Autowired
private MySingletonBean mySingletonBean1;
@Autowired
private MySingletonBean mySingletonBean2;
@GetMapping("/test")
public String testSingleton() {
System.out.println(mySingletonBean1 == mySingletonBean2); // Prints: true
return "Check console for output";
}
}
Cross Questions:
What are the other scopes available in Spring?
1. prototype: Creates a new instance each time the bean is requested.
2. request: One instance per HTTP request (web applications).
3. session: One instance per HTTP session (web applications).
4. application: One instance per ServletContext.
5. websocket: One instance per WebSocket lifecycle.
When should you use prototype over singleton?
o Use prototype when each bean instance requires a different state, such as in
stateful components like HTTP requests or threads.
Can a singleton bean depend on a prototype bean?
o Yes, but it requires special handling, typically using the @Lookup annotation or a
Provider.
11. @EnableAutoConfiguration
Purpose: Enables Spring Boot’s auto-configuration feature.
Use Case: Automatically configures components like data sources, message queues, etc.,
based on dependencies in the classpath.
Example:
@SpringBootApplication
public class Application {
}
(Included implicitly in @SpringBootApplication)
Cross Questions:
o What if I want to exclude a specific auto-configuration?
o Can we use @EnableAutoConfiguration without @SpringBootApplication?
Using excludeName:
You can also use the fully qualified name of the auto-configuration class:
@SpringBootApplication(excludeName =
"org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration")
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
Cross Questions:
How do I find the list of auto-configurations in Spring Boot?
o Use the --debug flag when starting the application. It will log all enabled and
excluded auto-configurations.
java -jar myapp.jar --debug
What happens if you exclude a required auto-configuration?
o If you exclude a critical auto-configuration, the application context may fail to
start due to missing required beans.
Cross Questions:
What’s the difference between @EnableAutoConfiguration and
@SpringBootApplication?
o @SpringBootApplication is a convenience annotation that combines:
1. @EnableAutoConfiguration - Enables auto-configuration.
2. @ComponentScan - Scans for components, services, and repositories.
3. @Configuration - Marks the class as a source of bean definitions.
Why would you use @EnableAutoConfiguration without @SpringBootApplication?
o In scenarios where you want finer control over the application context or do not
want to include all the default behaviors provided by @SpringBootApplication.
Can I use custom packages for scanning with @EnableAutoConfiguration?
o No, @EnableAutoConfiguration only configures beans. Use @ComponentScan to
specify custom packages.
12. @Transactional
Purpose: Manages database transactions, ensuring atomicity and rollback on failure.
Use Case: To handle operations involving multiple database calls.
Example:
@Service
public class AccountService {
@Transactional
public void transferFunds(Long fromAccount, Long toAccount, Double amount) {
debit(fromAccount, amount);
credit(toAccount, amount);
}
}
Cross Questions:
o How does Spring manage transactions under the hood?
o What happens if you annotate a private method with @Transactional?
How It Works:
1. Proxy Creation:
o Spring creates a proxy object for the bean containing the transactional method.
o This proxy intercepts method calls and applies transactional logic before and
after the method execution.
2. Transaction Interception:
o When a method annotated with @Transactional is invoked, the proxy:
Opens a transaction (if none exists).
Executes the method within the transactional context.
Commits the transaction if the method executes successfully.
Rolls back the transaction in case of an exception.
3. Transaction Management:
o Spring uses a PlatformTransactionManager to coordinate the transaction with
the underlying database.
o Common implementations include:
DataSourceTransactionManager (JDBC transactions).
JpaTransactionManager (JPA or Hibernate transactions).
Example:
@Service
public class OrderService {
@Transactional
public void placeOrder(Order order) {
// Transaction starts here
orderRepository.save(order);
paymentService.processPayment(order);
// Transaction commits here
}
}
Cross Questions:
What is propagation in transactions?
o Transaction propagation defines how transactions interact when a
transactional method calls another transactional method.
o Example: REQUIRED, REQUIRES_NEW, NESTED.
How does Spring determine the rollback policy?
o By default, Spring rolls back transactions for unchecked exceptions
(RuntimeException or subclasses).
o To roll back for checked exceptions, explicitly configure
@Transactional(rollbackFor = Exception.class).
What are isolation levels in transactions?
o Isolation levels define how transactions interact with each other, e.g.,
READ_COMMITTED, REPEATABLE_READ, etc.
Example:
@Service
public class OrderService {
@Transactional
public void placeOrder(Order order) {
saveOrder(order); // Transactional logic applies here
}
@Transactional
private void saveOrder(Order order) {
orderRepository.save(order); // This is ignored by Spring
}
}
Result: The saveOrder method will not be executed within a transaction context because
it's private.
Cross Questions:
How do you handle transactional logic for private methods?
o Refactor the private method to be public or protected.
o Use programmatic transaction management with TransactionTemplate.
What are the limitations of Spring's proxy-based AOP?
o Cannot intercept calls to private methods.
o Self-invocation (calling another method within the same class) bypasses proxies
and doesn't apply AOP logic.
Can we use @Transactional on interfaces?
o Yes, Spring AOP works at the interface level when using JDK dynamic proxies. For
class-based proxies, it works on class methods.
// EmailMessageService.java
public class EmailMessageService implements MessageService {
@Override
public String getMessage() {
return "Email Message Service";
}
}
Step 3: Creating the Consumer Class
Now, we’ll create a consumer class MessagePrinter that depends on MessageService.
// MessagePrinter.java
public class MessagePrinter {
private MessageService messageService;
// EmailMessageService.java
import org.springframework.stereotype.Service;
@Service
public class EmailMessageService implements MessageService {
@Override
public String getMessage() {
return "Email Message Service";
}
}
Step 3: Creating the Consumer Class
Now, we’ll create a consumer class MessagePrinter that depends on MessageService.
// MessagePrinter.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MessagePrinter {
private final MessageService messageService;
// Constructor Injection
@Autowired
public MessagePrinter(MessageService messageService) {
this.messageService = messageService;
}
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}
Step 5: Running the Application
Finally, we’ll create a main class to load the Spring context and run the application.
// Application.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
How can we call third party API in java spring boot appln?
To call a third-party API in a Spring Boot application, you typically use a HTTP client library to
make the request and handle the response. Spring Boot provides built-in support for HTTP
clients like RestTemplate and WebClient.
@Service
public class ApiService {
@RestController
public class WeatherController {
@GetMapping("/weather")
public String getWeather(@RequestParam String city) {
return apiService.getWeatherData(city);
}
}
2. Using WebClient (Modern, Reactive Option)
WebClient is a reactive, non-blocking HTTP client introduced in Spring WebFlux. It is suitable for
both synchronous and asynchronous requests.
Steps:
1. Add the WebClient bean to your application.
2. Use it to send GET, POST, PUT, DELETE requests to the third-party API.
Example: Call a third-party API using WebClient
Dependencies (if not already included):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Code Implementation:
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
@Service
public class ApiService {
@Configuration
public class AppConfig {
@Bean
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
Usage in Controller:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class WeatherController {
@GetMapping("/weather")
public String getWeather(@RequestParam String city) {
return apiService.getWeatherData(city);
}
}
Recommended For Legacy applications, simple APIs Modern applications, high concurrency
Performance Less efficient under high load Better scalability for concurrent calls
Availability Still available but legacy Recommended by Spring for new projects
4. Best Practices
Handle Errors Gracefully: Use try-catch blocks or exchange() for error handling.
Use DTOs: Map the API responses to Data Transfer Objects (DTOs) for better structure.
Externalize Configurations: Store API URLs and keys in application.properties or
application.yml.
api.base.url=https://api.openweathermap.org/data/2.5
api.key=your_api_key