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 true

  • maxSize - int - the maximum number of idled open sessions to the legacy

  • minSize - int - the minimum number of idled open sessions to the legacy

  • keepAliveInterval - 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.