LogoLogo
timvero.comMaven Repository
  • timveroOS SDK guide
  • timveroOS how-to
  • timveroOS admin-side setup
  • Campaigns in timveroOS
    • 7.11
      • Business Context
      • Introduction
      • Core Concept
        • Entity Diagram
        • Lifecycle Diagram
        • Expression
      • Design and Development of the Campaign Model
        • Campaign model
        • Campaign repository
        • Campaign forms
        • Campaign сontroller
        • UI elements
        • Campaign actions
      • Design and Development of the CampaignExecution Model
        • CampaignExecution model
        • CampaignExecution repository
        • CampaignExecution controller
        • UI elements
      • Expression
      • Services
        • CampaignService
        • CampaignExecutionService
      • Campaign Processing
        • Producer
        • Consumer
      • Post-processing
        • Checker
Powered by GitBook
On this page

Was this helpful?

  1. Campaigns in timveroOS
  2. 7.11
  3. Services

CampaignExecutionService

CampaignExecutionService

The CampaignExecutionService is responsible for all aspects of campaign execution, including:

  • Creating CampaignExecution entities

  • Filtering clients using an Expression

  • Executing the campaign

  • Handling exceptions

  • Saving execution results

This service integrates with ScriptManager, ClientRepository, and ExceptionEntityService.


🔧 CampaignExecution createExecution(Campaign campaign)

Creates a new CampaignExecution linked to the provided campaign.

@Transactional(propagation = Propagation.MANDATORY)
public CampaignExecution createExecution(Campaign campaign) {
    CampaignExecution execution = new CampaignExecution();
    execution.setCampaign(campaign);
    return executionRepository.saveAndFlush(execution);
}
  • Called both manually (via CampaignService) and automatically (via CampaignExecutionProducer)

  • Saves the execution to the DB with status = NEW


🔐 _runExecution(CampaignExecution execution)

Private method containing the main business logic for campaign execution.

private void _runExecution(CampaignExecution execution) {
    try {
        Set<Client> clients = getSuitedBorrowers(execution, clientRepository.getAllIds());
        execution.getClients().addAll(clients);
        execution.setException(null);
    } catch (Exception e) {
        ExceptionEntity exceptionEntity = exceptionEntityService.saveException(e, e.getMessage());
        execution.setException(exceptionEntity);
        execution.setStatus(CampaignExecutionStatus.EXCEPTION_OCCURRED);
    }
    execution.setStatus(CampaignExecutionStatus.FINISHED);
    executionRepository.saveAndFlush(execution);
}

What it does:

  • Retrieves a list of clients matching the Expression

  • Clears the exception if successful

  • On error, stores an ExceptionEntity and marks the execution as EXCEPTION_OCCURRED

  • Sets the final status to FINISHED


🔍 Set<Client> getSuitedBorrowers(...)

Filters clients based on the campaign expression.

private Set<Client> getSuitedBorrowers(CampaignExecution execution, Set<UUID> candidates) throws ScriptException {
    Script matchingScript = getClientMatchingScript(execution.getCampaign().getExpression());
    Set<Client> suitedBorrowers = new HashSet<>();
    for (UUID clientId : candidates) {
        Optional<Client> client = evaluateClient(matchingScript, clientId);
        client.ifPresent(suitedBorrowers::add);
    }
    return suitedBorrowers;
}

🔍 Optional<Client> evaluateClient(...)

Evaluates a single client using the script.

private Optional<Client> evaluateClient(Script script, UUID clientId) throws ScriptException {
    Client client = clientRepository.getReferenceById(clientId);
    Object result = script.eval(Map.of("client", client));
    return Boolean.TRUE.equals(result) ? Optional.of(client) : Optional.empty();
}
  • The script must return true or false

  • Only matching clients are included


🧰 Script getClientMatchingScript(...)

Compiles the Expression into a Script.

private Script getClientMatchingScript(Expression expression) {
    try {
        return scriptManager.compile(expression);
    } catch (ScriptException e) {
        throw new RuntimeException("Script doesn't compile", e);
    }
}
  • Throws a RuntimeException on compilation failure


💡 Object evaluateExpression(UUID clientId, Expression expression)

Allows manual evaluation of an expression for a single client — useful in the UI.

@Transactional
public Object evaluateExpression(UUID clientId, Expression expression)
        throws ScriptException, NotFoundException {

    Client client = clientRepository.getReferenceById(clientId);
    Script script = scriptManager.compile(expression);
    return script.eval(Map.of("client", client));
}
  • Used by CampaignController for real-time filtering checks in the UI


Example service

@Service
public class CampaignExecutionService {

    private static final String CLIENT_KEY = "client";

    @Autowired
    private CampaignExecutionRepository executionRepository;
    @Autowired
    private ClientRepository clientRepository;
    @Autowired
    private ScriptManager scriptManager;
    @Autowired
    private ExceptionEntityService exceptionEntityService;

    @Transactional(propagation = Propagation.MANDATORY)
    public CampaignExecution createExecution(Campaign campaign) {
        CampaignExecution execution = new CampaignExecution();
        execution.setCampaign(campaign);
        return executionRepository.saveAndFlush(execution);
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void runExecution(CampaignExecution execution) {
        _runExecution(execution);
    }

    @Transactional
    public void runExecution(Long executionId) {
        CampaignExecution execution = executionRepository.getSync(executionId);
        _runExecution(execution);
    }

    private void _runExecution(CampaignExecution execution) {
        try {
            Set<Client> clients = getSuitedBorrowers(execution, clientRepository.getAllIds());
            execution.getClients().addAll(clients);
            execution.setException(null);
        } catch (Exception e) {
            ExceptionEntity exceptionEntity = exceptionEntityService.saveException(e, e.getMessage());
            execution.setException(exceptionEntity);
            execution.setStatus(CampaignExecutionStatus.EXCEPTION_OCCURRED);
        }
        execution.setStatus(CampaignExecutionStatus.FINISHED);
        executionRepository.saveAndFlush(execution);
    }

    private Set<Client> getSuitedBorrowers(CampaignExecution execution, Set<UUID> candidates) throws ScriptException {
        Script matchingScript = getClientMatchingScript(execution.getCampaign().getExpression());
        Set<Client> suitedBorrowers = new HashSet<>();
        for (UUID clientId : candidates) {
            Optional<Client> client = evaluateClient(matchingScript, clientId);
            client.ifPresent(suitedBorrowers::add);
        }
        return suitedBorrowers;
    }

    private Optional<Client> evaluateClient(Script script, UUID clientId) throws ScriptException {
        Client client = clientRepository.getReferenceById(clientId);
        Object evaluationResult = script.eval(Map.of(CLIENT_KEY, client));
        return Boolean.TRUE.equals(evaluationResult) ? Optional.of(client) : Optional.empty();
    }

    private Script getClientMatchingScript(Expression expression) {
        try {
            return scriptManager.compile(expression);
        } catch (ScriptException e) {
            throw new RuntimeException("Script doesn't compile", e);
        }
    }

    @Transactional
    public Object evaluateExpression(UUID clientId, Expression expression) throws ScriptException, NotFoundException {
        Client client = clientRepository.getReferenceById(clientId);
        Script script = scriptManager.compile(expression);
        Map<String, Client> binding = Map.of(CLIENT_KEY, client);
        return script.eval(binding);
    }
}
PreviousCampaignServiceNextCampaign Processing

Last updated 18 days ago

Was this helpful?