Fred
Fred

Reputation: 781

How to configure Spring Data REST to return the newly created entity as part of the body for a POST

I'm using Spring Data REST to expose my JPA repositories as Web Services.

I'm testing each of these Web Services using RestTemplate. I want those tests to be integration tests... meaning that I'm executing each test while my application is running. I don't want to mock anything.

Now what I want to know is how to configure Spring Data REST to return the newly created entity as part of the body when sending an HTTP POST.

I've tried to set the appropriate flags in configuration class RepositoryRestMvcConfiguration, but it doesn't seem to be working.

Here's my configuration class :

@Configuration
public class RepositoryRestMvcConfiguration extends org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration {

    @Override
    public RepositoryRestConfiguration config() {
        RepositoryRestConfiguration config = super.config();
        config.setBasePath("/sdr-api");                
        config.setReturnBodyOnCreate(Boolean.TRUE);
        config.setReturnBodyOnUpdate(Boolean.TRUE);        
        config.exposeIdsFor(Project.class);        
        config.setDefaultMediaType(MediaType.APPLICATION_JSON);        
        return config;
    }
}

Here's an example of a test I wanna be able to perform :

@Test
@SqlGroup({ @Sql(scripts = "/clear-data.sql", config = @SqlConfig(transactionMode = TransactionMode.ISOLATED)) })
public void create() {
    final String PROJECT_NAME = "MY_PROJECT";

    Project project = new Project();
    project.setName(PROJECT_NAME);

    ResponseEntity<Project> response = restTemplate().postForEntity(getBaseUrl() + "projects", project, Project.class);
    assertThat(response.getStatusCode(), equalTo(HttpStatus.CREATED));

    Project projectCreated = response.getBody();
    assertThat(projectCreated.getId(), notNullValue());
    assertThat(projectCreated.getCreatedBy(), notNullValue());
    assertThat(projectCreated.getCreatedDate(), notNullValue());
    assertThat(projectCreated.getLastModifiedBy(), notNullValue());
    assertThat(projectCreated.getLastModifiedDate(), notNullValue());
    assertThat(projectCreated.getName(), equalTo(PROJECT_NAME));
}

This test is failing on the following statement because the ID is null, as well as all the other properties...

assertThat(projectCreated.getId(), notNullValue());

Even when I try to call the WS using curl, it doesn't give the result I expect...

curl -i -X POST -H "Content-Type:application/json" -d '{ "name" : "MY_PROJECT" }' http://localhost:8081/myproject/sdr-api/projects

It should return the newly created entity and it should return the result as application/json and NOT application/hal+json as specified in my configuration class...

HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Access-Control-Allow-Methods: GET, POST, HEAD, PUT, DELETE, OPTIONS
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Accept, Origin, X-Requested-With, Content-Type, Last-Modified, Authorization
Access-Control-Allow-Credentials: true
ETag: "0"
Last-Modified: Tue, 10 Nov 2015 19:59:12 GMT
Location: http://localhost:8081/myproject/sdr-api/projects/4
Content-Type: application/hal+json
Transfer-Encoding: chunked
Date: Tue, 10 Nov 2015 19:59:12 GMT

{
  "_links" : {
    "self" : {
      "href" : "http://localhost:8081/myproject/sdr-api/projects/4"
    },
    "project" : {
      "href" : "http://localhost:8081/myproject/sdr-api/projects/4{?projection}",
      "templated" : true
    }
  }
}

Any idea on what the problem may be?

I've tried many things over the last few hours... with Spring 2.4.0.RELEASE, I've tried using the RepositoryRestConfigurerAdapter as suggested by

@Configuration
@Import(RepositoryRestMvcConfiguration.class)
public class SpringDataRestConfiguration extends RepositoryRestConfigurerAdapter {

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.setBasePath("/sdr-api");
        config.setReturnBodyOnCreate(Boolean.TRUE);
        config.setReturnBodyOnUpdate(Boolean.TRUE);
        config.exposeIdsFor(Project.class);
        config.useHalAsDefaultJsonMediaType(false);
        config.setDefaultMediaType(MediaType.APPLICATION_JSON);
    }
}

But I'm still getting the same result... the code seems to be executed though as my SDR API is available under /sdr-api.

So I've decided to downgrade the version of Spring Data Rest to 2.3.2.RELEASE. I've modified my configuration class this way :

@Configuration
public class MySDRConfiguration extends RepositoryRestMvcConfiguration {

    @Override
    public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
        config.setBasePath("/sdr-api");
        config.setReturnBodyOnCreate(Boolean.TRUE);
        config.setReturnBodyOnUpdate(Boolean.TRUE);
        config.exposeIdsFor(Project.class);
        config.useHalAsDefaultJsonMediaType(false);
        config.setDefaultMediaType(MediaType.APPLICATION_JSON);
    }
}

And this time, it's working! The result I get is what I was expecting :

HTTP/1.1 201 Created
Server: Apache-Coyote/1.1
Access-Control-Allow-Methods: GET, POST, HEAD, PUT, DELETE, OPTIONS
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Accept, Origin, X-Requested-With, Content-Type, Last-Modified, Authorization
Access-Control-Allow-Credentials: true
ETag: "0"
Last-Modified: Thu, 12 Nov 2015 20:55:32 GMT
Location: http://localhost:8081/myproject/sdr-api/projects/3
Content-Type: application/json
Transfer-Encoding: chunked
Date: Thu, 12 Nov 2015 20:55:32 GMT

{
  "id" : 3,
  "createdBy" : "anonymousUser",
  "createdDate" : "2015-11-12T20:55:32.368Z",
  "lastModifiedBy" : "anonymousUser",
  "lastModifiedDate" : "2015-11-12T20:55:32.368Z",
  "name" : "TEST",
  "links" : [ ],
  "content" : [ ],
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost:8081/myproject/sdr-api/projects/3"
  }, {
    "rel" : "testPlans",
    "href" : "http://localhost:8081/myproject/sdr-api/projects/3/testPlans"
  } ]
}

Am I missing something with the newest version of Spring Data REST?

Upvotes: 3

Views: 8821

Answers (1)

Tobias Hochg&#252;rtel
Tobias Hochg&#252;rtel

Reputation: 360

With Spring:

<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
@SpringBootApplication
public class QuizApplication implements ViewProvider {
    public static void main(String[] args) {
        SpringApplication.run(QuizApplication.class, args);
    }

    @Bean
    public RepositoryRestConfigurer repositoryRestConfigurer(EntityManager entityManager) {
        return RepositoryRestConfigurer.withConfig(config -> config.exposeIdsFor(Question.class));
    }
}

Upvotes: 0

Related Questions