Create microservice

Native microservice

Native microservice is a set of POJO Java classes available for JLupin Next Server through configured spring container.

Creating interface

package com.jlupin.sample.interfaces;

public interface ExampleService {
    String getName();
}

Creating implementation

package com.jlupin.sample.impl;

import com.jlupin.sample.interfaces.ExampleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

@Service(value = "exampleService")
public class ExampleServiceImpl implements ExampleService {
    private final static Logger logger = LoggerFactory.getLogger(ExampleServiceImpl.class);

    @Override
    public String getName() {
        logger.info("called getName() method");
        return "name";
    }
}

Interface is optional here (it is a good practice to create interface for every service) but is required for binary communication (generated proxy object is implementing interface). It is also a good practice to put interface in seperate jar to not share your internal implementation with the others. More details about logging can be found in Logging chapter.

Remote sharing

package com.jlupin.sample.configuration;

import java.util.ArrayList;
import java.util.List;

@Configuration
@ComponentScan("com.jlupin.sample")
public class SpringConfiguration {

    @Bean(name = "jLupinRegularExpressionToRemotelyEnabled")
    public List getRemotelyBeanList() {
        List<String> list = new ArrayList<>();
        list.add("exampleService");
        return list;
    }
}

Class is annotated as standard Spring configuration class with component scan (to scan package for used annotations). The important part is a bean named jLupinRegularExpressionToRemotelyEnabled. It is a list of regular expressions wich are working as a masks for services available to JLupin Next Server. What does it mean? For security reasons not all services are available for remote execution. And decision which are visible outside and which are not is being made by developer. Being specific, every object living inside spring container is a bean. And every bean in Spring container has a name (by default it is class name with first letter downcased). To determine wchich service should be exposed JLupin Next Server takes all beans from application container and then check if this name matches any of regular expressions on bean jLupinRegularExpressionToRemotelyEnabled (this bean is a list). If it matches service is remotely enabled and can be called with remote execution.

You also need to tell JLupin which context to use. You do this by creating proper class and putting it's name in microservice configuration (configuration.yml).

package com.example.currency.converter.configuration;

import com.jlupin.impl.container.application.spring.JLupinAbstractSpringApplicationContainer;
import com.jlupin.interfaces.configuration.microservice.container.application.JLupinAbstractApplicationContainerProducer;
import com.jlupin.interfaces.container.application.JLupinApplicationContainer;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;

public class JLupinConfiguration extends JLupinAbstractApplicationContainerProducer {
    @Override
    public JLupinApplicationContainer produceJLupinApplicationContainer() {
        return new JLupinAbstractSpringApplicationContainer() {
            @Override
            public AbstractApplicationContext getAbstractApplicationContext() {
                return new AnnotationConfigApplicationContext(SpringConfiguration.class);
            }
        };
    }
}

Running microservice

When your microservice is done compile it into jar file. Then put this file with all other required by your microservice (like configuration.yml, logger configuration file, properties file, etc.) into directory which name is your microservice name inside server/application directory. To start it just run control.sh/.cmd and type in command microservice start [your_microservice_name].

Example microservice configuration file is shown below full configuration file description:

SERVERS:
  JLRMC: #JLupin Remote Method Calls Fast Protocol
    readTimeout: 480000
    isWaitForFinishExecuteAllRequests: true
    waitToShutdownThreadsOnStop: 60000
    backlog: 0
    receiveBufferSize: 0
    isReuseAddress: false
    threadPoolSize: 128
    isLogPeriodicOnDebug: true
    isDestroyThreadOnTimeout: false
    threadExecutingTimeOut: 240000
  TRANSMISSION:
    readTimeout: 480000
    isWaitForFinishExecuteAllRequests: false
    waitToShutdownThreadsOnStop: 60000
    backlog: 0
    receiveBufferSize: 0
    isReuseAddress: false
    threadPoolSize: 8
    isLogPeriodicOnDebug: true
    isDestroyThreadOnTimeout: false
    threadExecutingTimeOut: 3600000
  QUEUE:
     readTimeout: 480000
     isWaitForFinishExecuteAllRequests: true
     waitToShutdownThreadsOnStop: 60000
     backlog: 1024
     receiveBufferSize: 1024
     isReuseAddress: false
     threadPoolSize: 128
     isLogPeriodicOnDebug: true
     isDestroyThreadOnTimeout: false
     threadExecutingTimeOut: 240000
ENTRY_POINTS:
  QUEUE:
     threadAmount: 512
     howOftenCheckingServerInMillis: 5000
     repeatsAmount: 4
     timeToWaitBetweenRepeatProbeInMillis: 1000
PROPERTIES:
  #jvmOptions1: '-Xms128M -Xmx256M -agentlib:jdwp=transport=dt_socket,address=12998,server=y,suspend=n'
  jvmOptions1: '-Xms64M -Xmx128M' #jvmOptions_2 - default the same as jvmOptions_1
  #jvmOptions2: '-Xms128M -Xmx256M'
  externalPort: '8000'
  version: '1.0'
  switchDelayTime: 0
  connectionSocketTimeoutInMillis: 1000
  readTimeoutInMillis: 30000
  isKeepAlive: false
  isOOBInline: false
  isTcpNoDelay: false
  isReuseAddress: false
  sendBufferSize: 0
  receiveBufferSize: 0
  soLinger: 0
  trafficClass: 0
  #javaExecutablePath: 'c:\\jvm\\bin\\java.exe'
  #additionalClassPath: 'c:\\temp\\*'
  isStartOnMainServerInitialize: true
  priorityStartOnMainServerInitialize: 4
  waitForProcessInitResponseTimeInMillis: 90000
  waitForProcessStartResponseTimeInMillis: 90000
  waitForProcessDestroyResponseTimeInMillis: 30000
  isAllFilesToJVMAppClassLoader: false
  isArchiveOnStart: false
  startLogMode: INFO
  isInitErrorCauseWithNetworkInformation: true
  checkAvailableScript: 'function isAvailable(checkResponseTimeInMillis, jrmcActiveThreads, jrmcMaxThreads,
                                              queueActiveThreads, queueMaxThreads, servletActiveThreads, servletMaxThreads,
                                              jvmMaxMemoryInBytes, jvmTotalMemoryInBytes, jvmFreeMemoryInBytes,
                                              jvmProcessCpuLoadInPercentage, userAvailableFlag) {

                          var isAvailableByUser = Boolean(userAvailableFlag);
                          if(checkResponseTimeInMillis > 20000 || !isAvailableByUser) {
                             return false;
                          }
                          return true;
                         }'
APPLICATION:
  applicationContainerProducerClassName: 'com.example.currency.converter.configuration.CurrencyConverterEurJLupinConfiguration'
INITIALIZING_LOGGER:
  #directoryPath: '/logs/server'
  #fileName: 'file_name'
  fileExtension: 'log'
  fileSizeInMB: 20
  maxFiles: 10
MEMORY_ERRORS:
  isRestartOnError: true
  howManyTimes: 4
  percentageGrowth: 15
  isHeapDump: true
THREAD_POOLS:
  THREAD_POOL_1:
    size: 8
    waitingTimeForTasksCompletionInMillis: 10000
  #THREAD_POOL_2:
  #  size: 8
  #  waitingTimeForTasksCompletionInMillis: 10000