-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Integrate chat agent web interaction to api-gateway UI (#80)
## Purpose + Update gateway frontend to add chat-agent part. + Reactive web socket server in api-gateway. + Call by name for chat agent. + Spring cloud gateway route config for chat agent. + Make chat agent as Eureka client, because it will be called by spring cloud gateway, which underlying uses load balancing. ![image](https://github.com/user-attachments/assets/324242bd-ef2d-4ecc-b11c-49a0659f3288) ## Does this introduce a breaking change? <!-- Mark one with an "x". --> ``` [ ] Yes [ ] No ``` ## Pull Request Type What kind of change does this Pull Request introduce? <!-- Please check the one that applies to this PR using "x". --> ``` [ ] Bugfix [ ] Feature [ ] Code style update (formatting, local variables) [ ] Refactoring (no functional changes, no api changes) [ ] Documentation content changes [ ] Other... Please describe: ``` ## How to Test * Get the code ``` git clone [repo-address] cd [repo-name] git checkout [branch-name] npm install ``` * Test the code <!-- Add steps to run the tests suite and/or manually test --> ``` ``` ## What to Check Verify that the following are valid * ... ## Other Information <!-- Add any other helpful information that may be needed here. --> --------- Co-authored-by: Hao Zhang <[email protected]>
- Loading branch information
Showing
17 changed files
with
551 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
...rc/main/java/org/springframework/samples/petclinic/api/application/ChatServiceClient.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* | ||
* Copyright 2002-2024 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.springframework.samples.petclinic.api.application; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.reactive.function.client.WebClient; | ||
import reactor.core.publisher.Mono; | ||
|
||
@Component | ||
@RequiredArgsConstructor | ||
public class ChatServiceClient { | ||
|
||
private final WebClient.Builder webClientBuilder; | ||
|
||
public Mono<String> chat(String sender, String message) { | ||
return webClientBuilder.build().get() | ||
.uri("http://chat-agent/chat/{sender}/{message}", sender, message) | ||
.retrieve() | ||
.bodyToMono(String.class); | ||
} | ||
} |
45 changes: 45 additions & 0 deletions
45
...-api-gateway/src/main/java/org/springframework/samples/petclinic/api/dto/ChatMessage.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
/* | ||
* Copyright 2002-2024 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.springframework.samples.petclinic.api.dto; | ||
|
||
import lombok.*; | ||
|
||
/** | ||
* Represents a chat message in the chat application. | ||
*/ | ||
@Getter | ||
@Setter | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
@Builder | ||
public class ChatMessage { | ||
|
||
private String content; | ||
|
||
private String sender; | ||
|
||
private MessageType type; | ||
|
||
/** | ||
* Enum representing the type of the chat message. | ||
*/ | ||
public enum MessageType { | ||
|
||
CHAT, LEAVE, JOIN | ||
|
||
} | ||
|
||
} |
89 changes: 89 additions & 0 deletions
89
...c/main/java/org/springframework/samples/petclinic/api/websocket/ChatWebSocketHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* Copyright 2002-2024 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.springframework.samples.petclinic.api.websocket; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.samples.petclinic.api.application.ChatServiceClient; | ||
import org.springframework.samples.petclinic.api.dto.ChatMessage; | ||
import org.springframework.stereotype.Component; | ||
import org.springframework.web.reactive.socket.WebSocketHandler; | ||
import org.springframework.web.reactive.socket.WebSocketMessage; | ||
import org.springframework.web.reactive.socket.WebSocketSession; | ||
import reactor.core.publisher.Mono; | ||
|
||
@Component | ||
public class ChatWebSocketHandler implements WebSocketHandler { | ||
|
||
private final Logger logger = LoggerFactory.getLogger(ChatWebSocketHandler.class); | ||
|
||
@Autowired | ||
private ChatServiceClient chatServiceClient; | ||
|
||
@Value("${petclinic.agent.name:petclinic agent}") | ||
private String agentName; | ||
|
||
@Override | ||
public Mono<Void> handle(WebSocketSession session) { | ||
return session.send( | ||
session.receive() | ||
.map(WebSocketMessage::getPayloadAsText) | ||
.flatMap( | ||
payload -> processMessage(session, payload) | ||
) | ||
); | ||
} | ||
|
||
private Mono<WebSocketMessage> processMessage(WebSocketSession session, String payload) { | ||
logger.info("received payload: {}", payload); | ||
|
||
var objectMapper = new ObjectMapper(); | ||
ChatMessage receivedMessage = null; | ||
try { | ||
receivedMessage = objectMapper.readValue(payload, ChatMessage.class); | ||
} catch (Exception e) { | ||
logger.error("Exception thrown when deserializing client chat message: {}", payload); | ||
return Mono.empty(); | ||
} | ||
|
||
if (receivedMessage.getType() == ChatMessage.MessageType.JOIN) { | ||
return Mono.just(session.textMessage(payload)); | ||
} else if (receivedMessage.getType() == ChatMessage.MessageType.CHAT) { | ||
return chatServiceClient.chat(receivedMessage.getSender(), receivedMessage.getContent()) | ||
.flatMap(responseContent -> { | ||
ChatMessage responseMessage = new ChatMessage(); | ||
responseMessage.setContent(responseContent); | ||
responseMessage.setSender(agentName); | ||
|
||
String responsePayload = null; | ||
try { | ||
responsePayload = objectMapper.writeValueAsString(responseMessage); | ||
} catch (Exception e) { | ||
logger.error("Exception thrown when serializing CHAT message: {}", responseMessage); | ||
return Mono.empty(); | ||
} | ||
|
||
logger.info("response payload: {}", responsePayload); | ||
return Mono.just(session.textMessage(responsePayload)); | ||
}); | ||
} | ||
|
||
return Mono.empty(); | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
...ay/src/main/java/org/springframework/samples/petclinic/api/websocket/WebSocketConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
/* | ||
* Copyright 2002-2024 the original author or authors. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
package org.springframework.samples.petclinic.api.websocket; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.web.reactive.HandlerMapping; | ||
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping; | ||
import org.springframework.web.reactive.socket.WebSocketHandler; | ||
import org.springframework.web.reactive.socket.server.support.WebSocketHandlerAdapter; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
@Configuration | ||
public class WebSocketConfig { | ||
|
||
@Bean | ||
public HandlerMapping webSocketMapping(ChatWebSocketHandler webSocketHandler) { | ||
Map<String, WebSocketHandler> map = new HashMap<>(); | ||
map.put("/websocket", webSocketHandler); | ||
|
||
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); | ||
mapping.setUrlMap(map); | ||
mapping.setOrder(-1); // give it higher precedence | ||
return mapping; | ||
} | ||
|
||
// This bean is necessary for WebSocket support in WebFlux | ||
@Bean | ||
public WebSocketHandlerAdapter handlerAdapter() { | ||
return new WebSocketHandlerAdapter(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.