JLUPIN PLATFORM WEBSITE
tutorials
  • Rating:
  • Views: 38
  • Author: JLupin
  • Skill level: easy
  • Comments: 0

Overview

In this tutorial you will see how to configure your microservice to call other ones. We will create application called exchange. It will convert money you send to other currencies. It will contain three microservices: two native, one servlet. This tutorial will show how to create connections: servlet-native, native-native.

Requirements

To complete this tutorial you will need JLupin Platform version 1.5.0.3. You can download it from here. You should also done two previous tutorials about basic microservice's types and their creation: native, servlet.

Configure project

Create project with three microservices called: exchange-rates (native), currency-converter (native), exchange (servlet). Create also common-pojo project to share pojo classes with all microservices. Maven tool will be used.

Figure 1. The example application.

Below directory structure is shown:

+--common-pojo
|  |
|  +--src
|  |  |
|  |  +--main
|  |     |
|  |     +--java
|  |
|  +--pom.xml
| 
+--currency-converter
|  |
|  +--additional-files
|  |
|  +--implementation
|  |  |
|  |  +--src
|  |  |  |
|  |  |  +--main
|  |  |     |
|  |  |     +--java
|  |  |
|  |  +--pom.xml
|  |
|  +--interfaces
|     |
|     +--src
|     |  |
|     |  +--main
|     |     |
|     |     +--java
|     |
|     +--pom.xml
|
+--exchange
|  |
|  +--additional-files
|  |
|  +--implementation
|     |
|     +--src
|     |  |
|     |  +--main
|     |     |
|     |     +--java
|     |     |
|     |     +--resources
|     |
|     +--pom.xml
|
+--exchange-rates
|  |
|  +--additional-files
|  |
|  +--implementation
|  |  |
|  |  +--src
|  |  |  |
|  |  |  +--main
|  |  |     |
|  |  |     +--java
|  |  |
|  |  +--pom.xml
|  |
|  +--interfaces
|     |
|     +--src
|     |  |
|     |  +--main
|     |     |
|     |     +--java
|     |
|     +--pom.xml
|
+--pom.xml

Now configure all pom.xml files. Their content is shown below.

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>

    <groupId>com.example.exchange</groupId>
    <artifactId>exchange-project</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>

    <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>common-pojo</module>
        <module>currency-converter/interfaces</module>
        <module>currency-converter/implementation</module>
        <module>exchange/implementation</module>
        <module>exchange-rates/interfaces</module>
        <module>exchange-rates/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>

common-pojo/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>exchange-project</artifactId>
        <groupId>com.example.exchange</groupId>
        <version>1.0.0</version>
        <relativePath>./../pom.xml</relativePath>
    </parent>

    <artifactId>common-pojo</artifactId>
</project>

currency-converter/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>exchange-project</artifactId>
        <groupId>com.example.exchange</groupId>
        <version>1.0.0</version>
        <relativePath>./../../pom.xml</relativePath>
    </parent>

    <name>currency-converter</name>
    <artifactId>currency-converter-implementation</artifactId>

    <properties>
        <jlupin.skipDeploy>false</jlupin.skipDeploy>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.context.version}</version>
        </dependency>

        <dependency>
            <groupId>com.example.exchange</groupId>
            <artifactId>currency-converter-interfaces</artifactId>
            <version>1.0.0</version>
        </dependency>

        <dependency>
            <groupId>com.example.exchange</groupId>
            <artifactId>common-pojo</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>

currency-converter/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>exchange-project</artifactId>
        <groupId>com.example.exchange</groupId>
        <version>1.0.0</version>
        <relativePath>./../../pom.xml</relativePath>
    </parent>

    <artifactId>currency-converter-interfaces</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.example.exchange</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>

exchange/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>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
    </parent>

    <name>exchange</name>
    <groupId>com.example.exchange</groupId>
    <artifactId>exchange-implementation</artifactId>
    <packaging>war</packaging>
    <version>1.0.0</version>

    <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>

    <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.servlet.monitor.version>1.5.0.0</jlupin.servlet.monitor.version>

        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- JLupin dependencies -->
        <dependency>
            <groupId>com.jlupin</groupId>
            <artifactId>jlupin-client-assembly</artifactId>
            <version>${jlupin.platform.client.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.jlupin</groupId>
            <artifactId>jlupin-spring-boot-2-servlet-monitor</artifactId>
            <version>${jlupin.servlet.monitor.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-logging</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.name}</finalName>

        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <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>
                            <includeDependenciesInZip>false</includeDependenciesInZip>
                        </configuration>
                    </execution>
                    <execution>
                        <id>jlupin-deploy</id>
                        <phase>pre-integration-test</phase>
                        <goals>
                            <goal>deploy</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

exchange-rates/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>exchange-project</artifactId>
        <groupId>com.example.exchange</groupId>
        <version>1.0.0</version>
        <relativePath>./../../pom.xml</relativePath>
    </parent>

    <name>exchange-rates</name>
    <artifactId>exchange-rates-implementation</artifactId>

    <properties>
        <jlupin.skipDeploy>false</jlupin.skipDeploy>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.context.version}</version>
        </dependency>

        <dependency>
            <groupId>com.example.exchange</groupId>
            <artifactId>exchange-rates-interfaces</artifactId>
            <version>1.0.0</version>
        </dependency>

        <dependency>
            <groupId>com.example.exchange</groupId>
            <artifactId>common-pojo</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>

exchange-rates/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>exchange-project</artifactId>
        <groupId>com.example.exchange</groupId>
        <version>1.0.0</version>
        <relativePath>./../../pom.xml</relativePath>
    </parent>

    <artifactId>exchange-rates-interfaces</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.example.exchange</groupId>
            <artifactId>common-pojo</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>
</project>

If you configure everything you are ready to start adding implementation.

Implementation

At first create suitable package structure. In this tutorial com.example.exchange will be used as main package. Recommended structure (also used by this tutorial) is presented below.

+--common-pojo
|  |
|  +--src
|  |  |
|  |  +--main
|  |     |
|  |     +--java
|  |        |
|  |        +--com
|  |           |
|  |           +--example
|  |              |
|  |              +--exchange
|  |                 |
|  |                 +--pojo
|  |
|  +--pom.xml
|
+--currency-converter
|  |
|  +--additional-files
|  |
|  +--implementation
|  |  |
|  |  +--src
|  |  |  |
|  |  |  +--main
|  |  |     |
|  |  |     +--java
|  |  |        |
|  |  |        +--com
|  |  |           |
|  |  |           +--example
|  |  |              |
|  |  |              +--exchange
|  |  |                 |
|  |  |                 +--bean
|  |  |                 |  |
|  |  |                 |  +--impl
|  |  |                 |  |
|  |  |                 |  +--interfaces
|  |  |                 |  |
|  |  |                 |  +--pojo
|  |  |                 |
|  |  |                 +--configuration
|  |  |                 |
|  |  |                 +--dao
|  |  |                 |  |
|  |  |                 |  +--impl
|  |  |                 |  |
|  |  |                 |  +--interfaces
|  |  |                 |  |
|  |  |                 |  +--pojo
|  |  |                 |
|  |  |                 +--service
|  |  |                    |
|  |  |                    +--impl
|  |  |
|  |  +--pom.xml
|  |
|  +--interfaces
|     |
|     +--src
|     |  |
|     |  +--main
|     |     |
|     |     +--java
|     |        |
|     |        +--com
|     |           |
|     |           +--example
|     |              |
|     |              +--exchange
|     |                 |
|     |                 +--service
|     |                    |
|     |                    +--interfaces
|     |                    |
|     |                    +--pojo
|     |
|     +--pom.xml
|
+--exchange
|  |
|  +--additional-files
|  |
|  +--implementation
|     |
|     +--src
|     |  |
|     |  +--main
|     |     |
|     |     +--java
|     |        |
|     |        +--com
|     |           |
|     |           +--example
|     |              |
|     |              +--exchange
|     |                 |
|     |                 +--configuration
|     |                 |
|     |                 +--controller
|     |
|     +--pom.xml
|
+--exchange-rates
|  |
|  +--additional-files
|  |
|  +--implementation
|  |  |
|  |  +--src
|  |  |  |
|  |  |  +--main
|  |  |     |
|  |  |     +--java
|  |  |        |
|  |  |        +--com
|  |  |           |
|  |  |           +--example
|  |  |              |
|  |  |              +--exchange
|  |  |                 |
|  |  |                 +--bean
|  |  |                 |  |
|  |  |                 |  +--impl
|  |  |                 |  |
|  |  |                 |  +--interfaces
|  |  |                 |  |
|  |  |                 |  +--pojo
|  |  |                 |
|  |  |                 +--configuration
|  |  |                 |
|  |  |                 +--dao
|  |  |                 |  |
|  |  |                 |  +--impl
|  |  |                 |  |
|  |  |                 |  +--interfaces
|  |  |                 |  |
|  |  |                 |  +--pojo
|  |  |                 |
|  |  |                 +--service
|  |  |                    |
|  |  |                    +--impl
|  |  |
|  |  +--pom.xml
|  |
|  +--interfaces
|     |
|     +--src
|     |  |
|     |  +--main
|     |     |
|     |     +--java
|     |        |
|     |        +--com
|     |           |
|     |           +--example
|     |              |
|     |              +--exchange
|     |                 |
|     |                 +--service
|     |                    |
|     |                    +--interfaces
|     |                    |
|     |                    +--pojo
|     |
|     +--pom.xml
|
+--pom.xml

Now add configuration files. They are same as the one in previous tutorial. You can copy them from below:

currency-converter

package com.example.exchange.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 CurrencyConverterJLupinConfiguration extends JLupinAbstractApplicationContainerProducer {
    @Override
    public JLupinApplicationContainer produceJLupinApplicationContainer() {
        return new JLupinAbstractSpringApplicationContainer() {
            @Override
            public AbstractApplicationContext getAbstractApplicationContext() {
                return new AnnotationConfigApplicationContext(CurrencyConverterSpringConfiguration.class);
            }
        };
    }
}
package com.example.exchange.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.exchange")
public class CurrencyConverterSpringConfiguration {
}

exchange

package com.example.exchange.configuration;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({
    "com.example.exchange",
    "com.jlupin.servlet.monitor.configuration"
})
public class ExchangeSpringConfiguration {
}
package com.example.exchange;

import com.example.exchange.configuration.ExchangeSpringConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootApplicationStarter {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(ExchangeSpringConfiguration.class, args);
    }
}

exchange-rates

package com.example.exchange.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 ExchangeRatesJLupinConfiguration extends JLupinAbstractApplicationContainerProducer {
    @Override
    public JLupinApplicationContainer produceJLupinApplicationContainer() {
        return new JLupinAbstractSpringApplicationContainer() {
            @Override
            public AbstractApplicationContext getAbstractApplicationContext() {
                return new AnnotationConfigApplicationContext(ExchangeRatesSpringConfiguration.class);
            }
        };
    }
}
package com.example.exchange.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.exchange")
public class ExchangeRatesSpringConfiguration {
}

Configuration is done. Let's implement microservices.

common-pojo

We will use common enum with currencies through all microservices. Let's crate it inside common-pojo module.

package com.example.exchange.pojo;

public enum Currency {
    EUR, USD, GBP
}

exchange-rates

This microservice will be responsible for returning actual exchange rates. Add interface to interface module and implementation to implementation module.

package com.example.exchange.service.interfaces;

import com.example.exchange.pojo.Currency;

import java.math.BigDecimal;

public interface ExchangeRatesService {
    BigDecimal getRate(Currency from, Currency to);
}
package com.example.exchange.service.impl;

import com.example.exchange.pojo.Currency;
import com.example.exchange.service.interfaces.ExchangeRatesService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

@Service("exchangeRatesService")
public class ExchangeRatesServiceImpl implements ExchangeRatesService {
    private Map<Pair, BigDecimal> rates;

    public ExchangeRatesServiceImpl() {
        rates = new HashMap<>();
        initRates();
    }

    private void initRates() {
        rates.put(new Pair(Currency.USD, Currency.EUR), BigDecimal.valueOf(0.89389));
        rates.put(new Pair(Currency.EUR, Currency.USD), BigDecimal.valueOf(1.11871));
        rates.put(new Pair(Currency.USD, Currency.GBP), BigDecimal.valueOf(0.78139));
        rates.put(new Pair(Currency.GBP, Currency.USD), BigDecimal.valueOf(1.27978));
        rates.put(new Pair(Currency.EUR, Currency.GBP), BigDecimal.valueOf(0.87416));
        rates.put(new Pair(Currency.GBP, Currency.EUR), BigDecimal.valueOf(1.14396));
    }

    @Override
    public BigDecimal getRate(Currency from, Currency to) {
        return rates.get(new Pair(from, to));
    }

    private class Pair {
        private Currency from;
        private Currency to;

        Pair(Currency from, Currency to) {
            this.from = from;
            this.to = to;
        }

        public Currency getFrom() {
            return from;
        }

        public Currency getTo() {
            return to;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Pair pair = (Pair) o;
            if (from != pair.from) return false;
            return to == pair.to;
        }

        @Override
        public int hashCode() {
            int result = from.hashCode();
            result = 31 * result + to.hashCode();
            return result;
        }
    }
}

For this tutorial exchange rates are constant. Remember to enable microservice for remote invocation by modifying configuration file.

package com.example.exchange.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.exchange")
public class ExchangeRatesSpringConfiguration {
    @Bean(name = "jLupinRegularExpressionToRemotelyEnabled")
    public List getRemotelyBeanList() {
        List<String> list = new ArrayList<>();
        list.add("exchangeRatesService");
        return list;
    }
}

That's all. Microservice is ready.

currency-converter

This microservice will communicate with exchange-rates microservice. We need to configure it to allow remote calls. Change configuration file to create bean of ExchangeRatesService type which will be proxy object.

package com.example.exchange.configuration;

import com.example.exchange.service.interfaces.ExchangeRatesService;
import com.jlupin.impl.client.util.JLupinClientUtil;
import com.jlupin.interfaces.client.delegator.JLupinDelegator;
import com.jlupin.interfaces.common.enums.PortType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan("com.example.exchange")
public class CurrencyConverterSpringConfiguration {
    @Bean
    public JLupinDelegator getJLupinDelegator() {
        return JLupinClientUtil.generateInnerMicroserviceLoadBalancerDelegator(PortType.JLRMC);
    }

    @Bean(name = "exchangeRatesService")
    public ExchangeRatesService getExchangeRatesService() {
        return JLupinClientUtil.generateRemote(getJLupinDelegator(), "exchange-rates", ExchangeRatesService.class);
    }
}

As you can see JLupin Platform gives tool to create proxy object which behaves like normal internal service but invocation is done remotely. And this is all. This few lines allows to autowire ExchangeRatesService.

Now create CurrencyConverterService. Put interface into interfaces module and implementation into implementation module.

package com.example.exchange.service.interfaces;

import com.example.exchange.pojo.Currency;

import java.math.BigDecimal;

public interface CurrencyConverterService {
    BigDecimal convert(BigDecimal value, Currency from, Currency to);
}
package com.example.exchange.service.impl;

import com.example.exchange.pojo.Currency;
import com.example.exchange.service.interfaces.CurrencyConverterService;
import com.example.exchange.service.interfaces.ExchangeRatesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

@Service("currencyConverterService")
public class CurrencyConverterServiceImpl implements CurrencyConverterService {
    @Autowired
    private ExchangeRatesService exchangeRatesService;

    @Override
    public BigDecimal convert(BigDecimal value, Currency from, Currency to) {
        final BigDecimal rate = exchangeRatesService.getRate(from, to);
        return rate != null ? value.multiply(rate).setScale(2, BigDecimal.ROUND_HALF_UP) : null;
    }
}

You can see there how easy is using remote service. From CurrencyConverterServiceImpl point of view it is transparent if bean is local or remote service thanks to Spring Inversion of Control mechanism. Remember to enable microservice for remote invocation by modifying configuration file.

package com.example.exchange.configuration;

import com.example.exchange.service.interfaces.ExchangeRatesService;
import com.jlupin.impl.client.util.JLupinClientUtil;
import com.jlupin.interfaces.client.delegator.JLupinDelegator;
import com.jlupin.interfaces.common.enums.PortType;
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.exchange")
public class CurrencyConverterSpringConfiguration {
    @Bean
    public JLupinDelegator getJLupinDelegator() {
        return JLupinClientUtil.generateInnerMicroserviceLoadBalancerDelegator(PortType.JLRMC);
    }

    @Bean(name = "exchangeRatesService")
    public ExchangeRatesService getExchangeRatesService() {
        return JLupinClientUtil.generateRemote(getJLupinDelegator(), "exchange-rates", ExchangeRatesService.class);
    }

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

Also update your currency-converter dependencies in pom.xml:

<project>
[...]
    <dependencies>
    [...]
        <dependency>
            <groupId>com.example.exchange</groupId>
            <artifactId>exchange-rates-interfaces</artifactId>
            <version>1.0.0</version>
        </dependency>
    [...]
    </dependencies>
[...]
</project>

Next microservice is done. Now implement the last one.

exchange

This microservice will call currency-converter microservice. We need to configure it to allow communication. To do so edit Spring configuration file.

package com.example.exchange.configuration;

import com.example.exchange.service.interfaces.CurrencyConverterService;
import com.jlupin.impl.client.util.JLupinClientUtil;
import com.jlupin.interfaces.client.delegator.JLupinDelegator;
import com.jlupin.interfaces.common.enums.PortType;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({
    "com.example.exchange",
    "com.jlupin.servlet.monitor.configuration"
})
public class ExchangeSpringConfiguration {
    @Bean
    public JLupinDelegator getJLupinDelegator() {
        return JLupinClientUtil.generateInnerMicroserviceLoadBalancerDelegator(PortType.JLRMC);
    }

    @Bean(name = "currencyConverterService")
    public CurrencyConverterService getCurrencyConverterService() {
        return JLupinClientUtil.generateRemote(getJLupinDelegator(), "currency-converter", CurrencyConverterService.class);
    }
}

Also update your currency-converter dependencies in pom.xml:

<project>
[...]
    <dependencies>
    [...]
        <dependency>
            <groupId>com.example.exchange</groupId>
            <artifactId>currency-converter-interfaces</artifactId>
            <version>1.0.0</version>
        </dependency>
    [...]
    </dependencies>
[...]
</project>

Again you can see created bean with type CurrencyConverterService. It can be now autowired in other services. We are going to add REST controller now. It will be called ExchangeController. But first create new package for it to have same structure like below:

+--com
   |
   +--example
      |
      +--exchange
         |
         +--configuration
         |
         +--controller
            |
            +--exchange
               |
               +--in
               |
               +--out

Packages in and out should contain data transfer objects definition for input and output. Create these objects and controller.

package com.example.exchange.controller.exchange.in;

import com.example.exchange.pojo.Currency;

import java.math.BigDecimal;

public class ConvertIn {
    private BigDecimal value;
    private Currency currency;

    public BigDecimal getValue() {
        return value;
    }

    public void setValue(BigDecimal value) {
        this.value = value;
    }

    public Currency getCurrency() {
        return currency;
    }

    public void setCurrency(Currency currency) {
        this.currency = currency;
    }
}
package com.example.exchange.controller.exchange.out;

import com.example.exchange.pojo.Currency;

import java.math.BigDecimal;

public class ConvertOut {
    private BigDecimal value;
    private Currency currency;

    public BigDecimal getValue() {
        return value;
    }

    public void setValue(BigDecimal value) {
        this.value = value;
    }

    public Currency getCurrency() {
        return currency;
    }

    public void setCurrency(Currency currency) {
        this.currency = currency;
    }
}
package com.example.exchange.controller.exchange;

import com.example.exchange.controller.exchange.in.ConvertIn;
import com.example.exchange.controller.exchange.out.ConvertOut;
import com.example.exchange.pojo.Currency;
import com.example.exchange.service.interfaces.CurrencyConverterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.LinkedList;
import java.util.List;

@RestController
public class ExchangeController {
    @Autowired
    private CurrencyConverterService currencyConverterService;

    @CrossOrigin
    @PostMapping("/convert")
    public List<ConvertOut> convert(@RequestBody ConvertIn in) {
        List<ConvertOut> result = new LinkedList<ConvertOut>();

        for (final Currency currency : Currency.values()) {
            final ConvertOut out = new ConvertOut();
            out.setCurrency(currency);
            if (currency.equals(in.getCurrency())) {
                out.setValue(in.getValue());
            } else {
                out.setValue(currencyConverterService.convert(in.getValue(), in.getCurrency(), currency));
            }
            result.add(out);
        }

        return result;
    }
}

Ok, implementation is done. Just add configuration files to proper additional-files directories.

exchange-rates

configuration.yml

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.0.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
  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.exchange.configuration.ExchangeRatesJLupinConfiguration'
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

log4j2.xml

<?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/exchange-rates_log4j2_status.log">
    <!-- Extract log directory and file name into variables -->
    <Properties>
        <Property name="logDirectory">../logs/microservice/exchange-rates</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>/.%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>

currency-converter

configuration.yml

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.0.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
  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.exchange.configuration.CurrencyConverterJLupinConfiguration'
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

log4j2.xml

<?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/currency-converter_log4j2_status.log">
    <!-- Extract log directory and file name into variables -->
    <Properties>
        <Property name="logDirectory">../logs/microservice/currency-converter</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>/.%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>

exchange

servlet_configuration.yml

SERVERS:
  HTTP:
    type: spring_boot
    httpPrimaryPort: -1
    httpSecondaryPort: -1
    waitForFinishExecuteAllRequests: true
    waitToShutdownThreadsOnStop: 5000
    springBootLoaderClassName: org.springframework.boot.loader.WarLauncher
    contextName: /exchange
    isStartOnMainServerInitialize: true
    httpStickySession: false
  TRANSMISSION:
    readTimeout: 480000
    isWaitForFinishExecuteAllRequests: false
    waitToShutdownThreadsOnStop: 60000
    backlog: 0
    receiveBufferSize: 0
    isReuseAddress: false
    threadPoolSize: 8
    isLogPeriodicOnDebug: true
    isDestroyThreadOnTimeout: false
    threadExecutingTimeOut: 3600000
    isStartOnMainServerInitialize: true
PROPERTIES:
  platformVersion: '1.5.0.3'
  #jvmOptions1: '-Xms128M -Xmx512M -agentlib:jdwp=transport=dt_socket,address=12998,server=y,suspend=n'
  jvmOptions1: '-Xms128M -Xmx512M' #jvmOptions_2 - default the same as jvmOptions_1
  #jvmOptions2: '-Xms128M -Xmx512M'
  externalPort: '8000'
  version: '1.0.0'
  switchDelayTime: 1000
  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: 5
  waitForProcessInitResponseTimeInMillis: 90000
  waitForProcessStartResponseTimeInMillis: 90000
  waitForProcessDestroyResponseTimeInMillis: 30000
  isAllFilesToJVMAppClassLoader: true
  #isStackDumping: true
  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
  isExternalHealthcheck: false
  externalHealthcheckURI: '/sampleURI/'
  httpStickySessionCookieOptions: 'option1=value1'
  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;
                         }'
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

log4j2.xml (put this also inside resources 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/exchange_log4j2_status.log">
    <!-- Extract log directory and file name into variables -->
    <Properties>
        <Property name="logDirectory">../logs/microservice/exchange</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>/.%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>

Now everything is ready for deploying.

Deploying

Run server (start/start.sh or start/start.cmd in main server directory). Then run maven commands to deploy your microservices:

mvn clean package jlupin-platform:deploy@jlupin-deploy --projects exchange-rates/implementation --also-make
mvn clean package jlupin-platform:deploy@jlupin-deploy --projects currency-converter/implementation --also-make
mvn clean package jlupin-platform:deploy@jlupin-deploy --projects exchange/implementation --also-make

Check microservice's list to see your microservices (start/control.sh):

./control.sh microservice list
Zone    Node   Microservice            Type    Version #Services
default NODE_1 currency-converter      native  1.0.0   1
default NODE_1 queueMicroservice       native  1.5.0.3 1
default NODE_1 exchange-rates          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.0.0   1
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 that all microservices are on the list. Now you can check your application with request to created controller:

curl -X POST -H "Content-Type: application/json" -d "{\"value\":12.50, \"currency\":\"USD\"}" localhost:8000/exchange/convert

As a result you should see:

[{"value":11.17,"currency":"EUR"},{"value":12.50,"currency":"USD"},{"value":9.77,"currency":"GBP"}]

Done tutorial

You can download project which is result of making this tutorial from GitHub: https://github.com/jlupin/communication-between-microservices-jlp-1503

RATE & DISCUSS (0)

No comments found.