Srik
Srik

Reputation: 2381

Spring MVC - restriction on objects received using @RequestBody

I am getting '400 Bad Request' when I use a class with inheritance in @RequestBody. I have another controller where I use the class without Inheritance and it works.

I want to know whether I can use regular EJBs in @RequestBody or are there any restrictions on the classes that can be used?

Below is the controller:

@RequestMapping(value = "auth/ping", method = RequestMethod.POST, consumes="application/json")
@ResponseStatus(HttpStatus.OK)
public @ResponseBody String pingPost(@RequestBody User model) {
    final String signature = CLASSNAME + "#pingPost(User model)";
    Helper.logEntrance(getLogger(), signature, new String[]{"model"}, new Object[]{model});
    return "unprotected ping post with data";
}

Below are the classes

public abstract class User extends AuditableEntity {

    @Indexed
    private String name;

    private String password;

    public User() {
        super();
    }


    public String getName() {
        return this.name;
    }

    public void setName(String value) {
        this.name = value;
    }

    public String getPassword() {
        return this.password;
    }

    public void setPassword(String value) {
        this.password = value;
    }

}

public abstract class AuditableEntity {

    private User createdBy;

    private Date createdDate;

    public AuditableEntity() {
        super();
    }

    public User getCreatedBy() {
        return this.createdBy;
    }

    public void setCreatedBy(User value) {
        this.createdBy = value;
    }

    public Date getCreatedDate() {
        return this.createdDate;
    }

    public void setCreatedDate(Date value) {
        this.createdDate = value;
    }

}

I have included below libraries in the maven

    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-core-asl</artifactId>
        <version>1.9.13</version>
    </dependency>
    <dependency>
        <groupId>org.codehaus.jackson</groupId>
        <artifactId>jackson-mapper-asl</artifactId>
        <version>1.9.13</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.4.2</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.4.2</version>
    </dependency>

Upvotes: 0

Views: 1086

Answers (1)

Master Slave
Master Slave

Reputation: 28519

Inheritance works just fine, your issue is due to the fact that your User class is an abstract class.

When Spring MVC finds the argument annotated with @RequestBody its argument resolving mechanism kicks in, and in the process it attempts at creating the instance of a class, the User class in your case. The process fails if the class cannot be instantiated as when being marked abstract.

Personally I would create and use a Data Transfer Object, but you can use EJB class as well, just make sure to either remove the abstract, or use the concrete subclass as the argument of your method

Note also that its OK to use abstract class as a method argument but you need to provide more info to help the framework resolve it. This largely depends on the message converter that handles the conversion, as you seem to be using JSON and Jackson, you might handle it by supplying your custom deserializer, so something like this will do.

public ConcreteUser extends User {
}

and than annotate your User class with

@JsonDeserialize(as=ConcreteUser.class)
public abstract class User extends AuditableEntity

Upvotes: 1

Related Questions