> ## Documentation Index
> Fetch the complete documentation index at: https://docs.matterai.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Spring Boot

> Spring Boot is an open-source Java-based framework used to create microservices and standalone Spring applications with minimal configuration. It simplifies the bootstrapping and development of new Spring applications.

<AccordionGroup>
  <Accordion title="Spring Boot Anti-Patterns Overview" icon="spring">
    Spring Boot, while designed to simplify Java application development, can still be misused. Here are the most important anti-patterns to avoid when developing Spring Boot applications.
  </Accordion>

  <Accordion title="Using @Autowired on Fields" icon="warning">
    ```java theme={null}
    // Anti-pattern: Field injection
    @Service
    public class UserService {
        @Autowired
        private UserRepository userRepository;
        
        @Autowired
        private EmailService emailService;
        
        // Methods using injected dependencies
    }

    // Better approach: Constructor injection
    @Service
    public class UserService {
        private final UserRepository userRepository;
        private final EmailService emailService;
        
        @Autowired // Optional in newer Spring versions
        public UserService(UserRepository userRepository, EmailService emailService) {
            this.userRepository = userRepository;
            this.emailService = emailService;
        }
        
        // Methods using injected dependencies
    }
    ```

    Field injection makes your code harder to test and hides dependencies. Use constructor injection to make dependencies explicit and enable easier unit testing.
  </Accordion>

  <Accordion title="Not Using Configuration Properties" icon="warning">
    ```java theme={null}
    // Anti-pattern: Hardcoded configuration values
    @Service
    public class EmailService {
        private final String smtpServer = "smtp.example.com";
        private final int port = 587;
        private final String username = "user";
        private final String password = "password";
        
        // Service methods
    }

    // Better approach: Use @ConfigurationProperties
    @Configuration
    @ConfigurationProperties(prefix = "mail")
    public class EmailProperties {
        private String smtpServer;
        private int port;
        private String username;
        private String password;
        
        // Getters and setters
    }

    @Service
    public class EmailService {
        private final EmailProperties emailProperties;
        
        public EmailService(EmailProperties emailProperties) {
            this.emailProperties = emailProperties;
        }
        
        // Service methods using emailProperties
    }
    ```

    Hardcoded configuration values make your application inflexible and difficult to deploy in different environments. Use `@ConfigurationProperties` to externalize configuration.
  </Accordion>

  <Accordion title="Misusing @Transactional" icon="warning">
    ```java theme={null}
    // Anti-pattern: Misusing @Transactional
    @Service
    public class OrderService {
        private final OrderRepository orderRepository;
        private final EmailService emailService;
        
        @Autowired
        public OrderService(OrderRepository orderRepository, EmailService emailService) {
            this.orderRepository = orderRepository;
            this.emailService = emailService;
        }
        
        @Transactional
        public void processOrder(Order order) {
            orderRepository.save(order);
            emailService.sendOrderConfirmation(order); // Might fail and roll back DB transaction
        }
    }

    // Better approach: Separate transactional boundaries
    @Service
    public class OrderService {
        private final OrderRepository orderRepository;
        private final EmailService emailService;
        
        @Autowired
        public OrderService(OrderRepository orderRepository, EmailService emailService) {
            this.orderRepository = orderRepository;
            this.emailService = emailService;
        }
        
        public void processOrder(Order order) {
            saveOrder(order);
            try {
                emailService.sendOrderConfirmation(order);
            } catch (Exception e) {
                // Log error but don't roll back transaction
                log.error("Failed to send confirmation email", e);
            }
        }
        
        @Transactional
        private void saveOrder(Order order) {
            orderRepository.save(order);
        }
    }
    ```

    Misusing `@Transactional` can lead to unexpected rollbacks or transaction leaks. Be mindful of transaction boundaries and separate transactional operations from non-transactional ones.
  </Accordion>

  <Accordion title="Not Using Spring Boot Starters" icon="warning">
    ```xml theme={null}
    <!-- Anti-pattern: Manually managing dependencies -->
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <!-- Many more dependencies -->
    </dependencies>

    <!-- Better approach: Use Spring Boot starters -->
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    ```

    Manually managing dependencies can lead to version conflicts and missing transitive dependencies. Use Spring Boot starters to get curated, compatible dependency sets.
  </Accordion>

  <Accordion title="Not Using Spring Data Repositories" icon="warning">
    ```java theme={null}
    // Anti-pattern: Manual JDBC or JPA code
    @Repository
    public class UserRepositoryImpl implements UserRepository {
        @Autowired
        private JdbcTemplate jdbcTemplate;
        
        @Override
        public User findById(Long id) {
            return jdbcTemplate.queryForObject(
                "SELECT * FROM users WHERE id = ?",
                new Object[]{id},
                (rs, rowNum) -> new User(
                    rs.getLong("id"),
                    rs.getString("username"),
                    rs.getString("email")
                )
            );
        }
        
        // Many more manual implementations
    }

    // Better approach: Use Spring Data repositories
    public interface UserRepository extends JpaRepository<User, Long> {
        // All basic CRUD operations are automatically implemented
        
        // Custom query methods
        Optional<User> findByEmail(String email);
        List<User> findByLastNameOrderByFirstNameAsc(String lastName);
        
        @Query("SELECT u FROM User u WHERE u.status = :status")
        List<User> findByStatus(@Param("status") UserStatus status);
    }
    ```

    Writing manual data access code is error-prone and time-consuming. Use Spring Data repositories to automatically implement common data access patterns.
  </Accordion>

  <Accordion title="Not Using Proper Exception Handling" icon="warning">
    ```java theme={null}
    // Anti-pattern: Poor exception handling
    @RestController
    @RequestMapping("/api/users")
    public class UserController {
        @Autowired
        private UserService userService;
        
        @GetMapping("/{id}")
        public User getUser(@PathVariable Long id) {
            return userService.findById(id); // Might throw exception
        }
    }

    // Better approach: Proper exception handling
    @RestController
    @RequestMapping("/api/users")
    public class UserController {
        private final UserService userService;
        
        @Autowired
        public UserController(UserService userService) {
            this.userService = userService;
        }
        
        @GetMapping("/{id}")
        public ResponseEntity<User> getUser(@PathVariable Long id) {
            return userService.findById(id)
                .map(user -> ResponseEntity.ok(user))
                .orElseThrow(() -> new ResourceNotFoundException("User not found with id " + id));
        }
    }

    @ControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler(ResourceNotFoundException.class)
        public ResponseEntity<?> handleResourceNotFoundException(ResourceNotFoundException ex) {
            ErrorResponse error = new ErrorResponse(HttpStatus.NOT_FOUND.value(), ex.getMessage());
            return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
        }
        
        // Other exception handlers
    }
    ```

    Not handling exceptions properly leads to poor user experience and security issues. Use `@ControllerAdvice` and `@ExceptionHandler` to handle exceptions globally.
  </Accordion>

  <Accordion title="Not Using Spring Profiles" icon="warning">
    ```java theme={null}
    // Anti-pattern: Environment-specific configuration in code
    @Configuration
    public class DatabaseConfig {
        @Bean
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            if (System.getProperty("env").equals("dev")) {
                dataSource.setUrl("jdbc:h2:mem:testdb");
                // Dev configuration
            } else {
                dataSource.setUrl("jdbc:mysql://production-db:3306/app");
                // Production configuration
            }
            return dataSource;
        }
    }

    // Better approach: Use Spring profiles
    @Configuration
    @Profile("dev")
    public class DevDatabaseConfig {
        @Bean
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setUrl("jdbc:h2:mem:testdb");
            // Dev configuration
            return dataSource;
        }
    }

    @Configuration
    @Profile("prod")
    public class ProdDatabaseConfig {
        @Bean
        public DataSource dataSource() {
            DriverManagerDataSource dataSource = new DriverManagerDataSource();
            dataSource.setUrl("jdbc:mysql://production-db:3306/app");
            // Production configuration
            return dataSource;
        }
    }
    ```

    Hardcoding environment-specific configuration makes deployment difficult. Use Spring profiles to separate configuration for different environments.
  </Accordion>

  <Accordion title="Not Using Spring Boot Actuator" icon="warning">
    ```java theme={null}
    // Anti-pattern: Custom health checks and metrics
    @RestController
    @RequestMapping("/system")
    public class SystemController {
        @Autowired
        private DataSource dataSource;
        
        @GetMapping("/health")
        public Map<String, Object> health() {
            Map<String, Object> health = new HashMap<>();
            try (Connection conn = dataSource.getConnection()) {
                health.put("database", "UP");
            } catch (SQLException e) {
                health.put("database", "DOWN");
            }
            // More manual health checks
            return health;
        }
    }

    // Better approach: Use Spring Boot Actuator
    // In pom.xml or build.gradle
    // <dependency>
    //     <groupId>org.springframework.boot</groupId>
    //     <artifactId>spring-boot-starter-actuator</artifactId>
    // </dependency>

    // In application.properties or application.yml
    // management.endpoints.web.exposure.include=health,info,metrics
    // management.endpoint.health.show-details=always

    // Custom health indicator if needed
    @Component
    public class CustomHealthIndicator implements HealthIndicator {
        @Override
        public Health health() {
            // Check health logic
            if (isHealthy()) {
                return Health.up().withDetail("details", "Service is running smoothly").build();
            }
            return Health.down().withDetail("details", "Service is experiencing issues").build();
        }
    }
    ```

    Implementing custom monitoring endpoints is unnecessary and lacks features. Use Spring Boot Actuator for production-ready features like health checks, metrics, and monitoring.
  </Accordion>

  <Accordion title="Not Using Spring Security Properly" icon="warning">
    ```java theme={null}
    // Anti-pattern: Custom security implementation
    @Component
    public class CustomAuthFilter implements Filter {
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest httpRequest = (HttpServletRequest) request;
            String token = httpRequest.getHeader("Authorization");
            
            // Manual token validation
            if (token != null && validateToken(token)) {
                chain.doFilter(request, response);
            } else {
                HttpServletResponse httpResponse = (HttpServletResponse) response;
                httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            }
        }
        
        private boolean validateToken(String token) {
            // Custom token validation logic
            return true;
        }
    }

    // Better approach: Use Spring Security
    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        private JwtTokenProvider tokenProvider;
        
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/api/auth/**").permitAll()
                .antMatchers("/api/public/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .apply(new JwtConfigurer(tokenProvider));
        }
    }
    ```

    Custom security implementations are prone to vulnerabilities. Use Spring Security for robust, well-tested security features.
  </Accordion>

  <Accordion title="Not Using Spring Boot Testing Features" icon="warning">
    ```java theme={null}
    // Anti-pattern: Manual test setup
    public class UserServiceTest {
        private UserRepository userRepository;
        private EmailService emailService;
        private UserService userService;
        
        @Before
        public void setup() {
            userRepository = mock(UserRepository.class);
            emailService = mock(EmailService.class);
            userService = new UserService(userRepository, emailService);
        }
        
        @Test
        public void testFindById() {
            // Test implementation
        }
    }

    // Better approach: Use Spring Boot Test
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class UserServiceIntegrationTest {
        @Autowired
        private UserService userService;
        
        @MockBean
        private EmailService emailService;
        
        @Test
        public void testFindById() {
            // Test implementation with Spring Boot test features
        }
    }

    // Or for slices of the application
    @RunWith(SpringRunner.class)
    @WebMvcTest(UserController.class)
    public class UserControllerTest {
        @Autowired
        private MockMvc mockMvc;
        
        @MockBean
        private UserService userService;
        
        @Test
        public void testGetUser() throws Exception {
            // Test with MockMvc
            mockMvc.perform(get("/api/users/1"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").value(1));
        }
    }
    ```

    Manual test setup is verbose and error-prone. Use Spring Boot's testing features like `@SpringBootTest`, `@WebMvcTest`, and `@DataJpaTest` for more effective testing.
  </Accordion>

  <Accordion title="Not Using Spring Boot DevTools" icon="warning">
    ```xml theme={null}
    <!-- Add to your pom.xml -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
    ```

    ```properties theme={null}
    # application.properties for development
    spring.devtools.restart.enabled=true
    spring.devtools.livereload.enabled=true
    ```

    Not using Spring Boot DevTools during development leads to slower development cycles. DevTools provides automatic restart, live reload, and other development-time features that improve productivity.
  </Accordion>

  <Accordion title="Not Using Spring Boot Caching" icon="warning">
    ```java theme={null}
    // Anti-pattern: Manual caching
    @Service
    public class ProductService {
        private final ProductRepository productRepository;
        private final Map<Long, Product> productCache = new ConcurrentHashMap<>();
        
        @Autowired
        public ProductService(ProductRepository productRepository) {
            this.productRepository = productRepository;
        }
        
        public Product getProductById(Long id) {
            if (productCache.containsKey(id)) {
                return productCache.get(id);
            }
            
            Product product = productRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Product not found"));
            productCache.put(id, product);
            return product;
        }
        
        public void updateProduct(Product product) {
            productRepository.save(product);
            productCache.put(product.getId(), product);
        }
    }

    // Better approach: Use Spring Boot Caching
    @Configuration
    @EnableCaching
    public class CachingConfig {
        @Bean
        public CacheManager cacheManager() {
            return new ConcurrentMapCacheManager("products");
        }
    }

    @Service
    public class ProductService {
        private final ProductRepository productRepository;
        
        @Autowired
        public ProductService(ProductRepository productRepository) {
            this.productRepository = productRepository;
        }
        
        @Cacheable("products")
        public Product getProductById(Long id) {
            return productRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("Product not found"));
        }
        
        @CachePut(value = "products", key = "#product.id")
        public Product updateProduct(Product product) {
            return productRepository.save(product);
        }
        
        @CacheEvict(value = "products", key = "#id")
        public void deleteProduct(Long id) {
            productRepository.deleteById(id);
        }
    }
    ```

    Manual caching is error-prone and difficult to maintain. Use Spring Boot's caching abstraction with annotations like `@Cacheable`, `@CachePut`, and `@CacheEvict` for declarative caching.
  </Accordion>

  <Accordion title="Not Using Spring Boot Validation" icon="warning">
    ```java theme={null}
    // Anti-pattern: Manual validation
    @RestController
    @RequestMapping("/api/users")
    public class UserController {
        @PostMapping
        public ResponseEntity<User> createUser(@RequestBody UserDto userDto) {
            // Manual validation
            if (userDto.getEmail() == null || !userDto.getEmail().contains("@")) {
                throw new BadRequestException("Invalid email");
            }
            if (userDto.getPassword() == null || userDto.getPassword().length() < 8) {
                throw new BadRequestException("Password must be at least 8 characters");
            }
            // More validations...
            
            // Process valid user
            User user = userService.createUser(userDto);
            return ResponseEntity.ok(user);
        }
    }

    // Better approach: Use Bean Validation
    public class UserDto {
        @NotBlank(message = "Name is required")
        private String name;
        
        @Email(message = "Invalid email format")
        @NotBlank(message = "Email is required")
        private String email;
        
        @Size(min = 8, message = "Password must be at least 8 characters")
        private String password;
        
        // Getters and setters
    }

    @RestController
    @RequestMapping("/api/users")
    public class UserController {
        @PostMapping
        public ResponseEntity<User> createUser(@Valid @RequestBody UserDto userDto) {
            // Validation is handled automatically
            User user = userService.createUser(userDto);
            return ResponseEntity.ok(user);
        }
    }

    // Global validation error handler
    @ControllerAdvice
    public class ValidationExceptionHandler {
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex) {
            Map<String, String> errors = new HashMap<>();
            ex.getBindingResult().getAllErrors().forEach(error -> {
                String fieldName = ((FieldError) error).getField();
                String errorMessage = error.getDefaultMessage();
                errors.put(fieldName, errorMessage);
            });
            return ResponseEntity.badRequest().body(errors);
        }
    }
    ```

    Manual validation is error-prone and verbose. Use Bean Validation (JSR-380) with annotations like `@Valid`, `@NotNull`, `@Size`, etc., for declarative validation.
  </Accordion>

  <Accordion title="Not Using Spring Boot Actuator for Health Checks" icon="warning">
    ```java theme={null}
    // Anti-pattern: Custom health check endpoints
    @RestController
    @RequestMapping("/health")
    public class HealthCheckController {
        @Autowired
        private DataSource dataSource;
        
        @GetMapping
        public Map<String, Object> checkHealth() {
            Map<String, Object> health = new HashMap<>();
            health.put("status", "UP");
            
            try (Connection conn = dataSource.getConnection()) {
                health.put("database", "UP");
            } catch (Exception e) {
                health.put("database", "DOWN");
                health.put("status", "DOWN");
            }
            
            // More health checks
            return health;
        }
    }

    // Better approach: Use Spring Boot Actuator
    // In application.properties
    // management.endpoint.health.show-details=always
    // management.endpoints.web.exposure.include=health,info,metrics

    // Custom health indicator
    @Component
    public class DatabaseHealthIndicator implements HealthIndicator {
        private final DataSource dataSource;
        
        @Autowired
        public DatabaseHealthIndicator(DataSource dataSource) {
            this.dataSource = dataSource;
        }
        
        @Override
        public Health health() {
            try (Connection conn = dataSource.getConnection()) {
                // Execute a simple query
                try (Statement stmt = conn.createStatement()) {
                    stmt.execute("SELECT 1");
                }
                return Health.up().withDetail("database", "Available").build();
            } catch (Exception e) {
                return Health.down()
                    .withDetail("database", "Unavailable")
                    .withException(e)
                    .build();
            }
        }
    }
    ```

    Custom health check endpoints lack standardization and features. Use Spring Boot Actuator's health endpoints and custom health indicators for comprehensive health monitoring.
  </Accordion>
</AccordionGroup>
