Spring MVC
Spring Data Rest
MVC responses
Java framework
REST API

Mixing Spring MVC Spring Data Rest results in odd MVC responses

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Spring MVC and Spring Data REST can coexist, but mixing them without clear boundaries often causes surprising responses. Teams typically see issues such as unexpected HAL payloads, broken content negotiation, or route collisions. The fix is to define explicit endpoint ownership and serialization rules for each layer.

Why Responses Look Wrong

Spring Data REST automatically exposes repository endpoints and uses hypermedia-friendly defaults. Spring MVC controllers usually return application-specific DTOs and response shapes.

When both are active on similar paths, request mapping and message conversion can conflict. Symptoms include:

  • Controller path returning repository-style links.
  • Repository path returning plain MVC JSON unexpectedly.
  • Different media types for nearby endpoints.

The issue is usually configuration overlap, not framework instability.

Separate Endpoint Spaces First

The easiest stabilization step is assigning a dedicated base path for Spring Data REST endpoints.

application.properties example:

properties
spring.data.rest.base-path=/data

Now repository endpoints live under /data, while MVC endpoints remain under your chosen API prefix such as /api.

Equivalent Java config:

java
1import org.springframework.context.annotation.Configuration;
2import org.springframework.data.rest.core.config.RepositoryRestConfiguration;
3import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer;
4import org.springframework.web.servlet.config.annotation.CorsRegistry;
5
6@Configuration
7public class RestConfig implements RepositoryRestConfigurer {
8    @Override
9    public void configureRepositoryRestConfiguration(
10            RepositoryRestConfiguration config,
11            CorsRegistry cors
12    ) {
13        config.setBasePath("/data");
14    }
15}

This simple separation resolves many odd response issues immediately.

Control Repository Exposure Explicitly

Not every repository should be exported as REST endpoints. Disable repository export where MVC controllers already own the contract.

java
1import org.springframework.data.jpa.repository.JpaRepository;
2import org.springframework.data.rest.core.annotation.RepositoryRestResource;
3
4@RepositoryRestResource(exported = false)
5public interface InternalOrderRepository extends JpaRepository<Order, Long> {
6}

This prevents accidental duplicate APIs with inconsistent behavior.

Keep DTO Serialization Consistent in MVC

MVC controllers should return stable DTO contracts, not entity objects directly.

java
1import org.springframework.web.bind.annotation.GetMapping;
2import org.springframework.web.bind.annotation.RequestMapping;
3import org.springframework.web.bind.annotation.RestController;
4
5import java.util.List;
6
7@RestController
8@RequestMapping("/api/users")
9public class UserController {
10
11    @GetMapping
12    public List<UserDto> listUsers() {
13        return List.of(new UserDto(1L, "Ava"));
14    }
15
16    public record UserDto(Long id, String name) {}
17}

Returning DTOs avoids leakage of repository-level defaults into your public API.

Pay Attention to Media Types and Accept Headers

Spring Data REST often uses HAL media types, while MVC controllers may return standard JSON. If clients mix headers inconsistently, response shape changes look random.

Use explicit produces configuration when needed:

java
1@GetMapping(produces = "application/json")
2public UserDto getUser() {
3    return new UserDto(1L, "Ava");
4}

Also document expected Accept headers in API contracts and client SDK code.

Testing Strategy to Catch Mixed Behavior

Add focused tests that verify route ownership and media types.

java
1import org.junit.jupiter.api.Test;
2import org.springframework.beans.factory.annotation.Autowired;
3import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
4import org.springframework.boot.test.context.SpringBootTest;
5import org.springframework.test.web.servlet.MockMvc;
6
7import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
8import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
9import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
10
11@SpringBootTest
12@AutoConfigureMockMvc
13class RouteSeparationTest {
14
15    @Autowired
16    MockMvc mockMvc;
17
18    @Test
19    void mvcEndpointReturnsJson() throws Exception {
20        mockMvc.perform(get("/api/users"))
21               .andExpect(status().isOk())
22               .andExpect(content().contentType("application/json"));
23    }
24}

These tests prevent regressions when dependencies or default converters change.

Operational Guidance

During debugging, capture:

  • Request path.
  • Request Accept header.
  • Matched handler.
  • Response media type.

With these four signals, mixed MVC and Data REST issues become straightforward to isolate.

Common Pitfalls

  • Leaving Data REST and MVC on overlapping path prefixes.
  • Exporting repositories unintentionally and creating duplicate API surfaces.
  • Returning entities directly from MVC controllers.
  • Ignoring media type differences between HAL and standard JSON.
  • Skipping route-separation tests and discovering breakage in integration.

Summary

  • Odd responses from mixed MVC and Data REST usually come from boundary ambiguity.
  • Separate path prefixes and endpoint ownership first.
  • Export only repositories that should be public REST resources.
  • Keep MVC responses explicit with DTOs and media type declarations.
  • Add tests that lock route mapping and response-type expectations.

Course illustration
Course illustration

All Rights Reserved.