// adapters/web/ProductController.java package com.example.adapters.web; import com.example.application.port.in.CreateProductUseCase; import com.example.application.port.in.CreateProductUseCase.CreateProductCommand; import com.example.domain.model.Product; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @RestController @RequiredArgsConstructor public class ProductController private final CreateProductUseCase createProductUseCase; // depends on incoming port
class CreateProductServiceTest @Test void shouldSaveProduct() ProductRepository mockRepo = mock(ProductRepository.class); var service = new CreateProductService(mockRepo); var command = new CreateProductCommand("Mouse", 25, "USD"); Product result = service.execute(command); verify(mockRepo).save(any(Product.class)); assertEquals("Mouse", result.name()); designing hexagonal architecture with java pdf
// application/service/CreateProductService.java package com.example.application.service; import com.example.application.port.in.CreateProductUseCase; import com.example.domain.model.Money; import com.example.domain.model.Product; import com.example.domain.spi.ProductRepository; import lombok.RequiredArgsConstructor; // adapters/web/ProductController
// adapters/persistence/JpaProductRepository.java package com.example.adapters.persistence; import com.example.domain.model.Product; import com.example.domain.spi.ProductRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; import java.util.Optional; @Component @RequiredArgsConstructor public class JpaProductRepository implements ProductRepository private final SpringDataJpaProductRepository jpaRepository; var service = new CreateProductService(mockRepo)
// domain/model/Money.java public record Money(double amount, String currency)