🎄 Happy Holidays! 🥳
Most of Solace is closed December 24–January 1 so our employees can spend time with their families. We will re-open Thursday, January 2, 2024. Please expect slower response times during this period and open a support ticket for anything needing immediate assistance.
Happy Holidays!
Please note: most of Solace is closed December 25–January 2, and will re-open Tuesday, January 3, 2023.
Configuring Solace w/ testcontainers
Hi
I'm trying to configure my Solace that runs on testcontainers and Springboot JMS. The container starts up just fine, but the container is not setup the way I need it. I need it to have some queues and I'm having a hard time finding a way to get it running.
I tried to create one with testcontainers equivalent to docker exec curl ...
but unsuccessfully so since the Solace container cant access curl or apt-get (error: starting container process caused: exec: "apt-get": stat apt-get: no such file or directory: unknown
)
I tried to create a queue with the JCSMPFactory, but I get a org.springframework.jms.InvalidDestinationException: Error sending message - queue not found (400: Queue Not Found - Topic '#P2P/QUE/MyQueue');
I could try to send POST request to SEMPv2 to set up the Queues but it doesn't feel right to add a foreign dependency just to setup solace.
Does anybody see the reason why my code isn't working?
Is there a way to setup Queues within the container (using docker exec)?
Here's my code:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) @ActiveProfiles("test") @Testcontainers @Slf4j @ExtendWith(SpringExtension.class) //The AbstractPubSubPlusTestCase is equal to https://github.com/solace-iot-team/pubsubplus-container-junit/blob/main/src/main/java/com/solace/junit/AbstractPubSubPlusTestCase.java class MessageControllerIT extends AbstractPubSubPlusTestCase { @Autowired private JmsTemplate jmsTemplate; private String inQueue = "MyQueue"; private String outQueue = "OutQueue"; private static JCSMPSession session; @BeforeAll public static void connectSMF() { final var properties = new JCSMPProperties(); properties.setProperty(JCSMPProperties.HOST, String.format("%s:%s", getHost(), getSMFPort())); properties.setProperty(JCSMPProperties.USERNAME, "default"); properties.setProperty(JCSMPProperties.VPN_NAME, "default"); try { session = JCSMPFactory.onlyInstance().createSession(properties); session.connect(); } catch (JCSMPException e) { e.printStackTrace(); } } @AfterAll public static void tearDown() { if(Objects.nonNull(session) && !session.isClosed()) { session.closeSession(); } } @BeforeEach void init() { var inQ = JCSMPFactory.onlyInstance().createQueue("Q/"+this.inQueue); var outQ = JCSMPFactory.onlyInstance().createQueue("Q/"+this.outQueue); var inT = JCSMPFactory.onlyInstance().createTopic("T/"+this.inQueue); var outT = JCSMPFactory.onlyInstance().createTopic("T/"+this.outQueue); session.addSubscribtion(inQ, inT, JCSMPSession.WAIT_FOR_CONFIRM); session.addSubscribtion(outQ, outT, JCSMPSession.WAIT_FOR_CONFIRM); } @DynamicPropertySource static void registerDynamicProperties(DynamicPropertyRegistry registry) { var host = "smf://" + getHost() + ":" + getSMFPort(); registry.add("solace.jms.host", () -> host); } @Test void shouldReceiveAndRespond() { var incomingMessage = MyMessageSupport.getInstance().getIncomingMessage(); var expectedMessage = MyMessageSupport.getInstance().getExpectedMessage(); this.jmsTemplate.convertAndSend("T/"+this.inQueue, incomingMessage); this.jmsTemplate.setReceiveTimeout(10_000); var ack = this.jmsTemplate.receiveAndConvert("Q/"+this.outQueue); assertThat(ack).isNotNull(); } }
Comments
-
Hi @rothek,
I think what is happening here is that
JCSMPFactory.createQueue(...)
just creates the queue object in your app locally and not on the broker. You'll need to callJCSMPSession.provision(...)
to actually create it on the broker. More info on provision hereSample code here: https://github.com/SolaceSamples/solace-samples-java-jcsmp/blob/master/src/main/java/com/solace/samples/jcsmp/features/TopicToQueueMapping.java#L103:L118
1 -
I'm still getting an error in the log:
INFO 639284 --- [2_ReactorThread] c.s.jcsmp.impl.flow.BindRequestTask : Client-2: Got BIND ('Q/MyQueue') Error Response (503) - Unknown Queue
And a few lines later:
[connect_service] c.s.j.protocol.impl.TcpClientChannel : Client-7: Connection attempt failed to host 'localhost' ReconnectException com.solacesystems.jcsmp.JCSMPTransportException: (Client name: <Client> Local addr: 127.0.0.1 Local port: 54176 Remote addr: localhost Remote port: 54137) - Error communicating with the router. cause: java.io.IOException: Unable to read enough bytes from stream!
Even more lines later:
com.solacesystems.jcsmp.JCSMPTransportException: (JCSMPTransportException) Error receiving data from underlying connection.at com.solacesystems.jcsmp.protocol.impl.TcpClientChannel$ClientChannelReconnect.call(TcpClientChannel.java:2439) ~[sol-jms-10.13.1.jar:na] at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[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:833) ~[na:na] Caused by: com.solacesystems.jcsmp.JCSMPTransportException: (Client name: <Client> Local port: -1 Remote addr: localhost Remote port: 54137) - Error communicating with the router. at com.solacesystems.jcsmp.protocol.impl.TcpChannel.executePostOnce(TcpChannel.java:251) ~[sol-jms-10.13.1.jar:na] at com.solacesystems.jcsmp.protocol.impl.ChannelOpStrategyClient.performOpen(ChannelOpStrategyClient.java:97) ~[sol-jms-10.13.1.jar:na] at com.solacesystems.jcsmp.protocol.impl.TcpClientChannel.performOpenSingle(TcpClientChannel.java:418) ~[sol-jms-10.13.1.jar:na] at com.solacesystems.jcsmp.protocol.impl.TcpClientChannel.access$800(TcpClientChannel.java:114) ~[sol-jms-10.13.1.jar:na] at com.solacesystems.jcsmp.protocol.impl.TcpClientChannel$ClientChannelReconnect.call(TcpClientChannel.java:2275) ~[sol-jms-10.13.1.jar:na] ... 4 common frames omitted
Caused by: java.nio.channels.AsynchronousCloseException: null at java.base/java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:202) ~[na:na] at java.base/sun.nio.ch.SocketChannelImpl.endRead(SocketChannelImpl.java:389) ~[na:na]
at java.base/sun.nio.ch.SocketChannelImpl.endConnect(SocketChannelImpl.java:792) ~[na:na] at java.base/sun.nio.ch.SocketChannelImpl.blockingConnect(SocketChannelImpl.java:1189) ~[na:na] at java.base/sun.nio.ch.SocketAdaptor.connect(SocketAdaptor.java:98) ~[na:na] at com.solacesystems.jcsmp.protocol.smf.SimpleSmfClient.open(SimpleSmfClient.java:905) ~[sol-jms-10.13.1.jar:na] at com.solacesystems.jcsmp.protocol.smf.SimpleSmfClient.doPostNoResponse(SimpleSmfClient.java:318) ~[sol-jms-10.13.1.jar:na] at com.solacesystems.jcsmp.protocol.smf.SimpleSmfClient.doPost(SimpleSmfClient.java:235) ~[sol-jms-10.13.1.jar:na] at com.solacesystems.jcsmp.protocol.impl.TcpChannel.executePostOnce(TcpChannel.java:196) ~[sol-jms-10.13.1.jar:na] ... 8 common frames omitted
INFO 639284 --- [connect_service] c.s.jcsmp.impl.JCSMPXMLMessageProducer : Client-7:Flow-3: [Client-7] Transport exception occurred when message Id is not available
But my tests turn out green for some reason. Note that these are not breaking errors but logged to the console at INFO level.
My test receives a message on the response queue and tests for null and that the content of the message contains specific strings.
Any idea why this could be?
0 -
Weird, does that happen every time you run it?
It looks like a network issue might have occurred but that doesn't make much sense if you're running against a local broker.
Another guess is maybe the broker isn't fully started inside of the container yet. Just to test sleep for 30 seconds after
solace.start()
in AbstractPubSubPlusTestCase. It shouldn't really take 30 seconds but that should be plenty of time to troubleshoot if that is the issue or not and you can shorten the time to see how long it really needs if so.0 -
Yeah happens every time, even with a 30s sleep after starting the container.
[Context_4_ReactorThread] INFO com.solacesystems.jcsmp.impl.flow.BindRequestTask - Client-4: Got BIND ('Q/MyQueue') Error Response (503) - Unknown Queue
I get this error like 3 times until my test for some reason still turn green.
I mean its ok, since in the end it still works somehow, but it would be nice to reduce logging during tests.
Maybe the following lines are more helpful?
[Context_7_ReactorThread] INFO com.solacesystems.jcsmp.protocol.impl.TcpClientChannel - Client-7: (Client name: <Client> Local port: 65162 Remote addr: localhost Remote port: 65125) - handleException(): Channel Closed Event (smfclient 7)
[Context_7_ReactorThread] INFO com.solacesystems.jcsmp.protocol.impl.TcpClientChannel - Client-7: handleException(): Channel Closed Event (smfclient 7) with exception: null cur_stack=Thread: "Context_7_ReactorThread" daemon id=176, prio=5: com.solacesystems.jcsmp.protocol.impl.TcpClientChannel.handleException(TcpClientChannel.java:1374) com.solacesystems.jcsmp.protocol.impl.TcpClientChannel.handleException(TcpClientChannel.java:1325) com.solacesystems.jcsmp.protocol.nio.impl.SubscriberMessageReader.handleClosedSocketDuringRead(SubscriberMessageReader.java:203) com.solacesystems.jcsmp.protocol.smf.SimpleSmfClient.handleClosedSocketDuringRead(SimpleSmfClient.java:1184) com.solacesystems.jcsmp.protocol.nio.impl.SyncEventDispatcherReactor.processReactorChannels(SyncEventDispatcherReactor.java:229) com.solacesystems.jcsmp.protocol.nio.impl.SyncEventDispatcherReactor.eventLoop(SyncEventDispatcherReactor.java:157) com.solacesystems.jcsmp.protocol.nio.impl.SyncEventDispatcherReactor$SEDReactorThread.run(SyncEventDispatcherReactor.java:338) java.base/java.lang.Thread.run(Thread.java:833)
(This is logged twice for the same client and no other client)
I'm also autowiring the JMSTemplate for my message handler with the default ConnectionFactory. I'm trying to find out if this is the culprit.
Some more info about my setup:
Running IntelliJ 2022.1 on Win 10, testcontainer on (1.17.1), my solace depencies are
com.solace.spring.boot:solace-jms-spring-boot-autoconfigure com.solace.spring.boot:solace-jms-spring-boot-starter org.springframework.integration:spring-integration-jms
all on their latest release.
I have a postgres db and some other containers running which are required for testing (they're not running via testcontainers atm)
0 -
Hi @rothek, In my case my container is created but as I am trying to login into solace the container is getting exited. I have tried with withStartupCheckStrategy but I am getting the same issue. Please let me know if you have faced similar issue and if so please can you guide me to solve this.
0