Warm tip: This article is reproduced from serverfault.com, please click

Spring Boot and Spring Integration. Problems

发布于 2020-12-02 20:20:31

I have a SpringBoot application. I have a dedicated server, where I shall read data by the HTTP GET requests. I configured the http-outbound-config.xml file for Spring Integration module. When I run the following code, everything is fine:

http-outbound-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:int="http://www.springframework.org/schema/integration"
   xmlns:int-http="http://www.springframework.org/schema/integration/http"
   xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration https://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/http https://www.springframework.org/schema/integration/http/spring-integration-http.xsd">

<int:channel id="requestChannel"/>
<int:channel id="replyChannel">
    <int:queue capacity='10'/>
</int:channel>

<int-http:outbound-gateway id="outboundGateway"
                           request-channel="requestChannel"
                           url="http://server/API.jsp?id=1"
                           http-method="GET"
                           expected-response-type="java.lang.String"
                           charset="UTF-8"
                           reply-channel="replyChannel"/>
</beans>

Main Application Class:

package test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
import ru.eco.products.waste.egr.Integration;

@SpringBootApplication
@ImportResource("/META-INF/spring/integration/http-outbound-config.xml")
public class Application {
    public static void main(String[] args) {
        Integration integration = new Integration();
        integration.start();
        SpringApplication.run(WasteWebClientApplication.class,
                              args
                             );
    }
    
}

Integration class:

package test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
@Configuration
public class Integration { 
    public void start() {
        ClassPathXmlApplicationContext
               context = new ClassPathXmlApplicationContext("classpath:META-INF/spring/integration/http-outbound-config.xml");
        context.start();


        MessageChannel requestChannel = context.getBean("requestChannel", MessageChannel.class);
        PollableChannel replyChannel = context.getBean("replyChannel", PollableChannel.class);
        Message<?> message = MessageBuilder.withPayload("").build();
        requestChannel.send(message);
        
        Message<?> receivedMsg = replyChannel.receive();
        System.out.println("RESULT IS : " + receivedMsg.getPayload());
    }
}

BUT, when I try to Autowire MessageChannel and PollableChannel, I receive a null pointer exception.

Integration class(not working example):

package test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
@Configuration
public class Integration {
    @Autowired
    @Qualifier("requestChannel")
    MessageChannel requestChannel;
    @Autowired
    @Qualifier("replyChannel")
    PollableChannel replyChannel;
    
    public void start() {
        Message<?> message = MessageBuilder.withPayload("").build();
        requestChannel.send(message);
        
        Message<?> receivedMsg = replyChannel.receive();
        System.out.println("RESULT IS : " + receivedMsg.getPayload()); 
    }
}

  1. Question 1: Why Autowiring is not working?
  2. Question 2: What is the best way to get data from dedicated server and save it into DB? Such config is ok? I will create a model class for the response and after will save it into DB via JPA.
  3. Question 3: I need reading from server works in Async mode. How can I implement it in Spring Boot? So the main idea here is that I will receive a POST method from the UI, and will launch the integration with web-service. After integration will be finished, I need to notify user.
  4. Question 4: Maybe Camel will be the best solution here?

Stack: Java 11, Spring Boot, thymeleaf + bootstrap.

Thank you for the answer in advance.

Questioner
Andrei Gavrilov
Viewed
0
Artem Bilan 2020-12-03 04:34:11
  1. Since you do new Integration();, you definitely not going to have dependency injection since inversion of control container is not involved. Although it is fully not clear why do you need that new ClassPathXmlApplicationContext("classpath:META-INF/spring/integration/http-outbound-config.xml") if you already do Spring Boot and that proper @ImportResource.

  2. The best way as you already do with the @ImportResource for that Spring Integration XML config. Then you need to get access to the ApplicationContext of the SpringApplication.run() and getBean(Integration.class) to call your start() method. However you fully need to forget about new Integratio(). Spring is going to manage a bean for that Integration and then dependency injection is going to work.

  3. Async mode can be achieved with an ExecutorChannel in Spring Integration. So, when you send a message to this channel, the logic is going to be processed on a different thread. However it is not clear why you state such a requirement since you still going to block via that replyChannel.receive()... Although this should be addressed in a separate SO thread.

  4. Camel VS Spring Integration question is out of StackOverflow policies.

Thymeleaf and Bootstrap are misleading in the context of this question.

Please, consider to learn how to ask properly here on SO: https://stackoverflow.com/help/how-to-ask

Also read some docs about dependency injection and inversion of control: https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#spring-core