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"
}
From the docs:
PUT
means that you replace the wholeroles
Set. So to remove a single link youPUT
all remaining links. If you only have a single link and want to remove it you wouldPUT
an empty collection:BTW: You won't send a body with a
DELETE
request. It doesn't make sense.EDIT
See also this answer from the developer of Spring HATEOAS.
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:
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:
Hope this helps.