上QQ阅读APP看书,第一时间看更新
Cloud connectivity using WebSockets
We've already covered how the WebSockets along with STOMP can be used to send data to and from the Edge to the Cloud. In this section, we will cover how to build a WebSocket server using Spring Boot:
- Before you run the server-side code you will need to install postgresql.
- Start postgresql using the following command line:
./pgc start
pg96 starting on port 5432
- The code for this application is in iiot-sample-alert-server.
- This application uses Maven, you will need to have maven installed on your machine.
- Step 1 is to add the Spring Boot WebSocket support and mvn dependency to the pom.xml under iiot-sample-alert-server as follows:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-WebSocket</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>stomp-WebSocket</artifactId>
<version>2.3.3</version>
</dependency>
- Add the WebSocket configuration for the Spring Boot application as given in the following code snippet. This enables us to configure a simple Spring Boot application to listen to WebSocket connections for incoming traffic:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
RequestUpgradeStrategy upgradeStrategy = new TomcatRequestUpgradeStrategy();
registry.addEndpoint("/iiot-sample-WebSocket")
.withSockJS();
registry.addEndpoint("/iiot-sample-WebSocket").setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy))
.setAllowedOrigins("*");
}
}
- Add the REST controller to handle the WebSocket messages. Essentially, as the messages arrive in the WebSocket they calls this REST endpoint to create alerts.
- IIotWebSocketController listens to messages at /app/createAlert and sends the response to any subscribers listening at /topic/alertCreated.
- The format of the message is the same Alert JSON and it's response is also of the Alert type:
@RestController
public class IiotWebSocketController {
private static final Logger logger = LoggerFactory.getLogger(IiotWebSocketController.class);
private final IiotService iiotService;
@Autowired
private TenantUtil tenantUtil;
@Autowired
public IiotWebSocketController(IiotService iiotService) {
this.iiotService = iiotService;
}
@MessageMapping("/createAlert")
@SendTo("/topic/alertCreated")
public Alert createAlert(Alert alertMessage) throws Exception {
StopWatch stopWatch = new StopWatch("create WebSocket using Alerts");
logger.info("{Message Received}", new StopWatchUtil(stopWatch));
//pass empty credentials since security and tenancy are not enabled
Credentials credentials = new Credentials(null, tenantUtil.getTenantUuid());
Alert createdAlert = iiotService.createAlerts(alertMessage,credentials,stopWatch);
return createdAlert;
}
}
- Add a case-IIotSampleTest.java test, to test our new IIotWebSocketController.
- This test case simulates the WebSocket client using the Stomp protocol, but connects to the server to test the end-to-end functionality.
- For the next step, we will go into details of the database connection, data model, and service details, as can be seen in the following example:
@Before
public void setup() {
List<Transport> socketTransports = new ArrayList<>();
socketTransports.add(new WebSocketTransport(new StandardWebSocketClient()));
this.sockJsClient = new SockJsClient(socketTransport);
this.stompClient = new WebSocketstompClient(sockJsClient);
this.stompClient.setMessageConverter(new MappingJackson2MessageConverter());
headers.add(HttpHeaders.CONTENT_TYPE,"application/json");
}
@Test
public void createAlert() throws Exception {
final AtomicReference<Throwable> alertCreationfailure = new AtomicReference<>();
final CountDownLatch alertlatch = new CountDownLatch(1);
StompSessionHandler alertHandler = new TestSessionHandler(alertCreationfailure) {
@Override
public void afterConnected(final StompSession session, StompHeaders connectedHeaders) {
session.subscribe("/topic/alertCreated", new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders headers) {
return Alert.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
Alert alert = (Alert) payload;
try {
assertEquals("Tempreture Alert", alert.getAlertName());
} catch (Throwable throw) {
failure.set(throw);
} finally {
session.disconnect();
alertlatch.countDown();
}
}
});
try {
Alert alert = new Alert();
alert.setAlertsUuid(String.format("AlertUUid" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())));
alert.setSeverity(1);
alert.setAlertName("Tempreture Alert");
alert.setAlertInfo("Tempreture Value:50");
session.send("/app/createAlert",alert);
} catch (Throwable throw) {
failure.set(throw);
alertlatch.countDown();
}
}
};
this.stompClient.connect("ws://localhost:{port}/iiot-sample-WebSocket", this.headers, alertHandler, this.port);
if (alertlatch.await(3, TimeUnit.SECONDS)) {
if (failure.get() != null) {
throw new AssertionError("Failed to create Alerts", failure.get());
}
}
else {
fail("Alerts Response not received");
}
}
- Run the test to make sure the unit tests passes, as follows:
./build.sh
[INFO] ------------------------------------------------------------------------
[INFO] Test Summary:
[INFO]
[INFO] IIOT Sample Management Modules ..................... SUCCESS [ 1.091 s]
[INFO] IIOT Sample Domain Entities ........................ SUCCESS [ 3.158 s]
[INFO] IIOT Sample Management ............................. SUCCESS [ 19.893 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO]