Add the message producers and listeners
You will next add the code required to send and receive messages to the visits
service. The message-emulator
will send a PetClinicMessageRequest
to the visits-requests
queue. The visits
service will need to listen to this queue and each time a VisitRequest
message is submitted, it will create a new Visit
for the pet ID referenced in the message. The visits
service will also send back a VisitResponse
as a confirmation to the visits-confirmations
queue. This is the queue the message-emulator
is listening to.
Step by step guidance
-
In the
spring-petclinic-visits-service
directory, create a newsrc/main/java/org/springframework/samples/petclinic/visits/entities
subdirectory and add aVisitRequest.java
class file containing the following code:package org.springframework.samples.petclinic.visits.entities; import java.io.Serializable; import java.util.Date; public class VisitRequest implements Serializable { private static final long serialVersionUID = -249974321255677286L; private Integer requestId; private Integer petId; private String message; public VisitRequest() { } public Integer getRequestId() { return requestId; } public void setRequestId(Integer id) { this.requestId = id; } public Integer getPetId() { return petId; } public void setPetId(Integer petId) { this.petId = petId; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } }
-
In the same directory, add a
VisitResponse.java
class containing the following code:package org.springframework.samples.petclinic.visits.entities; public class VisitResponse { Integer requestId; Boolean confirmed; String reason; public VisitResponse() { } public VisitResponse(Integer requestId, Boolean confirmed, String reason) { this.requestId = requestId; this.confirmed = confirmed; this.reason = reason; } public Boolean getConfirmed() { return confirmed; } public void setConfirmed(Boolean confirmed) { this.confirmed = confirmed; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } public Integer getRequestId() { return requestId; } public void setRequestId(Integer requestId) { this.requestId = requestId; } }
-
In the
spring-petclinic-visits-service
directory, create a newsrc/main/java/org/springframework/samples/petclinic/visits/config
subdirectory and add aMessagingConfig.java
class file containing the following code:package org.springframework.samples.petclinic.visits.config; import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jms.support.converter.MappingJackson2MessageConverter; import org.springframework.jms.support.converter.MessageConverter; import org.springframework.samples.petclinic.visits.entities.VisitRequest; import org.springframework.samples.petclinic.visits.entities.VisitResponse; @Configuration public class MessagingConfig { @Bean public MessageConverter jackson2Converter() { MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter(); Map<String, Class<?>> typeMappings = new HashMap<String, Class<?>>(); typeMappings.put("visitRequest", VisitRequest.class); typeMappings.put("visitResponse", VisitResponse.class); converter.setTypeIdMappings(typeMappings); converter.setTypeIdPropertyName("messageType"); return converter; } }
-
In the same directory, add a
QueueConfig.java
class file containing the following code:package org.springframework.samples.petclinic.visits.config; import org.springframework.beans.factory.annotation.Value; public class QueueConfig { @Value("${spring.jms.queue.visits-requests:visits-requests}") private String visitsRequestsQueue; public String getVisitsRequestsQueue() { return visitsRequestsQueue; } }
-
In the
spring-petclinic-visits-service
directory, create a newsrc/main/java/org/springframework/samples/petclinic/visits/service
subdirectory and add aVisitsReceiver.java
class file containing the following code:package org.springframework.samples.petclinic.visits.service; import java.util.Date; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.jms.annotation.JmsListener; import org.springframework.jms.core.JmsTemplate; import org.springframework.samples.petclinic.visits.entities.VisitRequest; import org.springframework.samples.petclinic.visits.entities.VisitResponse; import org.springframework.samples.petclinic.visits.model.Visit; import org.springframework.samples.petclinic.visits.model.VisitRepository; import org.springframework.stereotype.Component; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @Component @Slf4j @RequiredArgsConstructor public class VisitsReceiver { private final VisitRepository visitsRepository; private final JmsTemplate jmsTemplate; @JmsListener(destination = "visits-requests") void receiveVisitRequests(VisitRequest visitRequest) { log.info("Received message: {}", visitRequest.getMessage()); try { Visit visit = new Visit(null, new Date(), visitRequest.getMessage(), visitRequest.getPetId()); visitsRepository.save(visit); jmsTemplate.convertAndSend("visits-confirmations", new VisitResponse(visitRequest.getRequestId(), true, "Your visit request has been accepted")); } catch (Exception ex) { log.error("Error saving visit: {}", ex.getMessage()); jmsTemplate.convertAndSend("visits-confirmations", new VisitResponse(visitRequest.getRequestId(), false, ex.getMessage())); } } }
This
VisitsReceiver
service is listening to thevisits-requests
queue. Each time a message is present on the queue, it will dequeue this message and save a newVisit
in the database. In the next step, you will verify it by having it sent a confirmation message to thevisits-confirmations
queue. -
Rebuild the spring-petclinic-visits-service microservice
cd .. mvn clean package -DskipTests -rf :spring-petclinic-visits-service
-
Navigate to the
staging-acr
directory, copy the jar file of the visit-service and rebuild the container.cd staging-acr rm spring-petclinic-visits-service-$VERSION.jar cp ../spring-petclinic-visits-service/target/spring-petclinic-visits-service-$VERSION.jar spring-petclinic-visits-service-$VERSION.jar docker build -t $MYACR.azurecr.io/spring-petclinic-visits-service:$VERSION \ --build-arg ARTIFACT_NAME=spring-petclinic-visits-service-$VERSION.jar \ --build-arg APP_PORT=8080 \ --build-arg AI_JAR=ai.jar \ . docker push $MYACR.azurecr.io/spring-petclinic-visits-service:$VERSION
-
Navigate to the kubernetes folder and replace the
spring-petclinic-visits-service.yml
file with the contents of the spring-petclinic-visits-service.yml file. You can again curl the updates for these files and then fill out the correct container registry name.cd ../kubernetes curl -o spring-petclinic-visits-service.yml https://raw.githubusercontent.com/Azure-Samples/java-microservices-aks-lab/main/docs/05_lab_messaging/spring-petclinic-visits-service.yml IMAGE=${MYACR}.azurecr.io/spring-petclinic-visits-service:$VERSION sed -i "s|#image#|$IMAGE|g" spring-petclinic-visits-service.yml
-
Inspect the new contents of this file. The file has:
- An additional
SPRING_JMS_SERVICEBUS_CONNECTIONSTRING
environment variable mapped to thesbsecret
on lines47
to51
. - An additional
volumes
definition on lines19
to25
. - An additional
volumeMounts
definition on lines52
to55
.
- An additional
-
Reapply the yaml definition on the AKS cluster.
kubectl apply -f spring-petclinic-visits-service.yml
-
Double check that the visits-service started up correctly.
kubectl get pods -w
-
To validate the resulting functionality, in the Azure Portal, navigate back to the page of the
visits-requests
queue of the Service Bus namespace you deployed earlier in this lab. -
On the Overview page of the
visits-requests
queue, verify that there are no active messages. -
In the web browser window, open another tab and navigate to the public endpoint of the
api-gateway
service. -
On the Welcome to Petclinic page, select Owners and, in the drop-down menu, select All.
-
In the list of owners, select the first entry (George Franklin).
-
On the Owner Information page, in the Pets and Visits section, verify the presence of an entry representing the message you submitted earlier in this lab.