Show List
Service Discovery Demo - Creating Microservices
For the service discovery demo, first we are going to create microservices "order" and "payment".
We are going to use a multi module project structure. So the microservices will be modules in the project. Multi module project structure helps to easily maintain the code and allows to deploy the modules individually. All the dependencies are specified in the parent POM. Dependent modules can inherit the dependencies. Parent has the packaging as "pom". Child project can have any packaging.
Create Parent Project
Create a parent Spring Boot project with following dependencies:
- Lombok
- Spring Web
- Spring Data JPA
- H2 Database
- Cloud Bootstrap
You can go to the https://start.spring.io/ and add these dependencies to create Spring Boot starter project. You can also create the project in IntelliJ IDE after installing "Spring Assistant" plug in. After plugin is installed, go to create new project and click on "Spring Assistant" plugin. Then provide the group id, artifact id and then select the dependencies.
Delete the "src" folder from the parent project and update the packaging to "pom" in POM.xml.
Parent 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 https://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.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springcloud</groupId>
<artifactId>servicediscovery</artifactId>
<packaging>pom</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>servicediscovery</name>
<description>Demo project for Spring Cloud Service Discovery</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2021.0.4</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
Create "order" microservices (module)
Right click on the project and create a new maven module. Under the parent field, select parent project name and click finish.
Create the model, Dao control and main application class as below:
Order.java model class:
package com.springcloud.servicediscovery.order.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Table(name = "ORDERTBL")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int orderId;
private String itemName;
private int quantity;
private double price;
}
OrderRepo.java:
package com.springcloud.servicediscovery.order.dao;
import com.springcloud.servicediscovery.order.model.Order;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface OrderRepo extends CrudRepository<Order, Integer> {}
OrderController.java:
package com.springcloud.servicediscovery.order.controller;
import com.springcloud.servicediscovery.order.dao.OrderRepo;
import com.springcloud.servicediscovery.order.model.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class OrderController {
@Autowired
private OrderRepo repo;
@GetMapping("/orders")
private List<Order> getAllStudents(){
return (List<Order>) repo.findAll();
}
@PostMapping("/orders")
private Order addOrder(@RequestBody Order newOrder){
return repo.save(newOrder);
}
}
OrderApplication.java :
package com.springcloud.servicediscovery.order;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
application.yml file in the resources folder has properties for server port and to enable h2 console
server:
port: 9001
spring:
h2:
console:
enabled: true
banner.txt file in the resources folder has banner to display on the console when application starts instead of the default Spring Boot banner. Such banner was created from website https://devops.datenkollektiv.de/banner.txt/index.html.
,-----. ,--.
' .-. ' ,--.--. ,-| | ,---. ,--.--.
| | | | | .--' ' .-. | | .-. : | .--'
' '-' ' | | \ `-' | \ --. | |
`-----' `--' `---' `----' `--'
When the spring boot module is run we can see the h2 connection details in the log:
"C:\Program Files\Java\jdk-11.0.15\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.2\lib\idea_rt.jar=57472:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.2\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\mail2\Downloads\servicediscovery\order\target\classes;D:\.m2\repository\org\springframework\boot\spring-boot-starter-data-jpa\2.7.5\spring-boot-starter-data-jpa-2.7.5.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-aop\2.7.5\spring-boot-starter-aop-2.7.5.jar;D:\.m2\repository\org\springframework\spring-aop\5.3.23\spring-aop-5.3.23.jar;D:\.m2\repository\org\aspectj\aspectjweaver\1.9.7\aspectjweaver-1.9.7.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\2.7.5\spring-boot-starter-jdbc-2.7.5.jar;D:\.m2\repository\com\zaxxer\HikariCP\4.0.3\HikariCP-4.0.3.jar;D:\.m2\repository\org\springframework\spring-jdbc\5.3.23\spring-jdbc-5.3.23.jar;D:\.m2\repository\jakarta\transaction\jakarta.transaction-api\1.3.3\jakarta.transaction-api-1.3.3.jar;D:\.m2\repository\jakarta\persistence\jakarta.persistence-api\2.2.3\jakarta.persistence-api-2.2.3.jar;D:\.m2\repository\org\hibernate\hibernate-core\5.6.12.Final\hibernate-core-5.6.12.Final.jar;D:\.m2\repository\org\jboss\logging\jboss-logging\3.4.3.Final\jboss-logging-3.4.3.Final.jar;D:\.m2\repository\net\bytebuddy\byte-buddy\1.12.18\byte-buddy-1.12.18.jar;D:\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;D:\.m2\repository\org\jboss\jandex\2.4.2.Final\jandex-2.4.2.Final.jar;D:\.m2\repository\com\fasterxml\classmate\1.5.1\classmate-1.5.1.jar;D:\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.1.2.Final\hibernate-commons-annotations-5.1.2.Final.jar;D:\.m2\repository\org\glassfish\jaxb\jaxb-runtime\2.3.7\jaxb-runtime-2.3.7.jar;D:\.m2\repository\org\glassfish\jaxb\txw2\2.3.7\txw2-2.3.7.jar;D:\.m2\repository\com\sun\istack\istack-commons-runtime\3.0.12\istack-commons-runtime-3.0.12.jar;D:\.m2\repository\com\sun\activation\jakarta.activation\1.2.2\jakarta.activation-1.2.2.jar;D:\.m2\repository\org\springframework\data\spring-data-jpa\2.7.5\spring-data-jpa-2.7.5.jar;D:\.m2\repository\org\springframework\data\spring-data-commons\2.7.5\spring-data-commons-2.7.5.jar;D:\.m2\repository\org\springframework\spring-orm\5.3.23\spring-orm-5.3.23.jar;D:\.m2\repository\org\springframework\spring-context\5.3.23\spring-context-5.3.23.jar;D:\.m2\repository\org\springframework\spring-tx\5.3.23\spring-tx-5.3.23.jar;D:\.m2\repository\org\springframework\spring-beans\5.3.23\spring-beans-5.3.23.jar;D:\.m2\repository\org\slf4j\slf4j-api\1.7.36\slf4j-api-1.7.36.jar;D:\.m2\repository\org\springframework\spring-aspects\5.3.23\spring-aspects-5.3.23.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-web\2.7.5\spring-boot-starter-web-2.7.5.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter\2.7.5\spring-boot-starter-2.7.5.jar;D:\.m2\repository\org\springframework\boot\spring-boot\2.7.5\spring-boot-2.7.5.jar;D:\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.7.5\spring-boot-autoconfigure-2.7.5.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.7.5\spring-boot-starter-logging-2.7.5.jar;D:\.m2\repository\ch\qos\logback\logback-classic\1.2.11\logback-classic-1.2.11.jar;D:\.m2\repository\ch\qos\logback\logback-core\1.2.11\logback-core-1.2.11.jar;D:\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.17.2\log4j-to-slf4j-2.17.2.jar;D:\.m2\repository\org\apache\logging\log4j\log4j-api\2.17.2\log4j-api-2.17.2.jar;D:\.m2\repository\org\slf4j\jul-to-slf4j\1.7.36\jul-to-slf4j-1.7.36.jar;D:\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\.m2\repository\org\yaml\snakeyaml\1.30\snakeyaml-1.30.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-json\2.7.5\spring-boot-starter-json-2.7.5.jar;D:\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.13.4.2\jackson-databind-2.13.4.2.jar;D:\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.13.4\jackson-annotations-2.13.4.jar;D:\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.13.4\jackson-core-2.13.4.jar;D:\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jdk8\2.13.4\jackson-datatype-jdk8-2.13.4.jar;D:\.m2\repository\com\fasterxml\jackson\datatype\jackson-datatype-jsr310\2.13.4\jackson-datatype-jsr310-2.13.4.jar;D:\.m2\repository\com\fasterxml\jackson\module\jackson-module-parameter-names\2.13.4\jackson-module-parameter-names-2.13.4.jar;D:\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\2.7.5\spring-boot-starter-tomcat-2.7.5.jar;D:\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\9.0.68\tomcat-embed-core-9.0.68.jar;D:\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\9.0.68\tomcat-embed-el-9.0.68.jar;D:\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\9.0.68\tomcat-embed-websocket-9.0.68.jar;D:\.m2\repository\org\springframework\spring-web\5.3.23\spring-web-5.3.23.jar;D:\.m2\repository\org\springframework\spring-webmvc\5.3.23\spring-webmvc-5.3.23.jar;D:\.m2\repository\org\springframework\spring-expression\5.3.23\spring-expression-5.3.23.jar;D:\.m2\repository\org\springframework\cloud\spring-cloud-starter\3.1.4\spring-cloud-starter-3.1.4.jar;D:\.m2\repository\org\springframework\cloud\spring-cloud-context\3.1.4\spring-cloud-context-3.1.4.jar;D:\.m2\repository\org\springframework\security\spring-security-crypto\5.7.4\spring-security-crypto-5.7.4.jar;D:\.m2\repository\org\springframework\cloud\spring-cloud-commons\3.1.4\spring-cloud-commons-3.1.4.jar;D:\.m2\repository\org\springframework\security\spring-security-rsa\1.0.11.RELEASE\spring-security-rsa-1.0.11.RELEASE.jar;D:\.m2\repository\org\bouncycastle\bcpkix-jdk15on\1.69\bcpkix-jdk15on-1.69.jar;D:\.m2\repository\org\bouncycastle\bcprov-jdk15on\1.69\bcprov-jdk15on-1.69.jar;D:\.m2\repository\org\bouncycastle\bcutil-jdk15on\1.69\bcutil-jdk15on-1.69.jar;D:\.m2\repository\com\h2database\h2\2.1.214\h2-2.1.214.jar;D:\.m2\repository\org\projectlombok\lombok\1.18.24\lombok-1.18.24.jar;D:\.m2\repository\jakarta\xml\bind\jakarta.xml.bind-api\2.3.3\jakarta.xml.bind-api-2.3.3.jar;D:\.m2\repository\jakarta\activation\jakarta.activation-api\1.2.2\jakarta.activation-api-1.2.2.jar;D:\.m2\repository\org\springframework\spring-core\5.3.23\spring-core-5.3.23.jar;D:\.m2\repository\org\springframework\spring-jcl\5.3.23\spring-jcl-5.3.23.jar com.springcloud.servicediscovery.order.OrderApplication ,-----. ,--. ' .-. ' ,--.--. ,-| | ,---. ,--.--. | | | | | .--' ' .-. | | .-. : | .--' ' '-' ' | | \ `-' | \ --. | | `-----' `--' `---' `----' `--' 2022-10-26 16:00:50.403 INFO 9960 --- [ main] c.s.s.order.OrderApplication : Starting OrderApplication using Java 11.0.15 on sm15 with PID 9960 (C:\Users\mail2\Downloads\servicediscovery\order\target\classes started by mail2 in C:\Users\mail2\Downloads\servicediscovery) 2022-10-26 16:00:50.409 INFO 9960 --- [ main] c.s.s.order.OrderApplication : No active profile set, falling back to 1 default profile: "default" 2022-10-26 16:00:51.462 INFO 9960 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data JPA repositories in DEFAULT mode. 2022-10-26 16:00:51.536 INFO 9960 --- [ main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 62 ms. Found 1 JPA repository interfaces. 2022-10-26 16:00:51.813 INFO 9960 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=09d11aea-0332-3c92-b042-65599ff3a877 2022-10-26 16:00:52.642 INFO 9960 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 9001 (http) 2022-10-26 16:00:52.643 INFO 9960 --- [ main] o.a.catalina.core.AprLifecycleListener : An older version [1.2.28] of the Apache Tomcat Native library is installed, while Tomcat recommends a minimum version of [1.2.30] 2022-10-26 16:00:52.644 INFO 9960 --- [ main] o.a.catalina.core.AprLifecycleListener : Loaded Apache Tomcat Native library [1.2.28] using APR version [1.7.0]. 2022-10-26 16:00:52.644 INFO 9960 --- [ main] o.a.catalina.core.AprLifecycleListener : APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true]. 2022-10-26 16:00:52.644 INFO 9960 --- [ main] o.a.catalina.core.AprLifecycleListener : APR/OpenSSL configuration: useAprConnector [false], useOpenSSL [true] 2022-10-26 16:00:52.647 INFO 9960 --- [ main] o.a.catalina.core.AprLifecycleListener : OpenSSL successfully initialized [OpenSSL 1.1.1k 25 Mar 2021] 2022-10-26 16:00:52.658 INFO 9960 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2022-10-26 16:00:52.658 INFO 9960 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.68] 2022-10-26 16:00:52.854 INFO 9960 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2022-10-26 16:00:52.855 INFO 9960 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 2360 ms 2022-10-26 16:00:52.905 INFO 9960 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... 2022-10-26 16:00:53.220 INFO 9960 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed. 2022-10-26 16:00:53.240 INFO 9960 --- [ main] o.s.b.a.h2.H2ConsoleAutoConfiguration : H2 console available at '/h2-console'. Database available at 'jdbc:h2:mem:a9fb7432-5405-48d5-b897-d36cbba23d2d' 2022-10-26 16:00:53.527 INFO 9960 --- [ main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [name: default] 2022-10-26 16:00:53.607 INFO 9960 --- [ main] org.hibernate.Version : HHH000412: Hibernate ORM core version 5.6.12.Final 2022-10-26 16:00:53.862 INFO 9960 --- [ main] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.2.Final} 2022-10-26 16:00:54.063 INFO 9960 --- [ main] org.hibernate.dialect.Dialect : HHH000400: Using dialect: org.hibernate.dialect.H2Dialect 2022-10-26 16:00:54.881 INFO 9960 --- [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform] 2022-10-26 16:00:54.893 INFO 9960 --- [ main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default' 2022-10-26 16:00:55.317 WARN 9960 --- [ main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning 2022-10-26 16:00:56.187 INFO 9960 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 9001 (http) with context path '' 2022-10-26 16:00:56.518 INFO 9960 --- [ main] c.s.s.order.OrderApplication : Started OrderApplication in 7.321 seconds (JVM running for 8.003) 2022-10-26 16:03:42.156 INFO 9960 --- [nio-9001-exec-9] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' 2022-10-26 16:03:42.156 INFO 9960 --- [nio-9001-exec-9] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet' 2022-10-26 16:03:42.158 INFO 9960 --- [nio-9001-exec-9] o.s.web.servlet.DispatcherServlet : Completed initialization in 2 ms
In the log we see that:
- H2 console available at '/h2-console'
- Database available at 'jdbc:h2:mem:a9fb7432-5405-48d5-b897-d36cbba23d2d'
- Tomcat started on port(s): 9001
So we can access the H2 database by going to the URL localhost:9001/h2-console and then paste the jdbc:h2:mem:a9fb7432-5405-48d5-b897-d36cbba23d2d in the JDBC URL field. Click on connect.
Request can be sent through Postman to create the order:
Inserted data can also be verified from the database console:
Create "payment" microservices (module)
Follow the same steps to create the "payment" microservice as below:
Payment.java model:
package com.springcloud.servicediscovery.paymnt.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Table
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Payment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int paymentId;
private int orderId;
private double paymentAmt;
}
PaymentRepo.java :
package com.springcloud.servicediscovery.paymnt.dao;
import com.springcloud.servicediscovery.paymnt.model.Payment;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface PaymentRepo extends CrudRepository<Payment, Integer> {}
PaymentController.java :
package com.springcloud.servicediscovery.paymnt.controller;
import com.springcloud.servicediscovery.paymnt.dao.PaymentRepo;
import com.springcloud.servicediscovery.paymnt.model.Payment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class PaymentController {
@Autowired
private PaymentRepo repo;
@GetMapping("/payments")
private List<Payment> getAllPayments(){
return (List<Payment>) repo.findAll();
}
@PostMapping("/payments")
private Payment addPayment(@RequestBody Payment newPayment){
return repo.save(newPayment);
}
}
PaymentApplication.java
package com.springcloud.servicediscovery.paymnt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class PaymentApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentApplication.class, args);
}
}
application.yml
server:
port: 9002
spring:
h2:
console:
enabled: true
banner.txt
,------. ,--.
| .--. ' ,--,--. ,--. ,--. ,--,--,--. ,---. ,--,--, ,-' '-.
| '--' | ' ,-. | \ ' / | | | .-. : | \ '-. .-'
| | --' \ '-' | \ ' | | | | \ --. | || | | |
`--' `--`--' .-' / `--`--`--' `----' `--''--' `--'
`---'
H2 connection details for payment service can also be obtained from the console when the application is run.
Source code:
https://github.com/it-code-lab/spring-cloud-servicediscovery
Leave a Comment