Implementation command bus pattern with the support middleware as Angular module
npm install angular-command-bus --save
@NgModule({
imports: [
CommandBusModule.forRoot()
]
})
export class AppModule {
}
export class Order {
constructor(private id: string, private name: string) {}
}
export class CreateOrderCommand {
constructor(readonly orderId: string, readonly name: string) {}
}
export class CreateOrderHandler implements CommandHandler {
constructor(orderService: OrderService) {}
handle(command: CreateOrderCommand) {
const order = new Order(command.orderId, command.name);
orderService.save(order);
}
supportsCommand(): string {
return CreateOrderCommand.name;
}
}
@Component({
selector: 'app-orders-page',
templateUrl: './orders-page.component.html',
styleUrls: ['./orders-page.component.scss']
})
export class OrdersPageComponent {
constructor(private commandBus: CommandBus) {}
onSubmit() {
this.commandBus.handle(new CreateOrderCommand(id, name));
}
}
This is a kind of pattern Intercepting filter from Core J2EE Patterns
@NgModule({
providers: [
{provide: COMMAND_BUS_MIDDLEWARE, useClass: LoggingMiddleware, multi: true},
{provide: COMMAND_BUS_MIDDLEWARE, useClass: AuthorizationMiddleware, multi: true}
]
})
export class AppModule {
}
export class LoggingMiddleware implements CommandBusMiddleware {
/*
* @param next this is a reference for next middleware function
*/
handle(command, next) {
// before code
next(command);
// after code
}
}
if 'next' is not called, the processing of the command will be completed and further middleware, as well as the command handler, will not be executed.
For example AuthorizationMiddleware
export class AuthorizationMiddleware implements CommandBusMiddleware {
constructor(
private userService: UserService,
private notificationService: NotificationService
) {}
handle(command, next) {
if (!userService.hasRole('ROLE_ADMIN')) {
notificationService.alert(
'Access denied for handle command ' + command.constructor.name
);
return;
}
next(command);
}
}