public static final String READY = "READY";
private static final ObjectMapper MAPPER = new ObjectMapper();
private static final String TSO_DATA = "tsoData";
private static final String TSO_MESSAGE = "TSO MESSAGE";
private static final String TSO_PROMPT = "TSO PROMPT";
private static final String DATA = "DATA";
private static final String HIDDEN = "HIDDEN";
private static final String CODE_PAGE = "277";
private final String account;
private final TsoStart tsoStart;
private final TsoSend tsoSend;
private final TsoReply tsoReply;
private final TsoStop tsoStop;
private final TsoPing tsoPing;
private final String sessionId;
public ZoweExecutor(String host, String user, String password, String account, String port) {
this(account, ZosConnectionFactory.createBasicConnection(host, Integer.parseInt(port), user, password));
}
private ZoweExecutor(String account, ZosConnection connection) {
this(
account,
new TsoStart(connection),
new TsoSend(connection),
new TsoReply(connection),
new TsoStop(connection),
new TsoPing(connection));
}
ZoweExecutor(
String account, TsoStart tsoStart, TsoSend tsoSend, TsoReply tsoReply, TsoStop tsoStop, TsoPing tsoPing) {
this.account = account;
this.tsoStart = tsoStart;
this.tsoSend = tsoSend;
this.tsoReply = tsoReply;
this.tsoStop = tsoStop;
this.tsoPing = tsoPing;
this.sessionId = openAddressSpace();
}
public static ZoweExecutor fromConfig(ZoweConnectionConfigs.ZoweConnectionConfig config) {
return new ZoweExecutor(config.host(), config.user(), config.password(), config.account(), config.port());
}
public void runCommandAndCheckReadyResponse(String command) {
final var response = run(command);
if (!isReadyResponse(response)) {
throw new UnexpectedZoweResponse(command, READY, response);
}
}
public void runCommandAndCheckResponseContains(String command, String expectedResponse) {
final var response = run(command);
if (!response.contains(expectedResponse)) {
throw new UnexpectedZoweResponse(command, expectedResponse, response);
}
}
public static boolean isReadyResponse(String response) {
return READY.equals(response);
}
public String run(String command) {
log.debug("Running TSO command: {}", command);
final var commandResponse = sendAndCollect(command);
log.debug("Command response: {}", commandResponse);
return commandResponse;
}
@SneakyThrows
public boolean ping() {
final TsoCommonResponse response = tsoPing.ping(sessionId);
log.debug("Ping response: {}", response);
return response != null && !Boolean.TRUE.equals(response.getTimeout());
}
@Retry(name = "zowe")
@SneakyThrows
private String sendAndCollect(String command) {
final List<String> messages = new ArrayList<>();
var response = tsoSend.sendCommand(sessionId, command);
var promptReceived = collectMessages(response, messages);
while (!promptReceived) {
response = tsoReply.reply(sessionId);
promptReceived = collectMessages(response, messages);
}
return String.join("\n", messages).trim();
}
@SneakyThrows
private boolean collectMessages(String responseStr, List<String> messages) {
final JsonNode tsoData = MAPPER.readTree(responseStr).path(TSO_DATA);
if (!tsoData.isArray()) {
return false;
}
var promptReceived = false;
for (final JsonNode item : tsoData) {
final JsonNode message = item.get(TSO_MESSAGE);
if (message != null && message.hasNonNull(DATA)) {
messages.add(message.get(DATA).asText());
}
final JsonNode prompt = item.get(TSO_PROMPT);
if (prompt != null && prompt.hasNonNull(HIDDEN)) {
promptReceived = true;
}
}
return promptReceived;
}
@Override
public void close() {
try {
stopAddressSpace();
} catch (Exception e) {
log.warn("Failed to close Zowe address space: {}", sessionId, e);
}
}
@SneakyThrows
private String openAddressSpace() {
final var input = new StartTsoInputData();
input.setAccount(account);
input.setCodePage(CODE_PAGE);
final TsoStartResponse response = tsoStart.start(input);
if (!response.isSuccess()) {
throw new IllegalStateException("Failed to start TSO address space: " + response.getResponse());
}
return response.getSessionId();
}
@SneakyThrows
private void stopAddressSpace() {
tsoStop.stop(sessionId);
}
We recently switched from Zowe CLI to Zowe Java SDK.
We are using Zowe to execute multiple TSO commands in the same address space.
However, after switching we sporadically observe
Looking at the logs on the mainframe, we are quite certain that the problem is related to this stacktrace
We have tried to upgrade from 7.0.0 to 7.0.3. However, the problem persists.
Our Zowe "driver"
```` @slf4j public class ZoweExecutor implements AutoCloseable {}