SessionBuilder.java
package fr.sii.ogham.sms.builder.cloudhopper;
import com.cloudhopper.smpp.pdu.EnquireLink;
import fr.sii.ogham.core.builder.Builder;
import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilder;
import fr.sii.ogham.core.builder.configuration.ConfigurationValueBuilderHelper;
import fr.sii.ogham.core.builder.configurer.Configurer;
import fr.sii.ogham.core.builder.context.BuildContext;
import fr.sii.ogham.core.builder.env.EnvironmentBuilder;
import fr.sii.ogham.core.builder.retry.RetryBuilder;
import fr.sii.ogham.core.fluent.AbstractParent;
import fr.sii.ogham.core.retry.FixedDelayRetry;
import fr.sii.ogham.sms.sender.impl.cloudhopper.KeepAliveOptions;
import fr.sii.ogham.sms.sender.impl.cloudhopper.ReuseSessionOptions;
/**
* Configures Cloudhopper session management (timeouts, retry, session name...).
*
* @author Aurélien Baudet
*
*/
public class SessionBuilder extends AbstractParent<CloudhopperBuilder> implements Builder<CloudhopperSessionOptions> {
private final BuildContext buildContext;
private final ConfigurationValueBuilderHelper<SessionBuilder, Long> bindValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, Long> connectValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, Long> requestExpiryValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, Long> windowMonitorInvervalValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, Long> windowWaitValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, Integer> windowSizeValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, Long> writeValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, Long> responseValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, Long> unbindValueBuilder;
private final ConfigurationValueBuilderHelper<SessionBuilder, String> sessionNameValueBuilder;
private RetryBuilder<SessionBuilder> connectRetryBuilder;
private ReuseSessionBuilder reuseSessionBuilder;
private KeepAliveBuilder keepAliveBuilder;
/**
* Initializes the builder with a parent builder. The parent builder is used
* when calling {@link #and()} method. The {@link EnvironmentBuilder} is
* used to evaluate properties when {@link #build()} method is called.
*
* @param parent
* the parent builder
* @param buildContext
* for registering instances and property evaluation
*/
public SessionBuilder(CloudhopperBuilder parent, BuildContext buildContext) {
super(parent);
this.buildContext = buildContext;
bindValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
connectValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
requestExpiryValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
windowMonitorInvervalValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
windowWaitValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
windowSizeValueBuilder = buildContext.newConfigurationValueBuilder(this, Integer.class);
writeValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
responseValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
unbindValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
sessionNameValueBuilder = buildContext.newConfigurationValueBuilder(this, String.class);
}
/**
* A name for the session (used to name threads).
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #sessionName()}.
*
* <pre>
* .sessionName("my-name")
* .sessionName()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue("default-name")
* </pre>
*
* <pre>
* .sessionName("my-name")
* .sessionName()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue("default-name")
* </pre>
*
* In both cases, {@code sessionName("my-name")} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param name
* the name for the session
* @return this instance for fluent chaining
*/
public SessionBuilder sessionName(String name) {
sessionNameValueBuilder.setValue(name);
return this;
}
/**
* A name for the session (used to name threads).
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .sessionName()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue("default-name")
* </pre>
*
* <p>
* Non-null value set using {@link #sessionName(String)} takes precedence
* over property values and default value.
*
* <pre>
* .sessionName("my-name")
* .sessionName()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue("default-name")
* </pre>
*
* The value {@code "my-name"} is used regardless of the value of the
* properties and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, String> sessionName() {
return sessionNameValueBuilder;
}
/**
* Set the maximum amount of time (in milliseconds) to wait for the success
* of a bind attempt to the SMSC. Defaults to 5000.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #bindTimeout()}.
*
* <pre>
* .bindTimeout(1000L)
* .bindTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <pre>
* .bindTimeout(1000L)
* .bindTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* In both cases, {@code bindTimeout(1000L)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param timeout
* the timeout value in milliseconds
* @return this instance for fluent chaining
*/
public SessionBuilder bindTimeout(Long timeout) {
bindValueBuilder.setValue(timeout);
return this;
}
/**
* Set the maximum amount of time (in milliseconds) to wait for the success
* of a bind attempt to the SMSC. Defaults to 5000.
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .bindTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <p>
* Non-null value set using {@link #bindTimeout(Long)} takes precedence over
* property values and default value.
*
* <pre>
* .bindTimeout(1000L)
* .bindTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* The value {@code 1000L} is used regardless of the value of the properties
* and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Long> bindTimeout() {
return bindValueBuilder;
}
/**
* Set the maximum amount of time (in milliseconds) to wait for a
* establishing the connection. Defaults to 10000.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #connectTimeout()}.
*
* <pre>
* .connectTimeout(1000L)
* .connectTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <pre>
* .connectTimeout(1000L)
* .connectTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* In both cases, {@code connectTimeout(1000L)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param timeout
* the timeout in milliseconds
* @return this instance for fluent chaining
*/
public SessionBuilder connectTimeout(Long timeout) {
connectValueBuilder.setValue(timeout);
return this;
}
/**
* Set the maximum amount of time (in milliseconds) to wait for a
* establishing the connection. Defaults to 10000.
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .connectTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <p>
* Non-null value set using {@link #connectTimeout(Long)} takes precedence
* over property values and default value.
*
* <pre>
* .connectTimeout(1000L)
* .connectTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* The value {@code 1000L} is used regardless of the value of the properties
* and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Long> connectTimeout() {
return connectValueBuilder;
}
/**
* Configures how to handle a connection that fails. You can configure if
* retry should be done when a connection to the server couldn't be
* established. The builder lets you define the retry behavior.
*
* For now, only a {@link FixedDelayRetry} is handled. The
* {@link FixedDelayRetry} needs a delay between two tries and a maximum
* attempts. In the future, we could handle different strategies if needed
* like retrying with an exponential delay for example.
*
* If you don't configure it, no retry is applied at all.
*
* @return the builder to configure the retry handling
*/
public RetryBuilder<SessionBuilder> connectRetry() {
if (connectRetryBuilder == null) {
connectRetryBuilder = new RetryBuilder<>(this, buildContext);
}
return connectRetryBuilder;
}
/**
* Set the amount of time (milliseconds) to wait for an endpoint to respond
* to a request before it expires. Defaults to disabled (-1).
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #requestExpiryTimeout()}.
*
* <pre>
* .requestExpiryTimeout(1000L)
* .requestExpiryTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(-1L)
* </pre>
*
* <pre>
* .requestExpiryTimeout(1000L)
* .requestExpiryTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(-1L)
* </pre>
*
* In both cases, {@code requestExpiryTimeout(1000L)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param timeout
* the timeout in milliseconds
* @return this instance for fluent chaining
*/
public SessionBuilder requestExpiryTimeout(Long timeout) {
requestExpiryValueBuilder.setValue(timeout);
return this;
}
/**
* Set the amount of time (milliseconds) to wait for an endpoint to respond
* to a request before it expires. Defaults to disabled (-1).
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .requestExpiryTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(-1L)
* </pre>
*
* <p>
* Non-null value set using {@link #requestExpiryTimeout(Long)} takes
* precedence over property values and default value.
*
* <pre>
* .requestExpiryTimeout(1000L)
* .requestExpiryTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(-1L)
* </pre>
*
* The value {@code 1000L} is used regardless of the value of the properties
* and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Long> requestExpiryTimeout() {
return requestExpiryValueBuilder;
}
/**
* Sets the amount of time (milliseconds) between executions of monitoring
* the window for requests that expire. It's recommended that this generally
* either matches or is half the value of requestExpiryTimeout. Therefore,
* at worst a request would could take up 1.5X the requestExpiryTimeout to
* clear out. Defaults to -1 (disabled).
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #windowMonitorInterval()}.
*
* <pre>
* .windowMonitorInterval(1000L)
* .windowMonitorInterval()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(-1L)
* </pre>
*
* <pre>
* .windowMonitorInterval(1000L)
* .windowMonitorInterval()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(-1L)
* </pre>
*
* In both cases, {@code windowMonitorInterval(1000L)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param timeout
* the tiemout in milliseconds
* @return this instance for fluent chaining
*/
public SessionBuilder windowMonitorInterval(Long timeout) {
windowMonitorInvervalValueBuilder.setValue(timeout);
return this;
}
/**
* Sets the amount of time (milliseconds) between executions of monitoring
* the window for requests that expire. It's recommended that this generally
* either matches or is half the value of requestExpiryTimeout. Therefore,
* at worst a request would could take up 1.5X the requestExpiryTimeout to
* clear out. Defaults to -1 (disabled).
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .windowMonitorInterval()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(-1L)
* </pre>
*
* <p>
* Non-null value set using {@link #windowMonitorInterval(Long)} takes
* precedence over property values and default value.
*
* <pre>
* .windowMonitorInterval(1000L)
* .windowMonitorInterval()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(-1L)
* </pre>
*
* The value {@code 1000L} is used regardless of the value of the properties
* and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Long> windowMonitorInterval() {
return windowMonitorInvervalValueBuilder;
}
/**
* Sets the maximum number of requests permitted to be outstanding
* (unacknowledged) at a given time. Must be > 0. Defaults to 1.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #windowSize()}.
*
* <pre>
* .windowSize(5)
* .windowSize()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(1)
* </pre>
*
* <pre>
* .windowSize(5)
* .windowSize()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(1)
* </pre>
*
* In both cases, {@code windowSize(5)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param size
* the window size
* @return this instance for fluent chaining
*/
public SessionBuilder windowSize(Integer size) {
windowSizeValueBuilder.setValue(size);
return this;
}
/**
* Sets the maximum number of requests permitted to be outstanding
* (unacknowledged) at a given time. Must be > 0. Defaults to 1.
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .windowSize()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(1)
* </pre>
*
* <p>
* Non-null value set using {@link #windowSize(Integer)} takes precedence
* over property values and default value.
*
* <pre>
* .windowSize(5)
* .windowSize()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(1)
* </pre>
*
* The value {@code 5} is used regardless of the value of the properties and
* default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Integer> windowSize() {
return windowSizeValueBuilder;
}
/**
* Set the amount of time (milliseconds) to wait until a slot opens up in
* the sendWindow. Defaults to 60000.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #windowWait()}.
*
* <pre>
* .windowWait(10000L)
* .windowWait()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(60000L)
* </pre>
*
* <pre>
* .windowWait(10000L)
* .windowWait()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(60000L)
* </pre>
*
* In both cases, {@code windowWait(10000L)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param duration
* the amount of time in milliseconds to wait until a slot opens
* up
* @return this instance for fluent chaining
*/
public SessionBuilder windowWait(Long duration) {
windowWaitValueBuilder.setValue(duration);
return this;
}
/**
* Set the amount of time (milliseconds) to wait until a slot opens up in
* the sendWindow. Defaults to 60000.
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .windowWait()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(60000L)
* </pre>
*
* <p>
* Non-null value set using {@link #windowWait(Long)} takes precedence over
* property values and default value.
*
* <pre>
* .windowWait(10000L)
* .windowWait()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(60000L)
* </pre>
*
* The value {@code 10000L} is used regardless of the value of the
* properties and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Long> windowWait() {
return windowWaitValueBuilder;
}
/**
* Set the maximum amount of time (in milliseconds) to wait for bytes to be
* written when creating a new SMPP session. Defaults to 0 (no timeout, for
* backwards compatibility).
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #writeTimeout()}.
*
* <pre>
* .writeTimeout(10000L)
* .writeTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <pre>
* .writeTimeout(10000L)
* .writeTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* In both cases, {@code writeTimeout(10000L)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param timeout
* the timeout in milliseconds
* @return this instance for fluent chaining
*/
public SessionBuilder writeTimeout(Long timeout) {
writeValueBuilder.setValue(timeout);
return this;
}
/**
* Set the maximum amount of time (in milliseconds) to wait for bytes to be
* written when creating a new SMPP session. Defaults to 0 (no timeout, for
* backwards compatibility).
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .writeTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <p>
* Non-null value set using {@link #writeTimeout(Long)} takes precedence
* over property values and default value.
*
* <pre>
* .writeTimeout(10000L)
* .writeTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* The value {@code 10000L} is used regardless of the value of the
* properties and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Long> writeTimeout() {
return writeValueBuilder;
}
/**
* Set the maximum amount of time (in milliseconds) to wait until a valid
* response is received when a "submit" request is synchronously sends to
* the remote endpoint. The timeout value includes both waiting for a
* "window" slot, the time it takes to transmit the actual bytes on the
* socket, and for the remote endpoint to send a response back. Defaults to
* 5000.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #responseTimeout()}.
*
* <pre>
* .responseTimeout(1000L)
* .responseTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <pre>
* .responseTimeout(1000L)
* .responseTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* In both cases, {@code responseTimeout(1000L)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param timeout
* the timeout in milliseconds
* @return this instance for fluent chaining
*/
public SessionBuilder responseTimeout(Long timeout) {
responseValueBuilder.setValue(timeout);
return this;
}
/**
* Set the maximum amount of time (in milliseconds) to wait until a valid
* response is received when a "submit" request is synchronously sends to
* the remote endpoint. The timeout value includes both waiting for a
* "window" slot, the time it takes to transmit the actual bytes on the
* socket, and for the remote endpoint to send a response back. Defaults to
* 5000.
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .responseTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <p>
* Non-null value set using {@link #responseTimeout(Long)} takes precedence
* over property values and default value.
*
* <pre>
* .responseTimeout(1000L)
* .responseTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* The value {@code 1000L} is used regardless of the value of the properties
* and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Long> responseTimeout() {
return responseValueBuilder;
}
/**
* Set the maximum amount of time (in milliseconds) to wait until the
* session is unbounded, waiting up to a specified period of milliseconds
* for an unbind response from the remote endpoint. Regardless of whether a
* proper unbind response was received, the socket/channel is closed.
* Defaults to 5000.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #unbindTimeout()}.
*
* <pre>
* .unbindTimeout(10000L)
* .unbindTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <pre>
* .unbindTimeout(10000L)
* .unbindTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* In both cases, {@code unbindTimeout(10000L)} is used.
*
* <p>
* If this method is called several times, only the last value is used.
*
* <p>
* If {@code null} value is set, it is like not setting a value at all. The
* property/default value configuration is applied.
*
* @param timeout
* the timeout in milliseconds
* @return this instance for fluent chaining
*/
public SessionBuilder unbindTimeout(Long timeout) {
unbindValueBuilder.setValue(timeout);
return this;
}
/**
* Set the maximum amount of time (in milliseconds) to wait until the
* session is unbounded, waiting up to a specified period of milliseconds
* for an unbind response from the remote endpoint. Regardless of whether a
* proper unbind response was received, the socket/channel is closed.
* Defaults to 5000.
*
* <p>
* This method is mainly used by {@link Configurer}s to register some
* property keys and/or a default value. The aim is to let developer be able
* to externalize its configuration (using system properties, configuration
* file or anything else). If the developer doesn't configure any value for
* the registered properties, the default value is used (if set).
*
* <pre>
* .unbindTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <p>
* Non-null value set using {@link #unbindTimeout(Long)} takes precedence
* over property values and default value.
*
* <pre>
* .unbindTimeout(10000L)
* .unbindTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* The value {@code 10000L} is used regardless of the value of the
* properties and default value.
*
* <p>
* See {@link ConfigurationValueBuilder} for more information.
*
*
* @return the builder to configure property keys/default value
*/
public ConfigurationValueBuilder<SessionBuilder, Long> unbindTimeout() {
return unbindValueBuilder;
}
/**
* Reuse the previous session instead of closing and reopening one if
* possible. However, if the session has been closed by the remote server, a
* new session will be created.
*
* <p>
* When sending the first message, a new session is created. Later, when
* sending the next message, if the session is still alive, this session is
* reused. As the connection is not actively maintained, the session may be
* killed by the server. Therefore to check if the session is still alive,
* an {@link EnquireLink} request is sent. If a response is received from
* the server, then the session is still alive and the message can be sent
* using the same session. If a failure response or no response is received
* after some time from the server, then a new session must be created.
*
*
* <p>
* To check if the session is still alive, the {@link EnquireLink} request
* is sent just before sending the real message. In order to prevent sending
* an {@link EnquireLink} request before <strong>every</strong> message, the
* date of the last sent message or {@link EnquireLink} is kept. This date
* is compared to a delay to ensure that no {@link EnquireLink} is sent
* during this delay.
*
* <p>
* This builder let you configure:
* <ul>
* <li>Enable/disable reuse session management</li>
* <li>The maximum time to wait for a response from the server for
* {@link EnquireLink} request</li>
* <li>The time to wait before sending a new {@link EnquireLink} request
* again</li>
* </ul>
*
* <p>
* <strong>NOTE:</strong> If {@link #keepAlive()} strategy is enabled, this
* option has no effect.
*
* @return the builder to configure reuse session strategy
*/
public ReuseSessionBuilder reuseSession() {
if (reuseSessionBuilder == null) {
reuseSessionBuilder = new ReuseSessionBuilder(this, buildContext);
}
return reuseSessionBuilder;
}
/**
* Configure keep alive management. Keep alive strategy actively maintains
* the session opened by sending {@link EnquireLink} messages to the server.
*
* <p>
* Even if client sends messages to keep session alive, the connection may
* be broken or closed by the server. Therefore, automatic reconnection is
* done.
*
* <p>
* This builder let you configure:
* <ul>
* <li>Enable/disable active keep alive management</li>
* <li>The time to wait between two {@link EnquireLink} messages</li>
* <li>The maximum time to wait for a response from the server for
* {@link EnquireLink} request</li>
* </ul>
*
* <strong>NOTE:</strong> If this strategy is enabled,
* {@link #reuseSession()} has no effect.
*
* @return the builder to configure keep alive management
*/
public KeepAliveBuilder keepAlive() {
if (keepAliveBuilder == null) {
keepAliveBuilder = new KeepAliveBuilder(this, buildContext);
}
return keepAliveBuilder;
}
@Override
public CloudhopperSessionOptions build() {
CloudhopperSessionOptions sessionOpts = buildContext.register(new CloudhopperSessionOptions());
sessionOpts.setBindTimeout(bindValueBuilder.getValue());
sessionOpts.setConnectTimeout(connectValueBuilder.getValue());
sessionOpts.setRequestExpiryTimeout(requestExpiryValueBuilder.getValue());
sessionOpts.setWindowMonitorInterval(windowMonitorInvervalValueBuilder.getValue());
sessionOpts.setWindowSize(windowSizeValueBuilder.getValue());
sessionOpts.setWindowWaitTimeout(windowWaitValueBuilder.getValue());
sessionOpts.setWriteTimeout(writeValueBuilder.getValue());
sessionOpts.setResponseTimeout(responseValueBuilder.getValue());
sessionOpts.setUnbindTimeout(unbindValueBuilder.getValue());
if (connectRetryBuilder != null) {
sessionOpts.setConnectRetry(connectRetryBuilder.build());
}
sessionOpts.setKeepAlive(keepAliveBuilder != null ? keepAliveBuilder.build() : new KeepAliveOptions(false));
sessionOpts.setReuseSession(reuseSessionBuilder != null ? reuseSessionBuilder.build() : new ReuseSessionOptions(false));
return sessionOpts;
}
}