Skip to content

Reconsider PR #2769 #3130

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

Closed
garyrussell opened this issue Dec 24, 2019 · 4 comments · Fixed by #3142
Closed

Reconsider PR #2769 #3130

garyrussell opened this issue Dec 24, 2019 · 4 comments · Fixed by #3142

Comments

@garyrussell
Copy link
Contributor

garyrussell commented Dec 24, 2019

#2769

Deferring the creation of integration components prevents injection:

@SpringBootApplication
public class So59469573Application {

	public static void main(String[] args) {
		SpringApplication.run(So59469573Application.class, args);
	}

}

@Component
class Integration {

	@InboundChannelAdapter(channel = "channel", autoStartup = "true",
			poller = @Poller(fixedDelay = "5000"))
	public String foo() {
		return "foo";
	}

	@ServiceActivator(inputChannel = "channel")
	public void handle(String in) {
		System.out.println(in);
	}

}

@RestController
class Rest {

	@Autowired
	@Qualifier("integration.foo.inboundChannelAdapter")
	SourcePollingChannelAdapter adapter;

	@PostMapping("/foo/{command}")
	public void trigger(@PathVariable String command) {
		if ("start".equals(command)) {
			adapter.start();
		}
	}

}
Description:

Field adapter in com.example.demo.Rest required a bean of type 'org.springframework.integration.endpoint.SourcePollingChannelAdapter' that could not be found.

The injection point has the following annotations:
	- @org.springframework.beans.factory.annotation.Autowired(required=true)
	- @org.springframework.beans.factory.annotation.Qualifier(value=integration.foo.inboundChannelAdapter)


Action:

Consider defining a bean of type 'org.springframework.integration.endpoint.SourcePollingChannelAdapter' in your configuration.

I am sure that was not intended although the reason for the change is valid too.

Work around is to use a control bus:

@SpringBootApplication
@IntegrationComponentScan
public class So59469573Application {

	public static void main(String[] args) {
		SpringApplication.run(So59469573Application.class, args);
	}

}

@Component
class Integration {

	public Integration() {
		super();
	}

	@InboundChannelAdapter(channel = "channel", autoStartup = "false",
			poller = @Poller(fixedDelay = "5000"))
	public String foo() {
		return "foo";
	}

	@ServiceActivator(inputChannel = "channel")
	public void handle(String in) {
		System.out.println(in);
	}

	@ServiceActivator(inputChannel = "controlChannel")
	@Bean
	public ExpressionControlBusFactoryBean controlBus() {
		return new ExpressionControlBusFactoryBean();
	}

}

@MessagingGateway(defaultRequestChannel = "controlChannel")
interface Control {

	void send(String control);
}

@RestController
class Rest {

	@Autowired
	Control control;

	public Rest() {
		super();
	}

	@PostMapping("/foo/{command}")
	public void trigger(@PathVariable String command) {
		if ("start".equals(command)) {
			control.send("@'integration.foo.inboundChannelAdapter'.start()");
		}
	}

}
@garyrussell garyrussell added the status: waiting-for-triage The issue need to be evaluated and its future decided label Dec 24, 2019
@artembilan
Copy link
Member

This one is related: #3111

I don't have any immediate solution right now unless we will figure out some deep refactoring to resolve target message handlers much later in the endpoints, e.g. in their start().
But still: that's not easy task...

@artembilan
Copy link
Member

May I suggest @Lazy as a neat workaround to this issue?

@Autowired
@Lazy
@Qualifier("integration.foo.inboundChannelAdapter")
SourcePollingChannelAdapter adapter;

May that would be enough for us to just document in the Annotation section that beans which could be auto-wired from the messaging annotation processing should be marked with the @Lazy since they are created in the later phase?

@garyrussell
Copy link
Contributor Author

Cool - I didn't realize you can use @Lazy there

 * <p>In addition to its role for component initialization, this annotation may also be placed
 * on injection points marked with {@link org.springframework.beans.factory.annotation.Autowired}
 * or {@link javax.inject.Inject}: In that context, it leads to the creation of a
 * lazy-resolution proxy for all affected dependencies, as an alternative to using
 * {@link org.springframework.beans.factory.ObjectFactory} or {@link javax.inject.Provider}.

Yes; I think this can be resolved with documentation, but we need to be clear it has to be on the @Autowired dependency injection.

@artembilan
Copy link
Member

Yep! Let's see what @membersound can say us about similar approach for beans method arguments injection!
The we are good to go with docs. 😄

artembilan added a commit to artembilan/spring-integration that referenced this issue Jan 14, 2020
Fixes spring-projects#3111
Fixes spring-projects#3130

* Fix some typos in docs
* Ensure in tests that announced `@Lazy` works as expected
garyrussell added a commit that referenced this issue Jan 15, 2020
* GH-3111: Document @lazy for messaging annotations

Fixes #3111
Fixes #3130

* Fix some typos in docs
* Ensure in tests that announced `@Lazy` works as expected

* Doc Polishing

Co-authored-by: Gary Russell <[email protected]>
@garyrussell garyrussell added type: documentation and removed status: waiting-for-reporter Needs a feedback from the reporter status: waiting-for-triage The issue need to be evaluated and its future decided labels Dec 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants