Skip to content
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

Set value of isAutoStartup for DefaultMessageListenerContainerCoordinator #273

Closed
stephencassidy-r7 opened this issue Aug 7, 2020 · 2 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@stephencassidy-r7
Copy link

stephencassidy-r7 commented Aug 7, 2020

Hi,

Another edge case! As part of our applications, we use netflix-archaius for dynamic configuration at runtime - in this case, to control whether a queue listener is enabled or not, and to change if needed.

To do this, I have extended the DefaultMessageListenerContainerCoordinator to accept a small properties holder class that is used to determine the value of isAutoStartup, and add callbacks to properties to call start|stopContainer(identifier) to try and match the pattern used for creating other containers etc -

interface MessageListenerContainerCoordinatorProperties {
    /**
     * @return Whether the {@link MessageListenerContainerCoordinator}'s {@link MessageListenerContainerCoordinator#startAllContainers()} will be invoked by Spring.
     */
    boolean isAutoStartContainersEnabled();
}

@Value
@Builder(toBuilder = true)
class DefaultMessageListenerContainerCoordinatorProperties implements MessageListenerContainerCoordinatorProperties {
    Boolean isAutoStartContainersEnabled;
    
    @Override
    public boolean isAutoStartContainersEnabled() {
        return isAutoStartContainersEnabled;
    }
}

class ExtendedDefaultMessageListenerContainerCoordinator extends DefaultMessageListenerContainerCoordinator {
    private final MessageListenerContainerCoordinatorProperties properties;

    public ExtendedDefaultMessageListenerContainerCoordinator(final List<MessageListenerContainerFactory> factories, final MessageListenerContainerCoordinatorProperties properties) {
        super(factories);

        this.properties = properties;
    }

   // Used to get a list of all containers so we can build the property callbacks...
    public Collection<String> getContainerIdentifiers() {
        return getContainers().stream()
            .map(MessageListenerContainer::getIdentifier)
            .collect(toUnmodifiableSet());
    }

    @Override
    public boolean isAutoStartup() {
        return properties.isAutoStartContainersEnabled();
    }
}

class MessageListenerContainerLifecycleController implements SmartLifecycle {
    private final DefaultMessageListenerContainerCoordinator coordinator;
    private final Map<String, DynamicBooleanProperty> containerEnabled;

    public MessageListenerContainerLifecycleController(final DefaultMessageListenerContainerCoordinator coordinator) {
        this.coordinator = coordinator;
        /**
         * Create all the properties and callbacks for each container identifier returned from 
         * {@link ExtendedDefaultMessageListenerContainerCoordinator#getContainerIdentifiers()} on each to invoke the 
         * @{@link MessageListenerContainerCoordinator#startContainer(String)} or 
         * @{@link MessageListenerContainerCoordinator#stopContainer(String)}} depending on the value...
         */
        this.containerEnabled = createContainerLifecycleCallbacks(coordinator);
    }

    @Override
    public void start() {
        containerEnabled.forEach((identifier, enabled) -> {
            if (enabled.getValue()) {
                coordinator.startContainer(identifier);
            }
        });
    }

    @Override
    public void stop() {
        coordinator.stopAllContainers();
    }

    @Override
    public boolean isRunning() {}
}

Another tweak that would help is being able to return a collection of all identifiers if possible 😄 Currently I have these classes sitting under the same package as the original to access the getContainers() method - other than this the library does everything I needed and more, nice to get a consumer going with a few annotations!

If there is a better way to raise these let me know - technically this is not an issue or bug!

@JaidenAshmore JaidenAshmore self-assigned this Aug 7, 2020
@JaidenAshmore
Copy link
Owner

Perfect timing, I have been looking for something to do this weekend!

Will take a look at this and get back to you, the request sounds solid and I think it can be done pretty easily 😃

@JaidenAshmore JaidenAshmore added this to the 4.2.0 milestone Aug 7, 2020
@JaidenAshmore JaidenAshmore added the enhancement New feature or request label Aug 7, 2020
JaidenAshmore added a commit that referenced this issue Aug 8, 2020
Also adds a `MessageListenerContainerCoordinator#getContainers()` method
so consumers can get all the containers if they desire.
JaidenAshmore added a commit that referenced this issue Aug 8, 2020
#274)

Also adds a `MessageListenerContainerCoordinator#getContainers()` method
so consumers can get all the containers if they desire.
@JaidenAshmore
Copy link
Owner

Release Notes

Improves the DefaultMessageListenerContainerCoordinator by allowing the auto startup of the containers to be configured. For more information see the Spring - How to prevent containers starting on startup guide.

Adds a getContainers method to the MessageListenerContainerCoordinator to allow for smarter configuration of the containers during runtime.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants