Cascade AI is an AI‑powered development assistant designed specifically to ensure clean, consistent, and high‑quality Java code. Its core feature is a sophisticated hierarchical rules system that guides every line of generated code.

This system intelligently combines global industry best practices for technologies like Spring Boot (defined in .md files) with project‑specific, high‑priority guidelines (defined in .mdc files).

This dual structure allows the assistant to apply robust architectural patterns, such as constructor‑based dependency injection, while also respecting internal team conventions, such as writing comments exclusively in Spanish.

To adapt to different stages of software development, Cascade offers two complementary working modes:

In summary, this guide presents Cascade AI as an end‑to‑end solution that merges a powerful customizable rules engine with flexible interaction modes, ensuring every project is not only functional but also maintainable, scalable, and aligned with the highest quality standards.

Rules

Cascade uses a multi‑level rules system to guide code generation. It’s essential to understand the difference between the types of rule files:

  1. .md files (standard Markdown)

Example: the java.md file contains Java/Spring Boot best practices that Cascade applies automatically to any Java project.

  1. .mdc files (Markdown Cascade)

Example: the projectRules.mdc file specifies that comments must be in Spanish, requires consistent code style, forbids "*" imports, enforces constructor injection, and more.

These rules define general conventions, coding preferences, workflow requirements (such as planning before implementing, saving memory‑bank entries after major changes).

These rules must remain consistent with the global rules to avoid conflicts because—even with its hierarchy—Cascade can still make mistakes, and it’s best to prevent them whenever possible.

Rules hierarchy

Practical Example

On one hand, java.md says: “Use constructor injection for DI.”
On the other hand, projectRules.mdc says: “Comments must be in Spanish.”
Result? Cascade generates code using constructor injection with comments in Spanish.

Applied Java/Spring Boot Best Practices

Cascade includes a complete set of Spring Boot best practices, defined in java.md, which it applies automatically to the project. These are the rules we define in the file:

You are an expert in Java programming, Spring Boot, Spring Framework, Maven, JUnit, and related Java technologies.

Code Style and Structure
- Write clean, efficient, and well-documented Java code with accurate Spring Boot examples.
- Use Spring Boot best practices and conventions throughout your code.
- Implement RESTful API design patterns when creating web services.
- Use descriptive method and variable names following camelCase convention.
- Structure Spring Boot applications: controllers, services, repositories, models, configurations.

Spring Boot Specifics
- Use Spring Boot starters for quick project setup and dependency management.
- Implement proper use of annotations (e.g., @SpringBootApplication, @RestController, @Service).
- Utilize Spring Boot's auto-configuration features effectively.
- Implement proper exception handling using @ControllerAdvice and @ExceptionHandler.

Naming Conventions
- Use PascalCase for class names (e.g., UserController, OrderService).
- Use camelCase for method and variable names (e.g., findUserById, isOrderValid).
- Use ALL_CAPS for constants (e.g., MAX_RETRY_ATTEMPTS, DEFAULT_PAGE_SIZE).

Java and Spring Boot Usage
- Use Java 17 or later features when applicable (e.g., records, sealed classes, pattern matching).
- Leverage Spring Boot 3.x features and best practices.
- Use Spring Data JPA for database operations when applicable.
- Implement proper validation using Bean Validation (e.g., @Valid, custom validators).

Configuration and Properties
- Use application.properties or application.yml for configuration.
- Implement environment-specific configurations using Spring Profiles.
- Use @ConfigurationProperties for type-safe configuration properties.

Dependency Injection and IoC
- Use constructor injection over field injection for better testability.
- Leverage Spring's IoC container for managing bean lifecycles.

Testing
- Write unit tests using JUnit 5 and Spring Boot Test.
- Use MockMvc for testing web layers.
- Implement integration tests using @SpringBootTest.
- Use @DataJpaTest for repository layer tests.

Performance and Scalability
- Implement caching strategies using Spring Cache abstraction.
- Use async processing with @Async for non-blocking operations.
- Implement proper database indexing and query optimization.

Security
- Implement Spring Security for authentication and authorization.
- Use proper password encoding (e.g., BCrypt).
- Implement CORS configuration when necessary.

Logging and Monitoring
- Use SLF4J with Logback for logging.
- Implement proper log levels (ERROR, WARN, INFO, DEBUG).
- Use Spring Boot Actuator for application monitoring and metrics.

API Documentation
- Use Springdoc OpenAPI (formerly Swagger) for API documentation.

Data Access and ORM
- Use Spring Data JPA for database operations.
- Implement proper entity relationships and cascading.
- Use database migrations with tools like Flyway or Liquibase.

Build and Deployment
- Use Maven for dependency management and build processes.
- Implement proper profiles for different environments (dev, test, prod).
- Use Docker for containerization if applicable.

Follow best practices for:
- RESTful API design (proper use of HTTP methods, status codes, etc.).
- Microservices architecture (if applicable).
- Asynchronous processing using Spring's @Async or reactive programming with Spring WebFlux.

Adhere to SOLID principles and maintain high cohesion and low coupling in your Spring Boot application design.

Based on this, how does Cascade interpret these rules?

Structure and Architecture

Cascade organizes the code following Spring Boot patterns:

// ✅ Automatically generated 3-layer structure
@RestController
@RequestMapping("/api/orders")
public class OrderController {
    // Constructor injection (best practice)
    private final OrderService orderService;

    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }
}

@Service
public class OrderServiceImpl implements OrderService {
    private final OrderRepository orderRepository;

    public OrderServiceImpl(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
}

Naming Conventions

Spring Boot Specifics

// ✅ Appropriate annotations
@SpringBootApplication
@EnableScheduling
public class InfiniaSportsApplication {
    public static void main(String[] args) {
        SpringApplication.run(InfiniaSportsApplication.class, args);
    }
}

// ✅ Centralized exception handling
@ControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
        // ...
    }
}

// ✅ Type-safe configuration
@ConfigurationProperties(prefix = "app.jwt")
public class JwtProperties {
    private String secret;
    private long expiration;
    // getters/setters
}

Testing with JUnit 5

// ✅ Service tests with @SpringBootTest
@SpringBootTest
class OrderServiceImplTest {

    @Autowired
    private OrderService orderService;

    @MockBean
    private OrderRepository orderRepository;

    @Test
    void shouldCreateOrderSuccessfully() {
        // given - when - then pattern
    }
}

// ✅ Controller tests with MockMvc
@WebMvcTest(OrderController.class)
class OrderControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private OrderService orderService;

    @Test
    void shouldReturnOrderById() throws Exception {
        mockMvc.perform(get("/api/orders/1"))
               .andExpect(status().isOk());
    }
}

Security with Spring Security

// ✅ Robust security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            );
        return http.build();
    }

    // ✅ Password encoding with BCrypt
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

Persistence with Spring Data JPA

// ✅ Repositories with custom queries
public interface OrderRepository extends JpaRepository<Order, Long> {

    @Query("SELECT o FROM Order o WHERE o.user.email = :email")
    List<Order> findByUserEmail(@Param("email") String email);

    // ✅ Query methods with clear naming
    Optional<Order> findByOrderIdAndUserEmail(String orderId, String email);
}

// ✅ Entities with well-defined relationships
@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;
}

Configuration with Profiles

// ✅ Environment-specific configuration
// application.properties
spring.profiles.active=dev

// application-dev.properties
spring.datasource.url=jdbc:h2:mem:testdb

// application-prod.properties
spring.datasource.url=jdbc:postgresql://prod-db:5432/infinia

Logging with SLF4J

// ✅ Proper logging with correct levels
@Slf4j
@Service
public class RefreshTokenService {

    public RefreshToken createRefreshToken(String email) {
        log.info("Creating refresh token for user: {}", email);

        try {
            // logic
            log.debug("Token created successfully");
            return token;
        } catch (Exception e) {
            log.error("Error creating refresh token for user: {}", email, e);
            throw new TokenCreationException("Failed to create token", e);
        }
    }
}

API Documentation with OpenAPI

// ✅ Automatic documentation of endpoints
@RestController
@RequestMapping("/api/orders")
@Tag(name = "Orders", description = "Order management API")
public class OrderController {

    @Operation(summary = "Get order by ID")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "Order found"),
        @ApiResponse(responseCode = "404", description = "Order not found")
    })
    @GetMapping("/{id}")
    public ResponseEntity<OrderDTO> getOrderById(@PathVariable Long id) {
        // implementation
    }
}

Performance and Optimization

// ✅ Strategic caching
@Service
@CacheConfig(cacheNames = "products")
public class ProductService {

    @Cacheable(key = "#id")
    public Product findById(String id) {
        return productRepository.findById(id).orElseThrow();
    }
}

// ✅ Asynchronous processing
@Service
public class EmailService {

    @Async
    public CompletableFuture<Void> sendOrderConfirmation(Order order) {
        // send email asynchronously
        return CompletableFuture.completedFuture(null);
    }
}

Project-Specific Rules

In addition to global best practices, this project has specific rules defined in projectRules.mdc:

General Rules

Code Conventions

Backend (Java)

Frontend (React)

Implementation Patterns

Philosophy and Workflow

Work Modes: Code vs Chat

Cascade offers two fundamental interaction modes that adapt to different development needs:

Chat Mode

Designed for conversational pair programming.

Code Mode

Mode for smart autocompletion and inline assistance.

Mode Comparison

Aspect Chat Mode Code Mode
Interaction Conversational Inline
Speed Slower, more thoughtful Fast, immediate
Complexity Multi-file tasks Localized changes
Explanations Detailed and reasoned Minimal
Control You approve before execution Direct suggestions
Best for Architecture, debugging Repetitive code

What has been my usage strategy?

During the pilot development, I mostly used chat mode for complex tasks that required analysis, learning, and plan validation. However, I occasionally used code mode to complete imports, generate repetitive tests, and write DTOs.

My recommendation is to start with chat mode to establish the project's architecture and patterns. Once consolidated, alternate between both modes depending on the task.

Conclusion

In conclusion, Cascade AI is a development tool that generates high-quality Java code by applying a hierarchical rule system. It combines global best practice guidelines for technologies like Spring Boot (defined in .md files) with custom, high-priority project-specific rules (in .mdc files), such as the language for comments.

These rules should be mutually consistent to ensure the lowest possible error rate in what we define. It offers two complementary working modes: chat mode, ideal for complex architecture and design tasks, and code mode for fast autocomplete and inline assistance. This fusion of customizable rules and flexible interaction modes helps maintain consistency and efficiency throughout the entire software development lifecycle.

Tell us what you think.

Comments are moderated and will only be visible if they add to the discussion in a constructive way. If you disagree with a point, please, be polite.

Subscribe