Skip to content

Commit 59e965a

Browse files
authored
πŸŽ› Rest controller with Spring HATEOAS
1 parent d23e309 commit 59e965a

File tree

5 files changed

+278
-0
lines changed

5 files changed

+278
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package kr.ac.hansung.cse.hellospringhateoas.assembler;
2+
3+
import kr.ac.hansung.cse.hellospringhateoas.controller.WebController;
4+
import kr.ac.hansung.cse.hellospringhateoas.entity.ActorEntity;
5+
import kr.ac.hansung.cse.hellospringhateoas.entity.AlbumEntity;
6+
import kr.ac.hansung.cse.hellospringhateoas.model.ActorModel;
7+
import kr.ac.hansung.cse.hellospringhateoas.model.AlbumModel;
8+
import org.springframework.hateoas.CollectionModel;
9+
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
10+
import org.springframework.stereotype.Component;
11+
12+
import java.util.Collections;
13+
import java.util.List;
14+
import java.util.stream.Collectors;
15+
16+
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
17+
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
18+
19+
@Component
20+
public class ActorModelAssembler
21+
extends RepresentationModelAssemblerSupport<ActorEntity, ActorModel> {
22+
23+
public ActorModelAssembler() {
24+
super(WebController.class, ActorModel.class);
25+
}
26+
27+
@Override
28+
public ActorModel toModel(ActorEntity entity)
29+
{
30+
ActorModel actorModel = instantiateModel(entity);
31+
32+
actorModel.add(linkTo(methodOn(WebController.class).getActorById(entity.getId()))
33+
.withSelfRel() );
34+
35+
actorModel.setId(entity.getId());
36+
actorModel.setFirstName(entity.getFirstName());
37+
actorModel.setLastName(entity.getLastName());
38+
actorModel.setBirthDate(entity.getBirthDate());
39+
actorModel.setAlbums(toAlbumModel(entity.getAlbums()));
40+
return actorModel;
41+
}
42+
43+
@Override
44+
public CollectionModel<ActorModel> toCollectionModel(Iterable<? extends ActorEntity> entities)
45+
{
46+
CollectionModel<ActorModel> actorModels = super.toCollectionModel(entities);
47+
48+
actorModels.add(linkTo(methodOn(WebController.class).getAllActors()).withSelfRel());
49+
50+
return actorModels;
51+
}
52+
53+
private List<AlbumModel> toAlbumModel(List<AlbumEntity> albums) {
54+
if (albums.isEmpty())
55+
return Collections.emptyList();
56+
57+
return albums.stream()
58+
.map(album -> AlbumModel.builder()
59+
.id(album.getId())
60+
.title(album.getTitle())
61+
.build()
62+
.add(linkTo(methodOn(WebController.class).getAlbumById(album.getId()))
63+
.withSelfRel()))
64+
.collect(Collectors.toList());
65+
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package kr.ac.hansung.cse.hellospringhateoas.assembler;
2+
3+
import kr.ac.hansung.cse.hellospringhateoas.controller.WebController;
4+
import kr.ac.hansung.cse.hellospringhateoas.entity.ActorEntity;
5+
import kr.ac.hansung.cse.hellospringhateoas.entity.AlbumEntity;
6+
import kr.ac.hansung.cse.hellospringhateoas.model.ActorModel;
7+
import kr.ac.hansung.cse.hellospringhateoas.model.AlbumModel;
8+
import org.springframework.hateoas.CollectionModel;
9+
import org.springframework.hateoas.server.mvc.RepresentationModelAssemblerSupport;
10+
import org.springframework.stereotype.Component;
11+
12+
import java.util.Collections;
13+
import java.util.List;
14+
import java.util.stream.Collectors;
15+
16+
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
17+
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
18+
19+
// Class RepresentationModelAssemblerSupport<T,D extends RepresentationModel<D>>
20+
@Component
21+
public class AlbumModelAssembler
22+
extends RepresentationModelAssemblerSupport<AlbumEntity, AlbumModel> {
23+
24+
// Creates a new RepresentationModelAssemblerSupport
25+
// using the given controller class and resource type.
26+
public AlbumModelAssembler() {
27+
super(WebController.class, AlbumModel.class);
28+
}
29+
30+
// D toModel(T entity); Converts the given entity into a D, which extends RepresentationModel.
31+
@Override
32+
public AlbumModel toModel(AlbumEntity entity)
33+
{
34+
// Instantiates the resource object
35+
AlbumModel albumModel = instantiateModel(entity);
36+
37+
albumModel.add(linkTo(methodOn(WebController.class).getAlbumById(entity.getId()) )
38+
.withSelfRel() );
39+
40+
albumModel.setId(entity.getId());
41+
albumModel.setTitle(entity.getTitle());
42+
albumModel.setDescription(entity.getDescription());
43+
albumModel.setReleaseDate(entity.getReleaseDate());
44+
albumModel.setActors(toActorModel(entity.getActors()));
45+
return albumModel;
46+
}
47+
48+
// CollectionModel<D> toCollectionModel(Iterable<? extends T> entities)
49+
// Converts an Iterable or Ts into an Iterable of RepresentationModel and
50+
// wraps them in a CollectionModel instance.
51+
@Override
52+
public CollectionModel<AlbumModel> toCollectionModel(Iterable<? extends AlbumEntity> entities)
53+
{
54+
CollectionModel<AlbumModel> actorModels = super.toCollectionModel(entities);
55+
56+
actorModels.add(linkTo(methodOn(WebController.class).getAllAlbums()).withSelfRel());
57+
58+
return actorModels;
59+
}
60+
61+
private List<ActorModel> toActorModel(List<ActorEntity> actors) {
62+
if (actors.isEmpty())
63+
return Collections.emptyList();
64+
65+
return actors.stream()
66+
.map(actor -> ActorModel.builder()
67+
.id(actor.getId())
68+
.firstName(actor.getFirstName())
69+
.lastName(actor.getLastName())
70+
.build()
71+
.add(linkTo(
72+
methodOn(WebController.class)
73+
.getActorById(actor.getId()))
74+
.withSelfRel()))
75+
.collect(Collectors.toList());
76+
}
77+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package kr.ac.hansung.cse.hellospringhateoas.controller;
2+
3+
import kr.ac.hansung.cse.hellospringhateoas.assembler.ActorModelAssembler;
4+
import kr.ac.hansung.cse.hellospringhateoas.assembler.AlbumModelAssembler;
5+
import kr.ac.hansung.cse.hellospringhateoas.entity.ActorEntity;
6+
import kr.ac.hansung.cse.hellospringhateoas.entity.AlbumEntity;
7+
import kr.ac.hansung.cse.hellospringhateoas.model.ActorModel;
8+
import kr.ac.hansung.cse.hellospringhateoas.model.AlbumModel;
9+
import kr.ac.hansung.cse.hellospringhateoas.repository.ActorRepository;
10+
import kr.ac.hansung.cse.hellospringhateoas.repository.AlbumRepository;
11+
import org.springframework.beans.factory.annotation.Autowired;
12+
import org.springframework.hateoas.CollectionModel;
13+
import org.springframework.http.HttpStatus;
14+
import org.springframework.http.ResponseEntity;
15+
import org.springframework.web.bind.annotation.GetMapping;
16+
import org.springframework.web.bind.annotation.PathVariable;
17+
import org.springframework.web.bind.annotation.RestController;
18+
19+
import java.util.List;
20+
21+
@RestController
22+
public class WebController {
23+
24+
@Autowired
25+
private AlbumRepository albumRepository;
26+
27+
@Autowired
28+
private ActorRepository actorRepository;
29+
30+
@Autowired
31+
private ActorModelAssembler actorModelAssembler;
32+
33+
@Autowired
34+
private AlbumModelAssembler albumModelAssembler;
35+
36+
@GetMapping("/api/actors")
37+
public ResponseEntity<CollectionModel<ActorModel>> getAllActors()
38+
{
39+
List<ActorEntity> actorEntities = (List<ActorEntity>) actorRepository.findAll();
40+
41+
return ResponseEntity.ok(actorModelAssembler.toCollectionModel(actorEntities));
42+
}
43+
44+
// Optional
45+
46+
//The map call is simply used to transform a value to some other value.
47+
48+
// The orElse() method is used to retrieve the value wrapped inside an Optional instance.
49+
// It takes one parameter, which acts as a default value.
50+
// The orElse() method returns the wrapped value if it's present, and its argument otherwise:
51+
52+
@GetMapping("/api/actors/{id}")
53+
public ResponseEntity<ActorModel> getActorById(@PathVariable("id") Long id)
54+
{
55+
return actorRepository.findById(id)
56+
.map(actorModelAssembler::toModel)
57+
.map(ResponseEntity::ok)
58+
.orElse(ResponseEntity.notFound().build());
59+
}
60+
61+
@GetMapping("/api/albums")
62+
public ResponseEntity<CollectionModel<AlbumModel>> getAllAlbums()
63+
{
64+
List<AlbumEntity> albumEntities = (List<AlbumEntity>) albumRepository.findAll();
65+
66+
return new ResponseEntity<>(
67+
albumModelAssembler.toCollectionModel(albumEntities),
68+
HttpStatus.OK);
69+
}
70+
71+
@GetMapping("/api/albums/{id}")
72+
public ResponseEntity<AlbumModel> getAlbumById(@PathVariable("id") Long id)
73+
{
74+
return albumRepository.findById(id)
75+
.map(albumModelAssembler::toModel)
76+
.map(ResponseEntity::ok)
77+
.orElse(ResponseEntity.notFound().build());
78+
}
79+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package kr.ac.hansung.cse.hellospringhateoas.model;
2+
3+
// These are DTO objects which will be returned from controller classes as representation models.
4+
5+
import com.fasterxml.jackson.annotation.JsonInclude;
6+
import lombok.*;
7+
import org.springframework.hateoas.RepresentationModel;
8+
import org.springframework.hateoas.server.core.Relation;
9+
10+
import java.util.List;
11+
12+
@Getter
13+
@Setter
14+
@Builder
15+
@NoArgsConstructor
16+
@AllArgsConstructor
17+
@EqualsAndHashCode(callSuper = false)
18+
@Relation(collectionRelation = "actors", itemRelation = "actor")
19+
@JsonInclude(JsonInclude.Include.NON_NULL)
20+
public class ActorModel extends RepresentationModel<ActorModel>
21+
{
22+
private Long id;
23+
private String firstName;
24+
private String lastName;
25+
private String birthDate;
26+
27+
private List<AlbumModel> albums;
28+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package kr.ac.hansung.cse.hellospringhateoas.model;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
import lombok.*;
5+
import org.springframework.hateoas.RepresentationModel;
6+
import org.springframework.hateoas.server.core.Relation;
7+
8+
import java.util.List;
9+
10+
// These are DTO objects which will be returned from controller classes as representation models.
11+
12+
@Getter
13+
@Setter
14+
@Builder
15+
@NoArgsConstructor
16+
@AllArgsConstructor
17+
@EqualsAndHashCode(callSuper = false)
18+
@Relation(collectionRelation = "albums", itemRelation = "album")
19+
@JsonInclude(JsonInclude.Include.NON_NULL)
20+
public class AlbumModel extends RepresentationModel<AlbumModel>
21+
{
22+
private Long id;
23+
private String title;
24+
private String description;
25+
private String releaseDate;
26+
27+
private List<ActorModel> actors;
28+
}

0 commit comments

Comments
Β (0)