Skip to content

Instantly share code, notes, and snippets.

@radium226
Created March 13, 2018 16:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save radium226/60c245ea1357d9b2cc712060565b8af4 to your computer and use it in GitHub Desktop.
Save radium226/60c245ea1357d9b2cc712060565b8af4 to your computer and use it in GitHub Desktop.
Server Side Event in HTML with Spring Boot and Thymeleaf Fragment
package radium226;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.IContext;
import org.thymeleaf.expression.Sets;
import org.thymeleaf.spring5.SpringTemplateEngine;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@Controller
public class ApplicationController {
@Autowired
private TemplateEngine templateEngine;
@RequestMapping("/")
public String index(Model model) {
List<String> items = new ArrayList<>();
items.add("Initial Ping");
items.add("Initial Pong");
model.addAttribute("items", items);
return "index";
}
@RequestMapping(path = "/sse", method = RequestMethod.GET)
public SseEmitter sse() {
SseEmitter sseEmitter = new SseEmitter();
AtomicBoolean shouldContinue = new AtomicBoolean(true);
Thread thread = new Thread(() -> {
int i = 0;
while (shouldContinue.get()) {
try {
Thread.sleep(1000);
Context context = new Context();
context.setVariable("item", i++ % 2 == 0 ? "Ping" : "Pong");
Set<String> fragments = new HashSet<>();
fragments.add("item");
String html = templateEngine.process("index.html", fragments, context);
System.out.println(html);
sseEmitter.send(html, MediaType.TEXT_HTML);
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
sseEmitter.onCompletion(() -> {
shouldContinue.set(false);
});
return sseEmitter;
}
}
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>SSE with Thymeleaf Fragment</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="/webjars/jquery/3.3.1-1/jquery.min.js"></script>
<script th:src="@{/scripts/jquery-sse.min.js}"></script>
<script type="text/javascript">
$(document).ready(function() {
var items = $("#items")
var sse = $.SSE("/sse", {
onMessage: function(message) {
var html = message.data;
var item = $(html);
item.appendTo(items);
}
});
sse.start();
});
</script>
</head>
<body>
<ul id="items">
<th:block th:each="item : ${items}">
<li th:fragment="item" th:text="${item}">Item</li>
</th:block>
</ul>
</body>
</html>
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>radium226</groupId>
<artifactId>sse-thymeleaf-fragments</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.1-1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Package as an executable jar/war -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment