Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deleting an association over REST in Spring Data REST+HATEOAS

I wish to know how to delete a many-to-many association via a REST call. I am able to create records, and associated them, but do not understand how to delete.

I have a Spring Boot project where i'm using REST and HATEOAS to by pass Services and Controllers and expose my Repository directly.

I have a User Model/Domain class

@Entity
@Table(name = "usr")
public class User implements Serializable {

private static final long serialVersionUID = 1L;

@Version
private long version = 0;

@Id
@GeneratedValue(generator="optimized-sequence")
private Long id;

@Column(nullable = false, unique = true, length = 500)
@Size(max = 500)
private String userName;

@Column(nullable = false, length = 500)
@Size(max = 500)
private String firstName;

@Column(nullable = false, length = 500)
@Size(max = 500)
private String lastName;

@ManyToMany(    fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinTable( name="user_role",
            joinColumns={ @JoinColumn(  name = "user_id", 
                                        nullable = false
                                    ) 
                        }, 
            inverseJoinColumns={ @JoinColumn(   name="role_id", 
                                                nullable=false
                                            ) 
                                }
)
private Set<Role> roles = new HashSet<Role>(0);

...Getters/Setters Below...

As as you can see, I have a roles member that is Many-To-Many association with Role class, of which the code is such:

@Entity
public class Role {

@Id
@GeneratedValue(generator="optimized-sequence")
private Long id;

@Column(nullable = false)
private String name;

@Column(nullable = false)
private String description;

...Getters/Setters Below...

My repositories look like so:

UserRepository

public interface UserRepository extends 
        JpaRepository<User, Long>, JpaSpecificationExecutor<User> {

    List<User> findByUserName(String username);

}

RoleRepository

public interface RoleRepository 
        extends JpaRepository<Role, Long> {

}

Now, all is well. When I access the project root from a browser, I get the repository index/directory in JSON+HAL format. Wonderful.

(Note I'm remove the http:// part from the test below because StackOverflow is counting it towards my links quota)

I, using WizTools REST Client, HTTP.POST to the Role ( localhost:8080/resttest/roles ) repository and create a new Role. Success, Role ID #4 created.

Then I POST to the User repository to create a User ( localhost:8080/resttest/users ). Success, User ID #7 created.

Then I PUT to the User repository to create an association with the role:

PUT localhost:8080/resttest/users/7/roles
Content-type: uri-list
Body: localhost:8080/resttest/roles/4

Great! Association made. User 9 is now associated with Role 4.

Now I can't for the life of me figure out how to DELETE this association.

I'm sending an HTTP DELETE instead of PUT with the same command as above.

DELETE localhost:8080/resttest/users/7/roles
Content-type: uri-list
Body: localhost:8080/resttest/roles/4

I get back: HTTP/1.1 405 Method Not Allowed

{
    "timestamp":1424827169981,
    "status":405,
    "error":"Method Not  Allowed",
    "exception": "org.springframework.web.HttpRequestMethodNotSupportedException",
    "message":"Request method 'POST' not supported"
}
like image 298
BKaun Avatar asked Dec 20 '22 06:12

BKaun


1 Answers

Although creating a PUT request with remaining elements does the trick, DELETE is an accepted command to delete an association resource and is in most cases easier to use.

As for your example, this should work:

DELETE localhost:8080/resttest/users/7/roles/4

On a separate note, when creating the association, it is expected to have URIs in the payload. You shouldn't need to write the whole URL in the body, this should be enough:

PUT localhost:8080/resttest/users/7/roles
Content-type: uri-list
Body: /roles/4

Hope this helps.

like image 83
Anthony Drogon Avatar answered Dec 29 '22 00:12

Anthony Drogon