From a197fdd036ac34a2f9fc379a68107aa32da578e6 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 7 Feb 2019 12:21:47 +0100 Subject: [PATCH] GH-1603 Addressed concurrency issue with BinderAwareChannelResolver Resolves #1603 --- .../binding/BinderAwareChannelResolver.java | 78 +++++++++---------- 1 file changed, 35 insertions(+), 43 deletions(-) diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/BinderAwareChannelResolver.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/BinderAwareChannelResolver.java index 2c47bd7f4..812b713bc 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/BinderAwareChannelResolver.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/BinderAwareChannelResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2013-2018 the original author or authors. + * Copyright 2013-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -102,57 +102,49 @@ public class BinderAwareChannelResolver this.beanFactory = (ConfigurableListableBeanFactory) beanFactory; } + /* + * See the following for more discussion on it as well as demo reproducing it, thanks + * to Anshul Mehra (@Walliee) + * https://github.com/spring-cloud/spring-cloud-stream/issues/1603 + */ @SuppressWarnings("unchecked") @Override - public MessageChannel resolveDestination(String channelName) { + public synchronized MessageChannel resolveDestination(String channelName) { + BindingServiceProperties bindingServiceProperties = this.bindingService + .getBindingServiceProperties(); + String[] dynamicDestinations = bindingServiceProperties.getDynamicDestinations(); + + MessageChannel channel; + boolean dynamicAllowed = ObjectUtils.isEmpty(dynamicDestinations) + || ObjectUtils.containsElement(dynamicDestinations, channelName); try { - return super.resolveDestination(channelName); + channel = super.resolveDestination(channelName); } catch (DestinationResolutionException e) { - // intentionally empty; will check again while holding the monitor - } - synchronized (this) { - BindingServiceProperties bindingServiceProperties = this.bindingService - .getBindingServiceProperties(); - String[] dynamicDestinations = bindingServiceProperties - .getDynamicDestinations(); - boolean dynamicAllowed = ObjectUtils.isEmpty(dynamicDestinations) - || ObjectUtils.containsElement(dynamicDestinations, channelName); - try { - return super.resolveDestination(channelName); + if (!dynamicAllowed) { + throw e; } - catch (DestinationResolutionException e) { - if (!dynamicAllowed) { - throw e; + else { + channel = this.bindingTargetFactory.createOutput(channelName); + this.beanFactory.registerSingleton(channelName, channel); + channel = (MessageChannel) this.beanFactory.initializeBean(channel, + channelName); + if (this.newBindingCallback != null) { + ProducerProperties producerProperties = bindingServiceProperties + .getProducerProperties(channelName); + Object extendedProducerProperties = this.bindingService + .getExtendedProducerProperties(channel, channelName); + this.newBindingCallback.configure(channelName, channel, + producerProperties, extendedProducerProperties); + bindingServiceProperties.updateProducerProperties(channelName, + producerProperties); } + Binding binding = this.bindingService + .bindProducer(channel, channelName); + this.dynamicDestinationsBindable.addOutputBinding(channelName, binding); } - - MessageChannel channel = this.bindingTargetFactory.createOutput(channelName); - this.beanFactory.registerSingleton(channelName, channel); - - // TODO: Investigate if the following call is necessary. - // initializeBean call on the next line also calling the - // addMatchingInterceptors method in GlobalChannelInterceptorProcessor - // this.instrumentChannelWithGlobalInterceptors(channel, channelName); - - channel = (MessageChannel) this.beanFactory.initializeBean(channel, - channelName); - if (this.newBindingCallback != null) { - ProducerProperties producerProperties = bindingServiceProperties - .getProducerProperties(channelName); - Object extendedProducerProperties = this.bindingService - .getExtendedProducerProperties(channel, channelName); - this.newBindingCallback.configure(channelName, channel, - producerProperties, extendedProducerProperties); - bindingServiceProperties.updateProducerProperties(channelName, - producerProperties); - } - Binding binding = this.bindingService.bindProducer(channel, - channelName); - this.dynamicDestinationsBindable.addOutputBinding(channelName, binding); - - return channel; } + return channel; } /**