Web Socket Config
package com.example.logdemo.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/logs").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic/log");
}
}
Controller
package com.example.logdemo.controller;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Controller;
import com.example.logdemo.models.Message;
@Controller
public class FileWatchController {
@MessageMapping("/logs")
@SendTo("/topic/log")
public Message getMessage(Message message) {
return message;
}
}
Models
package com.example.logdemo.models;
public class Message {
String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
Service
package com.example.logdemo.service;
import java.io.RandomAccessFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class FileWatchService {
private final static String FILE_NAME="log.txt";
private final static String READ_MODE="r";
private final static String DESTINATION="/topic/log";
private final RandomAccessFile randomAccessFile;
private long offset;
@Autowired
SimpMessagingTemplate messagingTemplate;
public FileWatchService() throws Exception {
randomAccessFile = new RandomAccessFile(FILE_NAME, READ_MODE);
offset = initialOffset();
}
@Scheduled(fixedDelay = 100, initialDelay = 3000)
public void sendUpdates() throws Exception {
long fileLength = randomAccessFile.length();
randomAccessFile.seek(offset);
while (randomAccessFile.getFilePointer() < fileLength) {
String latestData = randomAccessFile.readLine();
String payload = "{" + "\"content\":\"" + latestData + "\"" + "}";
messagingTemplate.convertAndSend(DESTINATION, payload);
}
offset = fileLength;
}
private long initialOffset() throws Exception {
long fileLength = randomAccessFile.length();
if (fileLength == 0) {
return 0;
}
long pos = fileLength - 1;
int linesFound = 0;
while (pos > 0 && linesFound < 10) {
randomAccessFile.seek(pos);
if (randomAccessFile.read() == '\n') {
linesFound++;
}
pos--;
}
if (pos > 0) {
pos += 2;
}
return pos;
}
}