ReuseSessionBuilder.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.fluent.AbstractParent;
import fr.sii.ogham.sms.sender.impl.cloudhopper.ReuseSessionOptions;
/**
* Builder to configure how reuse session management should behave.
*
* <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>
*
* @author Aurélien Baudet
*
*/
public class ReuseSessionBuilder extends AbstractParent<SessionBuilder> implements Builder<ReuseSessionOptions> {
private final ConfigurationValueBuilderHelper<ReuseSessionBuilder, Boolean> enableValueBuilder;
private final ConfigurationValueBuilderHelper<ReuseSessionBuilder, Long> lastInteractionExpirationDelayValueBuilder;
private final ConfigurationValueBuilderHelper<ReuseSessionBuilder, Long> enquireLinkTimeoutValueBuilder;
public ReuseSessionBuilder(SessionBuilder parent, BuildContext buildContext) {
super(parent);
this.enableValueBuilder = buildContext.newConfigurationValueBuilder(this, Boolean.class);
this.lastInteractionExpirationDelayValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
this.enquireLinkTimeoutValueBuilder = buildContext.newConfigurationValueBuilder(this, Long.class);
}
/**
* Enable or disable the reuse the same session (if possible) for sending
* messages.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #enable()}.
*
* <pre>
* .enable(true)
* .enable()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(false)
* </pre>
*
* <pre>
* .enable(true)
* .enable()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(false)
* </pre>
*
* In both cases, {@code enable(true)} 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 enable
* enable reuse of same session
* @return this instance for fluent chaining
*/
public ReuseSessionBuilder enable(Boolean enable) {
enableValueBuilder.setValue(enable);
return this;
}
/**
* Enable or disable the reuse the same session (if possible) for sending
* messages.
*
* <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>
* .enable()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(false)
* </pre>
*
* <p>
* Non-null value set using {@link #enable(Boolean)} takes precedence over
* property values and default value.
*
* <pre>
* .enable(true)
* .enable()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(false)
* </pre>
*
* The value {@code true} 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<ReuseSessionBuilder, Boolean> enable() {
return enableValueBuilder;
}
/**
* To check if the session is still alive, an {@link EnquireLink} request is
* sent. This request may fail since the session may be killed by the
* server. The timeout ensures that the client doesn't wait too long for a
* response that may never come.
*
* The maximum amount of time (in milliseconds) to wait for receiving a
* response from the server to an {@link EnquireLink} request.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #responseTimeout()}.
*
* <pre>
* .responseTimeout(10000L)
* .responseTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* <pre>
* .responseTimeout(10000L)
* .responseTimeout()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(5000L)
* </pre>
*
* In both cases, {@code responseTimeout(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 maximum amount of time (in milliseconds) to wait for the
* response
* @return this instance for fluent chaining
*/
public ReuseSessionBuilder responseTimeout(Long timeout) {
enquireLinkTimeoutValueBuilder.setValue(timeout);
return this;
}
/**
* To check if the session is still alive, an {@link EnquireLink} request is
* sent. This request may fail since the session may be killed by the
* server. The timeout ensures that the client doesn't wait too long for a
* response that may never come.
*
* The maximum amount of time (in milliseconds) to wait for receiving a
* response from the server to an {@link EnquireLink} request.
*
* <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(10000L)
* .responseTimeout()
* .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<ReuseSessionBuilder, Long> responseTimeout() {
return enquireLinkTimeoutValueBuilder;
}
/**
* To check if the session is still alive, an {@link EnquireLink} request is
* sent. The request is sent just before sending the message.
*
* This is the time (in milliseconds) to wait before considering last
* {@link EnquireLink} response as expired (need to send a new
* {@link EnquireLink} request to check if session is still alive).
*
* <p>
* This is needed to prevent sending {@link EnquireLink} request every time
* a message has to be sent. Instead it considers that the time elapsed
* between now and the last {@link EnquireLink} response (or the last sent
* message) is not enough so a new {@link EnquireLink} is not necessary to
* check if session is still alive.
*
* <p>
* Set to 0 to always check session before sending message.
*
* <p>
* The value set using this method takes precedence over any property and
* default value configured using {@link #lastInteractionExpiration()}.
*
* <pre>
* .delay(60000L)
* .delay()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(60000L)
* </pre>
*
* <pre>
* .delay(60000L)
* .delay()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(60000L)
* </pre>
*
* In both cases, {@code delay(60000L)} 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 delay
* The time to wait (in milliseconds) to wait before sending a
* new {@link EnquireLink} request to check if session is still
* alive.
* @return this instance for fluent chaining
*/
public ReuseSessionBuilder lastInteractionExpiration(Long delay) {
lastInteractionExpirationDelayValueBuilder.setValue(delay);
return this;
}
/**
* To check if the session is still alive, an {@link EnquireLink} request is
* sent. The request is sent just before sending the message.
*
* This is the time (in milliseconds) to wait before considering last
* {@link EnquireLink} response as expired (need to send a new
* {@link EnquireLink} request to check if session is still alive).
*
* <p>
* This is needed to prevent sending {@link EnquireLink} request every time
* a message has to be sent. Instead it considers that the time elapsed
* between now and the last {@link EnquireLink} response (or the last sent
* message) is not enough so a new {@link EnquireLink} is not necessary to
* check if session is still alive.
*
* <p>
* Set to 0 to always check session before sending message.
*
* <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>
* .delay()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(60000L)
* </pre>
*
* <p>
* Non-null value set using {@link #lastInteractionExpiration(Long)} takes precedence over
* property values and default value.
*
* <pre>
* .delay(60000L)
* .delay()
* .properties("${custom.property.high-priority}", "${custom.property.low-priority}")
* .defaultValue(60000L)
* </pre>
*
* The value {@code 60000L} 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<ReuseSessionBuilder, Long> lastInteractionExpiration() {
return lastInteractionExpirationDelayValueBuilder;
}
@Override
public ReuseSessionOptions build() {
ReuseSessionOptions reuseSessionOptions = new ReuseSessionOptions();
reuseSessionOptions.setEnable(enableValueBuilder.getValue(false));
reuseSessionOptions.setLastInteractionExpirationDelay(lastInteractionExpirationDelayValueBuilder.getValue(0L));
reuseSessionOptions.setEnquireLinkTimeout(enquireLinkTimeoutValueBuilder.getValue(0L));
return reuseSessionOptions;
}
}