I want to write a web api that returns same text every 5 seconds in an infinite stream using java. What are the possible ways? and how to do it?
example:
curl 'https://localhost:8080/abcd'
response as below :
"some text"
.
.<wait 5 seconds>
.
"some text"
.
.<wait 5 seconds>
.
"some text"
.
.
etc...
CodePudding user response:
@SpringBootApplication
public class InfinitetextApplication {
public static void main(String[] args) {
SpringApplication.run(InfinitetextApplication.class, args);
}
@Bean
public TaskScheduler taskScheduler() {
return new ThreadPoolTaskScheduler();
}
@RestController
static class InfiniteText {
private TaskScheduler taskScheduler;
public InfiniteText(TaskScheduler taskScheduler) {
this.taskScheduler = taskScheduler;
}
@GetMapping("/")
public ResponseEntity<ResponseBodyEmitter> textStream() throws IOException {
ResponseBodyEmitter rbe = new ResponseBodyEmitter();
sendMessage(rbe);
return ResponseEntity.ok()
.contentType(MediaType.TEXT_PLAIN)
.body(rbe);
}
private void sendMessage(ResponseBodyEmitter rbe) {
try {
rbe.send("Hello\n");
taskScheduler.schedule(() -> sendMessage(rbe), inFiveSeconds());
} catch (IOException e) {
rbe.completeWithError(e);
throw new UncheckedIOException(e);
}
}
private Instant inFiveSeconds() {
return Instant.now()
.plusSeconds(5);
}
}
}
CodePudding user response:
When you say "infinite stream" I believe you're looking for "reactive stream". Probably You're looking for Spring Reactive Web and not Spring Web MVC
Spring Reactive Web Also Known as Spring Web Flux, It uses Netty as non blocking Web Server, rather than Tomact 9 for Spring MVC (blocking).
Web Controller
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
@RestController
@RequestMapping("api/read")
@CrossOrigin
public class ReadController {
@Autowired
private ElementRepo elementRepo;
@GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Element> getAll(){
return elementRepo.flux();
}
}
Data Source
@Repository
public class ElementRepo {
public Flux<Element> flux() {
return Flux
.just({something....}
.delayElements(Duration.ofSeconds(5));
}
}