From 757b4de01a0902ca3e76b02657f4ca7959d093a4 Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sat, 31 Jan 2026 15:11:20 +0100 Subject: [PATCH 1/9] cleaning --- .gitignore | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.gitignore b/.gitignore index cb31b43..af5d541 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,14 @@ logs/ /mqjms.log.0 /.claude/ /.idea/ +/.idea/ +/.idea/dictionaries/ +/.idea/inspectionProfiles/ +/.idea/.gitignore +/.idea/compiler.xml +/.idea/copilot.data.migration.agent.xml +/.idea/encodings.xml +/.idea/jarRepositories.xml +/.idea/misc.xml +/.idea/vcs.xml +/.idea/workspace.xml From 3642f4711f5940304dbbb9d8ff47e98d3cca1c67 Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sun, 1 Feb 2026 10:08:57 +0100 Subject: [PATCH 2/9] change refresh layout --- .../com/aquila/ibm/mq/gui/ui/MainWindow.java | 88 ++++----------- .../ibm/mq/gui/ui/MessageBrowserPanel.java | 5 +- .../aquila/ibm/mq/gui/ui/QueueListViewer.java | 103 +++++++++++++++++- 3 files changed, 126 insertions(+), 70 deletions(-) diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java b/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java index 5ec02cd..8674109 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java @@ -48,6 +48,9 @@ @Slf4j public class MainWindow { + @Getter + private static MainWindow instance; + private final Display display; @Getter private final Shell shell; @@ -68,13 +71,10 @@ public class MainWindow { private QueueHandlesPanel queueHandlesPanel; private Label statusLabel; private Label alertLabel; - private Button autoRefreshButton; - private Combo refreshIntervalCombo; - private boolean autoRefreshEnabled = false; - private QueueInfo selectedQueue; public MainWindow(Display display) { + instance = this; this.display = display; this.configuration = new Configuration(); this.connectionManager = new MQConnectionManager(); @@ -87,7 +87,7 @@ public MainWindow(Display display) { shell.setSize(1600, 800); shell.setLayout(new GridLayout()); try { - shell.setImages(new Image[] { + shell.setImages(new Image[]{ new Image(display, getClass().getResourceAsStream("/icons/Aquila-16.png")), new Image(display, getClass().getResourceAsStream("/icons/Aquila-32.png")), new Image(display, getClass().getResourceAsStream("/icons/Aquila-48.png")), @@ -232,6 +232,19 @@ public void onExportSelectedConfiguration(HierarchyNode node) { // EXISTING: Queue List (30%) queueListViewer = new QueueListViewer(sashForm, SWT.BORDER, alertManager); queueListViewer.addSelectionListener(this::onQueueSelected); + queueListViewer.setAutoRefreshListener(new QueueListViewer.AutoRefreshListener() { + @Override + public void onAutoRefreshToggled(boolean enabled) { + toggleAutoRefresh(enabled); + } + + @Override + public void onRefreshIntervalChanged(int intervalMs) { + if (queueMonitor != null && queueMonitor.isRunning()) { + queueMonitor.setRefreshInterval(intervalMs); + } + } + }); queueListViewer.setContextMenuActionListener(new QueueListViewer.ContextMenuActionListener() { @Override public void onSendMessage(QueueInfo queue) { @@ -297,7 +310,7 @@ private void createHandlesTab() { private void createStatusBar() { Composite statusBar = new Composite(shell, SWT.NONE); statusBar.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); - GridLayout layout = new GridLayout(6, false); + GridLayout layout = new GridLayout(2, false); layout.marginHeight = 2; statusBar.setLayout(layout); @@ -308,59 +321,6 @@ private void createStatusBar() { alertLabel = new Label(statusBar, SWT.NONE); alertLabel.setLayoutData(new GridData(SWT.END, SWT.CENTER, false, false)); alertLabel.setText(""); - - new Label(statusBar, SWT.SEPARATOR | SWT.VERTICAL) - .setLayoutData(new GridData(SWT.CENTER, SWT.FILL, false, false)); - - Label refreshLabel = new Label(statusBar, SWT.NONE); - refreshLabel.setText("Refresh:"); - - refreshIntervalCombo = new Combo(statusBar, SWT.READ_ONLY); - refreshIntervalCombo.add("1s"); - refreshIntervalCombo.add("5s"); - refreshIntervalCombo.add("10s"); - refreshIntervalCombo.add("30s"); - refreshIntervalCombo.add("1min"); - refreshIntervalCombo.add("5min"); - refreshIntervalCombo.select(1); - refreshIntervalCombo.addListener(SWT.Selection, e -> updateRefreshInterval()); - - autoRefreshButton = new Button(statusBar, SWT.TOGGLE); - autoRefreshButton.setText("Auto"); - autoRefreshButton.setToolTipText("Toggle automatic refresh of queue information"); - autoRefreshButton.addListener(SWT.Selection, e -> { - autoRefreshEnabled = autoRefreshButton.getSelection(); - toggleAutoRefresh(autoRefreshEnabled); - updateAutoRefreshButtonState(); - }); - } - - private void updateAutoRefreshButtonState() { - if (autoRefreshEnabled) { - autoRefreshButton.setText("Auto ON"); - } else { - autoRefreshButton.setText("Auto"); - } - } - - private void updateRefreshInterval() { - if (queueMonitor != null && queueMonitor.isRunning()) { - int intervalMs = getSelectedRefreshInterval(); - queueMonitor.setRefreshInterval(intervalMs); - } - } - - private int getSelectedRefreshInterval() { - int index = refreshIntervalCombo.getSelectionIndex(); - return switch (index) { - case 0 -> 1000; - case 1 -> 5000; - case 2 -> 10000; - case 3 -> 30000; - case 4 -> 60000; - case 5 -> 300000; - default -> 10000; - }; } private void showConnectionDialog() { @@ -449,7 +409,7 @@ private void toggleAutoRefresh(boolean enabled) { private void startMonitoring() { if (queueMonitor == null || !queueMonitor.isRunning()) { queueMonitor = new QueueMonitor(this, queueService, alertManager); - queueMonitor.setRefreshInterval(getSelectedRefreshInterval()); + queueMonitor.setRefreshInterval(queueListViewer.getSelectedRefreshInterval()); queueMonitor.setMonitoredQueues(queueListViewer.getQueues()); queueMonitor.setListener(new QueueMonitor.QueueMonitorListener() { @Override @@ -806,17 +766,17 @@ private void showAbout() { IBM MQ GUI Desktop application for IBM MQ Browsing Version 1.0 - + Author: Anthony Bussani GitHub: https://github.com/tonioBus - + Licensed under the MIT License. Copyright (c) 2026 Anthony Bussani - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. """); textLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true)); diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/MessageBrowserPanel.java b/src/main/java/com/aquila/ibm/mq/gui/ui/MessageBrowserPanel.java index b3b9f3d..5896d21 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/MessageBrowserPanel.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/MessageBrowserPanel.java @@ -16,6 +16,7 @@ import com.aquila.ibm.mq.gui.model.MessageInfo; import com.aquila.ibm.mq.gui.model.QueueInfo; import com.aquila.ibm.mq.gui.mq.MessageService; +import lombok.extern.slf4j.Slf4j; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.layout.GridData; @@ -26,8 +27,8 @@ import java.util.List; +@Slf4j public class MessageBrowserPanel extends Composite { - private static final Logger logger = LoggerFactory.getLogger(MessageBrowserPanel.class); private final MessageService messageService; private Table messagesTable; private Text messageDetailText; @@ -124,7 +125,7 @@ private void browseMessages() { messages = messageService.browseMessages(currentQueue.getQueue()); refreshTable(); } catch (Exception e) { - logger.error("Failed to browse messages on queue:{}", currentQueue.getQueue(), e); + log.error("Failed to browse messages on queue:{}", currentQueue.getQueue(), e); showError("Failed to browse messages: " + e.getMessage()); } } diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java index 4950b30..19343c6 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java @@ -44,6 +44,12 @@ public interface ContextMenuActionListener { void onCopyQueueName(QueueInfo queue); } + public interface AutoRefreshListener { + void onAutoRefreshToggled(boolean enabled); + + void onRefreshIntervalChanged(int intervalMs); + } + private final Table table; private final List queues; private final List filteredQueues; @@ -67,6 +73,13 @@ public interface ContextMenuActionListener { private Spinner depthFilterSpinner; private Label filterStatusLabel; + // Auto-refresh controls + private Button autoRefreshButton; + private Combo refreshIntervalCombo; + private boolean autoRefreshEnabled = false; + @Setter + private AutoRefreshListener autoRefreshListener; + public QueueListViewer(Composite parent, int style, AlertManager alertManager) { super(parent, style); this.queues = new ArrayList<>(); @@ -124,6 +137,8 @@ public QueueListViewer(Composite parent, int style, AlertManager alertManager) { createContextMenu(); + createRefreshPanel(this); + // Create progress panel at bottom (hidden by default) progressPanel = new Composite(this, SWT.NONE); GridLayout progressLayout = new GridLayout(1, false); @@ -131,7 +146,7 @@ public QueueListViewer(Composite parent, int style, AlertManager alertManager) { progressLayout.marginWidth = 0; progressPanel.setLayout(progressLayout); GridData progressPanelData = new GridData(SWT.FILL, SWT.CENTER, true, false); - progressPanelData.exclude = true; // Hidden by default + // progressPanelData.exclude = true; // Hidden by default progressPanel.setLayoutData(progressPanelData); progressPanel.setVisible(false); @@ -150,7 +165,7 @@ public QueueListViewer(Composite parent, int style, AlertManager alertManager) { private void createFilterPanel(Composite parent) { Composite panel = new Composite(parent, SWT.NONE); - GridLayout layout = new GridLayout(5, false); + GridLayout layout = new GridLayout(9, false); layout.marginHeight = 5; layout.marginWidth = 0; panel.setLayout(layout); @@ -186,6 +201,86 @@ private void createFilterPanel(Composite parent) { } + void createRefreshPanel(Composite parent) { + Composite panel = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(6, false); + layout.marginHeight = 2; + layout.marginWidth = 2; + panel.setLayout(layout); + panel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + // Refresh Now button + autoRefreshButton = new Button(panel, SWT.PUSH); + autoRefreshButton.setText("Refresh Now"); + autoRefreshButton.setToolTipText("Refresh immediately queues information"); + autoRefreshButton.addListener(SWT.Selection, e -> { + MainWindow.getInstance().refreshQueueList(); + }); + + Label verticalSeparator = new Label(panel, SWT.SEPARATOR | SWT.VERTICAL); + + // Refresh interval combo + Label refreshLabel = new Label(panel, SWT.NONE); + refreshLabel.setText("Refresh:"); + + refreshIntervalCombo = new Combo(panel, SWT.READ_ONLY); + refreshIntervalCombo.add("1s"); + refreshIntervalCombo.add("5s"); + refreshIntervalCombo.add("10s"); + refreshIntervalCombo.add("30s"); + refreshIntervalCombo.add("1min"); + refreshIntervalCombo.add("5min"); + refreshIntervalCombo.select(1); + refreshIntervalCombo.addListener(SWT.Selection, e -> { + if (autoRefreshListener != null) { + autoRefreshListener.onRefreshIntervalChanged(getSelectedRefreshInterval()); + } + }); + + // Auto-refresh button + autoRefreshButton = new Button(panel, SWT.TOGGLE); + autoRefreshButton.setText("Auto OFF"); + autoRefreshButton.setToolTipText("Toggle automatic refresh of queues information"); + autoRefreshButton.addListener(SWT.Selection, e -> { + autoRefreshEnabled = autoRefreshButton.getSelection(); + updateAutoRefreshButtonState(); + if (autoRefreshListener != null) { + autoRefreshListener.onAutoRefreshToggled(autoRefreshEnabled); + } + }); + } + + private void updateAutoRefreshButtonState() { + if (autoRefreshEnabled) { + autoRefreshButton.setText("Auto ON "); + } else { + autoRefreshButton.setText("Auto OFF"); + } + } + + public int getSelectedRefreshInterval() { + int index = refreshIntervalCombo.getSelectionIndex(); + return switch (index) { + case 0 -> 1000; + case 1 -> 5000; + case 2 -> 10000; + case 3 -> 30000; + case 4 -> 60000; + case 5 -> 300000; + default -> 10000; + }; + } + + public boolean isAutoRefreshEnabled() { + return autoRefreshEnabled; + } + + public void setAutoRefreshEnabled(boolean enabled) { + this.autoRefreshEnabled = enabled; + autoRefreshButton.setSelection(enabled); + updateAutoRefreshButtonState(); + } + public void setQueues(List queues) { this.queues.clear(); this.queues.addAll(queues); @@ -325,7 +420,7 @@ public void refreshQueue(QueueInfo queue) { public void showProgress(String message) { GridData progressPanelData = (GridData) progressPanel.getLayoutData(); - progressPanelData.exclude = false; + // progressPanelData.exclude = false; progressPanel.setVisible(true); progressLabel.setText(message); layout(true); @@ -333,7 +428,7 @@ public void showProgress(String message) { public void hideProgress() { GridData progressPanelData = (GridData) progressPanel.getLayoutData(); - progressPanelData.exclude = true; + // progressPanelData.exclude = true; progressPanel.setVisible(false); progressLabel.setText(""); layout(true); From 0963701b0e43374344bdc03a29d2357a15dce579 Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sun, 1 Feb 2026 15:55:33 +0100 Subject: [PATCH 3/9] Features/speed up queue services (#8) * attempt to speed up QueueService * attempt to speed up QueueService * attempt to speed up QueueService --- doc/IBMMQRegularExpression | 30 ++++++++ pom.xml | 11 ++- .../ibm/mq/gui/model/node/QueueNode.java | 5 ++ .../ibm/mq/gui/mq/MQConnectionManager.java | 56 +++++--------- .../aquila/ibm/mq/gui/mq/QueueService.java | 76 +++++++++++++------ .../com/aquila/ibm/mq/gui/ui/MainWindow.java | 28 ++++--- .../ibm/mq/gui/ui/QueueBrowserDialog.java | 24 +++++- .../ibm/mq/gui/ui/QueueHandlesPanel.java | 9 +++ .../aquila/ibm/mq/gui/ui/QueueListViewer.java | 18 ++--- 9 files changed, 169 insertions(+), 88 deletions(-) create mode 100644 doc/IBMMQRegularExpression diff --git a/doc/IBMMQRegularExpression b/doc/IBMMQRegularExpression new file mode 100644 index 0000000..a694514 --- /dev/null +++ b/doc/IBMMQRegularExpression @@ -0,0 +1,30 @@ + Yes, you can query multiple queues in a single PCF request using wildcard patterns: + + What works: + - * - matches all queues - ABC.* - matches all queues starting with "ABC." + - *.REQUEST - matches queues ending with ".REQUEST" + + The PCF agent returns multiple response messages, one per matching queue. + + What doesn't work: + - You cannot specify a list of unrelated queue names (e.g., "QUEUE.A, QUEUE.B, QUEUE.C") in a single request + - Each unrelated queue name requires a separate PCF request + + Example with wildcard: + PCFMessageAgent agent = new PCFMessageAgent(queueManager); + PCFMessage request = new PCFMessage(CMQCFC.MQCMD_INQUIRE_Q); + request.addParameter(CMQC.MQCA_Q_NAME, "APP.*"); // wildcard pattern + request.addParameter(CMQC.MQIA_Q_TYPE, CMQC.MQQT_LOCAL); + request.addParameter(CMQCFC.MQIACF_Q_ATTRS, new int[] { + CMQC.MQCA_Q_NAME, + CMQC.MQIA_CURRENT_Q_DEPTH, + CMQC.MQIA_MAX_Q_DEPTH + }); + + PCFMessage[] responses = agent.send(request); // returns array with one entry per queue + + If your queues don't share a common pattern, you'll need to either: + 1. Send separate PCF requests for each queue + 2. Use a broad wildcard and filter the results client-side + + Is this related to the sequentialQueueRequest flag I see in your code? That seems to control whether queues are fetched one-by-one or in batch. diff --git a/pom.xml b/pom.xml index 4e955fb..c328c80 100644 --- a/pom.xml +++ b/pom.xml @@ -72,17 +72,24 @@ 2.0.9 - org.projectlombok lombok ${lombok.version} + ch.qos.logback logback-classic - 1.4.14 + 1.5.13 + + + + + com.google.guava + guava + 33.5.0-jre diff --git a/src/main/java/com/aquila/ibm/mq/gui/model/node/QueueNode.java b/src/main/java/com/aquila/ibm/mq/gui/model/node/QueueNode.java index 5e06d46..50e25b9 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/model/node/QueueNode.java +++ b/src/main/java/com/aquila/ibm/mq/gui/model/node/QueueNode.java @@ -31,6 +31,7 @@ public class QueueNode { private static final ObjectMapper objectMapper = new ObjectMapper(); + public record QueueDescription(String label) { } @@ -42,6 +43,10 @@ public record QueueDescription(String label) { */ @lombok.Builder.Default private final boolean sequencialQueueRequest = false; + + @lombok.Builder.Default + private final int nbThread = 1; + /** * Queue filter pattern. Supports both: * - IBM MQ wildcards: * (any chars), ? (single char) - e.g., "DEV.*" diff --git a/src/main/java/com/aquila/ibm/mq/gui/mq/MQConnectionManager.java b/src/main/java/com/aquila/ibm/mq/gui/mq/MQConnectionManager.java index e67871d..62e9d85 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/mq/MQConnectionManager.java +++ b/src/main/java/com/aquila/ibm/mq/gui/mq/MQConnectionManager.java @@ -18,9 +18,10 @@ import com.ibm.mq.MQException; import com.ibm.mq.MQQueueManager; import com.ibm.mq.constants.MQConstants; +import com.ibm.mq.headers.MQDataException; +import com.ibm.mq.headers.pcf.PCFMessageAgent; +import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.Hashtable; @@ -30,9 +31,13 @@ @Slf4j public class MQConnectionManager { + record ConnectionInfo(MQQueueManager queueManager, QueueManagerConfig queueManagerConfig, PCFMessageAgent agent) {} + // Multi-connection support - private final Map activeConnections; - private final Map connectionConfigs; + private final Map activeConnections = new HashMap<>();; + private final Map activeAgent = new HashMap<>();; + private final Map connectionConfigs = new HashMap<>();; + @Getter private String activeConnectionId; // Legacy fields (deprecated but maintained for backward compatibility) @@ -40,11 +45,6 @@ public class MQConnectionManager { private QueueManagerConfig currentConfig; private boolean connected = false; - public MQConnectionManager() { - this.activeConnections = new HashMap<>(); - this.connectionConfigs = new HashMap<>(); - } - /** * Legacy connect method for backward compatibility. * Connects using the connection's name as the ID and sets it as active. @@ -95,6 +95,7 @@ public void connect(String connectionId, QueueManagerConfig config) throws MQExc MQQueueManager qm = new MQQueueManager(config.getQueueManager(), properties); activeConnections.put(connectionId, qm); connectionConfigs.put(connectionId, config); + activeAgent.put(connectionId,new PCFMessageAgent(qm)); // Update legacy fields for backward compatibility if (activeConnectionId == null || connectionId.equals(activeConnectionId)) { @@ -111,9 +112,15 @@ public void connect(String connectionId, QueueManagerConfig config) throws MQExc config.getHost(), config.getPort(), config.getChannel(), config.getQueueManager()); throw new MQException(e.getCompCode(), e.getReason(), formatMQError(e, config)); + } catch (MQDataException e) { + log.error("MQDataException", e); } } + public PCFMessageAgent getActiveAgent() { + return activeAgent.get(this.activeConnectionId); + } + /** * Get a stable connection ID from a ConnectionConfig. */ @@ -227,6 +234,7 @@ public void disconnect(String connectionId) { if (qm != null) { try { if (qm.isConnected()) { + activeAgent.get(connectionId).disconnect(); qm.disconnect(); QueueManagerConfig config = connectionConfigs.get(connectionId); log.info("Disconnected from queue manager: {} (ID: {})", @@ -235,7 +243,10 @@ public void disconnect(String connectionId) { } } catch (MQException e) { log.error("Error disconnecting from queue manager (ID: {})", connectionId, e); + } catch (MQDataException e) { + log.error("Error disconnecting Agent from queue manager (ID: {})", connectionId, e); } finally { + activeAgent.remove(connectionId); activeConnections.remove(connectionId); connectionConfigs.remove(connectionId); @@ -345,33 +356,6 @@ public MQQueueManager getQueueManager(String connectionId) { return activeConnections.get(connectionId); } - /** - * Get the currently active queue manager. - * @return The active MQQueueManager, or null if none is active - */ - public MQQueueManager getActiveQueueManager() { - if (activeConnectionId == null) { - return null; - } - return activeConnections.get(activeConnectionId); - } - - /** - * Get all connected connection IDs. - * @return Set of connection IDs - */ - public Set getConnectedIds() { - return Set.copyOf(activeConnections.keySet()); - } - - /** - * Get the active connection ID. - * @return The active connection ID, or null if none is active - */ - public String getActiveConnectionId() { - return activeConnectionId; - } - /** * Legacy getCurrentConfig - returns the active connection's config. */ diff --git a/src/main/java/com/aquila/ibm/mq/gui/mq/QueueService.java b/src/main/java/com/aquila/ibm/mq/gui/mq/QueueService.java index 02deada..4472355 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/mq/QueueService.java +++ b/src/main/java/com/aquila/ibm/mq/gui/mq/QueueService.java @@ -16,6 +16,7 @@ import com.aquila.ibm.mq.gui.model.QueueHandle; import com.aquila.ibm.mq.gui.model.QueueInfo; import com.aquila.ibm.mq.gui.util.QueueNameRegexCalculator; +import com.google.common.collect.Lists; import com.ibm.mq.MQException; import com.ibm.mq.MQQueueManager; import com.ibm.mq.constants.CMQC; @@ -70,8 +71,7 @@ public List getAllQueues(String connectionId, String ibmPattern, bool private List getAllQueuesForManager(MQQueueManager qm, String ibmPattern, boolean includeSystemQueues) throws MQException, IOException, MQDataException { final List queues = new ArrayList<>(); - // Create PCF Message Agent - final PCFMessageAgent agent = new PCFMessageAgent(qm); + final PCFMessageAgent agent = connectionManager.getActiveAgent(); // Create PCF request to inquire queues final PCFMessage request = new PCFMessage(CMQCFC.MQCMD_INQUIRE_Q); @@ -104,7 +104,6 @@ private List getAllQueuesForManager(MQQueueManager qm, String ibmPatt queueInfo.setMaxDepth(maxDepth); } queueInfo.setQueueType(queueType); - queueInfo.setQueueType(queueType); queues.add(queueInfo); } catch (Exception e) { log.error("Error", e); @@ -116,7 +115,7 @@ private List getAllQueuesForManager(MQQueueManager qm, String ibmPatt public QueueInfo getQueueInfo(String queueName) throws IOException, MQDataException { final MQQueueManager qm = connectionManager.getQueueManager(); - final PCFMessageAgent agent = new PCFMessageAgent(qm); + final PCFMessageAgent agent = connectionManager.getActiveAgent(); final QueueInfo queueInfo = new QueueInfo(queueName); try { final PCFMessage request = new PCFMessage(MQConstants.MQCMD_INQUIRE_Q); @@ -130,12 +129,10 @@ public QueueInfo getQueueInfo(String queueName) throws IOException, MQDataExcept log.warn("Queue not found: {}", queueName); queueInfo.setAttribute("Exception", "Queue not found"); return queueInfo; - } catch(PCFException e) { + } catch (PCFException e) { log.error("Queue not found: {}", queueName, e); queueInfo.setAttribute("Exception", e.getMessage()); return queueInfo; - } finally { - agent.disconnect(); } } @@ -145,29 +142,23 @@ public QueueInfo getQueueInfo(String queueName) throws IOException, MQDataExcept * @param queueInfos List of queue names to retrieve information for * @return List of QueueInfo objects for the specified queues */ - public void populateQueueInfos(List queueInfos, boolean sequentialRequest) throws MQDataException, IOException { + public void populateQueueInfosShort(List queueInfos, int nbThread, boolean sequentialRequest) { if (queueInfos == null || queueInfos.isEmpty()) { return; } final MQQueueManager qm = connectionManager.getQueueManager(); - final PCFMessageAgent agent = new PCFMessageAgent(qm); long startTime = System.currentTimeMillis(); if (sequentialRequest) { - for (final QueueInfo queueInfo : queueInfos) { - final PCFMessage request = new PCFMessage(MQConstants.MQCMD_INQUIRE_Q); - request.addParameter(MQConstants.MQCA_Q_NAME, queueInfo.getQueue()); - log.info("Before agent.send()"); - try { - final PCFMessage[] responses = agent.send(request); - log.info("After agent.send() responses;{}", responses.length); - populateQueueInfo(queueInfo, responses[0]); - } catch (Exception e) { - log.error("Error retrieving queues: {} ", queueInfo.getQueue(), e); - } + if (nbThread > 1 && (nbThread < queueInfos.size() * 2)) { + multiThreadRequest(qm, queueInfos, nbThread); + } else { + final PCFMessageAgent agent = connectionManager.getActiveAgent(); + populateQueueInfosShort(agent, queueInfos); } } else { List queueNames = queueInfos.stream().map(QueueInfo::getQueue).toList(); List optimizedIBMMQPatterns = QueueNameRegexCalculator.createOptimizedIBMMQPatterns(queueNames); + final PCFMessageAgent agent = connectionManager.getActiveAgent(); for (final String optimizedIBMMQPattern : optimizedIBMMQPatterns) { final PCFMessage request = new PCFMessage(MQConstants.MQCMD_INQUIRE_Q); request.addParameter(MQConstants.MQCA_Q_NAME, optimizedIBMMQPattern); @@ -175,7 +166,7 @@ public void populateQueueInfos(List queueInfos, boolean sequentialReq try { final PCFMessage[] responses = agent.send(request); log.info("After agent.send() optimise responses: {}", responses.length); - populateQueueInfos(queueInfos, responses); + populateQueueInfosShort(queueInfos, responses); } catch (Exception e) { log.error("Error retrieving queues for pattern: {} ", optimizedIBMMQPattern, e); } @@ -185,7 +176,38 @@ public void populateQueueInfos(List queueInfos, boolean sequentialReq log.info("Retrieved information for {} out of {} queues in {} ms", queueInfos.size(), queueInfos.size(), endTime - startTime); } - private void populateQueueInfos(List queueInfos, PCFMessage[] responses) { + void multiThreadRequest(MQQueueManager qm, List queueInfos, int nbThread) { + final int nbParts = queueInfos.size() / nbThread; + final List> listPerThread = Lists.partition(queueInfos, nbParts); + log.info("Creating {} sub-list -- nbParts:{}", listPerThread.size(), nbParts); + final PCFMessageAgent agent = connectionManager.getActiveAgent(); + listPerThread.parallelStream().forEach(tmpQueueInfos -> { + //log.info("multiThreadRequest -> create agent {}", tmpQueueInfos.get(0).getQueue()); + populateQueueInfosShort(agent, tmpQueueInfos); + //log.info("End multiThreadRequest: {}", tmpQueueInfos.get(0).getQueue()); + }); + } + + void populateQueueInfosShort(final PCFMessageAgent agent, List queueInfos) { + for (final QueueInfo queueInfo : queueInfos) { + final PCFMessage request = new PCFMessage(MQConstants.MQCMD_INQUIRE_Q); + request.addParameter(MQConstants.MQCA_Q_NAME, queueInfo.getQueue()); + request.addParameter(CMQCFC.MQIACF_Q_ATTRS, new int[]{ + CMQC.MQCA_Q_NAME, + CMQC.MQIA_Q_TYPE, + CMQC.MQIA_CURRENT_Q_DEPTH, + CMQC.MQIA_MAX_Q_DEPTH + }); + try { + final PCFMessage[] responses = agent.send(request); + populateQueueInfoShort(queueInfo, responses[0]); + } catch (Exception e) { + log.warn("Error retrieving queues: {} ", queueInfo.getQueue(), e); + } + } + } + + private void populateQueueInfosShort(List queueInfos, PCFMessage[] responses) { final Map mapQueuesInfos = new HashMap<>(); queueInfos.forEach(queueInfo -> mapQueuesInfos.put(queueInfo.getQueue(), queueInfo)); Arrays.stream(responses).parallel().forEach(response -> { @@ -195,7 +217,7 @@ private void populateQueueInfos(List queueInfos, PCFMessage[] respons final QueueInfo queueInfo = mapQueuesInfos.get(queueName); if (queueInfo != null) { log.info("populateQueueInfo({}) -> {}", queueName, queueInfo); - populateQueueInfo(queueInfo, response); + populateQueueInfoShort(queueInfo, response); } else log.warn("QueueName:{} found on PCF agent response but not part of the list: ignored", queueName); } catch (PCFException e) { @@ -204,6 +226,14 @@ private void populateQueueInfos(List queueInfos, PCFMessage[] respons }); } + private void populateQueueInfoShort(QueueInfo queueInfo, PCFMessage response) throws PCFException { + queueInfo.setQueueType(response.getIntParameterValue(MQConstants.MQIA_Q_TYPE)); + if (queueInfo.getQueueType() == CMQC.MQQT_LOCAL) { + queueInfo.setCurrentDepth(retrieveIntParameter(queueInfo, response, MQConstants.MQIA_CURRENT_Q_DEPTH, "MQIA_CURRENT_Q_DEPTH")); + queueInfo.setMaxDepth(retrieveIntParameter(queueInfo, response, MQConstants.MQIA_MAX_Q_DEPTH, "MQIA_MAX_Q_DEPTH")); + } + } + private void populateQueueInfo(QueueInfo queueInfo, PCFMessage response) { try { queueInfo.setQueueType(response.getIntParameterValue(MQConstants.MQIA_Q_TYPE)); diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java b/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java index 8674109..0882e66 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java @@ -29,6 +29,7 @@ import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.eclipse.swt.SWT; +import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; @@ -66,7 +67,6 @@ public class MainWindow { private TabFolder tabFolder; private QueuePropertiesPanel propertiesPanel; private MessageBrowserPanel messageBrowserPanel; - private SendMessageDialog sendMessageDialog; private DepthChartPanel depthChartPanel; private QueueHandlesPanel queueHandlesPanel; private Label statusLabel; @@ -531,7 +531,7 @@ private void refreshQueueList(final QueueNode queueNode, // Set active and load queues (BLOCKING) connectionManager.setActiveConnection(connectionId); - queueService.populateQueueInfos(queueInfos, queueNode.isSequencialQueueRequest()); + queueService.populateQueueInfosShort(queueInfos, queueNode.getNbThread(), queueNode.isSequencialQueueRequest()); // Update UI on UI thread display.asyncExec(() -> { @@ -558,23 +558,27 @@ private void refreshQueueList(final QueueNode queueNode, } // If already connected, just set active and load queues connectionManager.setActiveConnection(connectionId); - Display.getDefault().syncExec(() -> loadQueuesAsync(nodeName, queueInfos, queueNode.isSequencialQueueRequest())); + Display.getDefault().syncExec(() -> loadQueuesAsync(nodeName, queueInfos, queueNode.getNbThread(), queueNode.isSequencialQueueRequest())); } - private void loadQueuesAsync(String queueManagerName, List queueInfos, boolean sequentialQueueRequest) { + private void loadQueuesAsync(String queueManagerName, List queueInfos, int nbThread, boolean sequentialQueueRequest) { queueListViewer.showProgress("Loading queues from " + queueManagerName + "..."); new Thread(() -> { try { - queueService.populateQueueInfos(queueInfos, sequentialQueueRequest); - + queueService.populateQueueInfosShort(queueInfos, nbThread, sequentialQueueRequest); + if(queueListViewer.isDisposed()) return; display.asyncExec(() -> { - queueListViewer.setQueues(queueInfos); - queueListViewer.hideProgress(); - updateStatus("Loaded queues from " + queueManagerName); - if (depthChartPanel != null) { - depthChartPanel.setQueues(queueInfos); - } + try { + queueListViewer.setQueues(queueInfos); + queueListViewer.hideProgress(); + updateStatus("Loaded queues from " + queueManagerName); + if (depthChartPanel != null) { + depthChartPanel.setQueues(queueInfos); + } + } catch(SWTException e) { + log.warn("Monitoring during quitting ? ", e); + } }); } catch (Exception e) { log.error("Failed to load queues", e); diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueBrowserDialog.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueBrowserDialog.java index 193b459..5fcf8a5 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueBrowserDialog.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueBrowserDialog.java @@ -47,6 +47,7 @@ public class QueueBrowserDialog { private Text label; private Text queuePattern; private Button sequencialQueueRequestCheckbox; + private Spinner nbThreadSpinner; private List queueManagerList; private Map connections; private InspectedQueueViewer availableQueuesViewer; @@ -188,19 +189,35 @@ private void createRegularExpressionField(Composite parent) { private void createSequencialQueueRequestField(Composite parent) { final Group sequencialGroup = new Group(parent, SWT.NONE); sequencialGroup.setText("Queue Request Options"); - sequencialGroup.setLayout(new GridLayout(1, false)); + sequencialGroup.setLayout(new GridLayout(2, false)); sequencialGroup.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); sequencialQueueRequestCheckbox = new Button(sequencialGroup, SWT.CHECK); sequencialQueueRequestCheckbox.setText("Sequential Queue Request"); - sequencialQueueRequestCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + GridData checkboxGridData = new GridData(SWT.FILL, SWT.CENTER, true, false); + checkboxGridData.horizontalSpan = 2; + sequencialQueueRequestCheckbox.setLayoutData(checkboxGridData); sequencialQueueRequestCheckbox.setToolTipText("Request queue information sequentially instead of in parallel"); - // Initialize with existing value if in edit mode + // Number of threads field + Label nbThreadLabel = new Label(sequencialGroup, SWT.NONE); + nbThreadLabel.setText("Number of Threads:"); + nbThreadLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); + + nbThreadSpinner = new Spinner(sequencialGroup, SWT.BORDER); + nbThreadSpinner.setMinimum(1); + nbThreadSpinner.setMaximum(32); + nbThreadSpinner.setIncrement(1); + nbThreadSpinner.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + nbThreadSpinner.setToolTipText("Number of threads to use for parallel queue requests"); + + // Initialize with existing values if in edit mode if (edit && hierarchyNode.getQueueNode() != null) { sequencialQueueRequestCheckbox.setSelection(hierarchyNode.getQueueNode().isSequencialQueueRequest()); + nbThreadSpinner.setSelection(hierarchyNode.getQueueNode().getNbThread()); } else { sequencialQueueRequestCheckbox.setSelection(false); + nbThreadSpinner.setSelection(1); } } @@ -339,6 +356,7 @@ private QueueNode getQueueNode() { final QueueNode queueNode = QueueNode.builder() .queuePattern(this.queuePattern.getText().trim()) .sequencialQueueRequest(this.sequencialQueueRequestCheckbox.getSelection()) + .nbThread(this.nbThreadSpinner.getSelection()) .queueManager(queueManagerKey) .descriptions(descriptions) .build(); diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueHandlesPanel.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueHandlesPanel.java index 8ff1655..7b186ce 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueHandlesPanel.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueHandlesPanel.java @@ -15,6 +15,7 @@ import com.aquila.ibm.mq.gui.model.QueueHandle; import com.aquila.ibm.mq.gui.mq.QueueService; +import com.ibm.mq.headers.pcf.PCFException; import lombok.extern.slf4j.Slf4j; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; @@ -156,6 +157,14 @@ public void refresh() { statusLabel.setText(handles.size() + " handle(s) found"); } }); + } catch (PCFException e) { + if (!(e.completionCode == 2 && e.getReason() == 4091)) { + log.error("Failed to retrieve queue handles", e); + display.asyncExec(() -> { + if (isDisposed()) return; + statusLabel.setText("Error: " + e.getMessage()); + }); + } } catch (Exception e) { log.error("Failed to retrieve queue handles", e); display.asyncExec(() -> { diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java index 19343c6..b15a83d 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java @@ -271,16 +271,6 @@ public int getSelectedRefreshInterval() { }; } - public boolean isAutoRefreshEnabled() { - return autoRefreshEnabled; - } - - public void setAutoRefreshEnabled(boolean enabled) { - this.autoRefreshEnabled = enabled; - autoRefreshButton.setSelection(enabled); - updateAutoRefreshButtonState(); - } - public void setQueues(List queues) { this.queues.clear(); this.queues.addAll(queues); @@ -288,6 +278,7 @@ public void setQueues(List queues) { } public void refresh() { + final int oldSelection = table.getSelectionIndex(); table.removeAll(); for (QueueInfo queue : filteredQueues) { @@ -298,8 +289,11 @@ public void refresh() { if (!filteredQueues.isEmpty() && table.getSelectionIndex() < 0) { if (table.getSelectionIndex() == -1) { - log.info("Table Selection"); - table.select(0); + log.info("Table Selection: {}", oldSelection); + table.select(oldSelection); + if (oldSelection >= 0 && oldSelection < filteredQueues.size() && selectionListener != null) { + selectionListener.accept(filteredQueues.get(oldSelection)); + } } if (selectionListener != null) { selectionListener.accept(filteredQueues.get(0)); From 9d308a2a430f7eb6ff460dc3805c889de1628566 Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sun, 1 Feb 2026 18:33:30 +0100 Subject: [PATCH 4/9] Features/speed up queue services (#9) * attempt to speed up QueueService * attempt to speed up QueueService * attempt to speed up QueueService * attempt to speed up QueueService --- .../com/aquila/ibm/mq/gui/ui/MainWindow.java | 2 + .../aquila/ibm/mq/gui/ui/QueueListViewer.java | 7 +- .../native-image/reachability-metadata.json | 7 + .../native-image/resource-config.json | 141 +----------------- 4 files changed, 13 insertions(+), 144 deletions(-) diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java b/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java index 0882e66..26a3820 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/MainWindow.java @@ -441,6 +441,8 @@ private void stopMonitoring() { private void onQueueSelected(QueueInfo queue) { this.selectedQueue = queue; + log.info("onQueueSelected: {}", queue.getQueue()); + if (propertiesPanel != null) { try { queueService.refreshQueueInfo(queue); diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java index b15a83d..253227d 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java @@ -294,10 +294,9 @@ public void refresh() { if (oldSelection >= 0 && oldSelection < filteredQueues.size() && selectionListener != null) { selectionListener.accept(filteredQueues.get(oldSelection)); } - } - if (selectionListener != null) { - selectionListener.accept(filteredQueues.get(0)); - } +// if (selectionListener != null) { +// selectionListener.accept(filteredQueues.get(0)); +// } } } diff --git a/src/main/resources/META-INF/native-image/reachability-metadata.json b/src/main/resources/META-INF/native-image/reachability-metadata.json index d54f07d..53ce528 100644 --- a/src/main/resources/META-INF/native-image/reachability-metadata.json +++ b/src/main/resources/META-INF/native-image/reachability-metadata.json @@ -884,6 +884,9 @@ { "name": "descriptions" }, + { + "name": "nbThread" + }, { "name": "queueManager" }, @@ -903,6 +906,10 @@ "name": "getDescriptions", "parameterTypes": [] }, + { + "name": "getNbThread", + "parameterTypes": [] + }, { "name": "getQueueManager", "parameterTypes": [] diff --git a/src/main/resources/META-INF/native-image/resource-config.json b/src/main/resources/META-INF/native-image/resource-config.json index 5c19507..445ab6a 100644 --- a/src/main/resources/META-INF/native-image/resource-config.json +++ b/src/main/resources/META-INF/native-image/resource-config.json @@ -1,140 +1 @@ -{ - "resources":{ - "includes":[{ - "pattern":"\\QMETA-INF/BuildInfo.properties\\E" - }, { - "pattern":"\\QMETA-INF/ccsid_merged.map\\E" - }, { - "pattern":"\\QMETA-INF/compinfo.properties\\E" - }, { - "pattern":"\\QMETA-INF/jmqiCharsets.dat\\E" - }, { - "pattern":"\\QMETA-INF/jmqiversion.properties\\E" - }, { - "pattern":"\\QMETA-INF/jms.config\\E" - }, { - "pattern":"\\QMETA-INF/product.properties\\E" - }, { - "pattern":"\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E" - }, { - "pattern":"\\QMETA-INF/services/java.net.spi.InetAddressResolverProvider\\E" - }, { - "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" - }, { - "pattern":"\\QMETA-INF/services/java.util.spi.ResourceBundleControlProvider\\E" - }, { - "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" - }, { - "pattern":"\\QMETA-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.commons.support.scanning.ClasspathScanner\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.engine.TestEngine\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.LauncherSessionListener\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.PostDiscoveryFilter\\E" - }, { - "pattern":"\\QMETA-INF/services/org.junit.platform.launcher.TestExecutionListener\\E" - }, { - "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" - }, { - "pattern":"\\Qcom/ibm/mq/BuildInfo.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/headers/internal/HeaderMessages.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/headers/internal/HeaderMessages_fr.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/headers/internal/HeaderMessages_fr_FR.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/jmqi/internal/messages.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/jmqi/internal/messages_fr.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/jmqi/internal/messages_fr_FR.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/jms/BuildInfo.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/jms/version.properties\\E" - }, { - "pattern":"\\Qcom/ibm/mq/version.properties\\E" - }, { - "pattern":"\\Qcom/ibm/msg/client/commonservices/j2se/version.properties\\E" - }, { - "pattern":"\\Qcom/ibm/msg/client/jms/internal/version.properties\\E" - }, { - "pattern":"\\Qcom/ibm/msg/client/wmq/factories/version.properties\\E" - }, { - "pattern":"\\Qicons/Aquila-16.png\\E" - }, { - "pattern":"\\Qicons/Aquila-256.png\\E" - }, { - "pattern":"\\Qicons/Aquila-32.ico\\E" - }, { - "pattern":"\\Qicons/Aquila-32.png\\E" - }, { - "pattern":"\\Qicons/Aquila-48.png\\E" - }, { - "pattern":"\\Qicons/connected.png\\E" - }, { - "pattern":"\\Qicons/error.png\\E" - }, { - "pattern":"\\Qicons/folder.png\\E" - }, { - "pattern":"\\Qicons/tonio.png\\E" - }, { - "pattern":"\\Qjunit-platform.properties\\E" - }, { - "pattern":"\\Qlogback-test.scmo\\E" - }, { - "pattern":"\\Qlogback-test.xml\\E" - }, { - "pattern":"\\Qlogback.scmo\\E" - }, { - "pattern":"\\Qlogback.xml\\E" - }, { - "pattern":"\\Qmqji.properties\\E" - }, { - "pattern":"\\Qmqji_en.properties\\E" - }, { - "pattern":"\\Qmqji_en_US.properties\\E" - }, { - "pattern":"\\Qmqji_fr.properties\\E" - }, { - "pattern":"\\Qmqji_fr_FR.properties\\E" - }, { - "pattern":"\\Qorg/eclipse/swtchart/internal/axis/messages.properties\\E" - }, { - "pattern":"\\Qorg/eclipse/swtchart/internal/axis/messages_fr.properties\\E" - }, { - "pattern":"\\Qorg/eclipse/swtchart/internal/axis/messages_fr_FR.properties\\E" - }, { - "pattern":"\\Qorg/eclipse/swtchart/internal/messages.properties\\E" - }, { - "pattern":"\\Qorg/eclipse/swtchart/internal/messages_fr.properties\\E" - }, { - "pattern":"\\Qorg/eclipse/swtchart/internal/messages_fr_FR.properties\\E" - }, { - "pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt76b/nfkc.nrm\\E" - }, { - "pattern":"jdk.jfr:\\Qjdk/jfr/internal/query/view.ini\\E" - }, { - "pattern":"jdk.jfr:\\Qjdk/jfr/internal/types/metadata.bin\\E" - }]}, - "bundles":[{ - "name":"com.ibm.mq.headers.internal.HeaderMessages", - "locales":["fr", "und"] - }, { - "name":"com.ibm.mq.jmqi.internal.messages", - "locales":["fr", "und"] - }, { - "name":"mqji", - "locales":["fr", "und"] - }, { - "name":"org.eclipse.swtchart.internal.axis.messages" - }, { - "name":"org.eclipse.swtchart.internal.messages" - }] -} +{"resources":{"includes":[{"pattern":"java.base:\\Qjdk/internal/icu/impl/data/icudt76b/nfkc.nrm\\E"},{"pattern":"jdk.jfr:\\Qjdk/jfr/internal/query/view.ini\\E"},{"pattern":"jdk.jfr:\\Qjdk/jfr/internal/types/metadata.bin\\E"}]},"bundles":[{"name":"com.ibm.mq.headers.internal.HeaderMessages","locales":["fr","und"]},{"name":"com.ibm.mq.jmqi.internal.messages","locales":["fr","und"]},{"name":"mqji","locales":["fr","und"]},{"name":"org.eclipse.swtchart.internal.axis.messages"},{"name":"org.eclipse.swtchart.internal.messages"}],"globs":[{"glob":"META-INF/BuildInfo.properties"},{"glob":"META-INF/ccsid_merged.map"},{"glob":"META-INF/compinfo.properties"},{"glob":"META-INF/jmqiCharsets.dat"},{"glob":"META-INF/jmqiversion.properties"},{"glob":"META-INF/jms.config"},{"glob":"META-INF/product.properties"},{"glob":"META-INF/services/ch.qos.logback.classic.spi.Configurator"},{"glob":"META-INF/services/java.net.spi.InetAddressResolverProvider"},{"glob":"META-INF/services/java.time.zone.ZoneRulesProvider"},{"glob":"META-INF/services/java.util.spi.ResourceBundleControlProvider"},{"glob":"META-INF/services/javax.xml.parsers.SAXParserFactory"},{"glob":"META-INF/services/org.apache.maven.surefire.spi.MasterProcessChannelProcessorFactory"},{"glob":"META-INF/services/org.junit.platform.commons.support.scanning.ClasspathScanner"},{"glob":"META-INF/services/org.junit.platform.engine.TestEngine"},{"glob":"META-INF/services/org.junit.platform.launcher.LauncherDiscoveryListener"},{"glob":"META-INF/services/org.junit.platform.launcher.LauncherSessionListener"},{"glob":"META-INF/services/org.junit.platform.launcher.PostDiscoveryFilter"},{"glob":"META-INF/services/org.junit.platform.launcher.TestExecutionListener"},{"glob":"META-INF/services/org.slf4j.spi.SLF4JServiceProvider"},{"glob":"com/ibm/mq/BuildInfo.properties"},{"glob":"com/ibm/mq/headers/internal/HeaderMessages.properties"},{"glob":"com/ibm/mq/headers/internal/HeaderMessages_fr.properties"},{"glob":"com/ibm/mq/headers/internal/HeaderMessages_fr_FR.properties"},{"glob":"com/ibm/mq/jmqi/internal/messages.properties"},{"glob":"com/ibm/mq/jmqi/internal/messages_fr.properties"},{"glob":"com/ibm/mq/jmqi/internal/messages_fr_FR.properties"},{"glob":"com/ibm/mq/jms/BuildInfo.properties"},{"glob":"com/ibm/mq/jms/version.properties"},{"glob":"com/ibm/mq/version.properties"},{"glob":"com/ibm/msg/client/commonservices/j2se/version.properties"},{"glob":"com/ibm/msg/client/jms/internal/version.properties"},{"glob":"com/ibm/msg/client/wmq/factories/version.properties"},{"glob":"icons/Aquila-16.png"},{"glob":"icons/Aquila-256.png"},{"glob":"icons/Aquila-32.ico"},{"glob":"icons/Aquila-32.png"},{"glob":"icons/Aquila-48.png"},{"glob":"icons/connected.png"},{"glob":"icons/error.png"},{"glob":"icons/folder.png"},{"glob":"icons/tonio.png"},{"glob":"junit-platform.properties"},{"glob":"logback-test.scmo"},{"glob":"logback-test.xml"},{"glob":"logback.scmo"},{"glob":"logback.xml"},{"glob":"mqji.properties"},{"glob":"mqji_en.properties"},{"glob":"mqji_en_US.properties"},{"glob":"mqji_fr.properties"},{"glob":"mqji_fr_FR.properties"},{"glob":"org/eclipse/swtchart/internal/axis/messages.properties"},{"glob":"org/eclipse/swtchart/internal/axis/messages_fr.properties"},{"glob":"org/eclipse/swtchart/internal/axis/messages_fr_FR.properties"},{"glob":"org/eclipse/swtchart/internal/messages.properties"},{"glob":"org/eclipse/swtchart/internal/messages_fr.properties"},{"glob":"org/eclipse/swtchart/internal/messages_fr_FR.properties"},{"module":"java.base","glob":"jdk/internal/icu/impl/data/icudt76b/nfkc.nrm"},{"module":"jdk.jfr","glob":"jdk/jfr/internal/query/view.ini"}]} From d9b12cc88de308f91d8295de2a267ad306236f2e Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sun, 1 Feb 2026 18:38:26 +0100 Subject: [PATCH 5/9] correct missing } --- src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java index 253227d..f2e2345 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java @@ -294,9 +294,7 @@ public void refresh() { if (oldSelection >= 0 && oldSelection < filteredQueues.size() && selectionListener != null) { selectionListener.accept(filteredQueues.get(oldSelection)); } -// if (selectionListener != null) { -// selectionListener.accept(filteredQueues.get(0)); -// } + } } } From 7380d5b5eadbff64c62c3714b5020c81ee5aa922 Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sun, 1 Feb 2026 10:08:57 +0100 Subject: [PATCH 6/9] change refresh layout --- .../aquila/ibm/mq/gui/ui/QueueListViewer.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java index 253227d..19343c6 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java @@ -271,6 +271,16 @@ public int getSelectedRefreshInterval() { }; } + public boolean isAutoRefreshEnabled() { + return autoRefreshEnabled; + } + + public void setAutoRefreshEnabled(boolean enabled) { + this.autoRefreshEnabled = enabled; + autoRefreshButton.setSelection(enabled); + updateAutoRefreshButtonState(); + } + public void setQueues(List queues) { this.queues.clear(); this.queues.addAll(queues); @@ -278,7 +288,6 @@ public void setQueues(List queues) { } public void refresh() { - final int oldSelection = table.getSelectionIndex(); table.removeAll(); for (QueueInfo queue : filteredQueues) { @@ -289,14 +298,12 @@ public void refresh() { if (!filteredQueues.isEmpty() && table.getSelectionIndex() < 0) { if (table.getSelectionIndex() == -1) { - log.info("Table Selection: {}", oldSelection); - table.select(oldSelection); - if (oldSelection >= 0 && oldSelection < filteredQueues.size() && selectionListener != null) { - selectionListener.accept(filteredQueues.get(oldSelection)); - } -// if (selectionListener != null) { -// selectionListener.accept(filteredQueues.get(0)); -// } + log.info("Table Selection"); + table.select(0); + } + if (selectionListener != null) { + selectionListener.accept(filteredQueues.get(0)); + } } } From 3de28236f4d2e868fc7d7ac393365c44d07bcdf1 Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sun, 1 Feb 2026 15:55:33 +0100 Subject: [PATCH 7/9] Features/speed up queue services (#8) * attempt to speed up QueueService * attempt to speed up QueueService * attempt to speed up QueueService --- .../aquila/ibm/mq/gui/ui/QueueListViewer.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java index 19343c6..b15a83d 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java @@ -271,16 +271,6 @@ public int getSelectedRefreshInterval() { }; } - public boolean isAutoRefreshEnabled() { - return autoRefreshEnabled; - } - - public void setAutoRefreshEnabled(boolean enabled) { - this.autoRefreshEnabled = enabled; - autoRefreshButton.setSelection(enabled); - updateAutoRefreshButtonState(); - } - public void setQueues(List queues) { this.queues.clear(); this.queues.addAll(queues); @@ -288,6 +278,7 @@ public void setQueues(List queues) { } public void refresh() { + final int oldSelection = table.getSelectionIndex(); table.removeAll(); for (QueueInfo queue : filteredQueues) { @@ -298,8 +289,11 @@ public void refresh() { if (!filteredQueues.isEmpty() && table.getSelectionIndex() < 0) { if (table.getSelectionIndex() == -1) { - log.info("Table Selection"); - table.select(0); + log.info("Table Selection: {}", oldSelection); + table.select(oldSelection); + if (oldSelection >= 0 && oldSelection < filteredQueues.size() && selectionListener != null) { + selectionListener.accept(filteredQueues.get(oldSelection)); + } } if (selectionListener != null) { selectionListener.accept(filteredQueues.get(0)); From 3d101670f71ee2cd23e6bae4d792a921db5e730e Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sun, 1 Feb 2026 18:33:30 +0100 Subject: [PATCH 8/9] Features/speed up queue services (#9) * attempt to speed up QueueService * attempt to speed up QueueService * attempt to speed up QueueService * attempt to speed up QueueService --- .../java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java index b15a83d..253227d 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java @@ -294,10 +294,9 @@ public void refresh() { if (oldSelection >= 0 && oldSelection < filteredQueues.size() && selectionListener != null) { selectionListener.accept(filteredQueues.get(oldSelection)); } - } - if (selectionListener != null) { - selectionListener.accept(filteredQueues.get(0)); - } +// if (selectionListener != null) { +// selectionListener.accept(filteredQueues.get(0)); +// } } } From 2957af3d94ced3199625a575cd49ff8b33a78134 Mon Sep 17 00:00:00 2001 From: Anthony Bussani Date: Sun, 1 Feb 2026 18:38:26 +0100 Subject: [PATCH 9/9] correct missing } --- src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java index 253227d..f2e2345 100644 --- a/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java +++ b/src/main/java/com/aquila/ibm/mq/gui/ui/QueueListViewer.java @@ -294,9 +294,7 @@ public void refresh() { if (oldSelection >= 0 && oldSelection < filteredQueues.size() && selectionListener != null) { selectionListener.accept(filteredQueues.get(oldSelection)); } -// if (selectionListener != null) { -// selectionListener.accept(filteredQueues.get(0)); -// } + } } }