# Why Cursor Suggests Outdated Framework Patterns

- Tool: Cursor
- Difficulty: Beginner
- Time required: 10-15 min
- Compatibility: Cursor Free+, Spring Boot projects
- Last updated: March 2026

## TL;DR

Cursor sometimes suggests JSP templates, XML-based Spring configuration, and other legacy Java patterns because its training data includes older codebases. By adding a .cursor/rules/ file that specifies your Spring Boot version and modern conventions, referencing your existing code with @file, and prompting with framework-specific context, you can ensure Cursor generates code using Spring Boot 3, REST controllers, and annotation-based configuration.

## Why Cursor suggests outdated framework patterns and how to fix it

AI code generators are trained on vast codebases that include legacy code from every era of Java development. Cursor may generate JSP views, XML bean definitions, or deprecated Spring APIs simply because those patterns appear frequently in its training data. This tutorial shows you how to anchor Cursor to your specific framework version and coding conventions so it produces modern, annotation-driven Spring Boot code.

## Before you start

- Cursor installed with a Spring Boot project open
- Spring Boot 3.x with Java 17+ or Kotlin
- Basic understanding of Spring Boot conventions
- Familiarity with Cursor Chat (Cmd+L) and project rules

## Step-by-step guide

### 1. Create a Spring Boot conventions rule

Add a project rule that specifies your exact Spring Boot version, Java version, and architectural patterns. Be explicit about which legacy patterns are forbidden. The more version-specific your rules, the less likely Cursor is to suggest outdated code.

```
---
description: Spring Boot 3.x modern conventions
globs: "*.java,*.kt"
alwaysApply: true
---

# Spring Boot Project Rules
- Project uses Spring Boot 3.2, Java 21, Gradle
- NEVER use JSP, Thymeleaf, or server-side templating
- NEVER use XML-based Spring configuration
- NEVER use WebMvcConfigurerAdapter (removed in Spring 6)
- NEVER use javax.* imports (use jakarta.* instead)
- ALWAYS use @RestController for API endpoints
- ALWAYS use constructor injection (never @Autowired on fields)
- ALWAYS use records for DTOs
- ALWAYS use Spring Data JPA repositories
- Use @Validated and Jakarta Bean Validation for input
- Use ResponseEntity for consistent API responses
- Use @ExceptionHandler with @ControllerAdvice for error handling
- Return JSON responses, not HTML views
```

**Expected result:** Cursor generates modern Spring Boot 3.x code with annotation-based configuration and REST controllers.

### 2. Reference your build file for version context

When prompting Cursor, reference your build.gradle or pom.xml with @file. This gives Cursor concrete version numbers for every dependency, reducing the chance of it suggesting APIs from incompatible versions.

```
@spring-boot.mdc @build.gradle

Create a REST API for managing products with these endpoints:
- GET /api/products (list with pagination)
- GET /api/products/{id} (single product)
- POST /api/products (create)
- PUT /api/products/{id} (update)
- DELETE /api/products/{id} (delete)

Use a @RestController, Spring Data JPA repository,
record DTOs, and proper validation. Follow Spring Boot 3.2 patterns.
```

> Pro tip: Reference @build.gradle or @pom.xml in every prompt. Cursor reads dependency versions and adjusts its suggestions accordingly, avoiding APIs that were removed or changed between major versions.

**Expected result:** Cursor generates a ProductController with @RestController, ProductRepository extending JpaRepository, and record-based DTOs with jakarta.validation annotations.

### 3. Use @docs to anchor Cursor to current documentation

Add the Spring Boot 3.x documentation URL to Cursor's indexed docs. This gives Cursor access to current API references when generating code. Open Cursor Settings, find the Docs section, and add the Spring Boot reference URL. Then reference it in prompts with @docs.

```
@docs Spring Boot Reference @spring-boot.mdc

Generate a GlobalExceptionHandler using @ControllerAdvice that handles:
1. MethodArgumentNotValidException (validation errors) -> 400
2. EntityNotFoundException (custom) -> 404
3. DataIntegrityViolationException -> 409
4. Generic Exception -> 500

Return a consistent ErrorResponse record with timestamp, status,
message, and path fields. Use ProblemDetail from Spring 6.
```

**Expected result:** Cursor generates a @ControllerAdvice class using Spring 6 ProblemDetail and jakarta imports, not legacy javax or SimpleMappingExceptionResolver.

### 4. Refactor legacy-style output with Cmd+K

If Cursor generates code with legacy patterns despite your rules, select the offending code and use Cmd+K to modernize it. This is faster than re-prompting the entire generation and teaches you which patterns Cursor tends to fall back on.

```
Refactor this to Spring Boot 3.2 patterns:
- Replace javax.* imports with jakarta.*
- Replace @Autowired field injection with constructor injection
- Replace class DTOs with Java records
- Replace WebMvcConfigurerAdapter with WebMvcConfigurer
- Remove any XML configuration references
- Use ResponseEntity instead of returning plain objects
```

**Expected result:** The selected code is updated to use modern Spring Boot 3 patterns with jakarta imports and constructor injection.

### 5. Verify output against your project structure

After generating code, use Cursor Chat to verify it follows your project structure. Reference your existing source directory with @folder so Cursor can see your package naming, layer organization, and existing patterns.

```
@spring-boot.mdc @src/main/java/com/example/

Review the generated ProductController and ProductService.
Check that they follow the same patterns as existing controllers
in this project. Flag any inconsistencies with:
1. Package naming conventions
2. Method naming conventions
3. Exception handling patterns
4. DTO naming and structure
5. Repository method naming
```

**Expected result:** Cursor identifies any inconsistencies between the generated code and existing project patterns, suggesting corrections.

## Complete code example

File: `.cursor/rules/spring-boot.mdc`

```markdown
---
description: Spring Boot 3.x modern conventions
globs: "*.java,*.kt"
alwaysApply: true
---

# Spring Boot Project Rules
- Project uses Spring Boot 3.2, Java 21, Gradle
- NEVER use JSP, Thymeleaf, or server-side templating
- NEVER use XML-based Spring configuration
- NEVER use WebMvcConfigurerAdapter (removed in Spring 6)
- NEVER use javax.* imports (use jakarta.* instead)
- NEVER use @Autowired on fields (constructor injection only)
- ALWAYS use @RestController for API endpoints
- ALWAYS use constructor injection via final fields
- ALWAYS use Java records for DTOs and value objects
- ALWAYS use Spring Data JPA repositories
- Use @Validated and Jakarta Bean Validation
- Use ResponseEntity for API responses
- Use @ControllerAdvice with @ExceptionHandler
- Use ProblemDetail (RFC 7807) for error responses

# Package Structure:
- controller/ — REST controllers
- service/ — Business logic
- repository/ — Data access (JPA)
- model/ — Entities
- dto/ — Request/response records
- config/ — Configuration classes
- exception/ — Custom exceptions and handlers

# Example Controller Pattern:
```java
@RestController
@RequestMapping("/api/products")
@RequiredArgsConstructor
public class ProductController {
    private final ProductService productService;

    @GetMapping
    public ResponseEntity<Page<ProductResponse>> list(Pageable pageable) {
        return ResponseEntity.ok(productService.findAll(pageable));
    }
}
```
```

## Common mistakes

- **Not specifying the exact Spring Boot and Java version in rules** — Without version numbers, Cursor cannot distinguish between Spring Boot 2.x and 3.x APIs. The javax to jakarta migration alone causes compilation failures if Cursor picks the wrong imports. Fix: Always include exact version numbers: 'Spring Boot 3.2, Java 21' in your project rules.
- **Asking Cursor to generate Spring code without referencing build.gradle** — Cursor guesses dependency versions and may use APIs from libraries not in your project, or wrong versions of libraries that are. Fix: Always reference @build.gradle or @pom.xml so Cursor sees your actual dependency versions.
- **Accepting generated code without checking import statements** — The most common Spring Boot 3 issue is javax vs jakarta imports. Code may look correct but fail to compile due to wrong import packages. Fix: Check imports first. If you see javax.persistence or javax.validation, Cursor generated Spring Boot 2 code. Use Cmd+K to fix imports.

## Best practices

- Specify exact framework and language versions in every .cursor/rules/ file
- Reference @build.gradle or @pom.xml in prompts for accurate dependency context
- Add Spring Boot documentation via @docs for up-to-date API references
- Use Cmd+K to quickly fix legacy patterns in generated code
- Include example code patterns in rules so Cursor matches your style exactly
- Start fresh Chat sessions when Cursor reverts to legacy patterns mid-conversation
- Review generated import statements first since they reveal version mismatches immediately

## Frequently asked questions

### Why does Cursor suggest JSP when my project has no views?

Cursor's training data includes millions of Spring MVC projects that use JSP. Without explicit rules stating you are building a REST API, Cursor may default to full-stack patterns including view templates.

### Can I use @docs with Spring Boot reference documentation?

Yes. Add the Spring Boot 3.x reference URL in Cursor Settings under Docs. Then use @docs Spring Boot in your prompts for current API references.

### How do I stop Cursor from using @Autowired on fields?

Add 'NEVER use @Autowired on fields. ALWAYS use constructor injection via final fields and @RequiredArgsConstructor' to your rules. Include an example showing the correct pattern.

### Does this approach work for other frameworks like Django or Rails?

Yes. The same technique applies to any framework: specify the exact version, list forbidden legacy patterns, provide correct pattern examples, and reference your project configuration file.

### What if I need to maintain a legacy Spring Boot 2 project?

Create rules that specify Spring Boot 2.x with javax imports. The key is version specificity. Cursor can generate code for any version when explicitly told which one to target.

### Can RapidDev help modernize our Spring Boot project?

Yes. RapidDev helps teams migrate from Spring Boot 2 to 3, configure Cursor for Java development, and establish modern patterns across the codebase.

---

Source: https://www.rapidevelopers.com/cursor-tutorial/how-to-fix-cursor-ai-suggesting-legacy-jsp-patterns-in-a-modern-spring-boot-project
© RapidDev — https://www.rapidevelopers.com/cursor-tutorial/how-to-fix-cursor-ai-suggesting-legacy-jsp-patterns-in-a-modern-spring-boot-project
