Skip to content

Commit 0ec4c5d

Browse files
committed
Fix Payara remote instance handling: improve error reporting and version mismatch detection
Fix Payara remote instance handling: improve error reporting and version mismatch detection - Add RemoteInstanceStateListener to handle remote server-specific warnings - Introduce new TaskEvent types: VERSION_MISMATCH, CONNECTION_FAILED, CMD_URL_FAILED - Improve CommandVersion logic with isVersionMismatch() for accurate comparison - Treat version mismatch on remote servers as SUCCESS with warning instead of failure - Update Runner to emit CONNECTION_FAILED instead of generic EXCEPTION - Add user-facing warning messages for: - version mismatch - connection failure (host/port issues) - command URL construction errors - Prevent popup spam with throttling in RemoteInstanceStateListener
1 parent ad4ae12 commit 0ec4c5d

7 files changed

Lines changed: 260 additions & 8 deletions

File tree

enterprise/payara.common/src/org/netbeans/modules/payara/common/PayaraState.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.netbeans.modules.payara.tooling.data.PayaraPlatformVersionAPI;
2525
import org.netbeans.modules.payara.common.status.AuthFailureStateListener;
2626
import org.netbeans.modules.payara.common.status.MonitoringInitStateListener;
27+
import org.netbeans.modules.payara.common.status.RemoteInstanceStateListener;
2728
import org.openide.util.NbBundle;
2829
import org.netbeans.modules.payara.tooling.data.PayaraServer;
2930
import org.netbeans.modules.payara.tooling.data.PayaraServerStatus;
@@ -114,6 +115,11 @@ public static boolean monitor(final PayaraServer instance) {
114115
PayaraStatus.addChangeListener(instance, authListener, PayaraStatus.STARTUP);
115116
PayaraStatus.addErrorListener(instance, authListener);
116117
}
118+
if (instance.isRemote()) {
119+
RemoteInstanceStateListener remoteInstanceListener
120+
= new RemoteInstanceStateListener();
121+
PayaraStatus.addErrorListener(instance, remoteInstanceListener);
122+
}
117123
try {
118124
long startTime = System.currentTimeMillis();
119125
long waitTime = INIT_MONITORING_TIMEOUT;

enterprise/payara.common/src/org/netbeans/modules/payara/common/status/Bundle.properties

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,16 @@ AuthFailureStateListener.message=<html>Authorization failed while checking {0} \
1919
status. Please provide valid administrator credentials.</html>
2020
AuthFailureStateListener.error.exception=Exception was thrown in server status \
2121
check.
22+
RemoteInstanceStateListener.versionMismatch=<html>The version of the remote \
23+
Payara server <b>{0}</b> does not match the version of the local Payara \
24+
installation. Some features may not work correctly. Consider updating the \
25+
server registration or aligning the server versions.</html>
26+
RemoteInstanceStateListener.connectionFailed=<html>Could not connect to the \
27+
administration interface of Payara server <b>{0}</b> at {1}:{2}. Please \
28+
verify that the host name and administration port are correct in the server \
29+
registration.</html>
30+
RemoteInstanceStateListener.commandException=<html>Could not build the \
31+
administration command URL for Payara server <b>{0}</b>. The configured \
32+
host <b>{1}</b> or port <b>{2}</b> may be malformed. Please verify the \
33+
server registration settings.</html>
2234

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.netbeans.modules.payara.common.status;
20+
21+
import org.netbeans.modules.payara.tooling.PayaraStatus;
22+
import static org.netbeans.modules.payara.tooling.data.PayaraStatusCheck.VERSION;
23+
import org.netbeans.modules.payara.tooling.TaskEvent;
24+
import org.openide.DialogDisplayer;
25+
import org.openide.NotifyDescriptor;
26+
import org.openide.util.NbBundle;
27+
import org.netbeans.modules.payara.tooling.data.PayaraServer;
28+
import org.netbeans.modules.payara.tooling.data.PayaraStatusTask;
29+
30+
/**
31+
* Handle version mismatch and connection/URL failures in administration command
32+
* calls during server status monitoring.
33+
* <p/>
34+
* Displays a warning notification to the user in three cases:
35+
* <ul>
36+
* <li>The version reported by a remote Payara server differs from the
37+
* locally registered installation ({@link TaskEvent#VERSION_MISMATCH}).</li>
38+
* <li>A connection failure occurred reaching the administration interface —
39+
* typically caused by a wrong host name or port number configured in the
40+
* server registration ({@link TaskEvent#CONNECTION_FAILED}).</li>
41+
* <li>An exception was thrown while constructing the administration command —
42+
* the configured host/port values may be malformed
43+
* ({@link TaskEvent#CMD_EXCEPTION}).</li>
44+
* </ul>
45+
* <p/>
46+
* For every Payara server instance being monitored there must be its own
47+
* {@code RemoteInstanceStateListener} instance to avoid duplicate popups.
48+
* <p/>
49+
* @author Gaurav Gupta
50+
*/
51+
public class RemoteInstanceStateListener extends BasicStateListener {
52+
53+
// Class attributes //
54+
/** Minimal delay between displaying warning popups [ms].
55+
* <p/>
56+
* Currently it shall not open a popup again sooner than after 60 seconds
57+
* to avoid spamming the user during periodic status checks. */
58+
private static final long POPUP_DELAY = 60000;
59+
60+
// Instance attributes //
61+
/** Timestamp of last popup window. */
62+
private volatile long lastTm;
63+
64+
// Constructors //
65+
/**
66+
* Constructs an instance of the remote instance state notification handler.
67+
*/
68+
public RemoteInstanceStateListener() {
69+
super();
70+
this.lastTm = 0;
71+
}
72+
73+
// Methods //
74+
/**
75+
* Callback to notify about current server status after every check
76+
* when enabled.
77+
* <p/>
78+
* Not used.
79+
* <p/>
80+
* @param server Payara server instance being monitored.
81+
* @param status Current server status.
82+
* @param task Last Payara server status check task details.
83+
*/
84+
@Override
85+
public void currentState(final PayaraServer server,
86+
final PayaraStatus status, final PayaraStatusTask task) {
87+
// Not used.
88+
}
89+
90+
/**
91+
* Callback to notify about server status change when enabled.
92+
* <p/>
93+
* Not used.
94+
* <p/>
95+
* @param server Payara server instance being monitored.
96+
* @param status Current server status.
97+
* @param task Last Payara server status check task details.
98+
*/
99+
@Override
100+
public void newState(final PayaraServer server,
101+
final PayaraStatus status, final PayaraStatusTask task) {
102+
// Not used.
103+
}
104+
105+
/**
106+
* Callback to notify about server status check failures.
107+
* <p/>
108+
* Shows a non-blocking warning popup on the VERSION check for:
109+
* <ul>
110+
* <li>{@link TaskEvent#VERSION_MISMATCH} — server version differs from
111+
* the locally registered installation.</li>
112+
* <li>{@link TaskEvent#CONNECTION_FAILED} — connection failed; likely caused by
113+
* a wrong host name or administration port.</li>
114+
* <li>{@link TaskEvent#CMD_EXCEPTION} — an exception was thrown while
115+
* constructing the administration command; host/port may be malformed.</li>
116+
* </ul>
117+
* <p/>
118+
* @param server Payara server instance being monitored.
119+
* @param task Payara server status check task details.
120+
*/
121+
@Override
122+
public void error(final PayaraServer server,
123+
final PayaraStatusTask task) {
124+
if (task.getType() != VERSION) {
125+
return;
126+
}
127+
TaskEvent event = task.getEvent();
128+
if (event == TaskEvent.VERSION_MISMATCH) {
129+
showWarningNotification(server, "RemoteInstanceStateListener.versionMismatch",
130+
server.getName());
131+
} else if (event == TaskEvent.CONNECTION_FAILED) {
132+
// Connection failed — wrong host or port configured for the server.
133+
showWarningNotification(server, "RemoteInstanceStateListener.connectionFailed",
134+
server.getName(), server.getHost(),
135+
Integer.toString(server.getAdminPort()));
136+
} else if (event == TaskEvent.CMD_EXCEPTION) {
137+
// constructCommandUrl() threw a CommandException — host/port
138+
// value may be malformed.
139+
showWarningNotification(server, "RemoteInstanceStateListener.commandException",
140+
server.getName(), server.getHost(),
141+
Integer.toString(server.getAdminPort()));
142+
}
143+
}
144+
145+
/**
146+
* Shows a non-blocking warning notification at most once per
147+
* {@link #POPUP_DELAY} milliseconds.
148+
* <p/>
149+
* @param server Payara server instance (unused, for future use).
150+
* @param bundleKey NbBundle key for the message text.
151+
* @param args Arguments to the bundle message.
152+
*/
153+
private void showWarningNotification(final PayaraServer server,
154+
final String bundleKey, final Object... args) {
155+
long now = System.currentTimeMillis();
156+
synchronized (this) {
157+
if (now - lastTm < POPUP_DELAY) {
158+
return;
159+
}
160+
lastTm = now;
161+
}
162+
String message = NbBundle.getMessage(
163+
RemoteInstanceStateListener.class, bundleKey, args);
164+
NotifyDescriptor nd = new NotifyDescriptor.Message(
165+
message, NotifyDescriptor.WARNING_MESSAGE);
166+
DialogDisplayer.getDefault().notifyLater(nd);
167+
}
168+
169+
}

enterprise/payara.tooling/src/org/netbeans/modules/payara/tooling/TaskEvent.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,14 @@ public enum TaskEvent {
6565
/** Java VM execution failed. */
6666
JAVA_VM_EXEC_FAILED,
6767
/** Signals wrong proxy settings. */
68-
BAD_GATEWAY;
68+
BAD_GATEWAY,
69+
70+
/** Version returned by server does not match expected version. */
71+
VERSION_MISMATCH,
72+
/** Connection to the server administration interface failed. */
73+
CONNECTION_FAILED,
74+
/** Administration command URL could not be constructed. */
75+
CMD_URL_FAILED;
6976

7077
// Class attributes //
7178
/** A <code>String</code> representation of SUBMIT value. */
@@ -119,6 +126,15 @@ public enum TaskEvent {
119126
/** A <code>String</code> representation of BAD_GATEWAY value. */
120127
private static final String BAD_GATEWAY_STR = "BadGateway";
121128

129+
/** A <code>String</code> representation of VERSION_MISMATCH value. */
130+
private static final String VERSION_MISMATCH_STR = "VersionMismatch";
131+
132+
/** A <code>String</code> representation of CONNECTION_FAILED value. */
133+
private static final String CONNECTION_FAILED_STR = "ConnectionFailed";
134+
135+
/** A <code>String</code> representation of CMD_URL_FAILED value. */
136+
private static final String CMD_URL_FAILED_STR = "CmdUrlFailed";
137+
122138
/**
123139
* Stored <code>String</code> values for backward <code>String</code>
124140
* conversion.
@@ -180,7 +196,10 @@ public String toString() {
180196
case WRONG_JAVA_VM: return WRONG_JAVA_VM_STR;
181197
case JAVA_VM_EXEC_FAILED: return JAVA_VM_EXEC_FAILED_STR;
182198
case BAD_GATEWAY: return BAD_GATEWAY_STR;
183-
// This is unrecheable. Returned null value means that some
199+
case VERSION_MISMATCH: return VERSION_MISMATCH_STR;
200+
case CONNECTION_FAILED: return CONNECTION_FAILED_STR;
201+
case CMD_URL_FAILED: return CMD_URL_FAILED_STR;
202+
// This is unreachable. Returned null value means that some
184203
// enum value is not handled correctly.
185204
default: return null;
186205
}

enterprise/payara.tooling/src/org/netbeans/modules/payara/tooling/admin/CommandVersion.java

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,17 @@ public static PayaraPlatformVersionAPI getPayaraPlatformVersion(
117117
}
118118

119119
/**
120-
* Verifies if domain directory returned by version command result matches
121-
* domain directory of provided Payara server entity.
120+
* Verifies if version command result confirms Payara server is running.
121+
* <p/>
122+
* The version returned by the server must match the version of the local
123+
* Payara installation. Both major and minor version values are compared.
122124
* <p/>
123125
* @param result Version command result.
124126
* @param server Payara server entity.
125-
* @return For local server value of <code>true</code> means that server
126-
* major and minor version value matches values returned by version
127-
* command and value of <code>false</code> that they differs.
127+
* @return Value of <code>true</code> means that server major and minor
128+
* version value matches values returned by version command and
129+
* value of <code>false</code> that they differ or a comparison
130+
* could not be made.
128131
*/
129132
public static boolean verifyResult(
130133
final ResultString result, final PayaraServer server) {
@@ -140,6 +143,34 @@ public static boolean verifyResult(
140143
return verifyResult;
141144
}
142145

146+
/**
147+
* Checks whether the version returned by the server is a known mismatch
148+
* against the locally registered Payara installation.
149+
* <p/>
150+
* A version mismatch is reported only when both the server response and
151+
* the local installation carry parseable version information that differs.
152+
* When either side is unknown this method returns <code>false</code>.
153+
* <p/>
154+
* @param result Version command result.
155+
* @param server Payara server entity.
156+
* @return Value of <code>true</code> when the server responded with a
157+
* version that is different from the locally registered version,
158+
* or <code>false</code> when the versions match or comparison
159+
* could not be performed.
160+
*/
161+
public static boolean isVersionMismatch(
162+
final ResultString result, final PayaraServer server) {
163+
String value = ServerUtils.getVersionString(result.getValue());
164+
if (value != null) {
165+
PayaraPlatformVersionAPI valueVersion = PayaraPlatformVersion.toValue(value);
166+
PayaraPlatformVersionAPI serverVersion = server.getPlatformVersion();
167+
if (valueVersion != null && serverVersion != null) {
168+
return !serverVersion.equals(valueVersion);
169+
}
170+
}
171+
return false;
172+
}
173+
143174
// Constructors //
144175
/**
145176
* Constructs an instance of Payara server version command entity.

enterprise/payara.tooling/src/org/netbeans/modules/payara/tooling/admin/Runner.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ public Result call() {
902902
retries = 0;
903903
} catch (ConnectException ce) {
904904
return handleStateChange(TaskState.FAILED,
905-
TaskEvent.EXCEPTION,
905+
TaskEvent.CONNECTION_FAILED,
906906
stateChangeArgs(ce.getLocalizedMessage()));
907907
} catch (IOException ex) {
908908
if (retries <= 0) {

enterprise/payara.tooling/src/org/netbeans/modules/payara/tooling/server/state/StatusJob.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,21 @@ public void operationStateChanged(final TaskState newState,
298298
event));
299299
break;
300300
}
301+
// COMPLETED but versions do not match.
302+
// For remote servers, accept the server as
303+
// running (SUCCESS) but fire VERSION_MISMATCH
304+
// so the user is notified via a warning popup.
305+
if (job.status.getServer().isRemote()
306+
&& taskResult != null
307+
&& CommandVersion.isVersionMismatch(
308+
taskResult, job.status.getServer())) {
309+
job.version.setResult(new StatusResultVersion(
310+
taskResult,
311+
PayaraStatusCheckResult.SUCCESS,
312+
TaskEvent.VERSION_MISMATCH));
313+
notifyError = true;
314+
break;
315+
}
301316
case FAILED:
302317
job.version.setResult(new StatusResultVersion(taskResult,
303318
PayaraStatusCheckResult.FAILED,

0 commit comments

Comments
 (0)