Java 8 Stream and generic interface in chain of responsibility pattern

Viewed 1416

In a Spring Boot application, running on Java 8, I want to implement a generic behavior to process different types of commands.

The code below illustrates the solution I had in mind.

A generic processor pattern

public interface Processor<C extends Command> {
    TypeCommand getCommandType();
    void processCommand(C command);
}

public abstract class AbstractProcessor<C extends Command> implements Processor<C> {
    @Override
    public void processCommand(C command) {
        // Some common stuff 
        // ...

        // Specific process
        Result result = executeCommand(command);

        // More common stuff
        // ...
    }

    protected abstract Result executeCommand(C command);
}

@Component
public AddCommandProcessor extends AbstractProcessor<AddCommand> {

    @Override
    protected Result executeCommand(AddCommand addCommand) {
        // Execute command
        // ...
        return result; 
    }

    @Override
    public TypeCommand getCommandType() {
        return TypeCommand.ADD_COMMAND;
    }
}

The command :

public abstract class Command {
    private final String uid;
    private final LocalDateTime creationDate;
    private final TypeCommand type;
    // Constructor and getters omited ...
}

public class AddCommand extends Command {
    private final Double amount;
    // Constructor and getters omited ...
}

The service with the chain of responsibility :

@Service
public class MyService {

    private final List<Processor<? extends Command>> processors;

    @Autowired
    public MyService(final List<Processor<? extends Command>> processors) {
        this.processors = processors;
    }

    public void processCommand(final Command command) {
        processors.stream()
            .filter(p -> command.getType() == p.getCommandType())
            .findFirst()
            .ifPresent(processor -> processor.processCommand(command));
    }
}

Unfortunately, this code does not compile. The line :

.ifPresent(processor -> processor.processCommand(command));

failed to compiles with the message :

processCommand(capture <? extends Command>) in Processor cannot be applied to (Command)

I don't see any other way to do it as intended. Where am I wrong ?

Thanks a lot.

1 Answers
Related