使用 RabbitTemplate 在接收回复消息时获取 NPE

Getting NPE while receiving the reply message using RabbitTemplate

我有两个微服务。一个包含 REST 控制器,它具有 Get 方法,该方法在发送到特定队列时接收消息。其他微服务只是将回复消息发送到同一个队列,以便在点击 REST API

时可以在浏览器中看到已处理的消息

但是,在接收消息时出现NPE。 下面是完整的堆栈跟踪:

2018-05-19 15:46:13.409  INFO 30104 --- [nio-8097-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/unit]   : Initializing Spring FrameworkServlet 'dispatcherServlet' 2018-05-19 15:46:13.409  INFO 30104 --- [nio-8097-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started 2018-05-19 15:46:13.443  INFO 30104 --- [nio-8097-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 34 ms 2018-05-19 15:46:13.533  INFO 30104 --- [nio-8097-exec-1] o.s.a.r.c.CachingConnectionFactory       : Attempting to connect to: [35.154.27.134:5672] 2018-05-19 15:46:13.593  INFO 30104 --- [nio-8097-exec-1] o.s.a.r.c.CachingConnectionFactory       : Created new connection: rabbitConnectionFactory#5b2b49d6:0/SimpleConnection@3e4f13fa [delegate=amqp://guest@35.154.27.134:5672/, localPort= 58742] 2018-05-19 15:46:18.681 ERROR 30104 --- [nio-8097-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [/unit] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause

java.lang.NullPointerException: null
        at com.infy.ci.unitamqpservice.UnitAmqpRestController.getAggregatedDataForSectionOfNightlyBuild(UnitAmqpRestController.java:83) ~[classes!/:0.0.1-SNAPSHOT]
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_151]
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_151]
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_151]
        at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_151]
        at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.14.RELEASE.jar!/:4.3.14.RELEASE]
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) ~[tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:504) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:803) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_151]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_151]
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.27.jar!/:8.5.27]
        at java.lang.Thread.run(Thread.java:748) [na:1.8.0_151]

此外,当在网络浏览器中点击 REST API 时,在控制台上获取以下日志

2018-05-19 15:45:22.328 INFO 30023 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'rabbitConnectionFactory': registering with JMX server as MBean [org.springframework.amqp.rabbit.connection:name=rabbitConnectionFactory,type=CachingConnectionFactory] 2018-05-19 15:45:22.423 INFO 30023 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647 2018-05-19 15:45:22.445 INFO 30023 --- [cTaskExecutor-1] o.s.a.r.c.CachingConnectionFactory : Attempting to connect to: [35.154.27.134:5672] 2018-05-19 15:45:22.471 INFO 30023 --- [cTaskExecutor-1] o.s.a.r.c.CachingConnectionFactory : Created new connection: rabbitConnectionFactory#325fc787:0/SimpleConnection@38a7acf7 [delegate=amqp://guest@35.154.27.134:5672/, localPort= 58736] 2018-05-19 15:45:22.875 INFO 30023 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8099 (http) 2018-05-19 15:45:22.902 INFO 30023 --- [ main] com.infy.ci.unitdbamqpservice.RPCServer : Started RPCServer in 7.517 seconds (JVM running for 8.286) Sat May 19 15:45:23 UTC 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification. Sat May 19 15:46:13 UTC 2018 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

这会是 NPE 的原因吗?我已经在 JDBC 代码中包含了以下内容,但仍然没有成功。

prop.setProperty("useSSL", "false");
prop.setProperty("autoReconnect", "true");

两项服务都在 github 签到:

return rabbitTemplate.convertSendAndReceive("myExchange", requestQueueName, message).toString();

您无条件调用 toString() 回复。

如果在收到回复之前超过模板的 replyTimeout,回复将是 null(超时默认为 5 秒)。

您必须在调用 toString() 之前检查 null 结果。

just sends the reply message to same queue

您不能将回复发送到同一个 queue - 它必须转到请求中的 replyTo header。

如果您在服务器端使用 @RabbitListenerMessageListenerAdapter,它会为您处理。

这与 SSL 无关

WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set.

那个警告是关于 MySQL.

编辑

我只是将你的应用程序降到最低限度,它们对我来说工作得很好......

@Controller
@Configuration
@PropertySource("classpath:/application.properties")
@RequestMapping("/unittestdata")
public class UnitAmqpRestController {

    private final String requestQueueName = "rpc_queue1";

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    private final Logger logger = LoggerFactory.getLogger(UnitAmqpRestController.class);

    private final RabbitTemplate rabbitTemplate;

    @Autowired
    public UnitAmqpRestController(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        rabbitTemplate.setReplyTimeout(15_000L);
    }

    @RequestMapping(value = "/{projectid}/ut/aggregate",
            method = RequestMethod.GET,
            produces = MediaType.TEXT_HTML_VALUE)
    public @ResponseBody String getAggregatedDataForSectionOfNightlyBuild(@PathVariable("projectid") int projectid,
            @RequestParam("buildtype") String buildtype, @RequestParam("build") String build) throws Exception {

        if (build.toLowerCase().equals("latest") && buildtype.equals("nightly")) {

            String message = String.format("aggregate");
            logger.info("Sending: " + message);
            Object returned = rabbitTemplate.convertSendAndReceive("", requestQueueName, message);
            logger.info("Reply: " + returned);
            if (returned == null) {
                throw new RuntimeException("failed to get a response");
            }
            return returned.toString();

        }
        else {
            return null;
        }

    }

}

@Configuration
@SpringBootApplication
@PropertySource("classpath:/application.properties")
public class RPCServer {

    private static final Logger logger = LoggerFactory.getLogger(RPCServer.class);

    public static void main(String[] args) throws IOException, TimeoutException, InterruptedException {
        SpringApplication.run(RPCServer.class, args);
    }

    private static final String RPC_QUEUE_NAME = "rpc_queue1";

    @Bean
    public Queue queue() {
        return new Queue(RPC_QUEUE_NAME);
    }

    @Component
    public static class RpcListener {

        @RabbitListener(queues = RPC_QUEUE_NAME)
        public String reply(String request) throws IOException, TimeoutException, ClassNotFoundException, SQLException {
            logger.info(request);
            return request.toUpperCase();
        }

    }

}

2018-05-20 12:46:00.298  INFO 13369 --- [nio-8097-exec-1] c.i.c.u.UnitAmqpRestController           : Sending: aggregate
...
o.s.amqp.rabbit.core.RabbitTemplate      : Publishing message on exchange [], routingKey = [rpc_queue1]
2018-05-20 12:46:00.554 DEBUG 13369 --- [nio-8097-exec-1] o.s.amqp.rabbit.core.RabbitTemplate      : Reply: (Body:'AGGREGATE' MessageProperties [headers={}, timestamp=null, messageId=null, userId=null, receivedUserId=null, appId=null, clusterId=null, type=null, correlationId=null, correlationIdString=null, replyTo=null, contentType=text/plain, contentEncoding=UTF-8, contentLength=0, deliveryMode=null, receivedDeliveryMode=PERSISTENT, expiration=null, priority=0, redelivered=false, receivedExchange=, receivedRoutingKey=amq.rabbitmq.reply-to.g2dkABByYWJiaXRAbG9jYWxob3N0AAAHFAAAAAAC.3M1LyvOdR9dHQehSV4l67A==, receivedDelay=null, deliveryTag=1, messageCount=null, consumerTag=null, consumerQueue=null])
2018-05-20 12:46:00.561  INFO 13369 --- [nio-8097-exec-1] c.i.c.u.UnitAmqpRestController           : Reply: AGGREGATE