JMS에서 Azure Service Bus에 메시지 보내기

Microsoft Learn의 이하 컨텐츠를 시험했습니다만, 일부 변경이 필요한 곳이나 부족한 곳이 있었으므로 보충 기사를 씁니다.

변경: Azure Spring Boot Starter For Azure Service Bus JMS 종속성



pom.xml에 추가하는 종속성은 현재 com.microsoft.azure가 아닌 com.azure.spring의 것입니다.
<dependency>
    <groupId>com.microsoft.azure</groupId>
    <artifactId>azure-servicebus-jms-spring-boot-starter</artifactId>
    <version>2.3.3</version>
</dependency>



그래서 다음을 추가했습니다.
<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>azure-spring-boot-starter-servicebus-jms</artifactId>        
    <version>3.4.0</version>
</dependency>

보충: 구성 매개변수



'구성 매개변수 추가' 부분에서 application.properties에 다음을 추가한다고 쓰고 있습니다만, 지식이 부족한 나에게는 <xxxxx> 에 무엇이 들어가는지 몰랐습니다.
spring.jms.servicebus.connection-string=<xxxxx>
spring.jms.servicebus.idle-timeout=20000

여기에는 연결 문자열을 넣는 것 같습니다. 만든 Service Bus의 "공유 액세스 정책"에 표시되는 기본 연결 문자열을 복사했습니다.


spring.jms.servicebus.connection-string=Endpoint=sb://xxxxxxxxxx.servicebus.windows.net/;SharedAccessKeyName=xxxxxxxx;SharedAccessKey=xxxxxxxxx+xxxxx+xxxxxxxx=
spring.jms.servicebus.idle-timeout=20000

추가: 구성 매개변수



application.properties에는 spring.jms.servicebus.topic-client-id와 spring.jms.servicebus.pricing-tier의 정의도 필요했습니다.

없으면 다음 오류가 발생합니다.
2021-05-02 10:03:08.497  WARN 53623 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'sendController': Unsatisfied dependency expressed through field 'jmsTemplate'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jmsTemplate' defined in class path resource [org/springframework/boot/autoconfigure/jms/JmsAutoConfiguration$JmsTemplateConfiguration.class]: Unsatisfied dependency expressed through method 'jmsTemplate' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'jmsConnectionFactory' defined in class path resource [com/azure/spring/autoconfigure/jms/NonPremiumServiceBusJMSAutoConfiguration.class]: Unsatisfied dependency expressed through method 'jmsConnectionFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'spring.jms.servicebus-com.azure.spring.autoconfigure.jms.AzureServiceBusJMSProperties': Invocation of init method failed; nested exception is java.lang.NullPointerException

결국 다음과 같은 정의가 되었습니다.
spring.jms.servicebus.connection-string=Endpoint=sb://xxxxxxxxxx.servicebus.windows.net/;SharedAccessKeyName=xxxxxxxx;SharedAccessKey=xxxxxxxxx+xxxxx+xxxxxxxx=
spring.jms.servicebus.topic-client-id=kikutaroservicebus
spring.jms.servicebus.idle-timeout=20000
spring.jms.servicebus.pricing-tier=basic

spring.jms.servicebus.topic-client-id는 Service Bus의 이름입니다.



보충: 큐 생성



소스 코드는 Learn의 것을 그대로 사용했습니다.
package com.example.demo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class SendController {

    private static final String queue = "test-queue-jms";

    @Autowired
    private JmsTemplate jmsTemplate;

    @GetMapping("/messages")
    public String postMessage(@RequestParam String message) {
        jmsTemplate.send(queue, s -> s.createTextMessage(message));
        return message;
    }
}

Learn에는 대기열을 만드는 단계가 없다고 생각합니다. . 실행하면 다음 오류가 발생했습니다.
2021-05-02 09:57:00.674 ERROR 52938 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.jms.InvalidDestinationException: The messaging entity 'sb://kikutaroservicebus.servicebus.windows.net/test-queue-jms' could not be found. To know more visit https://aka.ms/sbResourceMgrExceptions.  TrackingId:663a3a569bea493fb4f805e6142f5c81_G25, SystemTracker:gateway7, Timestamp:2021-05-02T09:56:59 [condition = amqp:not-found]; nested exception is javax.jms.InvalidDestinationException: The messaging entity 'sb://kikutaroservicebus.servicebus.windows.net/test-queue-jms' could not be found. To know more visit https://aka.ms/sbResourceMgrExceptions.  TrackingId:663a3a569bea493fb4f805e6142f5c81_G25, SystemTracker:gateway7, Timestamp:2021-05-02T09:56:59 [condition = amqp:not-found]] with root cause

org.apache.qpid.jms.provider.exceptions.ProviderInvalidDestinationException: The messaging entity 'sb://kikutaroservicebus.servicebus.windows.net/test-queue-jms' could not be found. To know more visit https://aka.ms/sbResourceMgrExceptions.  TrackingId:663a3a569bea493fb4f805e6142f5c81_G25, SystemTracker:gateway7, Timestamp:2021-05-02T09:56:59 [condition = amqp:not-found]
        at org.apache.qpid.jms.provider.amqp.AmqpSupport.convertToNonFatalException(AmqpSupport.java:177) ~[qpid-jms-client-0.53.0.jar!/:na]
        at org.apache.qpid.jms.provider.amqp.builders.AmqpResourceBuilder.getOpenAbortExceptionFromRemote(AmqpResourceBuilder.java:299) ~[qpid-jms-client-0.53.0.jar!/:na]
        at org.apache.qpid.jms.provider.amqp.builders.AmqpResourceBuilder.handleClosed(AmqpResourceBuilder.java:185) ~[qpid-jms-client-0.53.0.jar!/:na]
        at org.apache.qpid.jms.provider.amqp.builders.AmqpResourceBuilder.processRemoteClose(AmqpResourceBuilder.java:129) ~[qpid-jms-client-0.53.0.jar!/:na]
        at org.apache.qpid.jms.provider.amqp.AmqpProvider.processUpdates(AmqpProvider.java:985) ~[qpid-jms-client-0.53.0.jar!/:na]
        at org.apache.qpid.jms.provider.amqp.AmqpProvider.onData(AmqpProvider.java:871) ~[qpid-jms-client-0.53.0.jar!/:na]
        at org.apache.qpid.jms.transports.netty.NettyTcpTransport$NettyTcpTransportHandler.channelRead0(NettyTcpTransport.java:563) ~[qpid-jms-client-0.53.0.jar!/:na]
        at org.apache.qpid.jms.transports.netty.NettyTcpTransport$NettyTcpTransportHandler.channelRead0(NettyTcpTransport.java:556) ~[qpid-jms-client-0.53.0.jar!/:na]
        at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1504) ~[netty-handler-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1253) ~[netty-handler-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1300) ~[netty-handler-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508) ~[netty-codec-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447) ~[netty-codec-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276) ~[netty-codec-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) ~[netty-transport-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.channel.epoll.AbstractEpollStreamChannel$EpollStreamUnsafe.epollInReady(AbstractEpollStreamChannel.java:795) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar!/:4.1.63.Final]
        at io.netty.channel.epoll.EpollEventLoop.processReady(EpollEventLoop.java:480) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar!/:4.1.63.Final]
        at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:378) ~[netty-transport-native-epoll-4.1.63.Final-linux-x86_64.jar!/:4.1.63.Final]
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.63.Final.jar!/:4.1.63.Final]
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.63.Final.jar!/:4.1.63.Final]
        at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]

그래서 코드에서 볼 수 있듯이 "test-queue-jms"라는 큐를 만듭니다.



다시 실행하면 움직였습니다! !



대기열이 있는지 확인합니다.



메시지가 도착했습니다.



프로그래밍 방식으로 수신하는 것 외에도 Service Bus Explorer를 사용하여 화면에서 메시지를 확인할 수 있습니다. 편리.



확인할 수 있었습니다!

좋은 웹페이지 즐겨찾기