ConnectionPersister is a class that creates, reads, updates, and deletes the ConnectionInfo objects. ConnectionPersister is a wrapper of IEndpointConfigurationService and hides the conversions between IEndpointConfigurationService and ConnectionInfo.

Defining the Configuration Persister Interface

public interface ConnectionPersister {
 /*
 * Returns a collection of all stored configurations (resources under
 * a folder with the plug-in name)
 */
 public List<ConnectionInfo> findAll();
 /*
 * Returns a collection by its ID or null if not found
 */
 public ConnectionInfo findById(Sid id);
 /*
 * Stores a connection info or updates it if already available.
 * The persister checks the availability of a connection by its ID
 */
 public ConnectionInfo save(ConnectionInfo connection);
 /*
 * Deletes a connection info. The persister will use the ID of the
connection
 */
 public void delete(ConnectionInfo connectionInfo);
 /*
 * Allows us to subscribe to the events of the persister.
 * For example, if a connection is deleted, the persister will
 * trigger an event, notifying all subscribers.
 * This is an implementation of the observer pattern.
 */
 void addChangeListener(ConfigurationChangeListener listener);
 /*
 * Forces the persister to read all the configurations and trigger
 * the events. This method is invoked when the plug-in is loaded
 * on server start-up.
 */
 public void load();
}

Implementing the Default Connection Persister Interface

@Component
public class DefaultConnectionPersister implements ConnectionPersister {
 private static final String CHARSET = "UTF-8";
 /*
 * A list of listeners, who have subscribed to any configuration events,
such as
 * connection updates and deletions.
 */
 private final Collection<ConfigurationChangeListener> listeners;
 /*
 * Always use loggers
 */
 private static final Logger log =
LoggerFactory.getLogger(DefaultConnectionPersister.class);
 /*
 * Constants of the key names under which the connection values will be
stored.
 */
 private static final String ID = "connectionId";
 private static final String NAME = "name";
 private static final String SUBSCRIPTION_ID = "sunscriptionId";
 private static final String KEYSTORE_CONTENT = "keystoreContent";
 private static final String KEYSTORE_PASSWORD = "keystorePassword";
 private static final String SERVICE_URI = "serviceUri";
 /*
 * The IEndpointConfigurationService will be injected through spring
 * if the plug-in has a spring context.
 */
 @Autowired
 private IEndpointConfigurationService endpointConfigurationService;

 /*
 * Persister constructor
 */
 public DefaultConnectionPersister() {
 //Initialize the listeners
 listeners = new CopyOnWriteArrayList<ConfigurationChangeListener>();
 }

 /*
 * Returns a collection of all stored configurations for this plug-in only
 * The service is aware of the plug-in name, thus will return only
configurations for this plug-in.
 */
 @Override
 public List<ConnectionInfo> findAll() {
 Collection<IEndpointConfiguration> configs;
 try {
 //Use the configuration service to retrieve all configurations.
 //The service is aware of the plug-in name, thus will return only
configurations for this plug-in.
 configs =
endpointConfigurationService.getEndpointConfigurations();
 List<ConnectionInfo> result = new ArrayList<>(configs.size());

 //Iterate all the connections
 for (IEndpointConfiguration config : configs) {
 //Convert the IEndpointConfiguration to our domain object -
the ConnectionInfo
 ConnectionInfo connectionInfo = getConnectionInfo(config);
 if (connectionInfo != null) {
 log.debug("Adding connection info to result map: " +
connectionInfo);
 result.add(connectionInfo);
 }
 }
 return result;
 } catch (IOException e) {
 log.debug("Error reading connections.", e);
 throw new RuntimeException(e);
 }
 }

 /*
 * Returns a ConnectionInfo by its ID
 * The service is aware of the plug-in name, thus cannot return a
configuration for another plug-in.
 */
 @Override
 public ConnectionInfo findById(Sid id) {
 //Sanity checks
 Validate.notNull(id, "Sid cannot be null.");
 IEndpointConfiguration endpointConfiguration;
 try {
 //Use the configuration service to retrieve the configuration
service by its ID
 endpointConfiguration =
endpointConfigurationService.getEndpointConfiguration(id.toString());

 //Convert the IEndpointConfiguration to our domain object - the
ConnectionInfo
 return getConnectionInfo(endpointConfiguration);
 } catch (IOException e) {
 log.debug("Error finding connection by id: " + id.toString(), e);
 throw new RuntimeException(e);
 }
 }

 /*
 * Save or update a connection info.
 * The service is aware of the plug-in name, thus cannot save the
configuration
 * under the name of another plug-in.
 */
 @Override
 public ConnectionInfo save(ConnectionInfo connectionInfo) {
 //Sanity checks
 Validate.notNull(connectionInfo, "Connection info cannot be null.");
 Validate.notNull(connectionInfo.getId(), "Connection info must have an
id.");

 //Additional validation - in this case we want the name of the
connection to be unique
 validateConnectionName(connectionInfo);
 try {
 //Find a connection with the provided ID. We don't expect to have
an empty ID
 IEndpointConfiguration endpointConfiguration =
endpointConfigurationService

.getEndpointConfiguration(connectionInfo.getId().toString());
 //If the configuration is null, then we are performing a save
operation
 if (endpointConfiguration == null) {
 //Use the configuration service to create a new (empty)
IEndpointConfiguration.
 //In this case, we are responsible for assigning the ID of the
configuration,
 //which is done in the constructor of the ConnectionInfo
endpointConfiguration =
endpointConfigurationService.newEndpointConfiguration(connectionInfo.getId()
 .toString());
 }

 //Convert the ConnectionInfo the IEndpointConfiguration
 addConnectionInfoToConfig(endpointConfiguration, connectionInfo);

 //Use the configuration service to save the endpoint configuration

endpointConfigurationService.saveEndpointConfiguration(endpointConfiguration);

 //Fire an event to all subscribers, that we have updated a
configuration.
 //Pass the entire connectionInfo object and let the subscribers
decide if they need to do something
 fireConnectionUpdated(connectionInfo);
 return connectionInfo;
 } catch (IOException e) {
 log.error("Error saving connection " + connectionInfo, e);
 throw new RuntimeException(e);
 }
 }

 /*
 * Delete a connection info. The service is aware of the plug-in name,
thus cannot delete a configuration
 * from another plug-in.
 */
 @Override
 public void delete(ConnectionInfo connectionInfo) {
 try {
 //Use the configuration service to delete the connection info. The
service uses the ID

endpointConfigurationService.deleteEndpointConfiguration(connectionInfo.getId(
).toString());

 //Fire an event to all subscribers, that we have deleted a
configuration.
 //Pass the entire connectionInfo object and let the subscribers
decide if they need to do something
 fireConnectionRemoved(connectionInfo);
 } catch (IOException e) {
 log.error("Error deleting endpoint configuration: " +
connectionInfo, e);
 throw new RuntimeException(e);
 }
 }
 
 /*
 * This method is used to load the entire configuration set of the plugin.
 * As a second step we fire a notification to all subscribers. This method
 * is used when the plug-in is being loaded (on server startup).
 */
 @Override
 public void load() {
 List<ConnectionInfo> findAll = findAll();
 for (ConnectionInfo connectionInfo : findAll) {
 fireConnectionUpdated(connectionInfo);
 }
 }

 /*
 * Attach a configuration listener.
 */
 @Override
 public void addChangeListener(ConfigurationChangeListener listener) {
 listeners.add(listener);
 }

 /*
 * A helper method which iterates all event subscribers and fires the
 * update notification for the provided connection info.
 */
 private void fireConnectionUpdated(ConnectionInfo connectionInfo) {
 for (ConfigurationChangeListener li : listeners) {
 li.connectionUpdated(connectionInfo);
 }
 }

 /*
 * A helper method which iterates all event subscribers and fires the
 * delete notification for the provided connection info.
 */
 private void fireConnectionRemoved(ConnectionInfo connectionInfo) {
 for (ConfigurationChangeListener li : listeners) {
 li.connectionRemoved(connectionInfo);
 }
 }

 /*
 * A helper method which converts our domain object the ConnectionInfo to
an IEndpointConfiguration
 */
 private void addConnectionInfoToConfig(IEndpointConfiguration config,
ConnectionInfo info) {
 try {
 config.setString(ID, info.getId().toString());
 config.setString(NAME, info.getName());
 config.setString(SUBSCRIPTION_ID, info.getSubscriptionId());
 config.setString(KEYSTORE_CONTENT, new
String(info.getKeystoreContent(), CHARSET));
 config.setPassword(KEYSTORE_PASSWORD, info.getKeystorePassword());
 config.setString(SERVICE_URI, info.getUri());
 } catch (UnsupportedEncodingException e) {
 log.error("Error converting ConnectionInfo to
IEndpointConfiguration.", e);
 throw new RuntimeException(e);
 }
 }

 /*
 * A helper method which converts the IEndpointConfiguration to our domain
object the ConnectionInfo
 */
 private ConnectionInfo getConnectionInfo(IEndpointConfiguration config) {
 ConnectionInfo info = null;
 try {
 Sid id = Sid.valueOf(config.getString(ID));
 info = new ConnectionInfo(id);
 info.setName(config.getString(NAME));
 info.setUri(config.getString(SERVICE_URI));
 info.setSubscriptionId(config.getString(SUBSCRIPTION_ID));
 info.setKeystorePassword(config.getPassword(KEYSTORE_PASSWORD));

info.setKeystoreContent(config.getString(KEYSTORE_CONTENT).getBytes(CHARSET));
 } catch (IllegalArgumentException | UnsupportedEncodingException e) {
 log.warn("Cannot convert IEndpointConfiguration to ConnectionInfo:
" + config.getId(), e);
 }
 return info;
 }
 private void validateConnectionName(ConnectionInfo connectionInfo) {
 ConnectionInfo configurationByName =
getConfigurationByName(connectionInfo.getName());
 if (configurationByName != null
 &&
!configurationByName.getId().toString().equals(connectionInfo.getId().toString
())) {
 throw new RuntimeException("Connection with the same name already
exists: " + connectionInfo);
 }
 }
 private ConnectionInfo getConfigurationByName(String name) {
 Validate.notNull(name, "Connection name cannot be null.");
 Collection<ConnectionInfo> findAllClientInfos = findAll();
 for (ConnectionInfo info : findAllClientInfos) {
 if (name.equals(info.getName())) {
 return info;
 }
 }
 return null;
 }
}