Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pnnl.goss.core/src/pnnl/goss/core/client/GossClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,8 @@ public Serializable getResponse(Serializable message, String destinationName,

/**
* Sends request and gets response for synchronous communication, defaulting to
* QUEUE destination type, bounded by an explicit receive timeout (GADP-051). See
* QUEUE destination type, bounded by an explicit receive timeout (GADP-051).
* See
* {@link #getResponse(Serializable, String, RESPONSE_FORMAT, DESTINATION_TYPE, long)}
* for the full timeout semantics.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
* and the pre-existing unbounded overloads keep calling receive(0), preserving
* their exact prior "block indefinitely" behavior for other callers.
*
* <p>GADP-051 (session-isolation): getResponse() now derives a dedicated,
* <p>
* GADP-051 (session-isolation): getResponse() now derives a dedicated,
* listener-free Session from the Connection for its synchronous request/reply
* (so an async subscribe() listener on the shared session cannot poison the
* synchronous receive()). The mock wiring therefore stubs the Connection to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,45 @@
/**
* GADP-051 (session-isolation) regression coverage.
*
* <p>Root cause verified at runtime cold start: FieldBusManager registers an
* async device-output {@code MessageListener} via {@code subscribe(...)} and
* then issues a synchronous topology {@code getResponse(...)} on the SAME
* <p>
* Root cause verified at runtime cold start: FieldBusManager registers an async
* device-output {@code MessageListener} via {@code subscribe(...)} and then
* issues a synchronous topology {@code getResponse(...)} on the SAME
* {@link pnnl.goss.core.client.GossClient}. Both operations shared the client's
* single JMS {@code Session}, and {@code jakarta.jms} forbids a synchronous
* {@code receive()} on a session that has a {@code MessageListener} attached:
* {@code org.apache.activemq.ActiveMQSession.checkMessageListener} throws
* {@code jakarta.jms.IllegalStateException} with the message
* "Cannot synchronously receive a message when a MessageListener is set".
* That made every topology attempt throw instantly regardless of timing, so
* the caller's bounded-retry window (GADP-051 / GOSS-023) could never succeed.
* {@code jakarta.jms.IllegalStateException} with the message "Cannot
* synchronously receive a message when a MessageListener is set". That made
* every topology attempt throw instantly regardless of timing, so the caller's
* bounded-retry window (GADP-051 / GOSS-023) could never succeed.
*
* <p>This test reproduces the exact interaction against a real embedded broker
* (a mock cannot exercise {@code ActiveMQSession.checkMessageListener}): it
* <p>
* This test reproduces the exact interaction against a real embedded broker (a
* mock cannot exercise {@code ActiveMQSession.checkMessageListener}): it
* subscribes an async listener, then calls the bounded {@code getResponse}
* overload against a destination with no responder.
*
* <ul>
* <li>RED (pre-fix, shared session): the synchronous receive throws
* {@code IllegalStateException} within a few milliseconds; it never
* reaches its timeout budget.</li>
* <li>GREEN (post-fix, dedicated listener-free session): the synchronous
* receive runs cleanly on its own session, blocks for its timeout budget,
* and returns {@code null} (no reply arrived) without throwing.</li>
* <li>RED (pre-fix, shared session): the synchronous receive throws
* {@code IllegalStateException} within a few milliseconds; it never reaches its
* timeout budget.</li>
* <li>GREEN (post-fix, dedicated listener-free session): the synchronous
* receive runs cleanly on its own session, blocks for its timeout budget, and
* returns {@code null} (no reply arrived) without throwing.</li>
* </ul>
*
* <p>Same embedded-broker pattern as {@link GossClientBoundedReceiveWallClockTest}.
* <p>
* Same embedded-broker pattern as
* {@link GossClientBoundedReceiveWallClockTest}.
*/
public class GossClientSyncReceiveWithActiveListenerTest {

private static final String LISTENER_TOPIC = "goss.gridappsd.test.device.output";
private static final String SYNC_DESTINATION = "goss.gridappsd.test.topology.no.responder";
private static final long TIMEOUT_MILLIS = 1200L;
// Scheduling jitter margin, mirrored from GossClientBoundedReceiveWallClockTest.
// Scheduling jitter margin, mirrored from
// GossClientBoundedReceiveWallClockTest.
private static final long TOLERANCE_MILLIS = 400L;

private BrokerService broker;
Expand Down
Loading