feat(wcs): wire core module into RuoYi
This commit is contained in:
@@ -107,6 +107,19 @@
|
||||
<artifactId>HslCommunication</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tngtech.archunit</groupId>
|
||||
<artifactId>archunit-junit5</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.ruoyi.wcs;
|
||||
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
|
||||
|
||||
class AdminWcsBoundaryArchitectureTest {
|
||||
|
||||
@Test
|
||||
void adminAdaptersCannotReachCorePersistenceImplementations() {
|
||||
JavaClasses classes = new ClassFileImporter()
|
||||
.importPackages("com.ruoyi.api", "com.ruoyi.project");
|
||||
|
||||
noClasses().should().dependOnClassesThat()
|
||||
.resideInAPackage("com.ruoyi.wcs.infrastructure.persistence..")
|
||||
.check(classes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.ruoyi.wcs;
|
||||
|
||||
import com.ruoyi.wcs.port.out.DomainEventPublisher;
|
||||
import com.ruoyi.wcs.port.out.WorkflowDefinitionProvider;
|
||||
import org.mockito.Mockito;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestPersistenceConfiguration {
|
||||
|
||||
@Bean
|
||||
public WorkflowDefinitionProvider workflowDefinitionProvider() {
|
||||
return Mockito.mock(WorkflowDefinitionProvider.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DomainEventPublisher domainEventPublisher() {
|
||||
return Mockito.mock(DomainEventPublisher.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.ruoyi.wcs;
|
||||
|
||||
import com.ruoyi.wcs.application.task.TransportOrderApplicationService;
|
||||
import com.ruoyi.wcs.domain.shared.IdGenerator;
|
||||
import com.ruoyi.wcs.domain.shared.WcsClock;
|
||||
import com.ruoyi.wcs.infrastructure.persistence.task.MyBatisTransportOrderRepository;
|
||||
import com.ruoyi.wcs.port.in.TransportOrderUseCase;
|
||||
import com.ruoyi.wcs.port.out.TransportOrderRepository;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class WcsCoreWiringTest {
|
||||
|
||||
@Test
|
||||
void exposesTheTransportOrderUseCaseFromTheWcsModule() {
|
||||
try (AnnotationConfigApplicationContext context =
|
||||
new AnnotationConfigApplicationContext()) {
|
||||
context.register(WcsCoreConfiguration.class,
|
||||
TestPersistenceConfiguration.class);
|
||||
context.refresh();
|
||||
|
||||
assertTrue(context.getBean(TransportOrderUseCase.class)
|
||||
instanceof TransportOrderApplicationService);
|
||||
assertTrue(context.getBean(TransportOrderRepository.class)
|
||||
instanceof MyBatisTransportOrderRepository);
|
||||
assertTrue(context.containsBeanDefinition("transportOrderMapper"));
|
||||
|
||||
WcsClock clock = context.getBean(WcsClock.class);
|
||||
IdGenerator ids = context.getBean(IdGenerator.class);
|
||||
assertNotNull(clock.now());
|
||||
String firstId = ids.nextId();
|
||||
String secondId = ids.nextId();
|
||||
assertFalse(firstId.trim().isEmpty());
|
||||
assertFalse(firstId.equals(secondId));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void startsWithoutCoreAdaptersAndRejectsNewOrdersWithoutAffectingLegacyStartup() {
|
||||
try (AnnotationConfigApplicationContext context =
|
||||
new AnnotationConfigApplicationContext()) {
|
||||
context.register(WcsCoreConfiguration.class);
|
||||
context.refresh();
|
||||
|
||||
TransportOrderUseCase useCase = context.getBean(TransportOrderUseCase.class);
|
||||
IllegalStateException error = assertThrows(IllegalStateException.class,
|
||||
() -> useCase.cancel("REQ-1"));
|
||||
assertTrue(error.getMessage().contains("not configured"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package com.ruoyi.wcs;
|
||||
|
||||
import com.ruoyi.wcs.application.task.CreateTransportOrderCommand;
|
||||
import com.ruoyi.wcs.application.task.TransportOrderApplicationService;
|
||||
import com.ruoyi.wcs.application.task.TransportOrderResult;
|
||||
import com.ruoyi.wcs.domain.shared.IdGenerator;
|
||||
import com.ruoyi.wcs.domain.shared.WcsClock;
|
||||
import com.ruoyi.wcs.infrastructure.persistence.task.MyBatisTransportOrderRepository;
|
||||
import com.ruoyi.wcs.infrastructure.persistence.task.TransportOrderMapper;
|
||||
import com.ruoyi.wcs.port.in.TransportOrderUseCase;
|
||||
import com.ruoyi.wcs.port.out.DomainEventPublisher;
|
||||
import com.ruoyi.wcs.port.out.TransportOrderRepository;
|
||||
import com.ruoyi.wcs.port.out.WorkflowDefinitionProvider;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.UUID;
|
||||
|
||||
@Configuration
|
||||
@MapperScan(basePackageClasses = TransportOrderMapper.class, lazyInitialization = "true")
|
||||
public class WcsCoreConfiguration {
|
||||
|
||||
@Bean
|
||||
public WcsClock wcsClock() {
|
||||
return Instant::now;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IdGenerator wcsIdGenerator() {
|
||||
return () -> UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TransportOrderRepository transportOrderRepository(
|
||||
@Lazy TransportOrderMapper mapper) {
|
||||
return new MyBatisTransportOrderRepository(mapper);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TransportOrderUseCase transportOrderUseCase(
|
||||
TransportOrderRepository repository,
|
||||
ObjectProvider<WorkflowDefinitionProvider> workflowDefinitions,
|
||||
ObjectProvider<DomainEventPublisher> eventPublishers,
|
||||
IdGenerator idGenerator,
|
||||
WcsClock clock) {
|
||||
WorkflowDefinitionProvider workflowDefinitionProvider =
|
||||
workflowDefinitions.getIfAvailable();
|
||||
DomainEventPublisher eventPublisher = eventPublishers.getIfAvailable();
|
||||
if (workflowDefinitionProvider == null || eventPublisher == null) {
|
||||
return new UnavailableTransportOrderUseCase();
|
||||
}
|
||||
return new TransportOrderApplicationService(repository,
|
||||
workflowDefinitionProvider, eventPublisher, idGenerator, clock);
|
||||
}
|
||||
|
||||
private static final class UnavailableTransportOrderUseCase
|
||||
implements TransportOrderUseCase {
|
||||
@Override
|
||||
public TransportOrderResult create(CreateTransportOrderCommand command) {
|
||||
throw unavailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportOrderResult cancel(String externalRequestId) {
|
||||
throw unavailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportOrderResult suspend(String orderId, String reason) {
|
||||
throw unavailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransportOrderResult resume(String orderId) {
|
||||
throw unavailable();
|
||||
}
|
||||
|
||||
private static IllegalStateException unavailable() {
|
||||
return new IllegalStateException("WCS core adapters are not configured");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user