Skip to content

Commit

Permalink
INT-4539: Fix Java DSL for prototype beans
Browse files Browse the repository at this point in the history
JIRA: https://jira.spring.io/browse/INT-4539

The `IntegrationFlowBeanPostProcessor` doesn't check for prototype beans
and just override them in the application context with the singletons

* Since we can't in the DSL understand if provided object is a prototype
or not, we try to check for its bean definition by possible bean name.
Use `NamedComponent` for possible bean name to check.
* Remove `final` from the `IntegrationComponentSpec.get()` since its
result is not visible for CGI proxies when it is declared as a `@Bean`
and subsequent `getObject()` produces a new internal object
* Verify prototype beans with new test in the `IntegrationFlowTests`

**Cherry-pick to 5.0.x**
  • Loading branch information
artembilan authored and garyrussell committed Oct 6, 2018
1 parent 2df71fb commit c4d6cf2
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ public final String getId() {
/**
* @return the configured component.
*/
public final T get() {
public T get() {
if (this.target == null) {
this.target = doGet();
}
return this.target;
}

@Override
public T getObject() throws Exception {
public T getObject() {
return get();
}

Expand All @@ -80,11 +80,6 @@ public Class<?> getObjectType() {
return get().getClass();
}

@Override
public boolean isSingleton() {
return true;
}

@Override
public void afterPropertiesSet() throws Exception {
if (this.target instanceof InitializingBean) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,7 @@ else if (useFlowIdAsPrefix) {
id = flowNamePrefix + id;
}

Collection<?> messageHandlers =
this.beanFactory.getBeansOfType(messageHandler.getClass(), false, false)
.values();

if (!messageHandlers.contains(messageHandler)) {
if (noBeanPresentForComponent(messageHandler)) {
String handlerBeanName = generateBeanName(messageHandler, flowNamePrefix);

registerComponent(messageHandler, handlerBeanName, flowBeanName);
Expand All @@ -178,8 +174,7 @@ else if (useFlowIdAsPrefix) {
targetIntegrationComponents.put(endpoint, id);
}
else {
Collection<?> values = this.beanFactory.getBeansOfType(component.getClass(), false, false).values();
if (!values.contains(component)) {
if (noBeanPresentForComponent(component)) {
if (component instanceof AbstractMessageChannel) {
String channelBeanName = ((AbstractMessageChannel) component).getComponentName();
if (channelBeanName == null) {
Expand Down Expand Up @@ -216,10 +211,7 @@ else if (component instanceof SourcePollingChannelAdapterSpec) {
if (!CollectionUtils.isEmpty(componentsToRegister)) {
componentsToRegister.entrySet()
.stream()
.filter(o ->
!this.beanFactory.getBeansOfType(o.getKey().getClass(), false, false)
.values()
.contains(o.getKey()))
.filter(o -> noBeanPresentForComponent(o.getKey()))
.forEach(o ->
registerComponent(o.getKey(),
generateBeanName(o.getKey(), flowNamePrefix, o.getValue(),
Expand All @@ -239,9 +231,7 @@ else if (useFlowIdAsPrefix) {
targetIntegrationComponents.put(pollingChannelAdapterFactoryBean, id);

MessageSource<?> messageSource = spec.get().getT2();
if (!this.beanFactory.getBeansOfType(messageSource.getClass(), false, false)
.values()
.contains(messageSource)) {
if (noBeanPresentForComponent(messageSource)) {
String messageSourceId = id + ".source";
if (messageSource instanceof NamedComponent
&& ((NamedComponent) messageSource).getComponentName() != null) {
Expand Down Expand Up @@ -347,10 +337,7 @@ private void processIntegrationComponentSpec(String beanName, IntegrationCompone

componentsToRegister.entrySet()
.stream()
.filter(component ->
!this.beanFactory.getBeansOfType(component.getKey().getClass(), false, false)
.values()
.contains(component.getKey()))
.filter(component -> noBeanPresentForComponent(component.getKey()))
.forEach(component ->
registerComponent(component.getKey(),
generateBeanName(component.getKey(), component.getValue())));
Expand Down Expand Up @@ -391,6 +378,19 @@ private void invokeBeanInitializationHooks(final String beanName, final Object b
}
}

private boolean noBeanPresentForComponent(Object instance) {
if (instance instanceof NamedComponent) {
String beanName = ((NamedComponent) instance).getComponentName();
if (beanName != null) {
return !this.beanFactory.containsBean(beanName);
}
}

Collection<?> beans = this.beanFactory.getBeansOfType(instance.getClass(), false, false).values();

return !beans.contains(instance);
}

private void registerComponent(Object component, String beanName) {
registerComponent(component, beanName, null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
Expand All @@ -44,11 +45,13 @@
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.integration.MessageDispatchingException;
import org.springframework.integration.MessageRejectedException;
import org.springframework.integration.annotation.MessageEndpoint;
Expand All @@ -65,6 +68,7 @@
import org.springframework.integration.dsl.MessageChannels;
import org.springframework.integration.dsl.Pollers;
import org.springframework.integration.dsl.Transformers;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
import org.springframework.integration.handler.GenericHandler;
import org.springframework.integration.handler.advice.ErrorMessageSendingRecoverer;
Expand Down Expand Up @@ -499,6 +503,18 @@ public void testNullChannelInTheEndOfFlow() {
this.nullChannel.setCountsEnabled(false);
}

@Autowired
private EventDrivenConsumer flow1WithPrototypeHandlerConsumer;

@Autowired
private EventDrivenConsumer flow2WithPrototypeHandlerConsumer;

@Test
public void testPrototypeIsNotOverridden() {
assertNotSame(this.flow1WithPrototypeHandlerConsumer.getHandler(),
this.flow2WithPrototypeHandlerConsumer.getHandler());
}

@MessagingGateway
public interface ControlBusGateway {

Expand Down Expand Up @@ -865,6 +881,31 @@ public IntegrationFlow flowWithNullChannel() {
.nullChannel();
}

@Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public AbstractReplyProducingMessageHandler myHandler() {
return new AbstractReplyProducingMessageHandler() {

@Override
protected Object handleRequestMessage(Message<?> requestMessage) {
return requestMessage;
}

};
}

@Bean
public IntegrationFlow flow1WithPrototypeHandler(
@Qualifier("myHandler") AbstractReplyProducingMessageHandler handler) {
return f -> f.handle(handler, e -> e.id("flow1WithPrototypeHandlerConsumer"));
}

@Bean
public IntegrationFlow flow2WithPrototypeHandler(
@Qualifier("myHandler") AbstractReplyProducingMessageHandler handler) {
return f -> f.handle(handler, e -> e.id("flow2WithPrototypeHandlerConsumer"));
}

}

@Service
Expand Down

0 comments on commit c4d6cf2

Please sign in to comment.