我想使用 java DSL 重写以下 xml 配置示例:
现在我坚持配置的以下部分:
<int:gateway id="userGateway" default-request-timeout="5000"
default-reply-timeout="5000"
service-interface="org.springframework.integration.samples.enricher.service.UserService">
<int:method name="findUser" request-channel="findUserEnricherChannel"/>
<int:method name="findUserByUsername" request-channel="findUserByUsernameEnricherChannel"/>
<int:method name="findUserWithUsernameInMap" request-channel="findUserWithMapEnricherChannel"/>
</int:gateway>
我试图在这里找到任何模拟,但我还没有找到。
你能帮我找到它吗?
更新
我尝试编写以下代码:
配置:
@Bean
public IntegrationFlow findUserEnricherChannelFlow() {
return IntegrationFlows.from(UserService.class)
.handle(SystemService.class, "findUser") // I have no idea how to map all methods
.get();
}
发起人:
ConfigurableApplicationContext ctx = new SpringApplication(MyApplication.class).run(args);
UserService userService = ctx.getBean(UserService.class);
User user = new User("some_name",null,null);
System.out.println("Main:" + userService.findUser(user));
用户服务:
public interface UserService {
/**
* Retrieves a user based on the provided user. User object is routed to the
* "findUserEnricherChannel" channel.
*/
//@Gateway(requestChannel = "findUserEnricherChannel", replyChannel = )
User findUser(User user);
/**
* Retrieves a user based on the provided user. User object is routed to the
* "findUserByUsernameEnricherChannel" channel.
*/
User findUserByUsername(User user);
/**
* Retrieves a user based on the provided username that is provided as a Map
* entry using the mapkey 'username'. Map object is routed to the
* "findUserWithMapChannel" channel.
*/
Map<String, Object> findUserWithUsernameInMap(Map<String, Object> userdata);
}
系统服务:
public class SystemService {
private static final Log LOGGER = LogFactory.getLog(SystemService.class);
/** Default Constructor. */
public SystemService() {
super();
}
public User findUser(User user) {
LOGGER.info(String.format("Calling method 'findUser' with parameter %s", user));
final User fullUser = new User(user.getUsername(),
"secret",
user.getUsername() + "@springintegration.org");
return fullUser;
}
public User findUserByUsername(String username) {
LOGGER.info(String.format("Calling method 'findUserByUsername' with parameter: %s", username));
return new User(username, "secret", username + "@springintegration.org");
}
}
但在这种情况下,应用程序不能从以下跟踪开始:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-08-29 16:04:54.293 ERROR 7948 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'findUserEnricherChannelFlow' defined in class path resource [enricher/Config.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.integration.dsl.IntegrationFlow]: Factory method 'findUserEnricherChannelFlow' threw exception; nested exception is java.lang.IllegalStateException: Target object of type [class java.lang.Class] has no eligible methods for handling Messages.
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:627) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:456) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1321) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1160) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:742) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:389) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:311) ~[spring-boot-2.1.6.RELEASE.jar:2.1.6.RELEASE]
at enricher.MyApplication.main(MyApplication.java:13) ~[classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.integration.dsl.IntegrationFlow]: Factory method 'findUserEnricherChannelFlow' threw exception; nested exception is java.lang.IllegalStateException: Target object of type [class java.lang.Class] has no eligible methods for handling Messages.
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:622) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
... 17 common frames omitted
Caused by: java.lang.IllegalStateException: Target object of type [class java.lang.Class] has no eligible methods for handling Messages.
at org.springframework.util.Assert.state(Assert.java:94) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.findHandlerMethodsForTarget(MessagingMethodInvokerHelper.java:898) ~[spring-integration-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:293) ~[spring-integration-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:223) ~[spring-integration-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.<init>(MessagingMethodInvokerHelper.java:227) ~[spring-integration-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.integration.handler.MethodInvokingMessageProcessor.<init>(MethodInvokingMessageProcessor.java:54) ~[spring-integration-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.integration.handler.ServiceActivatingHandler.<init>(ServiceActivatingHandler.java:46) ~[spring-integration-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.integration.dsl.IntegrationFlowDefinition.handle(IntegrationFlowDefinition.java:996) ~[spring-integration-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.integration.dsl.IntegrationFlowDefinition.handle(IntegrationFlowDefinition.java:979) ~[spring-integration-core-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at enricher.Config.findUserEnricherChannelFlow(Config.java:36) ~[classes/:na]
at enricher.Config$$EnhancerBySpringCGLIB$$f36636fe.CGLIB$findUserEnricherChannelFlow$0(<generated>) ~[classes/:na]
at enricher.Config$$EnhancerBySpringCGLIB$$f36636fe$$FastClassBySpringCGLIB$$ada0b78a.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244) ~[spring-core-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363) ~[spring-context-5.1.8.RELEASE.jar:5.1.8.RELEASE]
at enricher.Config$$EnhancerBySpringCGLIB$$f36636fe.findUserEnricherChannelFlow(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.1.8.RELEASE.jar:5.1.8.RELEASE]
... 18 common frames omitted
附言
我提前走了几步,现在我有以下配置:
@Configuration
@EnableIntegration
@IntegrationComponentScan
public class Config {
@Bean
public SystemService systemService() {
return new SystemService();
}
@Bean
public IntegrationFlow findUserEnricherFlow(SystemService systemService) {
return IntegrationFlows.from("findUserEnricherChannel")
.<User>handle((p, h) -> systemService.findUser(p))
.get();
}
@Bean
public IntegrationFlow findUserByUsernameEnricherFlow(SystemService systemService) {
return IntegrationFlows.from("findUserByUsernameEnricherChannel")
.<User>handle((p, h) -> systemService.findUserByUsername(p.getUsername()))
.get();
}
@Bean
public IntegrationFlow findUserWithUsernameInMapFlow(SystemService systemService) {
return IntegrationFlows.from("findUserWithMapEnricherChannel")
.<Map<String, Object>>handle((p, h) -> {
User user = systemService.findUserByUsername((String) p.get("username"));
Map<String, Object> map = new HashMap<>();
map.put("username", user.getUsername());
map.put("email", user.getEmail());
map.put("password", user.getPassword());
return map;
})
.get();
}
}
服务接口:
@MessagingGateway
public interface UserService {
/**
* Retrieves a user based on the provided user. User object is routed to the
* "findUserEnricherChannel" channel.
*/
@Gateway(requestChannel = "findUserEnricherChannel")
User findUser(User user);
/**
* Retrieves a user based on the provided user. User object is routed to the
* "findUserByUsernameEnricherChannel" channel.
*/
@Gateway(requestChannel = "findUserByUsernameEnricherChannel")
User findUserByUsername(User user);
/**
* Retrieves a user based on the provided username that is provided as a Map
* entry using the mapkey 'username'. Map object is routed to the
* "findUserWithMapChannel" channel.
*/
@Gateway(requestChannel = "findUserWithMapEnricherChannel")
Map<String, Object> findUserWithUsernameInMap(Map<String, Object> userdata);
}
和目标服务:
public class SystemService {
private static final Log LOGGER = LogFactory.getLog(SystemService.class);
/** Default Constructor. */
public SystemService() {
super();
}
public User findUser(User user) {
LOGGER.info(String.format("Calling method 'findUser' with parameter %s", user));
final User fullUser = new User(user.getUsername(),
"secret",
user.getUsername() + "@springintegration.org");
return fullUser;
}
public User findUserByUsername(String username) {
LOGGER.info(String.format("Calling method 'findUserByUsername' with parameter: %s", username));
return new User(username, "secret", username + "@springintegration.org");
}
}
主要方法:
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new SpringApplication(MyApplication.class).run(args);
UserService userService = ctx.getBean(UserService.class);
User user = new User("some_name", null, null);
System.out.println("Main:" + userService.findUser(user));
System.out.println("Main:" + userService.findUserByUsername(user));
Map<String, Object> map = new HashMap<>();
map.put("username", "vasya");
System.out.println("Main:" + userService.findUserWithUsernameInMap(map));
}
输出:
2019-08-30 14:09:29.956 INFO 12392 --- [ main] enricher.MyApplication : Started MyApplication in 2.614 seconds (JVM running for 3.826)
2019-08-30 14:09:29.966 INFO 12392 --- [ main] enricher.SystemService : Calling method 'findUser' with parameter User{username='some_name', password='null', email='null'}
Main:User{username='some_name', password='secret', email='some_name@springintegration.org'}
2019-08-30 14:09:29.967 INFO 12392 --- [ main] enricher.SystemService : Calling method 'findUserByUsername' with parameter: some_name
Main:User{username='some_name', password='secret', email='some_name@springintegration.org'}
2019-08-30 14:09:29.967 INFO 12392 --- [ main] enricher.SystemService : Calling method 'findUserByUsername' with parameter: vasya
Main:{password=secret, email=vasya@springintegration.org, username=vasya}
如您所见,一切正常,但我在配置中进行转换。我不确定我是否必须这样做,因为 xml 配置没有这样的转换,并且一切都以某种方式使用内部魔法工作。这是正确的方法还是我应该使用一些内部DSL魔法进行转换?
该文档适用于Spring Integration 4.3的旧版本的DSL;从5.0版本开始,DSL被集成到主项目和文档中。该版本中不存在网关功能。
查看 Wiki 页面顶部的横幅
该项目已从 Spring Integration Core 从 5.0 版本开始吸收。有关实际文档,请参阅其参考手册。此项目仅处于维护、错误修复状态。
请参阅当前文档 - 集成流作为网关。
IntegrationFlow 可以从提供 GatewayProxyFactoryBean 组件的服务接口启动,如以下示例所示:
public interface ControlBusGateway {
void send(String command);
}
...
@Bean
public IntegrationFlow controlBusFlow() {
return IntegrationFlows.from(ControlBusGateway.class)
.controlBus()
.get();
}
它与该示例应用的工作方式相同
public interface RequestGateway {
String echo(String request);
}
....from(RequestGateway.class)
...
编辑
DSL 网关目前不支持具有不同通道的多方法网关。您可以使用几种技术...
@SpringBootApplication
@IntegrationComponentScan // finds the messaging gateway
public class So57709118Application {
public static void main(String[] args) {
SpringApplication.run(So57709118Application.class, args);
}
@Bean
public IntegrationFlow flow() {
return IntegrationFlows.from("gatewayChannel")
//.route(...)
.log()
.nullChannel();
}
@Bean
@DependsOn("flow")
public ApplicationRunner runner(Gate gate) {
return args -> {
gate.method1("bar");
gate.method2("bar");
};
}
}
@MessagingGateway(defaultRequestChannel = "gatewayChannel",
defaultHeaders = @GatewayHeader(name = "method", expression = "#gatewayMethod.name"))
interface Gate {
void method1(String foo);
void method2(String foo);
}
或者,您可以在每个方法上设置 requestChannel 而不是所有流的通用流
@MessagingGateway(defaultHeaders = @GatewayHeader(name = "method", expression = "#gatewayMethod.name"))
interface Gate {
@Gateway(requestChannel = "foo")
void method1(String foo);
@Gateway(requestChannel = "bar")
void method2(String foo);
}