Search code examples
springhibernatejacksonspring-restcontrollerspring-java-config

Spring @RequestBody REST services post method return 415 in some entity relation


I am working with spring rest and hibernate. I checked stackoverflow these linkes but they did not solve my issue!

Spring MVC 3.1 REST services post method return 415

415 Unsupported MediaType for POST request in spring application

HTTP Status 415 - Unsupported Media Type when doing POST

and so more post ..

When I have this kind of relation in my entities, there is no problem in post and @RequestBody

University.java

public class University extends BaseEntity {

    private String name;
    private String address;
    private String telephon;


    @OneToMany(fetch = FetchType.LAZY, mappedBy = "university", cascade = CascadeType.ALL)
    @JsonManagedReference
    private List<Student> students=new ArrayList<>();
// setter an getter
}

Student.java

public class Student extends BaseEntity{

    @Column(name = "FIRST_NAME")
    private String firstName;

    @Column(name = "LAST_NAME")
    private String lastName;

    @Column(name = "SECTION")
    private String section;

    @ManyToOne
    @JoinColumn(name = "UNIVERSITY_ID",nullable = false)
    @JsonBackReference
    private University university;

// setter an getter
    }

But when I add Certificate entity to my relation like below

Edited:

Student.java

public class Student extends BaseEntity{

    @Column(name = "FIRST_NAME")
    private String firstName;

    @Column(name = "LAST_NAME")
    private String lastName;

    @Column(name = "SECTION")
    private String section;

    @ManyToOne
    @JoinColumn(name = "UNIVERSITY_ID",nullable = false)
    @JsonBackReference
    private University university;

   // added new relation
    @ManyToOne
    @JoinColumn(name = "certificateid",nullable = false)
    @JsonBackReference
    private Certificate certificate;


// setter an getter
    }

Certificate.java

public class Certificate extends BaseEntity{

     private String name;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "certificate")
    @JsonManagedReference
    private List<Student> students=new ArrayList<>();
    // setter an getter
}

In this type of relations I encounter the 415 error. and in some post it is suggested to use @ModelAttribute instead of @RequestBody, and it solve the error. But due to this post, it says it is proper to use in MVC, not in rest template.

my controller api is:

   @RequestMapping(value = "/create3", method = RequestMethod.POST,consumes = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<University> create3( @RequestBody University model) throws Exception {
        return new ResponseEntity<University>(this.universityService.add(model), HttpStatus.OK);
    }

and my config class

@Configuration
@EnableTransactionManagement
@EnableWebMvc
public class moduleConfig extends WebMvcConfigurerAdapter {


    @Bean
    public ObjectMapper objectMapper(){
        ObjectMapper mapper = new ObjectMapper();

        Hibernate5Module module = new Hibernate5Module();
        module.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, false);

        mapper.registerModule(module);

        //Some other configuration....

        return mapper;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

        converters.add(new MappingJackson2HttpMessageConverter());
        super.configureMessageConverters(converters);
    }
//configure the output json format
//https://stackoverflow.com/questions/4823358/spring-configure-responsebody-json-format
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof AbstractJackson2HttpMessageConverter) {
                AbstractJackson2HttpMessageConverter c = (AbstractJackson2HttpMessageConverter) converter;
                ObjectMapper objectMapper = c.getObjectMapper();
                objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            }
        }

        super.extendMessageConverters(converters);
    }

@Bean
public MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    converter.setObjectMapper(this.jacksonBuilder().build());

    return converter;
}

public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();

    Hibernate5Module hibernateModule = new Hibernate5Module();

    hibernateModule.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, false);

    builder.modules(hibernateModule);

    // Spring MVC default Objectmapper configuration
    builder.featuresToDisable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    builder.featuresToDisable(MapperFeature.DEFAULT_VIEW_INCLUSION);

    return builder;
}



@Bean
public ViewResolver viewResolver() {
    InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
    viewResolver.setViewClass(JstlView.class);
    viewResolver.setSuffix(".jsp");
    return viewResolver;
}

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
    configurer.enable();
}



}

}

1.How Entities relation cause problem in my post method?

2.what I am missing in my code to do it correctly?

any help and idea appreciated.

enter image description here

enter image description here


Solution

  • Jackson doesn't support multiple @JsonBackReference on one entity class without naming them specifically (every relating have a default name given).

    Set a specific name for each relation like:

    @JsonManagedReference(value = "a_name")
    
    @JsonBackReference(value = "a_name")
    

    The problem comes from the format of the JSON (and any document oriented data) that doesn't allow multiple parent for one node.