TCP-клиент, использующий конфигурацию Java, отсутствует фабрика бинов - PullRequest
0 голосов
/ 24 ноября 2018

Я пытаюсь создать службу, которая запускает TCP-клиент с помощью Spring Spring.Служба передает hostName и port для создания AbstractClientConnectionFactory.Затем он создает TcpInboundGateway, используя тот же AbstractClientConnectionFactory.Наконец, начинается шлюз.Ошибка, которую я получаю, возникает после завершения endOfLineSerializer

@Service
public class TcpService {

    @Autowired
    private TaskScheduler taskScheduler;

    private TcpInboundGateway tcpInboundGateway;

    @Autowired
    private MessageChannel toTcp;

    @Autowired
    private EndOfLineSerializer endOfLineSerializer;

    @Scheduled(initialDelay = 1000, fixedRate = 10000000)
    public void test() {

        if(tcpInboundGateway != null && tcpInboundGateway.isRunning()) {
            return;
        }

        AbstractClientConnectionFactory abstractClientConnectionFactory = clientConnectionFactory("192.XXX.XXX.XX", 4321);
        tcpInboundGateway = tcpInbound(abstractClientConnectionFactory);
        tcpInboundGateway.setTaskScheduler(taskScheduler);
        tcpInboundGateway.start();
    }

    public AbstractClientConnectionFactory clientConnectionFactory(String hostName, int port) {
        TcpNetClientConnectionFactory tcpNetServerConnectionFactory = new TcpNetClientConnectionFactory(hostName, port);
        tcpNetServerConnectionFactory.setSingleUse(false);
        tcpNetServerConnectionFactory.setSoTimeout(300000);
        tcpNetServerConnectionFactory.setDeserializer(endOfLineSerializer);
        tcpNetServerConnectionFactory.setSerializer(endOfLineSerializer);
        tcpNetServerConnectionFactory.setMapper(new TimeoutMapper());
        return tcpNetServerConnectionFactory;
    }

    public TcpInboundGateway tcpInbound(AbstractClientConnectionFactory connectionFactory) {
        TcpInboundGateway gate = new TcpInboundGateway();
        gate.setConnectionFactory(connectionFactory);
        gate.setClientMode(true);
        gate.setRetryInterval(60000);
        gate.setRequestChannel(toTcp);
        gate.setReplyChannelName("toTcp");
        return gate;
    }
}

@EnableIntegration
@IntegrationComponentScan
@Configuration
public class TcpClientConfig {

    @Bean
    public EndOfLineSerializer endOfLineSerializer() {
        return new EndOfLineSerializer();
    }

    @MessageEndpoint
    public static class Echo {

        @Transformer(inputChannel = "toTcp", outputChannel = "serviceChannel")
        public String convert(byte[] bytes) {
            return new String(bytes);
        }
    }

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

    @Bean
    public MessageChannel toTcp() {
        return new DirectChannel();
    }
}

. Я попытался @Autowired BeanFactory и установил его на TcpInboundGateway, однако ошибка продолжает возникать.Почему MessageGateway не может найти BeanFactory?

Ошибка

java.lang.IllegalArgumentException: BeanFactory must not be null
    at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.1.2.RELEASE.jar:5.1.2.RELEASE]
    at org.springframework.integration.support.channel.BeanFactoryChannelResolver.<init>(BeanFactoryChannelResolver.java:76) ~[spring-integration-core-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at org.springframework.integration.context.IntegrationObjectSupport.getChannelResolver(IntegrationObjectSupport.java:218) ~[spring-integration-core-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.getReplyChannel(MessagingGatewaySupport.java:384) ~[spring-integration-core-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.registerReplyMessageCorrelatorIfNecessary(MessagingGatewaySupport.java:736) ~[spring-integration-core-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:483) ~[spring-integration-core-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:470) ~[spring-integration-core-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at org.springframework.integration.ip.tcp.TcpInboundGateway.doOnMessage(TcpInboundGateway.java:120) ~[spring-integration-ip-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at org.springframework.integration.ip.tcp.TcpInboundGateway.onMessage(TcpInboundGateway.java:98) ~[spring-integration-ip-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at org.springframework.integration.ip.tcp.connection.TcpNetConnection.run(TcpNetConnection.java:198) ~[spring-integration-ip-5.1.0.RELEASE.jar:5.1.0.RELEASE]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) [na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [na:na]
    at java.base/java.lang.Thread.run(Thread.java:844) [na:na]

1 Ответ

0 голосов
/ 24 ноября 2018

Это связано с тем, что Spring не управляет этими объектами - вам нужно либо удовлетворить все интерфейсы ...Aware и вызвать afterPropertiesSet(), либо вам нужно обратиться к нему за Spring.Есть два способа сделать последнее.

Использование фабрики бинов вручную

@Autowired
private ConfigurableListableBeanFactory beanFactory;

public AbstractClientConnectionFactory clientConnectionFactory(String hostName, int port) {
    TcpNetClientConnectionFactory server = new TcpNetClientConnectionFactory(hostName, port);
    server.setSingleUse(false);
    server.setSoTimeout(300000);
    server = (TcpNetClientConnectionFactory) this.beanFactory.initializeBean(server, "cf");
    this.beanFactory.registerSingleton("cf", server);
    return server;
}

public TcpInboundGateway tcpInbound(AbstractClientConnectionFactory connectionFactory) {
    TcpInboundGateway gate = new TcpInboundGateway();
    gate.setConnectionFactory(connectionFactory);
    gate.setClientMode(true);
    gate.setRetryInterval(60000);
    gate.setRequestChannelName("toTcp");
    gate = (TcpInboundGateway) this.beanFactory.initializeBean(gate, "gate");
    this.beanFactory.registerSingleton("gate", gate);
    return gate;
}

Использование функции регистрации динамического потока Java DSL

@Autowired
private IntegrationFlowContext flowContext;

public void tcpInbound(String host, int port, String flowId) {
    IntegrationFlow flow = IntegrationFlows.from(
                Tcp.inboundGateway(Tcp.netClient(host, port))
                    .clientMode(true))
            .channel("toTcp")
            .get();
    this.flowContext.registration(flow).id(flowId).register();
}

(Вы также можете настроить другие свойства с помощью DSL).

   gate.setRequestChannel(toTcp);
   gate.setReplyChannelName("toTcp");

Нельзя использовать один и тот же канал для запросов и ответов;Вам обычно не нужен канал ответа, фреймворк это выяснит.Канал ответа нужен только в том случае, если вы хотите сделать что-то вроде добавления проводного сигнала для регистрации ответа.

...