Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Functional Interface for Batch Message Listener #1301

Closed
Darshanbc opened this issue Dec 18, 2024 · 1 comment
Closed

Support Functional Interface for Batch Message Listener #1301

Darshanbc opened this issue Dec 18, 2024 · 1 comment

Comments

@Darshanbc
Copy link

Darshanbc commented Dec 18, 2024

Currently, in Java, default methods in functional interfaces cannot be overridden using lambda expressions. While functional interfaces are designed to simplify code using lambdas, default methods are excluded from this flexibility.

@FunctionalInterface
public interface MessageListener<T> {
    void onMessage(Message<T> message);

    default void onMessage(Collection<Message<T>> messages) {
        throw new UnsupportedOperationException("Batch not implemented by this MessageListener");
    }
}

If I want to override the
onMessage(Collection<Message<T>> messages)
method using a lambda, the following code is invalid

 
 MessageListener<String> listener = messages -> {
    messages.forEach(msg -> System.out.println(msg.getContent()));
};

Solution:
Have Separate Functional Interfaces:
Define separate interfaces for single and batch processing. However, this creates redundancy and bloats the codebase.

@shreyas957
Copy link

shreyas957 commented Dec 21, 2024

@Darshanbc You're correct that default methods in functional interfaces cannot be overridden using lambda expressions, as lambdas can only target the single abstract method of a functional interface. This is a design limitation in Java.

To address your specific use case, while avoiding redundancy or bloating the codebase with multiple interfaces, you can use an anonymous class to provide an implementation for the onMessage(Collection<Message> messages) method alongside the lambda for the single message handling:

MessageListener<String> listener = new MessageListener<>() {
    @Override
    public void onMessage(Message<String> message) {
        System.out.println(message.getContent());
    }

    @Override
    public void onMessage(Collection<Message<String>> messages) {
        messages.forEach(msg -> System.out.println(msg.getContent()));
    }
};

This approach avoids creating multiple interfaces while giving you flexibility to override the onMessage method for batch processing.

Java's current lambda behavior only targets the single abstract method (SAM) in a functional interface, so a direct workaround isn't possible without changes to the API design.
So either create second lambda expression or modify the default method to call another method that can be overridden with a lambda-friendly design. For example:

@FunctionalInterface
public interface MessageListener<T> {
    void onMessage(Message<T> message);

    default void onMessage(Collection<Message<T>> messages) {
        messages.forEach(this::handleSingleMessage);
    }

    default void defaultBehaviour(Message<T> message) {
        throw new UnsupportedOperationException("Single message handling not implemented");
}

CC : @maciejwalkowiak

@awspring awspring locked and limited conversation to collaborators Jan 1, 2025
@tomazfernandes tomazfernandes converted this issue into discussion #1315 Jan 1, 2025

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants