Skip to content

Commit fbd2ab3

Browse files
committed
OF-3181: Allow static configuration of cluster node ID
Previously, an Openfire server generated a new cluster node ID on every startup, causing the identifier to change after each restart. This commit ensures that a server reuses the same node ID over time by persisting the initially generated value. The node ID is now stored in `openfire.xml` under a new property: `clustering.nodeid` - If the property does not exist at startup, a random node ID is generated and persisted. - If the property exists, its value is reused. This allows administrators to optionally define stable, human-recognizable node IDs. When doing so, administrators are responsible for ensuring uniqueness across all cluster members. This change also removes the concept of a "default" node ID. Since Openfire 4.4.0 (OF-1705), node IDs no longer change when joining a cluster, making the distinction between default and runtime IDs obsolete. As a result, there is now a single node ID per server. As a functional consequence, the node ID is no longer available until after server initialization (it is no longer a static field). This is expected to have little to no practical impact, as the previous static value was not publicly accessible.
1 parent 954e2d4 commit fbd2ab3

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

xmppserver/src/main/java/org/jivesoftware/openfire/XMPPServer.java

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2004-2008 Jive Software, 2016-2025 Ignite Realtime Foundation. All rights reserved.
2+
* Copyright (C) 2004-2008 Jive Software, 2016-2026 Ignite Realtime Foundation. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -77,6 +77,7 @@
7777
import org.xmpp.packet.JID;
7878
import org.xmpp.packet.Message;
7979

80+
import javax.annotation.Nonnull;
8081
import java.io.*;
8182
import java.lang.reflect.Field;
8283
import java.lang.reflect.Method;
@@ -132,7 +133,6 @@ public class XMPPServer {
132133
private boolean initialized = false;
133134
private boolean started = false;
134135
private NodeID nodeID;
135-
private static final NodeID DEFAULT_NODE_ID = NodeID.getInstance( UUID.randomUUID().toString().getBytes() );
136136

137137
private Timer terminatorTimer;
138138
public static final String EXIT = "exit";
@@ -142,7 +142,7 @@ public class XMPPServer {
142142
// Admin console network settings
143143
"adminConsole.port", "adminConsole.securePort", "adminConsole.interface", "network.interface",
144144
// Misc. settings
145-
"locale", "fqdn", "setup", ClusterManager.CLUSTER_PROPERTY_NAME,
145+
"locale", "fqdn", "setup", ClusterManager.CLUSTER_PROPERTY_NAME, ClusterManager.NODEID_PROPERTY_NAME,
146146
// Database config
147147
"connectionProvider.className",
148148
"database.defaultProvider.driver", "database.defaultProvider.serverURL", "database.defaultProvider.username",
@@ -263,35 +263,37 @@ public boolean isRemote( JID jid )
263263
}
264264

265265
/**
266-
* Returns an ID that uniquely identifies this server in a cluster. When not running in cluster mode
267-
* the returned value is always the same. However, when in cluster mode the value should be set
268-
* when joining the cluster and must be unique even upon restarts of this node.
266+
* Returns an ID that uniquely identifies this server in a cluster.
269267
*
270268
* @return an ID that uniquely identifies this server in a cluster.
271269
*/
270+
@Nonnull
272271
public NodeID getNodeID() {
273-
return nodeID == null ? DEFAULT_NODE_ID : nodeID;
272+
if (nodeID == null) {
273+
throw new IllegalStateException("Not initialized yet.");
274+
}
275+
return nodeID;
274276
}
275277

276278
/**
277-
* Sets an ID that uniquely identifies this server in a cluster. When not running in cluster mode
278-
* the returned value is always the same. However, when in cluster mode the value should be set
279-
* when joining the cluster and must be unique even upon restarts of this node.
279+
* Sets an ID that uniquely identifies this server in a cluster.
280280
*
281-
* @param nodeID an ID that uniquely identifies this server in a cluster or null if not in a cluster.
281+
* @param nodeID an ID that uniquely identifies this server in a cluster.
282282
*/
283-
public void setNodeID(NodeID nodeID) {
283+
public void setNodeID(@Nonnull final NodeID nodeID) {
284+
if (nodeID == null) {
285+
throw new IllegalStateException("Not initialized yet.");
286+
}
284287
this.nodeID = nodeID;
285288
}
286289

287290
/**
288-
* Returns the default node ID used by this server before clustering is
289-
* initialized.
290-
*
291-
* @return The default node ID.
291+
* @return The node ID.
292+
* @deprecated use {@link #getNodeID()} instead. In versions of Openfire prior to 4.4.0, the cluster node identifier of a server was changed when a server joined a cluster. That's no longer the case: a cluster node now has a static identifier. As such, it's no longer needed to distinguish between the 'default' nodeID (which was used when no cluster was joind) and the cluster node ID.
292293
*/
294+
@Deprecated(forRemoval = true, since = "5.1.0") // Remove in or after Openfire 5.2.0.
293295
public NodeID getDefaultNodeID() {
294-
return DEFAULT_NODE_ID;
296+
return getNodeID();
295297
}
296298

297299
/**
@@ -427,6 +429,8 @@ private void initialize() throws FileNotFoundException {
427429
JiveGlobals.setXMLProperty("fqdn", hostname);
428430
JiveGlobals.deleteProperty("xmpp.fqdn");
429431
}
432+
433+
initClusterNodeID();
430434
}
431435

432436
void runAutoSetup() {
@@ -567,6 +571,20 @@ void runAutoSetup() {
567571
setupMode = false;
568572
}
569573

574+
/**
575+
* Initialize the (supposedly unique) identifier of this server in a cluster of servers.
576+
*/
577+
private void initClusterNodeID()
578+
{
579+
final String staticNodeID = JiveGlobals.getXMLProperty(ClusterManager.NODEID_PROPERTY_NAME);
580+
if (staticNodeID != null) {
581+
nodeID = NodeID.getInstance(staticNodeID.getBytes());
582+
} else {
583+
nodeID = NodeID.getInstance( UUID.randomUUID().toString().getBytes() );
584+
JiveGlobals.setXMLProperty(ClusterManager.NODEID_PROPERTY_NAME, nodeID.toString());
585+
}
586+
}
587+
570588
private void finalSetupSteps() {
571589
for (String propName : JiveGlobals.getXMLPropertyNames()) {
572590
if (!XML_ONLY_PROPERTIES.contains(propName)) {

xmppserver/src/main/java/org/jivesoftware/openfire/cluster/ClusterManager.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C) 2005-2008 Jive Software, 2017-2025 Ignite Realtime Foundation. All rights reserved.
2+
* Copyright (C) 2005-2008 Jive Software, 2017-2026 Ignite Realtime Foundation. All rights reserved.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -55,6 +55,7 @@ public class ClusterManager {
5555
private static final Logger Log = LoggerFactory.getLogger(ClusterManager.class);
5656

5757
public static String CLUSTER_PROPERTY_NAME = "clustering.enabled";
58+
public static String NODEID_PROPERTY_NAME = "clustering.nodeid";
5859
private static Queue<Pair<Integer, ClusterEventListener>> listeners = new ConcurrentLinkedQueue<>();
5960
private static BlockingQueue<Event> events = new LinkedBlockingQueue<>(10000);
6061
private static Thread dispatcher;

0 commit comments

Comments
 (0)