### Pagination Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Demonstrates the offset/limit pattern for pagination in GET requests. This example requests 10 items starting from the 20th item. ```text GET /courses?limit=10&offset=20 ``` -------------------------------- ### Course Search with Ordering and Pagination Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example of a GET request to search courses with a filter on duration, ordering by name, and specifying limit and offset for pagination. ```text GET /courses?filters[0][field]=duration&filters[0][operator]=%3E&filters[0][value]=30&order_by=name&order=ASC&limit=20&offset=0 ``` -------------------------------- ### Clone the DDD Example Repository Source: https://github.com/codelytv/java-ddd-example/blob/main/README.md Clones the Java DDD example project from GitHub. This is the first step to starting a new project with this template. ```bash git clone https://github.com/CodelyTV/java-ddd-example ``` -------------------------------- ### GET /courses/{id} Response Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example JSON response for retrieving a single course by ID. ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Advanced Java", "duration": "40" } ``` -------------------------------- ### Dispatch Command Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/command-query-event-bus.md Example of how to dispatch a command using the CommandBus. Ensure the CommandBus is properly initialized. ```java commandBus.dispatch(new CreateCourseCommand("550e8400-e29b-41d4-a716-446655440000", "Java", "40")); ``` -------------------------------- ### GET /courses-counter Response Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example JSON response for retrieving the total number of courses. ```json { "total": 42 } ``` -------------------------------- ### GET /courses Response Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example JSON response for a successful query to the /courses endpoint, showing a list of course objects with their IDs, names, and durations. ```json [ { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Advanced Java", "duration": "40" }, { "id": "550e8400-e29b-41d4-a716-446655440001", "name": "Spring Boot Basics", "duration": "20" } ] ``` -------------------------------- ### Search Courses API Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/README.md Demonstrates how to search for courses using a curl command. This example shows how to filter, sort, and paginate course results. ```bash curl "http://localhost:8082/courses?filters[0][field]=name&filters[0][operator]=CONTAINS&filters[0][value]=java&order_by=duration&order=ASC&limit=10&offset=0" \ -H "Authorization: Basic YWRtaW46YWRtaW4=" ``` -------------------------------- ### Install Java 11 with Corretto Source: https://github.com/codelytv/java-ddd-example/blob/main/README.md Installs Amazon Corretto 11 using Homebrew Cask. Ensure Java 11 is available for the project. ```bash brew cask install corretto ``` -------------------------------- ### PUT /courses/{id} Request Body Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example JSON request body for creating or updating a course. ```json { "name": "Advanced Java", "duration": "40" } ``` -------------------------------- ### Course Search with Multiple Filters Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example of a GET request to search courses using multiple filter criteria: by name and by duration. ```text GET /courses?filters[0][field]=name&filters[0][operator]=CONTAINS&filters[0][value]=java&filters[1][field]=duration&filters[1][operator]=%3E&filters[1][value]=20 ``` -------------------------------- ### Course Creation Usage Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Demonstrates how to create a new Course instance using the static `create` method and retrieve associated domain events. ```java CourseId id = new CourseId("550e8400-e29b-41d4-a716-446655440000"); CourseName name = new CourseName("Advanced Java"); CourseDuration duration = new CourseDuration(40); Course course = Course.create(id, name, duration); List events = course.pullDomainEvents(); ``` -------------------------------- ### Start Docker Environment Source: https://github.com/codelytv/java-ddd-example/blob/main/README.md Brings up the Docker environment required for the project. This command assumes a Makefile is present with a 'up' target. ```bash make up ``` -------------------------------- ### Simple Course Search Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Basic example of a GET request to search for courses, filtering by name using the 'CONTAINS' operator. ```text GET /courses?filters[0][field]=name&filters[0][operator]=CONTAINS&filters[0][value]=java ``` -------------------------------- ### GET /courses/{id} Error Response Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example JSON error response when a course is not found. ```json { "error_code": "course_not_exist", "error_message": "The course <550e8400-e29b-41d4-a716-446655440000> doesn't exist" } ``` -------------------------------- ### CourseResponse Implementation Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/command-query-event-bus.md Example implementation of a `Response`. It contains the data returned after a query is executed, typically derived from an aggregate. ```java public final class CourseResponse implements Response { private final String id; private final String name; private final String duration; public CourseResponse(String id, String name, String duration) { this.id = id; this.name = name; this.duration = duration; } public static CourseResponse fromAggregate(Course course) { return new CourseResponse( course.id().value(), course.name().value(), course.duration().value() ); } public String id() { return id; } public String name() { return name; } public String duration() { return duration; } } ``` -------------------------------- ### GET /health-check Response Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example JSON response for checking the health status of the MOOC backend service. ```json { "application": "mooc_backend", "status": "ok" } ``` -------------------------------- ### Install Corretto Java with Homebrew Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Provides a command for installing Amazon Corretto (a Java distribution) on macOS using Homebrew. This is a prerequisite for running the project. ```bash # macOS with Homebrew brew cask install corretto ``` -------------------------------- ### GET / Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Serves the backoffice frontend home page. This is the main entry point for the frontend application. ```APIDOC ## GET / ### Description Serves the backoffice frontend home page. ### Method GET ### Endpoint / ### Response Serves the HTML for the home page. ``` -------------------------------- ### Set JVM Memory Options Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Configure the maximum and initial heap size for the Java Virtual Machine when starting the application. ```bash java -Xmx1g -Xms512m -jar java-ddd-example-0.0.1.jar ``` -------------------------------- ### Querying Course Creation Events Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/analytics-module.md This example demonstrates how to query for 'course.created' events and analyze the distribution of course durations. It uses Java Streams for data processing. ```java List courseCreations = analyticsRepository.findByEventName("course.created"); courseCreations.stream() .map(event -> event.getBody().get("duration")) .collect(Collectors.groupingByConcurrent( duration -> duration, Collectors.counting() )) .forEach((duration, count) -> System.out.println("Duration: " + duration + ", Count: " + count) ); ``` -------------------------------- ### Example Usage of @Service Annotation Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/shared-infrastructure.md Demonstrates how to use the custom @Service annotation on a domain service and a command handler. ```java @Service public class CourseCreator { // ... } @Service public class CreateCourseCommandHandler implements CommandHandler { // ... } ``` -------------------------------- ### GET /health-check Response Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example JSON response for the /health-check endpoint, indicating the application name and its current status. ```json { "application": "backoffice_backend", "status": "ok" } ``` -------------------------------- ### Get Course API Request Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/README.md Example of a cURL command to retrieve a specific course by its ID. ```bash curl http://localhost:8081/courses/550e8400-e29b-41d4-a716-446655440000 ``` -------------------------------- ### Gradle Build Tasks Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Common Gradle tasks for building, testing, packaging, and running the Java DDD Example project. Use these commands in your terminal. ```bash # Build the project ./gradlew build # Run tests ./gradlew test # Create JAR ./gradlew bootJar # Run application ./gradlew bootRun # View project paths ./gradlew view_paths ``` -------------------------------- ### Get Course API Response Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/README.md Example of a JSON response when retrieving a course via the API. It includes the course ID, name, and duration. ```json { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Java Programming", "duration": "40" } ``` -------------------------------- ### Set JAVA_HOME Environment Variable Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Sets the JAVA_HOME environment variable to point to the installed Java Development Kit. This is an example for macOS and requires adjusting the path based on your installation. ```bash # Set default JVM (example for macOS) export JAVA_HOME='/Library/Java/JavaVirtualMachines/amazon-corretto-21.jdk/Contents/Home' ``` -------------------------------- ### Create Course API Request Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/README.md Example of a cURL command to create a course using the API. It specifies the HTTP method, URL, content type, and request body. ```bash curl -X PUT http://localhost:8081/courses/550e8400-e29b-41d4-a716-446655440000 \ -H "Content-Type: application/json" \ -d '{"name":"Java Programming","duration":"40"}' ``` -------------------------------- ### Dockerfile for Application Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Dockerfile used to build a Docker image for the Java DDD Example application. It copies the built JAR and sets the entrypoint to run the application. ```dockerfile FROM openjdk:21 COPY build/libs/java-ddd-example-0.0.1.jar app.jar ENTRYPOINT ["java", "-jar", "/app.jar"] ``` -------------------------------- ### Enable Debug Mode Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Start the application with Java Debug Wire Protocol enabled to allow remote debugging. ```bash java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 \ -jar java-ddd-example-0.0.1.jar ``` -------------------------------- ### DomainError Usage Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/core-domain-classes.md Example of extending DomainError to create a specific error like CourseNotExist. This demonstrates how to define custom domain errors with relevant context. ```java public final class CourseNotExist extends DomainError { public CourseNotExist(CourseId id) { super("course_not_exist", String.format("The course <%s> doesn't exist", id.value())); } } throw new CourseNotExist(courseId); ``` -------------------------------- ### Java Error Mapping Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Java code snippet demonstrating how to map domain errors to HTTP status codes within a controller. This example maps CourseNotExist to HttpStatus.NOT_FOUND. ```java @Override public HashMap, HttpStatus> errorMapping() { return new HashMap, HttpStatus>() { { put(CourseNotExist.class, HttpStatus.NOT_FOUND); } }; } ``` -------------------------------- ### HTTP Request to Search Courses Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md An example cURL command to search for courses containing 'java', ordered by duration ascending, with specified limit and offset. Includes Basic Authentication header. ```bash # Search courses containing "java", ordered by duration ascending curl -X GET "http://localhost:8082/courses?filters[0][field]=name&filters[0][operator]=CONTAINS&filters[0][value]=java&order_by=duration&order=ASC&limit=10&offset=0" \ -H "Authorization: Basic YWRtaW46YWRtaW4=" ``` -------------------------------- ### Set Java 11 as Default JVM Source: https://github.com/codelytv/java-ddd-example/blob/main/README.md Configures the JAVA_HOME environment variable to point to the installed Corretto 11 JDK. This ensures the system uses the correct Java version. ```bash export JAVA_HOME='/Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home' ``` -------------------------------- ### Get Current Course Count Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses-counter.md Example of how to retrieve the current total course count using the query bus. Assumes a configured query bus and FindCoursesCounterQuery. ```java // Via query bus FindCoursesCounterQuery query = new FindCoursesCounterQuery(); CoursesCounterResponse response = queryBus.ask(query); System.out.println("Total courses: " + response.total()); ``` -------------------------------- ### GET /courses Endpoint Parameters Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Demonstrates query parameters for filtering, ordering, and pagination of courses. Filters can be applied to fields like 'name' and 'duration' with various operators. ```text filters[0][field]=name filters[0][operator]=CONTAINS filters[0][value]=java filters[1][field]=duration filters[1][operator]=> filters[1][value]=30 order_by=duration&order=ASC&limit=10&offset=0 ``` -------------------------------- ### GET /courses (Frontend) Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Displays the courses list page in the frontend. This endpoint is used to navigate to the course listing view. ```APIDOC ## GET /courses (Frontend) ### Description Displays the courses list page. ### Method GET ### Endpoint /courses ### Response Serves the HTML for the courses list page. ``` -------------------------------- ### Usage Example for `hasIncremented` and `increment` Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses-counter.md Demonstrates how to check if a course has already been counted using `hasIncremented` before calling `increment` to ensure the counter is updated correctly. ```java CourseId courseId = new CourseId("550e8400-e29b-41d4-a716-446655440000"); if (!counter.hasIncremented(courseId)) { counter.increment(courseId); } ``` -------------------------------- ### CourseResponse Class Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/types.md Represents a single course in a response. Used for single course GET requests. ```Java public final class CourseResponse implements Response { private final String id; private final String name; private final String duration; public CourseResponse(String id, String name, String duration) public static CourseResponse fromAggregate(Course course) public String id() public String name() public String duration() } ``` -------------------------------- ### IntValueObject Usage Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/core-domain-classes.md Example of extending IntValueObject to create a specific type like CoursesCounterTotal. This demonstrates how to define a custom value object with an integer type. ```java public final class CoursesCounterTotal extends IntValueObject { public CoursesCounterTotal(Integer value) { super(value); } } CoursesCounterTotal total = new CoursesCounterTotal(42); ``` -------------------------------- ### HTTP Basic Authentication Header Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Example of the Authorization header format for HTTP Basic Authentication. The credentials must be base64 encoded. ```text Authorization: Basic base64(username:password) ``` -------------------------------- ### CoursesCounter Aggregate Initialization Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses-counter.md Initializes a new CoursesCounter aggregate with a given ID, zero total, and an empty list of existing courses. This is the starting point for tracking course creations. ```java public final class CoursesCounter { private CoursesCounterId id; private CoursesCounterTotal total; private List existingCourses; public CoursesCounter( CoursesCounterId id, CoursesCounterTotal total, List existingCourses ) { this.id = id; this.total = total; this.existingCourses = existingCourses; } public static CoursesCounter initialize(String id) { return new CoursesCounter( new CoursesCounterId(id), CoursesCounterTotal.initialize(), new ArrayList<>() ); } } ``` -------------------------------- ### Build and Run Project Commands Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/README.md Commands for building the project, running tests, creating a JAR, and managing Docker services. ```bash # Build the project ./gradlew build # Run tests ./gradlew test # Create JAR ./gradlew bootJar ``` ```bash # Start services make up # Stop services make down ``` -------------------------------- ### Create New Course Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md Creates a new course within the backoffice system. Authentication is required. ```APIDOC ## POST /courses ### Description Create a new course. ### Method POST ### Endpoint /courses ### Parameters #### Request Body - **id** (string) - Required - The unique identifier for the course. - **name** (string) - Required - The name of the course. - **duration** (integer) - Required - The duration of the course in minutes. ### Request Example ```json { "id": "new-course-id", "name": "New Course Title", "duration": 90 } ``` ### Response #### Success Response (201) - **message** (string) - Confirmation message indicating the course was created. #### Response Example ```json { "message": "Course created successfully" } ``` ``` -------------------------------- ### Basic Search with Filters Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/criteria.md Demonstrates how to create a basic search query using filters and order. Use this for simple filtering and sorting. ```java Filter nameFilter = Filter.create("name", "contains", "Java"); Filters filters = new Filters(Arrays.asList(nameFilter)); Order order = Order.asc("duration"); Criteria criteria = new Criteria(filters, order); List courses = courseRepository.matching(criteria); ``` -------------------------------- ### CreateCourseCommand Implementation Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/command-query-event-bus.md Concrete implementation of the Command interface for creating a course. It holds course details like ID, name, and duration. ```java public final class CreateCourseCommand implements Command { private final String id; private final String name; private final String duration; public CreateCourseCommand(String id, String name, String duration) { this.id = id; this.name = name; this.duration = duration; } public String id() { return id; } public String name() { return name; } public String duration() { return duration; } } ``` -------------------------------- ### Immutable Value Object Example Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/shared-infrastructure.md An example of an immutable value object, CourseResponse, which has private final fields and no setters, ensuring its state cannot be changed after creation. ```java public final class CourseResponse implements Response { private final String id; private final String name; private final String duration; // No setters, only constructor and getters } ``` -------------------------------- ### CreateCourseCommand Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Command to create a new course. Use this command to initiate the course creation process. ```java public final class CreateCourseCommand implements Command { private final String id; private final String name; private final String duration; public CreateCourseCommand(String id, String name, String duration) { this.id = id; this.name = name; this.duration = duration; } public String id() { return id; } public String name() { return name; } public String duration() { return duration; } } ``` -------------------------------- ### Create Course Command Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Use the command bus to dispatch a CreateCourseCommand to create a new course. Ensure the command bus is properly configured. ```java // Via command bus CreateCourseCommand command = new CreateCourseCommand( "550e8400-e29b-41d4-a716-446655440000", "Advanced Java", "40" ); commandBus.dispatch(command); ``` -------------------------------- ### Run All Tests with Gradle Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Command to execute all test classes in the project that follow the '*Should' naming convention. This is the standard way to run tests using Gradle. ```bash ./gradlew test ``` -------------------------------- ### GET /health-check Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Check the health status of the backoffice backend. This endpoint is useful for monitoring the application's availability. ```APIDOC ## GET /health-check ### Description Check the health status of the backoffice backend. ### Method GET ### Endpoint /health-check ### Response #### Success Response (200) - **application** (String) - The name of the application - **status** (String) - The health status of the application (e.g., "ok") #### Response Example ```json { "application": "backoffice_backend", "status": "ok" } ``` ``` -------------------------------- ### GET /courses-counter Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Retrieve the total number of courses. This endpoint provides the current count of all courses available in the system. ```APIDOC ## GET /courses-counter ### Description Retrieve the total number of courses. This endpoint provides the current count of all courses available in the system. ### Method GET ### Endpoint /courses-counter ### Response #### Success Response (200) - **total** (Integer) - Total number of courses created #### Response Example { "total": 42 } ``` -------------------------------- ### Build Project JAR with Gradle Source: https://github.com/codelytv/java-ddd-example/blob/main/README.md Executes the Gradle build task to create the project's JAR file. This verifies the build process and produces an executable artifact. ```bash make build ``` -------------------------------- ### Execute a Query Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/command-query-event-bus.md Use the `ask` method to execute a query and retrieve a response. Ensure the query handler is registered. ```java FindCourseQuery query = new FindCourseQuery("550e8400-e29b-41d4-a716-446655440000"); CourseResponse response = queryBus.ask(query); ``` -------------------------------- ### GET /health-check Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Check the health status of the MOOC backend service. This endpoint allows monitoring the operational status of the service. ```APIDOC ## GET /health-check ### Description Check the health status of the MOOC backend service. This endpoint allows monitoring the operational status of the service. ### Method GET ### Endpoint /health-check ### Response #### Success Response (200) - **application** (String) - Service name - **status** (String) - Health status #### Response Example { "application": "mooc_backend", "status": "ok" } ``` -------------------------------- ### Search Courses by Criteria Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md Shows how to search for courses using a query bus with specific filters, ordering, and pagination parameters. Requires filter, criteria, and query objects to be defined. ```java List filters = Arrays.asList( Filter.create("name", "contains", "java") ); Criteria criteria = new Criteria( new Filters(filters), Order.asc("duration"), Optional.of(10), Optional.of(0) ); SearchBackofficeCoursesByCriteriaQuery query = new SearchBackofficeCoursesByCriteriaQuery( filters, Optional.of("duration"), Optional.of("ASC"), Optional.of(10), Optional.of(0) ); BackofficeCoursesResponse response = queryBus.ask(query); ``` -------------------------------- ### Run Tests and Verification with Gradle Source: https://github.com/codelytv/java-ddd-example/blob/main/README.md Runs the Gradle test task and any associated plugin verification tasks. This ensures the project's tests pass and the build is stable. ```bash make test ``` -------------------------------- ### CoursesCounterTotal Integer Value Object Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/types.md Represents the total count of courses, starting at 0 and incrementing. Extends IntValueObject and is immutable. ```Java public final class CoursesCounterTotal extends IntValueObject { public static CoursesCounterTotal initialize() { return new CoursesCounterTotal(0); } public CoursesCounterTotal increment() { return new CoursesCounterTotal(value() + 1); } } ``` -------------------------------- ### Event Bus Implementation Configuration Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/README.md Configure the event bus implementation in the application.properties file. Options include mysql, rabbitmq, and spring. ```properties event.bus.implementation=mysql # or rabbitmq, or spring ``` -------------------------------- ### GET /courses/{id} Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Retrieve a single course by ID. This endpoint allows fetching course details using its unique identifier. ```APIDOC ## GET /courses/{id} ### Description Retrieve a single course by ID. This endpoint allows fetching course details using its unique identifier. ### Method GET ### Endpoint /courses/{id} #### Path Parameters - **id** (String) - Yes - Course UUID ### Response #### Success Response (200) - **id** (String) - Course UUID - **name** (String) - Course name - **duration** (String) - Course duration (hours) #### Response Example { "id": "550e8400-e29b-41d4-a716-446655440000", "name": "Advanced Java", "duration": "40" } ``` -------------------------------- ### Authenticate User via Command Bus Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md Demonstrates how to authenticate a user by dispatching an AuthenticateUserCommand through a command bus. Assumes the command bus is implemented and available. ```java AuthenticateUserCommand command = new AuthenticateUserCommand("admin", "admin"); commandBus.dispatch(command); ``` -------------------------------- ### BackofficeCoursesResponse Get Courses Method Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md A getter method for the list of course responses within the BackofficeCoursesResponse DTO. It returns the collection of courses found. ```java public List courses() ``` -------------------------------- ### CoursesCounterTotal `initialize` Method Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses-counter.md Static factory method to create a CoursesCounterTotal initialized to zero. Use this when creating a new counter. ```java public static CoursesCounterTotal initialize() ``` -------------------------------- ### Constructing Criteria from URL Parameters Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/criteria.md Illustrates how to build a Criteria object from request parameters, including filters and sorting. This is useful for dynamic searches based on user input. ```java Optional name = request.getParameter("name"); Optional order = request.getParameter("order"); Optional direction = request.getParameter("direction"); Filter filter = Filter.create("name", "contains", name.orElse("")); Criteria criteria = new Criteria( new Filters(Arrays.asList(filter)), Order.fromValues(order, direction) ); ``` -------------------------------- ### CoursesCounter Aggregate `initialize` Method Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses-counter.md Static factory method to create a new CoursesCounter instance. It sets the initial total to zero and the list of existing courses to empty. ```java public static CoursesCounter initialize(String id) ``` -------------------------------- ### Filter and Collect Monthly Course Creations Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/analytics-module.md This Java snippet retrieves all events between the start of the current month and now, filters them for 'course.created' events, and collects them into a list. ```java LocalDate month = LocalDate.now().withDayOfMonth(1); List monthly = analyticsRepository .findBetween( month.atStartOfDay(), LocalDate.now().atStartOfDay() ).stream() .filter(e -> e.getEventName().equals("course.created")) .collect(Collectors.toList()); ``` -------------------------------- ### Scenario: Non-existent Course Request Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/errors.md Illustrates the flow when a user requests a course that does not exist, leading to a CourseNotExist error and a 404 HTTP response. ```text GET /courses/invalid-uuid ↓ CourseGetController.index() ↓ FindCourseQuery executed ↓ CourseFinder.find() calls repository.search() ↓ Optional.empty() returned ↓ CourseNotExist thrown ↓ Controller error mapping catches ↓ HTTP 404 response with error details ``` -------------------------------- ### Dependency Injection via Constructor Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/shared-infrastructure.md Demonstrates dependency injection using constructor injection, a common pattern for ensuring dependencies are provided upon object creation. ```java @Service public class CreateCourseCommandHandler { private final CourseCreator creator; private final CourseRepository repository; public CreateCourseCommandHandler( CourseCreator creator, CourseRepository repository ) { this.creator = creator; this.repository = repository; } } ``` -------------------------------- ### ApiController Error Mapping Implementation Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/shared-infrastructure.md Example implementation of the errorMapping method in ApiController. Maps specific domain errors to HTTP status codes for REST responses. ```java @Override public HashMap, HttpStatus> errorMapping() { return new HashMap, HttpStatus>() { { put(CourseNotExist.class, HttpStatus.NOT_FOUND); put(InvalidAuthCredentials.class, HttpStatus.UNAUTHORIZED); } }; } ``` -------------------------------- ### CourseResponse constructor Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Response DTO for course queries. Use this constructor to create a course response object. ```java public CourseResponse(String id, String name, String duration) { this.id = id; this.name = name; this.duration = duration; } public String id() { return id; } public String name() { return name; } public String duration() { return duration; } ``` -------------------------------- ### Calculate Total Courses Created Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/analytics-module.md This Java snippet calculates the total number of 'course.created' events by querying the analytics repository and getting the size of the resulting list. ```java long totalCourses = analyticsRepository .findByEventName("course.created") .size(); ``` -------------------------------- ### Order Static Factory Methods Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/criteria.md Provides static methods to create Order instances, including creating an order from optional string values, a default 'none' order, descending order, and ascending order. ```java public static Order fromValues(Optional orderBy, Optional orderType) ``` ```java public static Order none() ``` ```java public static Order desc(String orderBy) ``` ```java public static Order asc(String orderBy) ``` -------------------------------- ### Error Hierarchy Visualization Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/errors.md Shows the inheritance structure of errors, starting from Throwable down to specific DomainError subclasses. This helps understand the relationship between different error types. ```text Throwable ├── Exception │ ├── RuntimeException │ │ ├── DomainError (abstract) │ │ │ ├── CourseNotExist │ │ │ ├── CoursesCounterNotInitialized │ │ │ ├── CommandHandlerExecutionError │ │ │ ├── CommandNotRegisteredError │ │ │ ├── QueryHandlerExecutionError │ │ │ ├── QueryNotRegisteredError │ │ │ ├── InvalidAuthUsername │ │ │ └── [other domain errors] │ │ └── InvalidAuthCredentials (extends RuntimeException directly) │ └── [checked exceptions from Java libraries] ``` -------------------------------- ### Automatic Counter Increment on Course Creation Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses-counter.md Demonstrates how creating a course via the command bus automatically triggers the courses counter increment due to event subscription. Assumes a configured command bus. ```java CreateCourseCommand command = new CreateCourseCommand( "550e8400-e29b-41d4-a716-446655440000", "Advanced Java", "40" ); commandBus.dispatch(command); // The courses counter is automatically incremented // because IncrementCoursesCounterOnCourseCreated listens to CourseCreatedDomainEvent ``` -------------------------------- ### IncrementCoursesCounterOnCourseCreated Event Subscriber Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses-counter.md Subscribes to CourseCreatedDomainEvent to automatically increment the courses counter when a new course is created. Requires Spring and DDD event subscription setup. ```java @Service @DomainEventSubscriber({CourseCreatedDomainEvent.class}) public final class IncrementCoursesCounterOnCourseCreated { private final CoursesCounterIncrementer incrementer; public IncrementCoursesCounterOnCourseCreated(CoursesCounterIncrementer incrementer) { this.incrementer = incrementer; } @EventListener public void on(CourseCreatedDomainEvent event) { CourseId courseId = new CourseId(event.aggregateId()); incrementer.increment(courseId); } } ``` -------------------------------- ### Service Annotation Usage Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/core-domain-classes.md Example of applying the @Service annotation to a command handler. This annotation marks the class as a Spring service component within the domain or application layer. ```java @Service public final class CreateCourseCommandHandler implements CommandHandler { // ... } ``` -------------------------------- ### Error Recovery: CourseNotExist Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/errors.md Outlines the recovery strategy for a CourseNotExist error, involving user action to verify the ID and system action to return a 404. ```text CourseNotExist - User Action: Verify course ID exists - System Action: Return 404 to client - Recovery: Create the course or correct the ID ``` -------------------------------- ### RabbitMQ Configuration Properties Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/shared-infrastructure.md Configuration properties for connecting to a RabbitMQ instance. Ensure these match your RabbitMQ server details. ```properties spring.rabbitmq.host=localhost sspring.rabbitmq.port=5672 sspring.rabbitmq.username=guest sspring.rabbitmq.password=guest ``` -------------------------------- ### Pull Domain Events from AggregateRoot Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/core-domain-classes.md Retrieves all recorded domain events from an aggregate and clears the internal event list. Use this to get events that have occurred since the last pull. ```java final public List pullDomainEvents() { List events = this.events; this.events = new ArrayList<>(); return events; } ``` ```java Course course = Course.create(new CourseId("123"), new CourseName("Java"), new CourseDuration("40h")); List events = course.pullDomainEvents(); // Returns CourseCreatedDomainEvent ``` -------------------------------- ### Backoffice Authentication Configuration Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Configuration properties for enabling and setting up HTTP Basic Authentication for the backoffice. Ensure these properties are set in application.properties. ```properties # application.properties auth.enabled=true auth.username=admin auth.password=admin ``` -------------------------------- ### MOOC Backend Application Properties Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Configures the application name and server port specifically for the MOOC backend. It also shows options for selecting the EventBus implementation. ```properties spring.application.name=mooc-backend server.port=8081 # Use MySQLEventBus event.bus.type=mysql # Or use RabbitMQ # event.bus.type=rabbitmq # Or use Spring event bus # event.bus.type=spring ``` -------------------------------- ### CourseCreator create method Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Creates a new course and publishes its creation event. This method requires valid CourseId, CourseName, and CourseDuration objects. ```java public void create(CourseId id, CourseName name, CourseDuration duration) ``` -------------------------------- ### CreateCourseCommandHandler Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Handles CreateCourseCommand by delegating to CourseCreator. Ensure CourseCreator is properly configured before using this handler. ```java @Service public final class CreateCourseCommandHandler implements CommandHandler { private final CourseCreator creator; public CreateCourseCommandHandler(CourseCreator creator) { this.creator = creator; } @Override public void handle(CreateCourseCommand command) { CourseId id = new CourseId(command.id()); CourseName name = new CourseName(command.name()); CourseDuration duration = new CourseDuration(command.duration()); creator.create(id, name, duration); } } ``` -------------------------------- ### Course Aggregate Creation Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Defines the Course aggregate root, including its properties and a static factory method for creation. Records a CourseCreatedDomainEvent upon instantiation. ```java public final class Course extends AggregateRoot { private final CourseId id; private final CourseName name; private final CourseDuration duration; public Course(CourseId id, CourseName name, CourseDuration duration) { this.id = id; this.name = name; this.duration = duration; } public static Course create(CourseId id, CourseName name, CourseDuration duration) { Course course = new Course(id, name, duration); course.record(new CourseCreatedDomainEvent(id.value(), name.value(), duration.value())); return course; } } ``` -------------------------------- ### Event Bus Implementation Selection Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Select the desired event bus implementation by setting the 'event.bus.implementation' property in application.properties. Options include mysql, rabbitmq, and spring. ```properties # application.properties event.bus.implementation=mysql # or event.bus.implementation=rabbitmq # or event.bus.implementation=spring ``` -------------------------------- ### Search Courses with Criteria Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Use the courseRepository to find matching courses based on criteria, including filters and sorting. The criteria can specify name filters and order by duration. ```java Filter nameFilter = Filter.create("name", "contains", "Java"); Criteria criteria = new Criteria( new Filters(Arrays.asList(nameFilter)), Order.asc("duration") ); List courses = courseRepository.matching(criteria); ``` -------------------------------- ### POST /courses (Frontend) Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Submits a course creation form from the frontend. This endpoint handles the submission of new course data. ```APIDOC ## POST /courses (Frontend) ### Description Submits a course creation form. ### Method POST ### Endpoint /courses ### Response Handles the submission of course creation form data. ``` -------------------------------- ### SearchBackofficeCoursesByCriteriaQueryHandler Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md Handles the search for backoffice courses using specified criteria. It delegates the actual search operation to the BackofficeCoursesSearcher. ```APIDOC ## SearchBackofficeCoursesByCriteriaQueryHandler ### Description Handles the search for backoffice courses using specified criteria. It delegates the actual search operation to the BackofficeCoursesSearcher. ### Method Not Applicable (This is a handler class, not a direct API endpoint) ### Endpoint Not Applicable ### Parameters This handler processes a `SearchBackofficeCoursesByCriteriaQuery` object which contains fields like filters, orderBy, orderType, limit, and offset. ### Request Example ```json { "filters": [ {"field": "name", "operator": "CONTAINS", "value": "Java"} ], "orderBy": "name", "orderType": "ASC", "limit": 10, "offset": 0 } ``` ### Response #### Success Response Returns a `BackofficeCoursesResponse` object containing a list of `BackofficeCourseResponse`. #### Response Example ```json { "courses": [ { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "name": "Introduction to Java", "duration": "10" } ] } ``` ``` -------------------------------- ### Filtering with Bracket Notation Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Demonstrates how to apply filters to API requests using bracket notation in query strings. Multiple filters are combined with AND logic. ```APIDOC ## Filtering Filters use a bracket notation in query strings: ``` filters[0][field]=name filters[0][operator]=CONTAINS filters[0][value]=java filters[1][field]=duration filters[1][operator]=> filters[1][value]=30 ``` Multiple filters are combined with AND logic. ``` -------------------------------- ### Spring Datasource and Server Configuration Properties Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/shared-infrastructure.md Configuration properties for setting up the datasource connection and server port using Spring Boot. ```properties spring.datasource.url=jdbc:mysql://localhost:3306/ddd spring.datasource.username=root spring.datasource.password=root server.port=8080 ``` -------------------------------- ### Environment Variables for Database and RabbitMQ Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Defines essential environment variables for configuring database and RabbitMQ connections. These variables are typically loaded from a .env file. ```bash # Database configuration DB_HOST=mysql DB_PORT=3306 DB_NAME=java_ddd_example DB_USER=root DB_PASSWORD=root # RabbitMQ configuration RABBITMQ_HOST=rabbitmq RABBITMQ_PORT=5672 RABBITMQ_USER=guest RABBITMQ_PASSWORD=guest # Application configuration SERVER_PORT=8080 ``` -------------------------------- ### Backoffice Frontend Application Properties Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Configures the application name and server port for the Backoffice frontend. This file is typically used for frontend-specific settings. ```properties spring.application.name=backoffice-frontend server.port=8083 ``` -------------------------------- ### Find Course Query Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Use the query bus to ask for course details using a FindCourseQuery. The response contains the course name and duration. ```java // Via query bus FindCourseQuery query = new FindCourseQuery("550e8400-e29b-41d4-a716-446655440000"); CourseResponse response = queryBus.ask(query); System.out.println("Course: " + response.name()); System.out.println("Duration: " + response.duration() + " hours"); ``` -------------------------------- ### Backoffice Backend Application Properties Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Sets the application name, server port, and basic authentication credentials for the Backoffice backend. This configuration is specific to the backoffice module. ```properties spring.application.name=backoffice-backend server.port=8082 # Basic auth credentials auth.username=admin auth.password=admin ``` -------------------------------- ### CourseNotExist Exception Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Custom domain error thrown when a requested course cannot be found. It includes a formatted error message indicating the non-existent course ID. ```java public final class CourseNotExist extends DomainError { public CourseNotExist(CourseId id) { super("course_not_exist", String.format("The course <%s> doesn't exist", id.value())); } } ``` -------------------------------- ### Gradle Subproject Configuration Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Configures common settings for all Gradle subprojects, including source set directories. This structure organizes the project into modules like 'shared', 'mooc', 'backoffice', and 'analytics'. ```gradle subprojects { group = "tv.codely.${rootProject.name}" sourceSets { main { java { srcDirs = ['main'] } resources { srcDirs = ['main/resources'] } } test { java { srcDirs = ['test'] } resources { srcDirs = ['test/resources'] } } } } ``` -------------------------------- ### Configure Hibernate JPA Settings Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Optimize JPA and Hibernate performance by configuring JDBC batch size and the order of SQL operations. ```properties spring.jpa.properties.hibernate.jdbc.batch_size=20 spring.jpa.properties.hibernate.order_inserts=true spring.jpa.properties.hibernate.order_updates=true ``` -------------------------------- ### CourseResponse fromAggregate method Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Creates a CourseResponse from a Course aggregate. This is useful for transforming domain objects into response DTOs. ```java public static CourseResponse fromAggregate(Course course) { return new CourseResponse( course.id().value(), course.name().value(), course.duration().value() ); } ``` -------------------------------- ### Spotless Java Code Formatting Configuration Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Configuration block for Spotless in build.gradle to format Java code using Prettier. It specifies import order, removes unused imports, and ensures files end with a newline. ```gradle spotless { java { prettier(['prettier': '2.8.8', 'prettier-plugin-java': '2.2.0']) .config(['parser': 'java', 'useTabs': true, 'printWidth': 120]) importOrder('\#', 'java', '', 'tv.codely') removeUnusedImports() endWithNewline() formatAnnotations() } } ``` -------------------------------- ### Error Recovery: CoursesCounterNotInitialized Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/errors.md Describes the recovery for CoursesCounterNotInitialized, indicating no user action is needed and the system recovers by initializing the counter on first use. ```text CoursesCounterNotInitialized - User Action: None (system error) - System Action: Initialize counter on first use - Recovery: Create first course to initialize counter ``` -------------------------------- ### BackofficeCourse Class Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/types.md Represents a course object specifically for the backoffice context. It does not extend AggregateRoot and is separate from the MOOC Course aggregate. ```Java public final class BackofficeCourse { private final String id; private final String name; private final String duration; public BackofficeCourse(String id, String name, String duration) public static BackofficeCourse fromPrimitives(Map plainData) public String id() public String name() public String duration() public HashMap toPrimitives() } ``` -------------------------------- ### CoursesResponse fromAggregates method Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Creates a CoursesResponse from a list of course aggregates. Use this method to return multiple courses in a single response. ```java public static CoursesResponse fromAggregates(List courses) ``` -------------------------------- ### BackofficeCourseRepository Interface Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md Defines the contract for persisting and retrieving BackofficeCourse entities. It supports searching courses based on specified criteria. ```java public interface BackofficeCourseRepository { List matching(Criteria criteria); } ``` -------------------------------- ### API Ordering with Query Parameters Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/endpoints.md Specify the field to order by and the sort direction (ASC or DESC) using the `order_by` and `order` query parameters. ```http GET /courses?order_by=duration&order=DESC ``` -------------------------------- ### CourseRepository Interface Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/mooc-courses.md Defines the contract for course data persistence operations, including saving, searching by ID, and searching by criteria. ```java public interface CourseRepository { void save(Course course); Optional search(CourseId id); List matching(Criteria criteria); } ``` -------------------------------- ### Courses Counter Not Initialized Error Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/errors.md Indicates that the courses counter has not been initialized. Extends DomainError. Triggered when attempting to access the counter before it's created. ```java public final class CoursesCounterNotInitialized extends DomainError { public CoursesCounterNotInitialized() { super( "courses_counter_not_initialized", "Courses counter has not been initialized" ); } } ``` -------------------------------- ### Query Bus - ask Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/command-query-event-bus.md Executes a query and returns a response. This method is used to retrieve data by dispatching a query to its corresponding handler. ```APIDOC ## ask(Query query) ### Description Executes a query and returns a response. ### Method Not applicable (SDK method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters - **query** (Query) - Required - The query to execute ### Returns `R extends Response` - The query result ### Throws `QueryHandlerExecutionError` - If handler execution fails ### Usage Example ```java FindCourseQuery query = new FindCourseQuery("550e8400-e29b-41d4-a716-446655440000"); CourseResponse response = queryBus.ask(query); ``` ``` -------------------------------- ### BackofficeCourse Domain Object Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md Represents a course within the backoffice context. It is not an aggregate root and includes methods for conversion to and from primitive data types. ```java public final class BackofficeCourse { private final String id; private final String name; private final String duration; public BackofficeCourse(String id, String name, String duration) { this.id = id; this.name = name; this.duration = duration; } public static BackofficeCourse fromPrimitives(Map plainData) { return new BackofficeCourse( (String) plainData.get("id"), (String) plainData.get("name"), (String) plainData.get("duration") ); } public String id() { return id; } public String name() { return name; } public String duration() { return duration; } public HashMap toPrimitives() { return new HashMap() {{ put("id", id); put("name", name); put("duration", duration); }}; } } ``` -------------------------------- ### Set Custom Java Properties Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/configuration.md Override default application properties like database connection URLs or server ports using system properties. ```bash java -Dspring.datasource.url=jdbc:mysql://custom-host:3306/db \ -Dserver.port=9090 \ -jar java-ddd-example-0.0.1.jar ``` -------------------------------- ### Basic HTTP Authentication Middleware Configuration Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/backoffice-module.md Configuration properties for the BasicHttpAuthMiddleware, specifying the username and password for basic HTTP authentication. ```properties auth.username=admin auth.password=admin ``` -------------------------------- ### Paginated Search with Criteria Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/criteria.md Shows how to perform a paginated search by specifying limit and offset in the Criteria object. Use this to retrieve specific pages of results. ```java Filter filter = Filter.create("duration", ">", "50"); Criteria criteria = new Criteria( new Filters(Arrays.asList(filter)), Order.desc("name"), Optional.of(20), // limit Optional.of(0) // offset ); List firstPage = courseRepository.matching(criteria); ``` -------------------------------- ### Publish Domain Events Source: https://github.com/codelytv/java-ddd-example/blob/main/_autodocs/api-reference/command-query-event-bus.md Use the `publish` method on the `EventBus` to send a list of domain events. Events are typically pulled from an aggregate. ```java Course course = Course.create(courseId, name, duration); List events = course.pullDomainEvents(); eventBus.publish(events); ```