Microservices – Architecture Example Application
We are going to build a simple Microservices application and assume we are going to start with the following microservices:
-
EDC-Microservice: Electronic Data Capture (EDC) system is software that stores patient data collected in clinical trials.It provides REST API to provide Electronic Data Capture functionalities.
-
TestReports
-
MedicalHistory
-
Visit Reports
-
-
MI- Microservice : Medical imaging systems give health-care providers and researchers the information they need using high-frequency sound waves (ultrasound and echocardiography), magnetic fields (MRI), and electromagnetic radiation (conventional 2-D X-ray, 3-D computed tomography or CT scan, and fluoroscopy).
-
RadiographyReports,
-
computed tomography (CT Scan Reports),
-
magnetic resonance imaging (MRI),
-
ultrasound,DentalScanReports
-
RTSM – Microservice Randomization and Trial Supply Management system, is responsible for enabling critical functions of a clinical trial, from randomizing patients (who gets the active drug vs. the placebo), dispensing drug (ensuring patients receive the correct dose) and site resupply (controls the flow of drug from the manufacturer to the depot to the clinical site).
-
UserManagent-ui: It is customer facing front-end web application.
We are going to build various services and REST endpoints through various microservice concepts.
a.EDC-MicroService
Create a SpringBoot app with Web, JPA, MySQL, Actuator, DevTools, Lombok starters
Database : MySQL as Docker Container
We are going to use Docker and run MySQL as a Docker container.
docker-compose.yml
version: '3'
services:
mysqldb:
image: 'mysql:5.7'
container_name: mysqldb
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: passw0rd
MYSQL_DATABASE: catalog
Download & Start MySQL Docker container
docker-compose up
Open any MySQL Editor & provide login details
application.properties
spring.application.name=EDC-MicroService
server.servlet.context-path=/edc
server.port=8031
spring.datasource.url= jdbc:mysql://localhost:3306/microservices?useSSL=false
spring.datasource.username= root
spring.datasource.password= root
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto= update
# springdoc.swagger-ui.path=/swagger-ui.html
# Azure KeyValut Server
# azure.keyvault.enabled=true
# azure.keyvault.uri=https://idamtestvalut.vault.azure.net/
# azure.keyvault.client-id=put-your-azure-client-id-here
# azure.keyvault.client-key=put-your-azure-client-key-here
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/
management.endpoints.web.exposure.include=*
spring.zipkin.base-url=http://localhost:9411/
spring.sleuth.sampler.probability=1
# Consumer properties
spring.kafka.producer.bootstrap-servers=127.0.0.1:9092
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.group-id=group_id
topic.name.consumer=user.provision.topic
# Common Kafka Properties
auto.create.topics.enable=true
azure.activedirectory.session-stateless=true
azure.activedirectory.client-id=D4N7Q~uBPMd~NIsUp8VYxX4-vFnpOZFqfWdPo
azure.activedirectory.appIdUri=http://localhost:3000/
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://login.windows.net/common/discovery/keys
logging.level.org.springframework.security=DEBUG
spring.jackson.serialization.fail-on-empty-beans=false
Java Code
@Entity
@Table(name = "edc_testreports")
@NoArgsConstructor
@AllArgsConstructor
@Data
public class TestReport {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Integer id;
@Column
String reportName;
@Column
String reportType;
@Column
String trialId;
@Column
String trialName;
@Column
private String userId;
}
@Repository
public interface TestReportRepository extends JpaRepository<TestReport, Integer>{
}
package com.edc.controller;
@CrossOrigin(origins = "http://localhost:3000")
@RestController
public class TestReportController {
@Autowired
TestReportRepository repository;
@Autowired
RestTemplate restTemplate;
@RequestMapping(value = "/", produces = "text/html")
public ResponseEntity<String> dashboard() {
String bodyStr = homePageData();
return ResponseEntity.ok().body(bodyStr);
}
@GetMapping("/testReport/{id}")
public ResponseEntity<TestReport> getReportByID(@PathVariable int id){
TestReport data = repository.getById(id);
System.out.println("data : "+data);
try {
return ResponseEntity
.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(data);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.NOT_FOUND);
}
}
@GetMapping("/testReport/all")
public ResponseEntity<List<TestReport>> getAllTestReports() {
try {
List<TestReport> reports = new ArrayList<TestReport>();
repository.findAll().forEach(reports::add);
System.out.println(reports.size());
if (reports.isEmpty()) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(reports, HttpStatus.OK);
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PostMapping("/testReport/add")
public ResponseEntity<TestReport> createReport(@RequestBody TestReport report) {
try {
TestReport testreport = repository.save(new TestReport(report.getReportName(), report.getReportType(), report.getTrialId(), report.getTrialName(), report.getUserId()));
return ResponseEntity
.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(testreport);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping(value = "/testReport/mi", produces = "application/json")
public ResponseEntity<Object> getAllMIReportsNoramlcall() {
try {
ResponseEntity<Object> responseEntity = restTemplate.getForEntity("http://MI-MICROSERVICE/mi/anthology/all", Object.class);
return new ResponseEntity<>(responseEntity, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping(value = "/testReport/mihystrix", produces = "application/json")
@HystrixCommand(fallbackMethod = "miReportFallBackMethod")
public ResponseEntity<Object> getAllMIReportsWithHyStrix() {
ResponseEntity<Object> responseEntity = restTemplate.getForEntity("http://MI-MICROSERVICE/mi/anthology/all", Object.class);
System.out.println(responseEntity);
return new ResponseEntity<>(responseEntity, HttpStatus.OK);
}
public ResponseEntity<Object> miReportFallBackMethod() {
return new ResponseEntity<>("MI Service is Not Avaialable", HttpStatus.OK);
}
}