Override a read use case
Goal: change the behaviour of one read — here, list events 12 per page sorted by newest instead of the platform's 6-by-start-date — without touching the controller, the store or any other use case.
- Seam:
GetEventsUseCase<T extends EventSummaryDto>(single-method use-case interface). - City files: one
@Service. - Applies to: both topologies.
Recipe
Declare a @Service implementing the interface anywhere under com.modelcity.<vertical>.
DefaultGetEventsUseCase backs off automatically.
// com.modelcity.leisure.events.usecase.MyGetEventsUseCase
@Service
@RequiredArgsConstructor
public class MyGetEventsUseCase implements GetEventsUseCase<EventSummaryDto> {
private static final int PAGE_SIZE = 12; // was 6
private final EventStore<? extends EventView, EventRequestDto> eventStore;
@Override
@Cacheable(cacheNames = CacheNames.EVENTS, key = "#locale + '-' + #type + '-' + #paid + '-' + #page")
@Transactional(readOnly = true)
public Page<EventSummaryDto> execute(EventType type, Boolean paid, int page, String locale) {
PageRequest pageable = PageRequest.of(page, PAGE_SIZE, Sort.by("startsAt").descending());
return eventStore.search(type, paid, LocalDateTime.now(), pageable)
.map(e -> EventSummaryDto.from(e, locale));
}
}
Notes
- Re-declare
@Cacheable/@Transactional. They live onDefaultGetEventsUseCase, and annotations are not inherited across separate implementations. Omit@Cacheableon purpose to disable caching for this use case while the rest keep theirs. - Reuse the same ports and factories (
EventStore,EventSummaryDto.from) — you are changing policy, not re-plumbing persistence. - To also return extra fields, this becomes an expose-a-new-field job (subtype the DTO and bind the controller).
- Overriding is whole-method: implement the smallest use case that isolates your change, not a coarse one, so you inherit platform fixes to the others.
Verify
npm-free: start the app and curl "/events?page=0" — 12 items, newest first. A
non-overridden read (e.g. GET /city-places) is unchanged, and the startup log shows
Model City default 'defaultGetEventsUseCase' … disabled: seam GetEventsUseCase is covered by bean 'myGetEventsUseCase'.