
- Rating:
- Views: 597
- Author: JLupin
- Skill level: easy
- Comments: 0
Overview
This tutorial will show you how to create native microservice for JLupin Platform. What is native microservice? It is just a microservice which uses built-in communication mechanism and Spring container to expose beans for remote calls. It sounds simple and it is. Let's start coding now.
Requirements
To complete this tutorial you will need JLupin Platform version 1.5.0.3. You can download it from here.
Configure project
When you create service which will be available to other users of your system, you probably want to tell them how to use it. If you want to allow them to call it easily you should also share your interface classes with them. But you don't want to share your implementation with them! You want to hide it from various reasons. That's why we are going to create two modules for every microservice: interfaces and implementation. Your users will have access only to interfaces module.
We will use Maven feature called reactor. It is built-in mechanism for handling multi-module project. So we are going to start with standard Maven structure.
+--implementation | | | +--src | | | | | +--main | | | | | +--java | | | +--pom.xml | +--interfaces | | | +--src | | | | | +--main | | | | | +--java | | | +--pom.xml | +--pom.xml
Below are presented pom files with proper configuration.
pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>welcome-microservice</artifactId> <groupId>com.example.application</groupId> <version>1.0.0</version> <packaging>pom</packaging> <repositories> <!-- Repository is also accessible using https connection: --> <!-- https://support.jlupin.com/maven2/ --> <repository> <id>jlupin-central</id> <name>jlupin</name> <url>http://support.jlupin.com/maven2/</url> </repository> </repositories> <pluginRepositories> <!-- Repository is also accessible using https connection: --> <!-- https://support.jlupin.com/maven2/ --> <pluginRepository> <id>jlupin-central</id> <name>jlupin</name> <url>http://support.jlupin.com/maven2/</url> </pluginRepository> </pluginRepositories> <modules> <module>interfaces</module> <module>implementation</module> </modules> <properties> <jlupin.platform.client.version>1.5.0.3</jlupin.platform.client.version> <jlupin.platform.maven.plugin.version>1.5.0.0</jlupin.platform.maven.plugin.version> <jlupin.skipDeploy>true</jlupin.skipDeploy> <maven.surefire.skipTests>false</maven.surefire.skipTests> <spring.context.version>5.0.8.RELEASE</spring.context.version> <slf4j.version>1.8.0-alpha2</slf4j.version> <log4j.slf4j.bridge.version>2.11.0</log4j.slf4j.bridge.version> <maven.failsafe.plugin.version>2.20</maven.failsafe.plugin.version> <maven.surefire.plugin.version>2.20</maven.surefire.plugin.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>${maven.surefire.plugin.version}</version> <configuration> <skipTests>${maven.surefire.skipTests}</skipTests> </configuration> </plugin> </plugins> <pluginManagement> <plugins> <plugin> <groupId>com.jlupin</groupId> <artifactId>jlupin-platform-maven-plugin</artifactId> <version>${jlupin.platform.maven.plugin.version}</version> <executions> <execution> <id>jlupin-zip</id> <goals> <goal>zip</goal> </goals> <configuration> <additionalFilesDirectories> <param>../additional-files</param> </additionalFilesDirectories> </configuration> </execution> <execution> <id>jlupin-deploy</id> <phase>pre-integration-test</phase> <goals> <goal>deploy</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <version>${maven.failsafe.plugin.version}</version> <executions> <execution> <id>integration-test</id> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> </execution> </executions> <configuration> <includes> <include>**/Test*.java</include> <include>**/*Test.java</include> <include>**/*Tests.java</include> <include>**/*TestCase.java</include> </includes> </configuration> </plugin> </plugins> </pluginManagement> </build> </project>
implementation/pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>welcome-microservice</artifactId> <groupId>com.example.application</groupId> <version>1.0.0</version> <relativePath>../pom.xml</relativePath> </parent> <name>welcome-microservice</name> <artifactId>welcome-microservice-implementation</artifactId> <properties> <jlupin.skipDeploy>false</jlupin.skipDeploy> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.context.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>com.example.application</groupId> <artifactId>welcome-microservice-interfaces</artifactId> <version>1.0.0</version> </dependency> <!-- JLupin dependencies --> <dependency> <groupId>com.jlupin</groupId> <artifactId>jlupin-client-assembly</artifactId> <version>${jlupin.platform.client.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.slf4j.bridge.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>com.jlupin</groupId> <artifactId>jlupin-platform-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
interfaces/pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>welcome-microservice</artifactId> <groupId>com.example.application</groupId> <version>1.0.0</version> <relativePath>../pom.xml</relativePath> </parent> <artifactId>welcome-microservice-interfaces</artifactId> </project>
JLupin Maven repository is configured to get access to required artifacts. Also dependencies required for this tutorial and development are added. JLupin Platform Maven Plugin is configured to zip microservice and deploy it. Also content of additional-files is added to created zip file. You need to create this directory on same level as implementation directory. Configuration files will be placed here. You should end up with structure:
+--additional-files | +--implementation | | | +--src | | | | | +--main | | | | | +--java | | | +--pom.xml | +--interfaces | | | +--src | | | | | +--main | | | | | +--java | | | +--pom.xml | +--pom.xml
Microservice implementation
At first create suitable package structure. In this tutorial com.example.application will be used as main package. Recommended structure (also used by this tutorial) is presented below.
+--additional-files | +--implementation | | | +--src | | | | | +--main | | | | | +--java | | | | | +--com | | | | | +--example | | | | | +--application | | | | | +--bean | | | | | | | +--impl | | | | | | | +--interfaces | | | | | | | +--pojo | | | | | +--configuration | | | | | +--dao | | | | | | | +--impl | | | | | | | +--interfaces | | | | | | | +--pojo | | | | | +--service | | | | | +--impl | | | +--pom.xml | +--interfaces | | | +--src | | | | | +--main | | | | | +--java | | | | | +--com | | | | | +--example | | | | | +--application | | | | | +--service | | | | | +--interfaces | | | | | +--pojo | | | +--pom.xml | +--pom.xml
When you done with package structure create basic Spring configuration file under configuration package.
package com.example.application.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import java.util.ArrayList; import java.util.List; @Configuration @ComponentScan("com.example.application") public class SpringConfiguration { }
Ok, we have Spring configuration file created. But our microservice does nothing. Create simple service interface and provide its implementation. Service should accept name as parameter and return welcome message. Put everything inside interfaces module.
package com.example.application.service.interfaces; import java.util.Map; public interface WelcomeService { Map<String, String> getWelcomeMessage(final Map<String, String> map); }
package com.example.application.service.impl; import com.example.application.service.interfaces.WelcomeService; import org.springframework.stereotype.Service; import java.util.Collections; import java.util.Map; @Service(value = "welcomeService") public class WelcomeServiceImpl implements WelcomeService { public Map<String, String> getWelcomeMessage(final Map<String, String> map) { return Collections.singletonMap("message", "Hello " + map.get("name") + "!"); } }
Since now we haven't added anything special for JLupin Platform, not even the smallest annotation. But now we want to expose our service for remote access so we need to tell JLupin Platform that this particular service can be externally called. To do so we need to change Spring configuration file and define bean named jLupinRegularExpressionToRemotelyEnabled. This bean is just a list of strings which are regular expressions. If service name matches any of regular expressions on the list then it is exposed for external usage. Modified class is showed below.
package com.example.application.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import java.util.ArrayList; import java.util.List; @Configuration @ComponentScan("com.example.application") public class SpringConfiguration { @Bean(name = "jLupinRegularExpressionToRemotelyEnabled") public List getRemotelyBeanList() { List<String> list = new ArrayList<>(); list.add("welcomeService"); return list; } }
Now we have configured Spring container with single service exposed as a remote bean. When we look at the description in the overview section it looks like everything is done. However one additional file is required. Through JLupinApplicationContainerProducer we need to create Spring ApplicationContext and return it to JLupin Platform. Required file can be found below.
package com.example.application.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); } }; } }
We used annotations to configure Spring container and that's why we had created AnnotationConfigApplicationContext. You may want to use any other ApplicationContext, for example WebXmlApplicationContext. It is up to you.
Now you can create configuration.yml file and setup your microservice - example below. Put this file inside additional-files directory.
SERVERS: JLRMC: #JLupin Remote Method Calls Fast Protocol readTimeout: 480000 isWaitForFinishExecuteAllRequests: true waitToShutdownThreadsOnStop: 60000 backlog: 256 receiveBufferSize: 256 isReuseAddress: false threadPoolSize: 128 isLogPeriodicOnDebug: true isDestroyThreadOnTimeout: false threadExecutingTimeOut: 240000 isStartOnMainServerInitialize: true TRANSMISSION: readTimeout: 480000 isWaitForFinishExecuteAllRequests: false waitToShutdownThreadsOnStop: 60000 backlog: 0 receiveBufferSize: 0 isReuseAddress: false threadPoolSize: 8 isLogPeriodicOnDebug: true isDestroyThreadOnTimeout: false threadExecutingTimeOut: 3600000 isStartOnMainServerInitialize: true QUEUE: readTimeout: 480000 isWaitForFinishExecuteAllRequests: true waitToShutdownThreadsOnStop: 60000 backlog: 256 receiveBufferSize: 256 isReuseAddress: false threadPoolSize: 128 isLogPeriodicOnDebug: true isDestroyThreadOnTimeout: false threadExecutingTimeOut: 240000 isStartOnMainServerInitialize: true ENTRY_POINTS: QUEUE: threadAmount: 128 howOftenCheckingServerInMillis: 5000 repeatsAmount: 4 timeToWaitBetweenRepeatProbeInMillis: 1000 TRANSMISSION: MICROSERVICES_GRANT_ACCESS: MICROSERVICES_LIST: #- microserviceName: 'sampleMicroservice' # serviceName: 'sampleServiceName' # methodName: 'sampleMethodName' #- microserviceName: 'sampleMicroservice2' # serviceName: 'sampleServiceName2' # methodName: 'sampleMethodName2' PROPERTIES: platformVersion: '1.5.0.3' #jvmOptions1: '-Xms128M -Xmx256M -agentlib:jdwp=transport=dt_socket,address=12998,server=y,suspend=n' jvmOptions1: '-Xms128M -Xmx256M' #jvmOptions_2 - default the same as jvmOptions_1 #jvmOptions2: '-Xms128M -Xmx256M' externalPort: '8000' version: '1.5.0.3' 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 isJmxEnabled: true jmxOptions: '-Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false' jmxPrimaryPort: -1 jmxSecondaryPort: -1 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.application.configuration.JLupinConfiguration' 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
As you can see you must provide full name of class extending JLupinAbstractApplicationContainerProducer. And that's all. Now your microservice is ready to deploy.
You should also configure logging system (Log4j2). Example configuration with asynchronous appender below. Put this into log4j2.xml file inside additional-files directory.
<?xml version="1.0" encoding="UTF-8"?> <!-- ===================================================================== --> <!-- --> <!-- Log4j2 Configuration --> <!-- --> <!-- ===================================================================== --> <!-- | For more configuration information and examples see the Apache Log4j2 | website: https://logging.apache.org/log4j/2.x/index.html --> <Configuration status="WARN" dest="errors/welcome-microservice_log4j2_status.log"> <!-- Extract log directory and file name into variables --> <Properties> <Property name="logDirectory">../logs/microservice/welcome-microservice</Property> <Property name="logFileName">microservice</Property> </Properties> <Appenders> <!-- RollingFileAppender configured to role every day --> <RollingFile name="FILE"> <FileName>\${logDirectory}/\${logFileName}.log</FileName> <FilePattern>\${logDirectory}/\${logFileName}.%d{yyyy-MM-dd}.log</FilePattern> <!-- Compress log files to gzip --> <!-- More configuration https://logging.apache.org/log4j/2.x/manual/appenders.html#DefaultRolloverStrategy --> <!-- <FilePattern>${logDirectory}/${logFileName}.%d{yyyy-MM-dd}.log.gz</FilePattern> --> <!-- Do not truncate file --> <Append>true</Append> <!-- The default pattern: Date Priority [Category] (Thread) Message\n --> <PatternLayout pattern="%d %-5p [%c] (%t) %m%n" /> <Policies> <!-- Rollover every microservice start - very useful for debugging --> <!-- <OnStartupTriggeringPolicy /> --> <!-- Rollover at the top of each day --> <TimeBasedTriggeringPolicy interval="1" modulate="true" /> <!-- Rollover if file size is greater than 200 MB --> <!-- <SizeBasedTriggeringPolicy size="200 MB"/> --> </Policies> <CreateOnDemand>true</CreateOnDemand> <!-- Keep last 10 log files --> <!-- More configuration https://logging.apache.org/log4j/2.x/manual/appenders.html#DefaultRolloverStrategy --> <!-- <DefaultRolloverStrategy max="10" /> --> </RollingFile> <!-- AsyncAppender for high performance --> <Async name="ASYNC_FILE"> <BufferSize>1000</BufferSize> <AppenderRef ref="FILE" /> </Async> </Appenders> <Loggers> <!-- Setup for root logger with AsyncAppender --> <Root level="info"> <AppenderRef ref="ASYNC_FILE" /> </Root> </Loggers> </Configuration>
Deploying microservice
Run server (start/start.sh or start/start.cmd in main server directory). Then run maven command to deploy your microservice:
mvn clean package jlupin-platform:deploy@jlupin-deploy --projects implementation --also-make
Check microservice's list to see your microservice (start/control.sh):
./control.sh microservice list
Zone Node Microservice Type Version #Services default NODE_1 queueMicroservice native 1.5.0.3 1 default NODE_1 exchange-rates native 1.5.0.3 1 default NODE_1 welcome-microservice native 1.0.0 1 default NODE_1 channelMicroservice native 1.5.0.3 1 default NODE_1 currency-converter-gbp native 1.5.0.3 1 default NODE_1 exchange servlet 1.5.0.3 4 default NODE_1 http-session-repository native 1.5.0.2 2 default NODE_1 currency-converter-chf native 1.5.0.3 1 default NODE_1 currency-converter-eur native 1.5.0.3 1
You can see your microservice on the list. You can check its status to see if it is running.
./control.sh microservice status welcome-microservice
Zone Node Microservice ProcessID Status Available Activated default NODE_1 welcome-microservice 9822 RUNNING yes yes
Integration tests
Now it is time to add some integration tests and check our microservice. We will put them into separate module called integration test. Let's add it with proper test package structure:
+--additional-files | +--implementation | | | +--[...] | +--integration-test | | | +--src | | | | | +--test | | | | | +--java | | | | | | | +--com | | | | | | | +--example | | | | | | | +--application | | | | | | | +--base | | | | | +--resources | | | +--pom.xml | +--interfaces | | | +--[...] | +--pom.xml
integration-test/pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <artifactId>welcome-microservice</artifactId> <groupId>com.example.application</groupId> <version>1.0.0</version> <relativePath>../pom.xml</relativePath> </parent> <artifactId>welcome-microservice-integration-test</artifactId> <properties> <maven.surefire.skipTests>true</maven.surefire.skipTests> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>com.example.application</groupId> <artifactId>welcome-microservice-interfaces</artifactId> <version>1.0.0</version> <scope>test</scope> </dependency> <dependency> <groupId>com.jlupin</groupId> <artifactId>jlupin-client-assembly</artifactId> <version>${jlupin.platform.client.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j-impl</artifactId> <version>${log4j.slf4j.bridge.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> </plugin> </plugins> </build> </project>
Add module into modules section inside top level pom.xml file:
[...] <modules> <module>interfaces</module> <module>implementation</module> <module>integration-test</module> </modules> [...]
Now create base class with delegators.
package com.example.application.base; import com.jlupin.common.various.JLupinMainServerInZoneConfiguration; import com.jlupin.impl.client.util.JLupinClientUtil; import com.jlupin.interfaces.client.delegator.JLupinDelegator; import com.jlupin.interfaces.client.delegator.exception.JLupinDelegatorException; import com.jlupin.interfaces.common.enums.PortType; import org.junit.After; import org.junit.Before; public abstract class BaseTest { private final JLupinMainServerInZoneConfiguration[] mainServerInZoneConfigurations; private final JLupinDelegator jLupinDelegator; public BaseTest() { mainServerInZoneConfigurations = new JLupinMainServerInZoneConfiguration[]{ new JLupinMainServerInZoneConfiguration("NODE_1", "127.0.0.1", 9090, 9095, 9096, 9097) }; jLupinDelegator = JLupinClientUtil.generateOuterMicroserviceLoadBalancerDelegator(PortType.JLRMC, mainServerInZoneConfigurations); } public JLupinDelegator getJLupinDelegator() { return jLupinDelegator; } @Before public void before() { try { jLupinDelegator.start(); } catch (JLupinDelegatorException e) { throw new IllegalStateException("can not start jlupin delegator caused by:", e); } } @After public void after() { try { jLupinDelegator.stop(); } catch (JLupinDelegatorException e) { throw new IllegalStateException("can not stop jlupin delegator caused by:", e); } JLupinClientUtil.closeResources(); } }
This base class is configured to make requests to localhost with default JLupin Platform ports' configuration. You can also see that default balancer is used. Now create test class.
package com.example.application; import com.example.application.base.BaseTest; import com.example.application.service.interfaces.WelcomeService; import com.jlupin.impl.client.util.JLupinClientUtil; import org.junit.Test; import java.util.Collections; import static org.junit.Assert.assertEquals; public class CurrencyConverterTest extends BaseTest { @Test public void exampleTest() { WelcomeService service = JLupinClientUtil.generateRemote(getJLupinDelegator(), "welcome-microservice", WelcomeService.class); assertEquals(Collections.singletonMap("message", "Hello Piotr!"), service.getWelcomeMessage(Collections.singletonMap("name", "Piotr"))); } }
Test class contains two tests. One is using JLRMC entry point (built-in remote method call protocol) to call service. Through JLupinProxyObjectProducer appropriate stub is created and assigned to service interfaces. This way remote calls are extremely easy to use. With combined power of Spring and Inversion of Control joining and splitting microservice is a piece of cake.
The last thing is to again configure logger (Log4j2) for this tests. Add log4j2.xml file to test resources.
<?xml version="1.0" encoding="UTF-8"?> <!-- ===================================================================== --> <!-- --> <!-- Log4j2 Configuration --> <!-- --> <!-- ===================================================================== --> <!-- | For more configuration information and examples see the Apache Log4j2 | website: https://logging.apache.org/log4j/2.x/index.html --> <Configuration status="WARN"> <Appenders> <Console name="STDOUT" target="SYSTEM_OUT"> <!-- The default pattern: Date Priority [Category] (Thread) Message\n --> <PatternLayout pattern="%d %-5p [%c] (%t) %m%n" /> </Console> <!-- AsyncAppender for high performance --> <Async name="ASYNC_STDOUT"> <BufferSize>1000</BufferSize> <AppenderRef ref="STDOUT" /> </Async> </Appenders> <Loggers> <!-- Setup for root logger with AsyncAppender --> <Root level="info"> <AppenderRef ref="ASYNC_STDOUT" /> </Root> </Loggers> </Configuration>
It is configured to write logs to standard out. Now you're ready to run tests.
mvn clean integration-test --projects integration-test --also-make
[INFO] Scanning for projects... [..] [INFO] ------------------------------------------------------- [INFO] T E S T S [INFO] ------------------------------------------------------- [INFO] Running com.example.application.CurrencyConverterTest 2018-10-11 09:35:14,650 INFO [com.jlupin.impl.balancer.base.JLupinBaseLoadBalancer] (main) MESSAGE ID:22 METHOD:start LINE:897 LOG:load balancer type:OUTER_CLIENT with settings: connectionConfigurationToConnectWithLocalMicroservicesMap:{} jLupinBalancerConnectionToMainServersAsPeersConfiguration:JLupinBalancerConnectionToServerConfiguration{address='null', jlrmcPort=0, queuePort=0, transmissionPort=0, informationPort=0, connectionTimeoutInMilliseconds=2000, readTimeoutInMilliseconds=300000, checkAvailableScript='null', isKeepAlive=false, isOOBInline=false, isTcpNoDelay=false, isReuseAddress=false, sendBufferSize=0, receiveBufferSize=0, soLinger=0, trafficClass=0} invoked from: java.lang.Thread;getStackTrace;1559 com.jlupin.impl.util.JLupinUtil;getCurrentFullStackAsString;634 com.jlupin.impl.balancer.base.JLupinBaseLoadBalancer;<init>;128 com.jlupin.impl.balancer.ext.impl.repeat.JLupinAbstractRepeatLoadBalancer;<init>;26 com.jlupin.impl.balancer.ext.impl.roundrobin.JLupinRoundRobinLoadBalancerImpl;<init>;43 com.jlupin.impl.client.util.JLupinClientUtil;generateLoadBalancer;66 com.jlupin.impl.client.util.JLupinClientUtil;generateOuterMicroserviceLoadBalancerDelegator;131 com.example.application.base.BaseTest;<init>;19 com.example.application.CurrencyConverterTest;<init>;12 sun.reflect.NativeConstructorAccessorImpl;newInstance0;-2 sun.reflect.NativeConstructorAccessorImpl;newInstance;62 sun.reflect.DelegatingConstructorAccessorImpl;newInstance;45 java.lang.reflect.Constructor;newInstance;423 org.junit.runners.BlockJUnit4ClassRunner;createTest;217 org.junit.runners.BlockJUnit4ClassRunner$1;runReflectiveCall;266 org.junit.internal.runners.model.ReflectiveCallable;run;12 org.junit.runners.BlockJUnit4ClassRunner;methodBlock;263 org.junit.runners.BlockJUnit4ClassRunner;runChild;78 org.junit.runners.BlockJUnit4ClassRunner;runChild;57 org.junit.runners.ParentRunner$3;run;290 org.junit.runners.ParentRunner$1;schedule;71 org.junit.runners.ParentRunner;runChildren;288 org.junit.runners.ParentRunner;access$000;58 org.junit.runners.ParentRunner$2;evaluate;268 org.junit.runners.ParentRunner;run;363 org.apache.maven.surefire.junit4.JUnit4Provider;execute;365 org.apache.maven.surefire.junit4.JUnit4Provider;executeWithRerun;272 org.apache.maven.surefire.junit4.JUnit4Provider;executeTestSet;236 org.apache.maven.surefire.junit4.JUnit4Provider;invoke;159 org.apache.maven.surefire.booter.ForkedBooter;invokeProviderInSameClassLoader;386 org.apache.maven.surefire.booter.ForkedBooter;runSuitesInProcess;323 org.apache.maven.surefire.booter.ForkedBooter;main;143 started correctly 2018-10-11 09:35:14,663 INFO [com.jlupin.impl.balancer.ext.impl.roundrobin.JLupinRoundRobinLoadBalancerImpl] (main) MESSAGE ID:52 METHOD:start LINE:111 LOG:computing node thread started correctly 2018-10-11 09:35:14,708 INFO [com.jlupin.impl.balancer.base.JLupinBaseLoadBalancer] (main) MESSAGE ID:26 METHOD:stop LINE:1014 LOG:load balancer type:OUTER_CLIENT, load balancer type:OUTER_CLIENT correctly stopped [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.844 s - in com.example.application.CurrencyConverterTest [INFO] [INFO] Results: [INFO] [INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] [WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent! The file encoding for reports output files should be provided by the POM property ${project.reporting.outputEncoding}. [INFO] ------------------------------------------------------------------------ [INFO] Reactor Summary: [INFO] [INFO] welcome-microservice ............................... SUCCESS [ 0.213 s] [INFO] welcome-microservice-interfaces .................... SUCCESS [ 2.079 s] [INFO] welcome-microservice-integration-test .............. SUCCESS [ 3.967 s] [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 6.444 s [INFO] Finished at: 2018-10-11T09:35:15+02:00 [INFO] Final Memory: 19M/209M [INFO] ------------------------------------------------------------------------
Elastic API
If you want you can call same services and their methods with text communication with use of built-in Elastic API. Let's start with ROA (Remote Object Access) call:
curl -X POST -H "Content-Type: application/json" -d "{\"name\":\"Piotr\"}" localhost:8082/welcome-microservice/welcomeService/getWelcomeMessage
As a result you should see:
{"message":"Hello Piotr!"}
This way JLupin Platform deserialize whole request body into method argument and serialize its result into response body. It is similar to RestController used by Spring.
Other option is to used RMC (Remote Method Call). JLupin Platform is configured to use ROA by default, that's why we must specify api id in request header.
curl -X POST -H "Content-Type: application/json" -H "X-JLNS-Api-Id: RMC" -d "[{\"name\":\"Piotr\"}]" localhost:8082/welcome-microservice/welcomeService/getWelcomeMessage
The result is same as for ROA - return value is serialized into response body.
{"message":"Hello Piotr!"}
Elastic API calls are more precisely described in this tutorial.
Done tutorial
You can download project which is result of making this tutorial from GitHub: https://github.com/jlupin/creating-native-microservice-jlp-1503
RATE & DISCUSS (0)