Terminal Connection Pool (Core v4.9.38.1 +)
In many cases, using a connection pool in a Terminal-based project gives a big improvement in performance, as opening a session and, in many cases, logging into the Terminal is a time-consuming operation. For this reason, OpenLegacy allows the use of Connection Pools when creating such Terminal-based projects.
To achieve this functionality, the user will need to do the following:
First, we need to enable the pool in the project's configuration, this is done by adding the following properties to the YAML file located in the resource folder:
ol:
h3270:
project:
{sdk name}:
pool:
enable: true
maxSize: 5
minSize: 1
keepAliveInterval: 20000
Let’s take a minute to explain these properties:
enable
- boolean - by default, the pool is not enabled. To enable it, we need to set the Enable flag to truemaxSize
- int - the maximum number of idled open sessions to the legacyminSize
- int - the minimum number of idled open sessions to the legacykeepAliveInterval
- long - the amount of time between each keep-alive action
To meet the conditions above, every project must implement three Spring beans of additional pool’s lifecycle actions (io.openlegacy.impl.greenscreen.pool.lifecycle.PoolLifecycleAction
):
Init Action
- The actions taken once a new session is created, such as log in to the terminal.Clean Up Action
- The actions taken once the application returns a session into the pool, for example navigating back to the main menu screen.Keep Alive Action
- An action that keeps the session alive when the session is stored in the pool. This action is usually is very quick. If the application takes a session from the pool, the applicative action will cancel the Keep Alive Action even if an action in progress.
Following is a code snippet we created to show a basic implementation of such pool configurations:
@Configuration
public class MfScreensSdkConfiguration {
private final KLogger logger = KotlinLogging.INSTANCE.logger(() -> null);
@Bean("mfScreensSdk" + CommonBeanNames.SESSION_POOL_INIT_ACTION_SUFFIX)
PoolLifecycleAction poolInitAction() {
return new PoolLifecycleAction() {
@Override
public ScreensPoolProperties getPoolProperties() {
// not in use by Init action
return null;
}
@Override
public void apply(GreenScreenSession session) {
logger.info("performing init action");
try {
Empty emptyScreen = session.getEntity(Empty.class);
logger.debug("after getEntity");
emptyScreen.setInq1("INQ1");
session.doAction(GreenScreenActions.INSTANCE.enter(), emptyScreen, LoansInquiry.class);
logger.debug("after doAction");
} catch (Exception e) {
GreenScreenEntity screen = session.doAction(GreenScreenActions.INSTANCE.escape(),
EmptyGreenScreenEntity.class, EmptyGreenScreenEntity.class);
while (!(screen instanceof Empty)) {
screen = session.doAction(GreenScreenActions.INSTANCE.escape(), EmptyGreenScreenEntity.class,
EmptyGreenScreenEntity.class);
}
}
logger.info("ending init action");
}
};
}
@Bean("mfScreensSdk" + CommonBeanNames.SESSION_POOL_CLEANUP_ACTION_SUFFIX)
PoolLifecycleAction poolCleanupAction() {
return new PoolLifecycleAction() {
@Override
public ScreensPoolProperties getPoolProperties() {
// not in use by CleanUp action
return null;
}
@Override
public void apply(GreenScreenSession session) {
logger.info("performing clean up action");
session.doAction(GreenScreenActions.INSTANCE.escape(), new EmptyGreenScreenEntity());
GreenScreenEntity screen = session.getEntity();
logger.debug("escape 1 " + screen.entityDefinition().getName() + ":" + screen.entityDefinition().getId());
while (!(screen instanceof Empty)) {
logger.debug("in while");
session.doAction(GreenScreenActions.INSTANCE.escape(), new EmptyGreenScreenEntity());
screen = session.getEntity();
logger.debug("escape 2 " + screen.entityDefinition().getName() + ":" + screen.entityDefinition().getId());
}
logger.debug("out while");
session.doAction(GreenScreenActions.INSTANCE.escape(), new EmptyGreenScreenEntity());
screen = session.getEntity();
logger.debug("escape 3 " + screen.entityDefinition().getName() + ":" + screen.entityDefinition().getId());
Empty emptyScreen = (Empty) screen;
emptyScreen.setInq1("INQ1");
session.doAction(GreenScreenActions.INSTANCE.enter(), emptyScreen, LoansInquiry.class);
logger.debug("done enter");
// session.close();
}
};
}
@Bean("mfScreensSdk" + CommonBeanNames.SESSION_POOL_KEEPALIVE_ACTION_SUFFIX)
PoolLifecycleAction poolKeepAliveAction(H3270Properties allProjectsProperties) {
return new PoolLifecycleAction() {
private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private Map<GreenScreenSession, ScheduledFuture<?>> futures = new ConcurrentHashMap<>();
@Override
public ScreensPoolProperties getPoolProperties() {
return allProjectsProperties.getProject().get("mfScreensSdk").getPool();
}
@Override
public void apply(GreenScreenSession session) {
//User can write his logic here.
logger.info("Invoke KeepAlive action (mfScreensSdk)");
Runnable command = () -> {
logger.debug("Do KeepAlive action (mfScreensSdk)");
session.getEntity(EmptyGreenScreenEntity.class);
};
long initialDelay = 0;
long delay = getPoolProperties().getKeepAliveInterval();
ScheduledFuture<?> future = executor.scheduleWithFixedDelay(command, initialDelay, delay, TimeUnit.MILLISECONDS);
futures.put(session, future);
logger.info("performing keep alive action");
}
@Override
public void cancel(GreenScreenSession session) {
logger.info("Cancel KeepAlive action (mfScreensSdk)");
final ScheduledFuture<?> future = futures.get(session);
if (future != null) {
future.cancel(true);
}
}
};
}
/* $-a-b-p */
// IMPORTANT! DO NOT REMOVE OR EDIT PLACEHOLDER
// Placeholder to add beans dynamically from code
}
For Spring to load the pool implementation, you will need to register it as a Beans to your projects configuration class located at:
package com.{Normalized SDK project name}.openlegacy.config;
named - {SDK Project name}Configuration.java
Attached below are sample API and SDK projects implementing the pool
To test them, you run the API* and execute one call, then you will be able to see in the logs that the pool actions are being executed as expected
*To run the API please add your OpenLegacy License string to the API YAML.