Tutorial on Microservices with Kotlin, SpringBoot, Akka and Docker – part 3

Intro

In the previous post we have built our first microservice, the persistence one. Now we will add a new one to simulate a long lasting requesting, i.e. a request that may take long time to be fulfilled.  Only the crucial aspects of the implementation will be covered here, so you may download the full code from the repository:

 git clone https://github.com/gitgabrio/container-microservices-tutorial-3.git

timeconsuming-service

For this tutorial we will reuse the User entity defined in service-common.Let’s begin adding the module declaration to the parent pom:

...
   </parent>
      <modules>
        <module>servicecommon</module>
        <module>registrationservice</module>
        <module>persistenceservice</module>
        <module>timeconsumingservice</module>
        <module>docker</module>
    </modules>
    <properties>
...

This is the timeconsuming-service pom:

<?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">
    <parent>
        <artifactId>container-microservice</artifactId>
        <groupId>net.microservices.tutorial</groupId>
        <version>0.1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>timeconsumingservice</artifactId>

    <properties>
        <start-class>net.microservices.tutorial.timeconsumingservice.TimeConsumingServer</start-class>
        <finalName>timeconsumingservice-${project.version}</finalName>
        <service.port>3333</service.port>
        <container.ip>localhost</container.ip>
        <rs.port>1111</rs.port>
        <rs.ip>localhost</rs.ip>
    </properties>
    <build>
        <finalName>${finalName}</finalName>
    </build>
    <dependencies>
        <dependency>
            <groupId>net.microservices.tutorial</groupId>
            <artifactId>servicecommon</artifactId>
            <version>0.1</version>
        </dependency>
    </dependencies>

</project>

code

Most of the code and configuration is really similar to the persistence-service one, so I won’t repeat the details. But there are some differences in the Controller and Service related to the asynchronous call:
net/microservices/tutorial/timeconsumingservice/services/TimeConsumingService.kt:

...
    @Throws(Exception::class)
    fun findAll(): List<UserDTO>? {
        logger.info("findAll() invoked")
        val toReturn: ArrayList<UserDTO> = ArrayList()
        repeat(6) { i ->
            val toAdd: UserDTO = createUserEntity(i)
            toReturn.add(toAdd)
            try {
                Thread.sleep(1000)
            } catch (e : InterruptedException) {
                logger.info("I've been interrupted")
            }
        }
        return toReturn
    }
...

This service returns five users just created on demand, but with some delay, to simulate a time consuming elaboration (it should take almost one minute to complete).

net/microservices/tutorial/timeconsumingservice/controllers/TimeConsumingController.kt:

...
    /*
     Use for long-polling
     */
    @RequestMapping("/deferredpersons")
    @Async // This means it will run on a different thread
    fun allDeferredUsers(): DeferredResult<List<UserDTO>?> {
        logger.info("web-service allDeferredUsers() invoked")
        val toReturn: DeferredResult<List<UserDTO>?> = DeferredResult()
        Thread({
            val users = timeConsumingService.findAll()
            logger.info("web-service allDeferredUsers() found: " + users!!)
            toReturn.setResult(users)
        }, "MyThread-$counter").start()
        counter += 1
        return toReturn
    }
...

This controller is actually implementing a long polling, returning a Spring Web DeferredResult.Basically, the actual data is populated inside the thread, and the client calling this method should do it in asynchronous manner, as we will see in the next part.

image creation

The docker image management is identical as what done before for the other services, beside the different image name and listening port.
docker/pom.xml:

...
 <properties>
      ...
        <!-- services properties -->
        <registration.service.port>1111</registration.service.port>
        <persistence.service.port>2222</persistence.service.port>
        <timeconsuming.service.port>3333</timeconsuming.service.port>
    </properties>
</properties>

    <dependencies>
        <dependency>
            <groupId>net.microservices.tutorial</groupId>
            <artifactId>registrationservice</artifactId>
            <version>0.1</version>
        </dependency>
        <dependency>
            <groupId>net.microservices.tutorial</groupId>
            <artifactId>persistenceservice</artifactId>
            <version>0.1</version>
        </dependency>
        <dependency>
            <groupId>net.microservices.tutorial</groupId>
            <artifactId>timeconsumingservice</artifactId>
            <version>0.1</version>
        </dependency>
    </dependencies>
...

After installing the artifacts and starting docker, we should have the timeconsuming service registered:

and the image running here;

with the time consuming service; here’s the result (of course, actual data will vary):

Conclusion

Well, you will find the &ltg;image&gt, definition (and all the other missing stuff) in the project:

git clone https://github.com/gitgabrio/container-microservices-tutorial-3.git

In the next part we will add another Eureka client container that will talk with persistence and the timeconsuming services so… stay tuned!!!

Any comment and suggestion will be greatly appreciated!!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s