Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 

README.md

Service Layer Documentation

The WFM Archive service layer provides the core business logic through a collection of well-defined service interfaces and their implementations.

Quick Links

Service Architecture

WFM Archive follows CUBA Platform's service pattern with interfaces in the global module and implementations in the core module.

graph TB
    subgraph "Global Module - Service Interfaces"
        AS[ArchiveService]
        MS[MongoService]
        S3S[S3Service]
        KS[KeycloakService]
        WS[WorkflowService]
        IS[IntegrationService]
    end

    subgraph "Core Module - Service Implementations"
        ASB[ArchiveServiceBean]
        MSB[MongoServiceBean]
        S3SB[S3ServiceBean]
        KSB[KeycloakServiceBean]
        WSB[WorkflowServiceBean]
        ISB[IntegrationServiceBean]
    end

    AS --> ASB
    MS --> MSB
    S3S --> S3SB
    KS --> KSB
    WS --> WSB
    IS --> ISB

    ASB --> MSB
    ASB --> S3SB
    ASB --> KSB
    WSB --> ASB
Loading

Service Categories

1. Core Document Services

  • ArchiveService - Primary document management operations
  • MongoService - Document storage and retrieval
  • AmazonS3Service - File storage and migration

2. Integration Services

  • KeycloakService - SSO and user management
  • SqlDataService - External database connections
  • RestMappingService - API data transformation
  • ISeriesIntegrationService - IBM i-Series connectivity

3. Process Services

  • WorkflowService - BPMN workflow execution
  • ProcessRuntimeService - Process instance management
  • ActivityInstanceDataService - Workflow tracking

4. Configuration Services

  • DocumentTypeService - Document type management
  • RegistrationService - System registration
  • JsonImportService - Data import functionality

5. Utility Services

  • RestCachedService - Caching and validation
  • CustomControllerService - Custom business logic

Service Implementation Pattern

All services follow the CUBA Platform pattern:

Interface Definition (Global Module)

// modules/global/src/dk/bpas/wfmarchive/service/ArchiveService.java
public interface ArchiveService {
    String NAME = "wfmarchive_ArchiveService";

    Document archiveDocument(DocumentDto document);
    Document retrieveDocument(String documentId);
    void deleteDocument(String documentId);
}

Implementation (Core Module)

// modules/core/src/dk/bpas/wfmarchive/service/ArchiveServiceBean.java
@Service(ArchiveService.NAME)
public class ArchiveServiceBean implements ArchiveService {

    @Inject
    private MongoService mongoService;

    @Inject
    private AmazonS3Service s3Service;

    @Override
    @Transactional
    public Document archiveDocument(DocumentDto document) {
        // Implementation
    }
}

Service Injection

// Usage in other services or controllers
public class DocumentController {
    @Inject
    private ArchiveService archiveService;

    public void processDocument() {
        archiveService.archiveDocument(dto);
    }
}

Service Dependencies

Dependency Hierarchy

graph TD
    REST[REST Controllers] --> ARCH[ArchiveService]
    ARCH --> MONGO[MongoService]
    ARCH --> S3[S3Service]
    ARCH --> KC[KeycloakService]

    WF[WorkflowService] --> ARCH
    WF --> PROC[ProcessRuntimeService]

    INTEG[IntegrationService] --> SQL[SqlDataService]
    INTEG --> ISERIES[ISeriesService]

    MAPPING[RestMappingService] --> ARCH
    MAPPING --> CACHE[RestCachedService]
Loading

Transaction Management

Services use Spring's @Transactional annotation for database operations:

@Service(ArchiveService.NAME)
public class ArchiveServiceBean implements ArchiveService {

    @Override
    @Transactional
    public Document archiveDocument(DocumentDto document) {
        // All database operations in single transaction
        validateDocument(document);
        Document saved = saveToDatabase(document);
        auditLog(saved);
        return saved;
    }

    @Override
    @Transactional(readOnly = true)
    public Document retrieveDocument(String id) {
        // Read-only transaction
        return findDocument(id);
    }
}

Error Handling

Services use consistent error handling patterns:

public class ArchiveServiceBean implements ArchiveService {

    @Override
    public Document archiveDocument(DocumentDto document) {
        try {
            validateDocument(document);
            return processDocument(document);
        } catch (ValidationException e) {
            log.error("Document validation failed: {}", e.getMessage());
            throw new ServiceException("Invalid document", e);
        } catch (StorageException e) {
            log.error("Storage error: {}", e.getMessage());
            throw new ServiceException("Storage unavailable", e);
        }
    }
}

Performance Considerations

Caching

@Service(RestCachedService.NAME)
public class RestCachedServiceBean implements RestCachedService {

    @Cacheable("documentTypes")
    public DocumentType getDocumentType(String code) {
        return dataManager.load(DocumentType.class)
            .query("select dt from DocumentType dt where dt.code = :code")
            .parameter("code", code)
            .one();
    }
}

Async Processing

@Service(WorkflowService.NAME)
public class WorkflowServiceBean implements WorkflowService {

    @Async
    public CompletableFuture<ProcessInstance> startProcessAsync(String processKey, Map<String, Object> variables) {
        ProcessInstance instance = runtimeService.startProcessInstanceByKey(processKey, variables);
        return CompletableFuture.completedFuture(instance);
    }
}

Connection Pooling

@Service(SqlDataService.NAME)
public class SqlDataServiceBean implements SqlDataService {

    @Value("${external.db.pool.size:10}")
    private int poolSize;

    private HikariDataSource createDataSource(Database database) {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(database.getConnectionString());
        config.setMaximumPoolSize(poolSize);
        config.setLeakDetectionThreshold(120000);
        return new HikariDataSource(config);
    }
}

Security Integration

Services integrate with CUBA Platform's security:

@Service(ArchiveService.NAME)
public class ArchiveServiceBean implements ArchiveService {

    @Inject
    private UserSessionSource userSessionSource;

    @Override
    public Document archiveDocument(DocumentDto document) {
        UserSession userSession = userSessionSource.getUserSession();

        // Check permissions
        if (!userSession.isPermitted("document.archive")) {
            throw new AccessDeniedException("Archive permission required");
        }

        // Set audit fields
        document.setCreatedBy(userSession.getUser().getLogin());
        document.setCreatedDate(new Date());

        return processDocument(document);
    }
}

Service Testing

Unit Testing

@ExtendWith(MockitoExtension.class)
class ArchiveServiceTest {

    @Mock
    private MongoService mongoService;

    @Mock
    private S3Service s3Service;

    @InjectMocks
    private ArchiveServiceBean archiveService;

    @Test
    void testArchiveDocument() {
        // Given
        DocumentDto dto = new DocumentDto();
        when(mongoService.store(any())).thenReturn("doc-123");

        // When
        Document result = archiveService.archiveDocument(dto);

        // Then
        assertThat(result.getId()).isEqualTo("doc-123");
        verify(mongoService).store(any());
    }
}

Integration Testing

@SpringBootTest
@Transactional
class ArchiveServiceIntegrationTest {

    @Autowired
    private ArchiveService archiveService;

    @Test
    void testArchiveDocumentIntegration() {
        // Test with real database and services
        DocumentDto dto = createTestDocument();
        Document result = archiveService.archiveDocument(dto);
        assertThat(result).isNotNull();
    }
}

Best Practices

  1. Interface Segregation - Keep service interfaces focused and cohesive
  2. Dependency Injection - Use @Inject for service dependencies
  3. Transaction Boundaries - Define clear transaction scopes
  4. Error Handling - Use consistent exception patterns
  5. Logging - Include comprehensive logging for troubleshooting
  6. Testing - Write both unit and integration tests
  7. Documentation - Document service contracts and behaviors

Next Steps

Explore the detailed documentation for each service: