com.pushtechnology.diffusion.client.features.control.RemoteServers Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2023 DiffusionData Ltd., All Rights Reserved.
*
* Use is subject to license terms.
*
* NOTICE: All information contained herein is, and remains the
* property of Push Technology. The intellectual and technical
* concepts contained herein are proprietary to Push Technology and
* may be covered by U.S. and Foreign Patents, patents in process, and
* are protected by trade secret or copyright law.
*******************************************************************************/
package com.pushtechnology.diffusion.client.features.control;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import com.pushtechnology.diffusion.client.Diffusion;
import com.pushtechnology.diffusion.client.features.ClusterRoutingException;
import com.pushtechnology.diffusion.client.features.ErrorReportsException;
import com.pushtechnology.diffusion.client.features.control.RemoteServers.RemoteServer.RemoteServerBuilder;
import com.pushtechnology.diffusion.client.features.control.topics.TopicControl.MissingTopicNotification;
import com.pushtechnology.diffusion.client.session.Feature;
import com.pushtechnology.diffusion.client.session.PermissionsException;
import com.pushtechnology.diffusion.client.session.Session;
import com.pushtechnology.diffusion.client.session.SessionAttributes;
import com.pushtechnology.diffusion.client.session.SessionClosedException;
import com.pushtechnology.diffusion.client.session.SessionException;
import com.pushtechnology.diffusion.client.topics.TopicSelector;
import com.pushtechnology.diffusion.client.types.Credentials;
import com.pushtechnology.diffusion.client.types.ErrorReport;
import com.pushtechnology.diffusion.client.types.GlobalPermission;
/**
* This feature allows a client session to manage remote servers.
*
* This feature provides the ability to configure the various modes of operation
* for the use of remote topic views. This is the ability for a topic view
* specification to indicate that the source topics for the view are to come
* from another server in a different Diffusion cluster. The server where the
* topic views are configured is referred to as the 'secondary server' and the
* server where the actual topics are is referred to as the 'primary server'.
*
*
Outbound Connection from the Secondary Server
*
* The typical configuration for a remote server is that there is only
* configuration at the secondary server (the configuration is automatically
* distributed to all members of the secondary cluster). In this case, each
* secondary server connects to a server in the primary cluster (typically via a
* load-balancer).
*
* Remote topic views can specify the use of such remote servers by name. The
* connection and disconnection is handled automatically by the server (or
* servers in the same cluster) where the remote servers are defined.
*
* A component can specify a remote server by name even if it does not exist
* (has not yet been created) and when the remote server is created the
* connection will take place automatically.
*
* If a remote server is removed and there are topic views that depend upon it,
* those topic views will be disabled.
*
* This form of connection is provided by a {@link RemoteServer} of type
* {@link RemoteServer.Type#SECONDARY_INITIATOR SECONDARY_INITIATOR} and
* represented by the sub-type {@link RemoteServers.SecondaryInitiator
* SecondaryInitiator}.
*
* Such a remote server can be built using an
* {@link RemoteServers.SecondaryInitiator.SecondaryInitiatorBuilder
* SecondaryInitiatorBuilder} created using
* {@link Diffusion#newRemoteServerBuilder(Class)}. It may then be added to the
* server (cluster) using {@link #createRemoteServer}.
*
* In this mode a connection from secondary to primary server is only maintained
* when there is a topic view that depends upon it. There will be no connections
* if there are no topic views that specify the remote server.
*
*
Outbound Connection from the Primary Server
*
* In some cases it may be preferred that the connection is initiated by the
* primary server, connecting to the secondary server cluster. In this case a
* single primary server will connect to all members of the secondary cluster.
*
* This form of connection is provided by a {@link RemoteServer} of type
* {@link RemoteServer.Type#PRIMARY_INITIATOR PRIMARY_INITIATOR} and represented
* by the sub-type {@link RemoteServers.PrimaryInitiator PrimaryInitiator}. This
* can be built using a
* {@link RemoteServers.PrimaryInitiator.PrimaryInitiatorBuilder
* PrimaryInitiatorBuilder} created using
* {@link Diffusion#newRemoteServerBuilder(Class)}. It may then be added to the
* primary server (cluster) using {@link #createRemoteServer}. Secondly a
* {@link RemoteServer} of type {@link RemoteServer.Type#SECONDARY_ACCEPTOR
* SECONDARY_ACCEPTOR} and represented by the sub-type
* {@link RemoteServers.SecondaryAcceptor SecondaryAcceptor} should be created
* in the secondary server (cluster) with the same name as the primary
* initiator. Such a remote server can be built using an
* {@link RemoteServers.SecondaryAcceptor.SecondaryAcceptorBuilder
* SecondaryAcceptorBuilder} created using
* {@link Diffusion#newRemoteServerBuilder(Class)}. It may then be added to the
* secondary server (cluster) using {@link #createRemoteServer}.
*
* Unlike the secondary initiator mode, this mode of connection will establish
* connections even if there are no topic views in the secondary server
* (cluster) that name the remote server. If the connection is lost any topic
* views that depend upon it will be disabled and the primary initiator will
* attempt to re-establish the connection(s). Topic views depending upon the
* remote server will only be enabled when the connection is re-established.
*
*
Remote Server persistence and replication
*
* Remote server configurations created through this feature are replicated
* across a cluster and persisted to disk.
*
*
Access control
*
* The following access control restrictions are applied:
*
*
* - To {@link #createRemoteServer create}, {@link #removeRemoteServer remove}
* or {@link #checkRemoteServer check} a remote server, a session needs the
* {@link GlobalPermission#CONTROL_SERVER CONTROL_SERVER} global permission. To
* {@link #listRemoteServers list} remote servers , a session needs the
* {@link GlobalPermission#VIEW_SERVER VIEW_SERVER} global permission.
*
*
*
* Accessing the feature
*
* This feature may be obtained from a {@link Session session} as follows:
*
*
* RemoteServers remoteServers = session.feature(RemoteServers.class);
*
*
* @author DiffusionData Limited
* @since 6.5
*/
public interface RemoteServers extends Feature {
/**
* Create a new remote server instance at the server.
*
* If a remote server with the same name already exists an error will be
* returned.
*
* @param remoteServer a remote server definition created using the
* appropriate sub-type of {@link RemoteServerBuilder}.
*
* @return a CompletableFuture that completes when a response is received
* from the server, returning a full definition of the remote server
* created by the operation. The returned object may need to be cast
* to the appropriate sub-type in order to obtain its full details.
*
*
* If the task fails, the CompletableFuture will complete
* exceptionally with a {@link CompletionException}. Common reasons
* for failure, listed by the exception reported as the
* {@link CompletionException#getCause() cause}, include:
*
*
* - {@link RemoteServerExistsException} – if a remote
* server with the given name already exists;
*
- {@link RemoteServerOptionsException} – if one or more
* connection options are invalid;
*
- {@link ClusterRoutingException} – if the operation
* failed due to a transient cluster error;
*
- {@link PermissionsException} – if the calling session
* does not have CONTROL_SERVER permission;
*
- {@link SessionClosedException} – if the session is
* closed.
*
*/
CompletableFuture createRemoteServer(
RemoteServer remoteServer);
/**
* Create a new remote server instance with default connection options.
*
* If a remote server with the same name already exists an error will be
* returned.
*
* @param name the name of the remote server
*
* @param url the URL to use to connect to the primary server
*
* @param principal the name of a principal used by the remote server to
* connect to the primary server. A zero length string may be
* supplied to indicate an anonymous connection
*
* @param credentials to use for connecting to the primary server
*
* @return a CompletableFuture that completes when a response is received
* from the server, returning a full definition of the remote server
* created by the operation.
*
*
* If the task fails, the CompletableFuture will complete
* exceptionally with a {@link CompletionException}. Common reasons
* for failure, listed by the exception reported as the
* {@link CompletionException#getCause() cause}, include:
*
*
* - {@link RemoteServerExistsException} – if a remote
* server with the given name already exists;
*
- {@link ClusterRoutingException} – if the operation
* failed due to a transient cluster error;
*
- {@link PermissionsException} – if the calling session
* does not have CONTROL_SERVER permission;
*
- {@link SessionClosedException} – if the session is
* closed.
*
*
* @deprecated since 6.7
*
* Use {@link #createRemoteServer(RemoteServer)} in preference.
* This method will be removed in a future release.
*/
@Deprecated
default CompletableFuture createRemoteServer(
String name,
String url,
String principal,
Credentials credentials) {
return createRemoteServer(
name,
url,
principal,
credentials,
Collections.emptyMap());
}
/**
* Create a new remote server instance.
*
* If a remote server with the same name already exists an error will be
* returned.
*
* @param name the name of the remote server
*
* @param url the URL to use to connect to the primary server
*
* @param principal the name of a principal used by the remote server to
* connect to the primary server. A zero length string may be
* supplied to indicate an anonymous connection
*
* @param credentials to use for connecting to the primary server
*
* @param connectionOptions a map of connection option settings. Any options
* not supplied will take their default values
*
* @return a CompletableFuture that completes when a response is received
* from the server, returning a full definition of the remote server
* created by the operation.
*
*
* If the task fails, the CompletableFuture will complete
* exceptionally with a {@link CompletionException}. Common reasons
* for failure, listed by the exception reported as the
* {@link CompletionException#getCause() cause}, include:
*
*
* - {@link RemoteServerExistsException} – if a remote
* server with the given name already exists;
*
- {@link RemoteServerOptionsException} – if one or more
* connection options are invalid;
*
- {@link ClusterRoutingException} – if the operation
* failed due to a transient cluster error;
*
- {@link PermissionsException} – if the calling session
* does not have CONTROL_SERVER permission;
*
- {@link SessionClosedException} – if the session is
* closed.
*
*
* @deprecated since 6.7
*
* Use {@link #createRemoteServer(RemoteServer)} in preference.
* This method will be removed in a future release.
*/
@Deprecated
CompletableFuture createRemoteServer(
String name,
String url,
String principal,
Credentials credentials,
Map connectionOptions);
/**
* List all the remote servers that have been created.
*
* @return a CompletableFuture that completes when a response is received
* from the server, returning a list of remote servers. The remote
* server objects may need to be cast to the appropriate sub-type in
* order to obtain all details.
*
*
* If the task fails, the CompletableFuture will complete
* exceptionally with a {@link CompletionException}. Common reasons
* for failure, listed by the exception reported as the
* {@link CompletionException#getCause() cause}, include:
*
*
* - {@link PermissionsException} – if the calling session
* does not have VIEW_SERVER permission;
*
- {@link SessionClosedException} – if the session is
* closed.
*
*/
CompletableFuture> listRemoteServers();
/**
* Check the current state of a named remote server.
*
* This will report back the current state of the remote server, but also
* can be used to forcibly retry a failed secondary initiator connection.
*
* Currently this only reports the state of the remote server at the server
* the session is connected to. In a cluster the state of the remote server
* on other cluster members is not reported.
*
* @param name the name of the remote server
*
* @return a CompletableFuture that completes when a response is received
* from the server, returning details of the remote server state.
*
*
* If the task fails, the CompletableFuture will complete
* exceptionally with a {@link CompletionException}. Common reasons
* for failure, listed by the exception reported as the
* {@link CompletionException#getCause() cause}, include:
*
*
* - {@link PermissionsException} – if the calling session
* does not have CONTROL_SERVER permission;
*
- {@link SessionClosedException} – if the session is
* closed.
*
*/
CompletableFuture checkRemoteServer(String name);
/**
* Remove a named remote server if it exists.
*
* If the named remote server does not exist the CompletableFuture will
* complete successfully.
*
* When a named remote server is removed, any topic views that specify it
* would be disabled.
*
* @param name the name of the remote server
*
* @return a CompletableFuture that completes when a response is received
* from the server.
*
*
* If the task fails, the CompletableFuture will complete
* exceptionally with a {@link CompletionException}. Common reasons
* for failure, listed by the exception reported as the
* {@link CompletionException#getCause() cause}, include:
*
*
* - {@link ClusterRoutingException} – if the operation
* failed due to a transient cluster error;
*
- {@link PermissionsException} – if the calling session
* does not have CONTROL_SERVER permission;
*
- {@link SessionClosedException} – if the session is
* closed.
*
*/
CompletableFuture removeRemoteServer(String name);
/**
* Base interface for a remote server definition.
*/
interface RemoteServer {
/**
* The remote server type.
*/
enum Type {
/**
* Secondary initiator remote server.
*
* Defined on secondary servers.
*
* This type will initiate connection from a secondary server
* (cluster) to a primary server (cluster member).
*/
SECONDARY_INITIATOR,
/**
* Primary initiator.
*
* Defined on primary servers.
*
* This type will connect to an inbound remote server of the same
* name configured at the secondary server (cluster).
*/
PRIMARY_INITIATOR,
/**
* Secondary acceptor remote server.
*
* Defined on secondary servers.
*
* This type will accept a primary remote server connection and
* support remote topic views.
*/
SECONDARY_ACCEPTOR
}
/**
* Returns the remote server type.
*
* A {@link RemoteServer} can be cast to the corresponding sub-type to
* access all methods, as follows:
*
*
*
* Type
* Type class
*
*
* {@link Type#SECONDARY_INITIATOR
* SECONDARY_INITIATOR}
* {@link SecondaryInitiator}
*
*
* {@link Type#PRIMARY_INITIATOR
* PRIMARY_INITIATOR}
* {@link PrimaryInitiator}
*
*
* {@link Type#SECONDARY_ACCEPTOR
* SECONDARY_ACCEPTOR}
* {@link SecondaryAcceptor}
*
*
*
* @return the remote server type.
*/
Type getType();
/**
* Return the remote server name.
*
* @return remote server name
*/
String getName();
/**
* Returns the url for connection to primary server.
*
* @deprecated since 6.9
*
* For backwards compatibility this method is retained for
* secondary initiator compatibility but will be removed at
* a future release.
*/
@Deprecated
String getUrl();
/**
* Return the principal used for the remote server connection.
*
* @deprecated since 6.9
*
* For backwards compatibility this method is retained for
* secondary initiator compatibility but will be removed at
* a future release.
*/
@Deprecated
String getPrincipal();
/**
* Return the remote server connection options.
*
* @deprecated since 6.9
*
* For backwards compatibility this method is retained for
* secondary initiator compatibility but will be removed at
* a future release.
*/
@Deprecated
Map getConnectionOptions();
/**
* Return the missing topic notification filter expression or null if
* one has not been specified.
*
* @deprecated since 6.9
*
* For backwards compatibility this method is retained for
* secondary initiator compatibility but will be removed at
* a future release.
*/
@Deprecated
String getMissingTopicNotificationFilter();
/**
* The base interface for all remote server builders.
*
* A builder of this type cannot be instantiated.
*
* @param the remote server type.
*/
interface RemoteServerBuilder {
/**
* Reset the builder to its default values.
*
* @return this Builder
*/
B reset();
}
/**
* A remote server builder.
*
* A builder of this type may be created using
* {@link Diffusion#newRemoteServerBuilder newRemoteServerBuilder} and
* used to create instances of {@link RemoteServer} that can be supplied
* to {@link RemoteServers#createRemoteServer(RemoteServer)
* createRemoteServer(RemoteServer)}.
*
* @since 6.7
*
* @deprecated since 6.9
*
* This builder is retained for backwards compatibility
* only. It can only be used to create a secondary
* initiator.
* {@link SecondaryInitiator.SecondaryInitiatorBuilder}
* should be used in preference. This builder will be
* removed in a future release.
*/
@Deprecated
interface Builder {
/**
* Specifies the name of a principal used by the remote server to
* connect to the primary server.
*
* The default, if not specified is the anonymous principal.
*
* @param principal principal name or a zero length string to
* indicate an anonymous connection
*
* @return this builder
*/
Builder principal(String principal);
/**
* Specifies the credentials to use when connecting to the primary
* server.
*
* The default, if not specified, is {@link Credentials.Type#NONE
* NONE}.
*
* @param credentials the credentials to use
*
* @return this builder
*/
Builder credentials(Credentials credentials);
/**
* Specifies a map of {@link ConnectionOption} settings.
*
* This will replace any options currently set for the builder.
*
* Any options not supplied will take their default values.
*
* If no connection options are specified, either using this method
* or {@link #connectionOption} then all options will take their
* default value.
*
* @param connectionOptions map of options
*
* @return this builder
*/
Builder connectionOptions(
Map connectionOptions);
/**
* Specifies a single connection option.
*
* This will add to the options currently specified to the builder,
* or replace a value if it has already been specified.
*
* @param connectionOption the connection option
*
* @param value the connection option value or null to remove the
* option
*
* @return this builder
*/
Builder connectionOption(
ConnectionOption connectionOption,
String value);
/**
* Specifies a topic selector expression which will filter missing
* topic notifications propagated from secondary to primary server.
*
* {@link MissingTopicNotification}s are notified when a client
* subscribes using a topic selector that matches no existing
* topics. By specifying a missing topic notification filter all
* notifications that match the filter on the secondary server will
* be propagated to the primary server.
*
* A match occurs if the path prefix of the subscription selector
* matches the path prefix of the specified selector. If the
* selector is a {@link TopicSelector#SELECTOR_SET_PREFIX selector
* set} then the notification will be propagated if it matches any
* selector in the set.
*
* If no filter is specified then no missing topic notifications
* will be propagated.
*
* The special selector expression "*.*" may be used to indicate
* that all missing topic notifications should be propagated.
*
* Only the path prefix of the specified selector(s) is considered
* when matching therefore any use of regular expressions would be
* ignored.
*
* @param filter a topic selector expression specifying the filter
* to apply or null to remove any existing filter
*
* @return this builder
*/
Builder missingTopicNotificationFilter(String filter);
/**
* Reset the builder.
*
* @return this Builder
*/
Builder reset();
/**
* Creates a remote server object using the current values known to
* this builder.
*
* @param name the name of the remote server
*
* @param url the URL to use to connect to the primary server
*
* @return a new remote server instance
*/
RemoteServer create(String name, String url);
}
/**
* Connection options for use with {@link SecondaryServer}s.
*/
enum ConnectionOption {
/**
* Specifies the reconnection timeout session attribute.
*
* This is the total time in milliseconds that will be allowed to
* reconnect a failed connection.
*
* For reconnection to work the remote server connector must have
* been configured to support reconnection.
*
* If a value is not specified
* {@link SessionAttributes#DEFAULT_RECONNECTION_TIMEOUT
* DEFAULT_RECONNECTION_TIMEOUT} is used.
*
* This value cannot be supplied for a
* {@link Type#SECONDARY_ACCEPTOR SECONDARY_ACCEPTOR} server.
*/
RECONNECTION_TIMEOUT,
/**
* Specifies the delay after losing a connection before attempting a
* reconnection.
*
* The value is specified in milliseconds. Default 1000 (1 second).
*
* This value cannot be supplied for a
* {@link Type#SECONDARY_ACCEPTOR SECONDARY_ACCEPTOR} server.
*/
RETRY_DELAY,
/**
* Specifies the recovery buffer size session attribute.
*
* If the remote server is configured to support reconnection, a
* session established with a non-zero reconnect-timeout retains a
* buffer of sent messages. If the session disconnects and
* reconnects, this buffer is used to re-send messages that the
* server has not received.
*
* The default value is 10,000 messages. If reconnect-timeout is 0
* then this value is ignored.
*
* This value cannot be supplied for a
* {@link Type#SECONDARY_ACCEPTOR SECONDARY_ACCEPTOR} server.
*/
RECOVERY_BUFFER_SIZE,
/**
* Specifies the input buffer size session attribute.
*
* This is the size of the input buffer to use for the connection
* with the remote server. It is used to receive messages from the
* remote server. This should be set to the same size as the output
* buffer used at the remote server.
*
* If not specified, a default of 1024k is used.
*/
INPUT_BUFFER_SIZE,
/**
* Specifies the output buffer size session attribute.
*
* This is the size of the output buffer to use for the connection
* with the remote server. It is used to send messages to the remote
* server. This should be set to the same size as the input buffer
* used by the remote server.
*
* If not specified, a default of 1024k is used.
*/
OUTPUT_BUFFER_SIZE,
/**
* Specifies the maximum queue size session attribute.
*
* This is the maximum number of messages that can be queued to send
* to the remote server. If this number is exceeded, the connection
* will be closed. This must be sufficient to cater for messages
* that may be queued whilst disconnected (awaiting reconnect).
*
* The default value is 10,000 messages.
*/
MAXIMUM_QUEUE_SIZE,
/**
* Specifies the connection timeout session attribute value (in
* milliseconds).
*
* If a value is not specified
* {@link SessionAttributes#DEFAULT_CONNECTION_TIMEOUT
* DEFAULT_CONNECTION_TIMEOUT} is used.
*/
CONNECTION_TIMEOUT,
/**
* Specifies the write timeout session attribute value (in
* milliseconds).
*
* If a value is not specified
* {@link SessionAttributes#DEFAULT_WRITE_TIMEOUT
* DEFAULT_WRITE_TIMEOUT} is used.
*/
WRITE_TIMEOUT;
}
}
/**
* A primary initiator.
*
* This type makes a connection from a primary server (cluster) to a
* secondary server (or all secondary cluster members) with an
* {@link SecondaryAcceptor} of the same name.
*
* Use a {@link PrimaryInitiatorBuilder} to create an instance of this type.
*/
interface PrimaryInitiator extends RemoteServer {
/**
* Returns the urls for connection to secondary servers.
*
* @return the list of urls for connection to secondary servers
*/
List getUrls();
/**
* Returns the connector that the primary initiator will use to
* establish a connection between the secondary server and the primary
* server.
*
* @return the connector name
*/
String getConnector();
/**
* Returns the interval in milliseconds between connection retries.
*
* If a primary initiator cannot connect to a secondary server, or loses
* the connection, this is the amount of time before it will try to
* connect again.
*
* @return the retry delay time in milliseconds
*/
int getRetryDelay();
/**
* Builder for a {@link PrimaryInitiator}.
*
* A builder of this type may be created using
* {@link Diffusion#newRemoteServerBuilder(Class)} specifying
* {@code PrimaryInitiatorBuilder.class} as the parameter.
*/
interface PrimaryInitiatorBuilder
extends RemoteServerBuilder {
/**
* Specifies the delay after losing a connection before attempting a
* reconnection.
*
* The value is specified in milliseconds. Default 1000 (1 second).
*/
PrimaryInitiatorBuilder retryDelay(int delay);
/**
* Builds a primary initiator using the current values known to this
* builder.
*
* @param name the name of the primary initiator which must
* correspond too the name of an {@link SecondaryAcceptor}
* defined on the secondary server
*
* @param urls the list of URLs to use to initiate connections to
* the secondary servers
*
* @param connector the name of the connector used to establish the
* connection with the secondary server
*
* @return a new primary initiator instance
*/
PrimaryInitiator build(
String name,
List urls,
String connector);
}
}
/**
* Base interface for a secondary remote server.
*/
interface SecondaryServer extends RemoteServer {
/**
* Return the principal used for the connection.
*
* This is used to authenticate the connection at the primary server.
*
* @return the principal
*/
@Override
String getPrincipal();
/**
* Return the remote server connection options.
*
* @return the connection options
*/
@Override
Map getConnectionOptions();
/**
* Return the missing topic notification filter expression.
*
* @return missing topic notification filter, or null if one has not
* been specified
*/
@Override
String getMissingTopicNotificationFilter();
/**
* Base builder interface for {@link SecondaryServer}.
*
* A builder of this type cannot be instantiated.
*
* @param the builder type
*/
interface SecondaryBuilder
extends RemoteServerBuilder {
/**
* Specifies the name of a principal to use to use for the
* connection.
*
* This specifies the principal for the connection to the primary
* server and is authenticated at the primary.
*
* The default, if not specified is the anonymous principal.
*
* @param principal principal name or a zero length string to
* indicate an anonymous connection
*
* @return this builder
*/
B principal(String principal);
/**
* Specifies the credentials to use to authenticate the connection.
*
* The default, if not specified, is {@link Credentials.Type#NONE
* NONE}.
*
* This is used along with the specified principal.
*
* @param credentials the credentials to use
*
* @return this builder
*
* @see #principal
*/
B credentials(Credentials credentials);
/**
* Specifies a map of {@link ConnectionOption} settings.
*
* This will replace any options currently set for the builder.
*
* Any options not supplied will take their default values.
*
* If no connection options are specified, either using this method
* or {@link #connectionOption} then all options will take their
* default value.
*
* Not all remote server types support all options. See
* {@link ConnectionOption} for details.
*
* @param connectionOptions map of options
*
* @return this builder
*
* @see #connectionOption
*/
B connectionOptions(
Map connectionOptions);
/**
* Specifies a single connection option.
*
* This will add to the options currently specified to the builder,
* or replace a value if it has already been specified.
*
* Not all remote server types support all options. See
* {@link ConnectionOption} for details.
*
* @param connectionOption the connection option
*
* @param value the connection option value or null to remove the
* option
*
* @return this builder
*/
B connectionOption(
ConnectionOption connectionOption,
String value);
/**
* Specifies a topic selector expression which will filter missing
* topic notifications propagated from secondary to primary server.
*
* {@link MissingTopicNotification}s are notified when a client
* subscribes using a topic selector that matches no existing
* topics. By specifying a missing topic notification filter all
* notifications that match the filter on the secondary server will
* be propagated to the primary server.
*
* A match occurs if the path prefix of the subscription selector
* matches the path prefix of the specified selector. If the
* selector is a {@link TopicSelector#SELECTOR_SET_PREFIX selector
* set} then the notification will be propagated if it matches any
* selector in the set.
*
* If no filter is specified then no missing topic notifications
* will be propagated.
*
* The special selector expression "*.*" may be used to indicate
* that all missing topic notifications should be propagated.
*
* Only the path prefix of the specified selector(s) is considered
* when matching therefore any use of regular expressions would be
* ignored.
*
* @param filter a topic selector expression specifying the filter
* to apply or null to remove any existing filter
*
* @return this builder
*/
B missingTopicNotificationFilter(String filter);
}
}
/**
* Secondary remote server that initiates a connection to a primary server.
*
* This type makes a connection from a secondary server (or each secondary
* cluster member) to a primary server. No remote server definition is
* required at the primary server.
*
* Use an {@link SecondaryInitiatorBuilder} to create an instance of this
* type.
*/
interface SecondaryInitiator extends SecondaryServer {
/**
* Builder for an {@link SecondaryInitiator}.
*
* A builder of this type may be created using
* {@link Diffusion#newRemoteServerBuilder(Class)} specifying
* {@code SecondaryInitiatorBuilder.class} as the parameter.
*/
interface SecondaryInitiatorBuilder
extends SecondaryBuilder {
/**
* Builds a secondary initiator instance using the current values
* known to this builder.
*
* @param name the remote server name. This is the name that will be
* specified in topic views
*
* @param url the URL to use to connect to the primary server
*
* @return a new secondary initiator instance
*/
SecondaryInitiator build(String name, String url);
}
/**
* Returns the url for connection to primary server.
*
* @return the primary server (cluster) url
*/
@Override
String getUrl();
}
/**
* Secondary remote server that accepts a connection from a primary server.
*
* This type accepts a connection from a {@link PrimaryInitiator} with the
* same name configured at the primary server (cluster).
*
* Use an {@link SecondaryAcceptorBuilder} to create an instance of this
* type.
*/
interface SecondaryAcceptor extends SecondaryServer {
/**
* Builder for a {@link SecondaryAcceptor}.
*
* A builder of this type may be created using
* {@link Diffusion#newRemoteServerBuilder(Class)} specifying
* {@code SecondaryAcceptorBuilder.class} as the parameter.
*/
interface SecondaryAcceptorBuilder
extends SecondaryBuilder {
/**
* Builds a secondary acceptor using the current values known to
* this builder.
*
* @param name the remote server name. A primary initiator of the
* same name will be able to connect to this acceptor. This
* is the name that will be specified in topic views
*
* @param primaryHostName the primary server host name that will be
* used in SSL validation of the primary server
*
* @return a new secondary acceptor instance
*/
SecondaryAcceptor build(String name, String primaryHostName);
}
/**
* Returns the primary server host name used in SSL validation.
*
* @return the primary server host name
*/
String getPrimaryHostName();
}
/**
* Result returned from a {@link #checkRemoteServer} invocation.
*/
interface CheckRemoteServerResult {
/**
* Represents the current connection state of the remote server.
*/
enum ConnectionState {
/**
* The connection is inactive.
*
* This is the initial state for all types.
*
* For a {@link SecondaryInitiator} this could also mean that the
* remote server can successfully connect but a physical connection
* is not being maintained as there are no components that require
* the remote server.
*
* If in an inactive or failed state, a test connection will have
* been tried to check that the connection can be made and the
* connection will then have been closed.
*/
INACTIVE,
/**
* The remote server is connected.
*
* For a {@link SecondaryInitiator} this means that there are
* components actually using it.
*
* A {@link SecondaryAcceptor} can be in this state even if there
* are no components using it as a reverse connection is always
* maintained.
*
* A {@link PrimaryInitiator} will only be in this state if it has
* a successful connection to all secondary acceptors configured for
* it. If any secondary acceptor connection has failed then it will
* be in a FAILED state even if there are some active connections.
*/
CONNECTED,
/**
* The connection has failed but is retrying.
*
* In this case {@link CheckRemoteServerResult#getFailureMessage}
* will provide details of the failure that resulted in a retry.
*/
RETRYING,
/**
* The connection has failed.
*
* If the connection was in an inactive or failed state state, a
* test connection was tried and failed.
*
* In this case {@link CheckRemoteServerResult#getFailureMessage}
* will provide more detail.
*/
FAILED,
/**
* The named remote server did not exist.
*/
MISSING
}
/**
* Returns the connection state of the remote server.
*
* @return the connection state
*/
ConnectionState getConnectionState();
/**
* Returns a failure message when the state returned is
* {@link ConnectionState#FAILED} or {@link ConnectionState#RETRYING}.
*
* For other states this will return an empty string.
*
* @return the failure message, if there is one, otherwise an empty
* string
*/
String getFailureMessage();
}
/**
* Exception thrown when an attempt has been made to create a remote server
* when one with the same name is already defined.
*/
final class RemoteServerExistsException extends SessionException {
private static final long serialVersionUID = 4675880972876068202L;
/**
* Constructor.
*/
public RemoteServerExistsException(String message) {
super(message);
}
}
/**
* Exception thrown when one or more of the options specified when creating
* a remote server have been found to be invalid.
*/
final class RemoteServerOptionsException extends ErrorReportsException {
private static final long serialVersionUID = 6069777787663040691L;
/**
* Constructor.
*/
public RemoteServerOptionsException(
String message,
List reports) {
super(message, reports);
}
}
}