Microservices Architecture Tutorial
1. Introduction
Microservices architecture builds an application with many loosely coupled and independently deployable artifacts. In this example, I will demonstrate a simplified microservices architecture with two services.
- The course service runs at port 9001.
- The student service runs at port 9002.
- The student service depends on the course service.
- The Eureka Server runs at port 8761.
2. Technologies Used
The example code in this article was built and run using:
- Java 11
- Maven 3.3.9
- Spring Tools Suite (STS) 4
- Spring Boot, Spring Cloud, Spring Data, and Spring Web
- Postman
3. Spring Cloud Eureka Server
Spring Cloud Eureka server provides service registration and discovery. It makes microservices easier to manage as each microservice registers with a server and can find the needed services without knowing the service’s location.
In this step, I will create a maven project from https://start.spring.io/ with a Eureka Server dependency. Then import the generated project into STS workspace. Finally alter the generated MsServiceregistraapplication.java
with @EnableEurekaServer
and configure a Eureka server.
3.1 Pom.xml
There is no change at the generated pom.xml
file.
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.5.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>org.jcg.zheng.ms.service-registry</groupId> <artifactId>ms-service-registry</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ms-service-registry</name> <description>Demo project for Eureka Server</description> <properties> <java.version>11</java.version> <spring-cloud.version>2020.0.3</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </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> </plugin> </plugins> </build> </project>
3.2 Service Registry Application
In this step, I will update the generated MsServiceRegistryApplication.java
file by adding the @EnableEurekaServer annotation.
MsServiceRegistryApplication.java
package org.jcg.zheng.ms.serviceregistry.msserviceregistry; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class MsServiceRegistryApplication { public static void main(String[] args) { SpringApplication.run(MsServiceRegistryApplication.class, args); } }
- line 8 – @EnableEurekaServer annotation marks it as a Eureka Server.
3.3 Configuration
In this step, I will add the Eureka Server configuration in the application.properties file.
application.properties
server.port=8761 euraka.client.register-with-eureka=false euraka.client.fetch-registry=false spring.application.name=EUREKA-SERVER
3.4 Start the Server
In this step, I will start the server and verify the server log.
Server.log
[2m2021-07-17 20:18:07.766[0;39m [32m INFO[0;39m [35m59992[0;39m [2m---[0;39m [2m[ Thread-9][0;39m [36mc.n.e.registry.AbstractInstanceRegistry [0;39m [2m:[0;39m Registered instance EUREKA-SERVER/USA-X1082608.ctl.intranet:EUREKA-SERVER:8761 with status UP (replication=true) [2m2021-07-17 20:18:07.766[0;39m [32m INFO[0;39m [35m59992[0;39m [2m---[0;39m [2m[ Thread-9][0;39m [36mc.n.e.r.PeerAwareInstanceRegistryImpl [0;39m [2m:[0;39m Got 1 instances from neighboring DS node [2m2021-07-17 20:18:07.766[0;39m [32m INFO[0;39m [35m59992[0;39m [2m---[0;39m [2m[ Thread-9][0;39m [36mc.n.e.r.PeerAwareInstanceRegistryImpl [0;39m [2m:[0;39m Renew threshold is: 1 [2m2021-07-17 20:18:07.767[0;39m [32m INFO[0;39m [35m59992[0;39m [2m---[0;39m [2m[ Thread-9][0;39m [36mc.n.e.r.PeerAwareInstanceRegistryImpl [0;39m [2m:[0;39m Changing status to UP [2m2021-07-17 20:18:07.779[0;39m [32m INFO[0;39m [35m59992[0;39m [2m---[0;39m [2m[ Thread-9][0;39m [36me.s.EurekaServerInitializerConfiguration[0;39m [2m:[0;39m Started Eureka Server
3.5 Eureka Server Dashboard
Open a web browser and navigate to the Eureka Server dashboard at http://localhost:8761. It should display the service’s details.
Next, I will create two maven projects from https://start.spring.io/: ms-course-services and ms-student-services. Both projects have the following dependencies: Eureka Discovery Client, Spring Web, Spring Data JPA, and H2 Database. Here is the ms-student-services project creation screenshot.
4. Course Services
In this step, I will import ms-course-services into STS and add a simple Rest Course service to save and retrieve a course via the Spring web library.
4.1 Pom.xml
There is no change at the generated pom.xml
file.
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.5.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>org.jcg.zheng.ms.course</groupId> <artifactId>ms-course-services</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ms-course-services</name> <description>Demo project for Course Service</description> <properties> <java.version>11</java.version> <!--for Spring Cloud --> <spring-cloud.version>2020.0.3</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> <!--for Spring Cloud --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </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>
4.2 Course Services Application
In this step, I will update the generated MsCourseServicesApplication.java
file by adding the @EnableEurekaClient
and @EnableJpaRepositories
annotations.
MsCourseServicesApplication.java
package org.jcg.zheng.ms.course; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @SpringBootApplication @EnableJpaRepositories(basePackages = "org.jcg.zheng.ms.course") @EnableEurekaClient public class MsCourseServicesApplication { public static void main(String[] args) { SpringApplication.run(MsCourseServicesApplication.class, args); } }
- line 10 – @EnableEurekaClient marks it as a Eureka Client.
4.3 Configuration
In this step, I will add the Eureka client configuration in the application.properties file.
application.properties
server.port=9001 spring.jackson.serialization.fail-on-empty-beans=false spring.application.name=COURSE-SERVICE euraka.client.register-with-eureka=true euraka.client.fetch-registry=true euraka.client.service-url.defaultZone=http://localhost:8761/euraka/ euraka.instance.hostname=localhost
- line 4 – Defines an application name so can be used to find service.
- line 8 – Eureka server URL.
4.4 Course Web Controller
In this step, I will create a Rest service via Spring web annotations: @RestController
, @RequestMapping
, @RequestBody
, @PathVariable
, @PostMapping
, and @GetMapping
.
CourseController.javao
package org.jcg.zheng.ms.course.controller; import org.jcg.zheng.ms.course.service.CourseService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/courses") public class CourseController { @Autowired private CourseService courseService; @PostMapping("/") public CourseDO saveCourse(@RequestBody CourseDO course) { return courseService.save(course); } @GetMapping("/{id}") public CourseDO getCourse(@PathVariable("id") Long courseId) { return courseService.findById(courseId); } }
The Rest service transforms the CourseDO
from the Course
Entity.
CourseDO.java
package org.jcg.zheng.ms.course.controller; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class CourseDO { private static final long serialVersionUID = 1L; private Long id; private String description; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
4.5 Course Service
In this step, I will create a CourseService
class which autowired a CourseRepository
to save and retrieve course information. Please reference Spring data JPA for detail about how to use Spring data JPA.
CourseService.java
package org.jcg.zheng.ms.course.service; import org.jcg.zheng.ms.course.controller.CourseDO; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class CourseService { @Autowired private CourseRepository courseRepo; public CourseDO save(CourseDO course) { Course courseDto = new Course(); BeanUtils.copyProperties(course, courseDto); courseDto = courseRepo.save(courseDto); course.setId(courseDto.getId()); return course; } public CourseDO findById(Long courseId) { CourseDO courseDo = new CourseDO(); try { Course courseDto = courseRepo.getById(courseId); BeanUtils.copyProperties(courseDto, courseDo); } catch (Exception e) { e.printStackTrace(); } return courseDo; } }
Here is the CourseRepostiory.java
interface.
CourseRepository.java
package org.jcg.zheng.ms.course.service; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface CourseRepository extends JpaRepository<Course, Long> { }
Here is the Course
entity class.
Course.java
package org.jcg.zheng.ms.course.service; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Course implements Serializable { public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getName() { return name; } public void setName(String name) { this.name = name; } private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; private String description; private String name; }
4.6 Start the Server
In this step, I will start the ms-course-service and verify the server log.
Server Log
2021-07-18 20:19:09.317[0;39m [32m INFO[0;39m [35m59992[0;39m [2m---[0;39m [2m[nio-8761-exec-7][0;39m [36mc.n.e.registry.AbstractInstanceRegistry [0;39m [2m:[0;39m Registered instance COURSE-SERVICE/USA-X1082608.ctl.intranet:COURSE-SERVICE:9001 with status UP (replication=true) [2m2021-07-18 20:19:27.516[0;39m [32m INFO[0;39m [35m59992[0;39m [2m---[0;39m [2m[a-EvictionTimer][0;39m [36mc.n.e.registry.AbstractInstanceRegistry [0;39m [2m:[0;39m Running the evict task with compensationTime 0ms
4.7 Test with Postman
In this step, I will create a course with with Postman.
save a math course via POST
POST /courses/ HTTP/1.1 Host: localhost:9001 Content-Type: application/json Cache-Control: no-cache Postman-Token: 393a505b-4c05-9d41-99f1-a504ebfc5fe1 { "name":"math", "description":"advance math 1001 for freshman" }
retrieve a course via GET
GET /courses/1 HTTP/1.1 Host: localhost:9001 Content-Type: application/json Cache-Control: no-cache Postman-Token: fdfac0f0-3e07-16ae-a961-45bd684310c8
Get course service’s response.
{ "id": 1, "description": "advance math 1001 for freshman", "name": "math" }
5. Student Service
In this step, I will create a simple Rest service to get the student details via the Spring web library. This service also depends on the course service created at step 4.
5.1 Pom.xml
There is no change at the generated pom.xml
file.
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.5.2</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>org.jcg.zheng.ms.student</groupId> <artifactId>ms-student-services</artifactId> <version>0.0.1-SNAPSHOT</version> <name>ms-student-services</name> <description>Demo project for Student Service</description> <properties> <java.version>11</java.version> <spring-cloud.version>2020.0.3</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-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </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>
5.2 Student Service Application
In this step, I will update the generated MsStudentServicesApplication.java
file by adding @EnableEurekaClient
and @EnableJpaRepositories annotations
. I will add a RestTemplate
bean to access the student service.
MsStudentServicesApplication.java
package org.jcg.zheng.ms.student; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.context.annotation.Bean; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.web.client.RestTemplate; @SpringBootApplication @EnableJpaRepositories(basePackages = "org.jcg.zheng.ms.student") @EnableEurekaClient public class MsStudentServicesApplication { public static void main(String[] args) { SpringApplication.run(MsStudentServicesApplication.class, args); } @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
5.3 Configuration
In this step, I will add the Eureka Client and course service endpoint configuration in the application.properties file.
application.properties
server.port=9002 spring.jackson.serialization.fail-on-empty-beans=false spring.application.name=STUDENT-SERVICE # host:port is connecting to courseService directly #courseservice.uri=http://localhost:9001/courses/ # host:port is connecting to courseService directly courseservice.uri=http://COURSE-SERVICE/courses/ euraka.client.register-with-eureka=true euraka.client.fetch-registry=true euraka.client..service-url.defaultZone=http://localhost:8761/euraka/ euraka.instance.hostname=localhost
- line 7 – The course service is specified with hostname and port. Commented as line 10 is better way to find a service.
- line 10 – The course service is discovered by Eureka Server via the application name.
5.4 Student Web Controller
In this step, I will create a Rest controller which creates and retrieves a student’s data.
StudentController.java
package org.jcg.zheng.ms.student.controller; import org.jcg.zheng.ms.student.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/students") public class StudentController { @Autowired private StudentService studentService; @GetMapping("/{id}") public StudentDO get(@PathVariable("id") Long studentId) { return studentService.findById(studentId); } @PostMapping("/") public StudentDO save(@RequestBody StudentDO student) { return studentService.save(student); } }
StudentDO.java
package org.jcg.zheng.ms.student.controller; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; @JsonIgnoreProperties(ignoreUnknown = true) public class StudentDO { private static final long serialVersionUID = 1L; private Long id; private String firstName; private String lastName; private Long courseId; private Course courseDetail; public Course getCourseDetail() { return courseDetail; } public Long getCourseId() { return courseId; } public String getFirstName() { return firstName; } public Long getId() { return id; } public String getLastName() { return lastName; } public void setCourseDetail(Course coureDetail) { this.courseDetail = coureDetail; } public void setCourseId(Long courseId) { this.courseId = courseId; } public void setFirstName(String firstName) { this.firstName = firstName; } public void setId(Long id) { this.id = id; } public void setLastName(String lastName) { this.lastName = lastName; } }
Here is the Course
class which should be same as the CourseDO
class in the ms-course-services project. Microservices reuse the source code to cut the dependencies among projects.
Course.java
package org.jcg.zheng.ms.student.controller; public class Course { private static final long serialVersionUID = 1L; private Long id; private String description; private String name; public String getDescription() { return description; } public Long getId() { return id; } public String getName() { return name; } public void setDescription(String description) { this.description = description; } public void setId(Long id) { this.id = id; } public void setName(String name) { this.name = name; } }
5.5 Student Service
In this step, I will create a StudentService
class which uses StudentRepository
to save and find a student.
StudentRepository.java
package org.jcg.zheng.ms.student.service; import org.jcg.zheng.ms.student.controller.Course; import org.jcg.zheng.ms.student.controller.StudentDO; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class StudentService { @Autowired private StudentRepository courseRepo; @Autowired private RestTemplate restTemplate; @Value("${courseservice.uri}") private String courseServiceUri; public StudentDO findById(Long studentId) { StudentDO studentDO = new StudentDO(); try { Student student = courseRepo.getById(studentId); BeanUtils.copyProperties(student, studentDO); if (student.getCourseId() != null) { String courseGetUrl = courseServiceUri + student.getCourseId().longValue(); System.out.println("courseServiceUri:" + courseServiceUri); System.out.println("Get Course-Service endpoint:" + courseGetUrl); Course c = restTemplate.getForObject(courseGetUrl, Course.class); studentDO.setCourseDetail(c); } } catch (Exception e) { e.printStackTrace(); } return studentDO; } public StudentDO save(StudentDO student) { Student stuDto = new Student(); BeanUtils.copyProperties(student, stuDto); stuDto = courseRepo.save(stuDto); student.setId(stuDto.getId()); return student; } }
Here is the StudentRepostitory
interface.
StudentRepository.java
package org.jcg.zheng.ms.student.service; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface StudentRepository extends JpaRepository<Student, Long> { }
Here is the Student
entity.
Student.java
package org.jcg.zheng.ms.student.service; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity public class Student implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue private Long id; private String firstName; private String lastName; private Long courseId; public Long getCourseId() { return courseId; } public String getFirstName() { return firstName; } public Long getId() { return id; } public String getLastName() { return lastName; } public void setCourseId(Long courseId) { this.courseId = courseId; } public void setFirstName(String firstName) { this.firstName = firstName; } public void setId(Long id) { this.id = id; } public void setLastName(String lastName) { this.lastName = lastName; } }
5.6 Start the Server
Start the ms-student-service spring boot application and verify the server log.
ms-student-server server log
2021-07-19 21:10:14.818[0;39m [32m INFO[0;39m [35m101236[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.s.b.w.embedded.tomcat.TomcatWebServer [0;39m [2m:[0;39m Tomcat started on port(s): 9002 (http) with context path '' [2m2021-07-19 21:10:14.819[0;39m [32m INFO[0;39m [35m101236[0;39m [2m---[0;39m [2m[ main][0;39m [36m.s.c.n.e.s.EurekaAutoServiceRegistration[0;39m [2m:[0;39m Updating port to 9002 [2m2021-07-19 21:10:14.894[0;39m [32m INFO[0;39m [35m101236[0;39m [2m---[0;39m [2m[nfoReplicator-0][0;39m [36mcom.netflix.discovery.DiscoveryClient [0;39m [2m:[0;39m DiscoveryClient_STUDENT-SERVICE/USA-X1082608.ctl.intranet:STUDENT-SERVICE:9002 - registration status: 204 [2m2021-07-19 21:10:15.895[0;39m [32m INFO[0;39m [35m101236[0;39m [2m---[0;39m [2m[ main][0;39m [36mo.j.z.m.s.MsStudentServicesApplication [0;39m [2m:[0;39m Started MsStudentServicesApplication in 17.152 seconds (JVM running for 23.527)
5.7 Eureka Server Dashboard
Navigate to http://localhost:8761. It should display both course and student services now.
6. Postman Test
6.1 Save a Student
Open a Postman and enter a POST request to save a student.
POST /students/ HTTP/1.1 Host: localhost:9002 Accept: application/json Content-Type: application/json Cache-Control: no-cache Postman-Token: 67fccb7f-1326-f31b-d404-f848e6e871e5 { "firstName":"Mary", "lastName":"Zheng", "courseId":1 }
You should receive a 200 ok status.
6.2 Find a Student
Open a Postman and enter a GET request to retrieve a student along with its course information.
GET /students/1 HTTP/1.1 Host: localhost:9002 Accept: application/json Content-Type: application/json Cache-Control: no-cache Postman-Token: 76339b48-80ac-38f7-2334-0ae4aa30c600
You should get 200 ok status along with the student’s course information which comes from the course service.
Get Student Service Response
{ "id": 1, "firstName": "Mary", "lastName": "Zheng", "courseId": 1, "courseDetail": { "id": 1, "description": "advance math 1001 for freshman", "name": "math" } }
Verify the ms-student-service server log, you should see the Course service URL is http://COURSE-SERVICE instead of http://localhost:9001.
ms-student-service log
2021-07-20 22:47:51.835[0;39m [32m INFO[0;39m [35m49164[0;39m [2m---[0;39m [2m[nio-9002-exec-1][0;39m [36mo.s.web.servlet.DispatcherServlet [0;39m [2m:[0;39m Completed initialization in 4 ms courseServiceUri:http://COURSE-SERVICE/courses/ Get Course-Service endpoint:http://COURSE-SERVICE/courses/1
7. Summary
The key principle of microservices architecture is the independent deployment. In this tutorial, I created three maven projects.
I demonstrated how to:
- Build two simple microservices via Spring web library.
- Create a spring-cloud Eureka server.
- Register microservices with a Eureka server.
- Find a microservice from a Eureka server based on the service name.
8. Download the Source Code
You can download the full source code of this example here: Microservices Architecture Tutorial
Just the architectural demo I was looking for
You have typos in your application.properties file causing errors
eureka is misspelled euraka
Thanks for the correction.