Skip to content

Commit ef1831c

Browse files
✨ feat: Creature Recruitment | add REST API endpoints (#4)
1 parent b93794e commit ef1831c

7 files changed

Lines changed: 186 additions & 2 deletions

File tree

generated-requests.http

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
### BuildDwelling
2+
@dwellingId = dwelling-1
3+
PUT http://localhost:8080/dwellings/{{dwellingId}}
4+
Content-Type: application/json
5+
6+
{
7+
"creatureId": "angel",
8+
"costPerTroop": {
9+
"gold": 3000,
10+
"gems": 1
11+
}
12+
}
13+
14+
### IncreaseAvailableCreatures
15+
PUT http://localhost:8080/dwellings/{{dwellingId}}/available-creatures-increases
16+
Content-Type: application/json
17+
18+
{
19+
"creatureId": "angel",
20+
"increaseBy": 1
21+
}
22+
23+
### RecruitCreature
24+
PUT http://localhost:8080/dwellings/{{dwellingId}}/creature-recruitments
25+
Content-Type: application/json
26+
27+
{
28+
"creatureId": "angel",
29+
"armyId": "army-1",
30+
"quantity": 3
31+
}
32+
33+
### Dwelling read model
34+
GET http://localhost:8080/dwellings/{{dwellingId}}
35+
Content-Type: application/json
36+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.dddheroes.heroesofddd.creaturerecruitment.read.getdwellingbyid;
2+
3+
import com.dddheroes.heroesofddd.creaturerecruitment.read.DwellingReadModel;
4+
import org.axonframework.queryhandling.QueryGateway;
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
import org.springframework.web.bind.annotation.PathVariable;
7+
import org.springframework.web.bind.annotation.RestController;
8+
9+
import java.util.concurrent.CompletableFuture;
10+
11+
@RestController
12+
class GetDwellingByIdRestApi {
13+
14+
private final QueryGateway queryGateway;
15+
16+
GetDwellingByIdRestApi(QueryGateway queryGateway) {
17+
this.queryGateway = queryGateway;
18+
}
19+
20+
@GetMapping("/dwellings/{dwellingId}")
21+
CompletableFuture<DwellingReadModel> getDwellings(
22+
@PathVariable String dwellingId
23+
) {
24+
var query = GetDwellingById.query(dwellingId);
25+
26+
return queryGateway.query(
27+
query,
28+
DwellingReadModel.class
29+
);
30+
}
31+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.dddheroes.heroesofddd.creaturerecruitment.write.builddwelling;
2+
3+
import org.axonframework.commandhandling.gateway.CommandGateway;
4+
import org.springframework.web.bind.annotation.PathVariable;
5+
import org.springframework.web.bind.annotation.PutMapping;
6+
import org.springframework.web.bind.annotation.RequestBody;
7+
import org.springframework.web.bind.annotation.RestController;
8+
9+
import java.util.Map;
10+
import java.util.concurrent.CompletableFuture;
11+
12+
@RestController
13+
class BuildDwellingRestApi {
14+
15+
record Body(String creatureId, Map<String, Integer> costPerTroop) {
16+
17+
}
18+
19+
private final CommandGateway commandGateway;
20+
21+
BuildDwellingRestApi(CommandGateway commandGateway) {
22+
this.commandGateway = commandGateway;
23+
}
24+
25+
@PutMapping("/dwellings/{dwellingId}")
26+
CompletableFuture<Void> putDwellings(
27+
@PathVariable String dwellingId,
28+
@RequestBody Body requestBody
29+
) {
30+
var command = BuildDwelling.command(
31+
dwellingId,
32+
requestBody.creatureId(),
33+
requestBody.costPerTroop()
34+
);
35+
return commandGateway.send(command);
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.dddheroes.heroesofddd.creaturerecruitment.write.changeavailablecreatures;
2+
3+
import com.dddheroes.heroesofddd.creaturerecruitment.write.builddwelling.BuildDwelling;
4+
import org.axonframework.commandhandling.gateway.CommandGateway;
5+
import org.springframework.web.bind.annotation.PathVariable;
6+
import org.springframework.web.bind.annotation.PutMapping;
7+
import org.springframework.web.bind.annotation.RequestBody;
8+
import org.springframework.web.bind.annotation.RestController;
9+
10+
import java.util.Map;
11+
import java.util.concurrent.CompletableFuture;
12+
13+
@RestController
14+
class IncreaseAvailableCreaturesRestApi {
15+
16+
record Body(String creatureId, Integer increaseBy) {
17+
18+
}
19+
20+
private final CommandGateway commandGateway;
21+
22+
IncreaseAvailableCreaturesRestApi(CommandGateway commandGateway) {
23+
this.commandGateway = commandGateway;
24+
}
25+
26+
@PutMapping("/dwellings/{dwellingId}/available-creatures-increases")
27+
CompletableFuture<Void> putDwellingAvailableCreaturesIncreases(
28+
@PathVariable String dwellingId,
29+
@RequestBody Body requestBody
30+
) {
31+
var command = IncreaseAvailableCreatures.command(
32+
dwellingId,
33+
requestBody.creatureId(),
34+
requestBody.increaseBy()
35+
);
36+
return commandGateway.send(command);
37+
}
38+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.dddheroes.heroesofddd.creaturerecruitment.write.recruitcreature;
2+
3+
import org.axonframework.commandhandling.gateway.CommandGateway;
4+
import org.springframework.web.bind.annotation.PathVariable;
5+
import org.springframework.web.bind.annotation.PutMapping;
6+
import org.springframework.web.bind.annotation.RequestBody;
7+
import org.springframework.web.bind.annotation.RestController;
8+
9+
import java.util.concurrent.CompletableFuture;
10+
11+
@RestController
12+
class RecruitCreatureRestApi {
13+
14+
record Body(String creatureId, String armyId, Integer quantity) {
15+
16+
}
17+
18+
private final CommandGateway commandGateway;
19+
20+
RecruitCreatureRestApi(CommandGateway commandGateway) {
21+
this.commandGateway = commandGateway;
22+
}
23+
24+
@PutMapping("/dwellings/{dwellingId}/creature-recruitments")
25+
CompletableFuture<Void> putDwellingsCreatureRecruitments(
26+
@PathVariable String dwellingId,
27+
@RequestBody Body requestBody
28+
) {
29+
var command = RecruitCreature.command(
30+
dwellingId,
31+
requestBody.creatureId(),
32+
requestBody.armyId(),
33+
requestBody.quantity()
34+
);
35+
return commandGateway.send(command);
36+
}
37+
}

src/main/java/com/dddheroes/heroesofddd/shared/Cost.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,14 @@ public Map<String, Integer> raw() {
7171
public static Cost fromRaw(Map<String, Integer> raw) {
7272
Map<ResourceType, Amount> resources = raw.entrySet().stream()
7373
.collect(Collectors.toMap(
74-
entry -> ResourceType.valueOf(entry.getKey()),
74+
entry -> ResourceType.from(entry.getKey()),
7575
entry -> new Amount(entry.getValue())
7676
));
7777
return new Cost(resources);
7878
}
79+
80+
// required by Jackson
81+
public Map<ResourceType, Amount> getResources() {
82+
return new HashMap<>(resources);
83+
}
7984
}

src/test/java/com/dddheroes/heroesofddd/creaturerecruitment/write/DwellingTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class DwellingTest {
1515
protected final CreatureId angelId = CreatureId.of("angel");
1616
protected final Cost costPerTroop = Cost
1717
.resources(ResourceType.GOLD, Amount.of(3000))
18-
.plus(ResourceType.CRYSTAL, Amount.of(1));
18+
.plus(ResourceType.GEMS, Amount.of(1));
1919

2020
protected AggregateTestFixture<?> fixture;
2121

0 commit comments

Comments
 (0)