Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Plug n Play REST API Development With Simple-Orchestrator

DZone's Guide to

Plug n Play REST API Development With Simple-Orchestrator

Simple-Orchestrator is a Java lightweight workflow orchestration framework, it helps to modulate, isolate, and reuse your application's functional tasks.

· Web Dev Zone
Free Resource

Learn how to build modern digital experience apps with Crafter CMS. Download this eBook now. Brought to you in partnership with Crafter Software

1. Sample Orchestrator Execution Flow:

Image title

Code for the Above Diagram: 

public interface CreditScoreContext extends HistoryContext<String> {
    String getSsn();
    void setCreditScore(int score);
}
public interface LoanContext extends HistoryContext<String> {
    LoanApplication getApplication();
    int getCreditScore();
    int getRiskScore();
    void setLoanApproveStatus(boolean isApproved);
}
@Component
public class CreditScoreTask implements Task<CreditScoreContext> {
    @Override
    public void execute(CreditScoreContext context) throws OrchestratorException {
        context.logHistory(this.getClass().getName());
        String ssn = context.getSsn();
        if(ssn != null && ssn.length()>0){
            context.setCreditScore((ssn.charAt(0)-'0')*100);
        } else
            context.setCreditScore(0);
    }
}
@Component
public class LoanTask implements Task<LoanContext> {
    @Override
    public void execute(LoanContext context) throws OrchestratorException {
        context.logHistory(this.getClass().getName());
        LoanApplication app = context.getApplication();
        int creditScore = context.getCreditScore();
        if(creditScore>650 && app.getSalary()>0 && app.getLoanAmount()/app.getSalary()<5)
            context.setLoanApproveStatus(true);
        else
            context.setLoanApproveStatus(false);
    }
}


The Service: (Create and Run Orchestrator)

@Component
@Path("/application/loan")
public class LoanService {

    @Autowired
    ValidationTask<LoanApplication> validationTask;

    @Autowired
    CreditScoreTask creditScoreTask;

    @Autowired
    AsyncCheckRiskTask asyncCheckRiskTask;

    @Autowired
    LoanTask loanTask;

    @Autowired
    Orchestrator<LoanOrchestratorConext> orchestrator;

    @Bean
    ValidationTask<LoanApplication> loanValidationTask(){
        return new ValidationTask<LoanApplication>();
    }

    @Bean
    Orchestrator<LoanOrchestratorConext> loanOrchestrator(){
        return new OrchestratorImpl<LoanOrchestratorConext>(
                validationTask,creditScoreTask, asyncCheckRiskTask, loanTask);
    }

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public AppliationResult applyloan(LoanApplication app) {
        LoanOrchestratorConext context = new LoanOrchestratorConext() ;
        context.init(app);
        try {
            orchestrator.execute(context);
        } catch (ValidationException e){
            return new AppliationResult(e.getErrors());
        }
        return new AppliationResult(context.getApplication().getPerson().getName(), context.isApproved(), context.getHistory());
    }
}


2. Plug and Play

Because a task depends on its context interface only, a task can be plugged into any orchestrator as long as the orchestrator's context implements the task's context interface.

The CreditScoreTask can be added into CardService (as in LoanService):

@Component
@Path("/application/card")
public class CardService {

    @Autowired
    ValidationTask<CardApplication> validationTask;

    @Autowired
    CreditScoreTask creditScoreTask;

    @Autowired
    DebitCardTask debitCardTask;

    @Autowired
    CreditCardTask creditCardTask;

    @Autowired
    AsyncCheckRiskTask asyncCheckRiskTask;

    @Autowired
    Channel<RiskCreditContext> riskCreditChannel;

    @Autowired
    Selector<CardApplication.CardType, CardSelectorConext> cardSelector;

    @Autowired
    Orchestrator<CardOrchestratorConext> orchestrator;

    @Bean
    ValidationTask<CardApplication> cardValidationTask(){
        return new ValidationTask<CardApplication>();
    }

    @Bean
    Channel<RiskCreditContext> riskCreditChannel(){
        return new Channel<RiskCreditContext>(asyncCheckRiskTask, creditCardTask);
    }

    @Bean
    Selector<CardApplication.CardType, CardSelectorConext> cardSelector(){
        return new CardSelector(new EnumMap(CardApplication.CardType.class){{
            put(CardApplication.CardType.Credit, riskCreditChannel);
            put(CardApplication.CardType.Debit, debitCardTask);
        }});
    }

    @Bean
    Orchestrator<CardOrchestratorConext> cardOrchestrator(){
        return new OrchestratorImpl<CardOrchestratorConext>(creditScoreTask, cardSelector);
    }

    @PostConstruct
    public void init(){
        System.out.println("aaa");
    }

    static private interface RiskCreditContext extends AsyncCheckRiskContext, CreditCardContext {};

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.APPLICATION_JSON)
    public AppliationResult applyCard(CardApplication app) {
        CardOrchestratorConext context = new CardOrchestratorConext() ;
        context.init(app);
        orchestrator.execute(context);
        return new AppliationResult(context.getApplication().getPerson().getName(), context.isApproved(), context.getHistory());
    }
}


3. Orchestration with Selector and Channel:

Image title

A Few Other Tips and Tricks

Now that we've seen how to code our orchestrator, and what this code will result in, here are a few more tips and tricks to help you get the most out of this tool: 

4. Type Safe

Since Orchestrator, Context, Task, Channel, and Selector are typed, a mismatch will result in a compile time error.

5. Minimum Coding

You should code in business logic, not boilerplate code. The framework will prepare data for the next task and process the task result for you.

6. Isolation

A task can only see it's own context interface, it has no access to other properties of the object upon which it executes.

7. Asynchronous Tasks

Easy implementation for asynchronous tasks with natural dependency order.

8. Integration

With Tasks calling other services, the orchestrator can be used for integration service.

9. Open Sourced

For complete framework project and sample project, see my GitHub page

Crafter is a modern CMS platform for building modern websites and content-rich digital experiences. Download this eBook now. Brought to you in partnership with Crafter Software.

Topics:
orchestrator ,rest api ,web dev

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}