001package io.jstach.opt.spring.web; 002 003import java.io.BufferedWriter; 004import java.io.IOException; 005import java.io.OutputStreamWriter; 006import java.io.Writer; 007import java.nio.charset.Charset; 008import java.nio.charset.StandardCharsets; 009 010import org.springframework.http.HttpInputMessage; 011import org.springframework.http.HttpOutputMessage; 012import org.springframework.http.MediaType; 013import org.springframework.http.converter.AbstractHttpMessageConverter; 014import org.springframework.http.converter.HttpMessageNotReadableException; 015import org.springframework.http.converter.HttpMessageNotWritableException; 016import org.springframework.web.bind.annotation.ResponseBody; 017 018import io.jstach.jstachio.JStachio; 019 020/** 021 * Typesafe way to use JStachio in Spring Web. 022 * <p> 023 * For this to work the controllers need to return JStache models and have the controller 024 * method return annotated with {@link ResponseBody}. 025 * <p> 026 * <strong>Example:</strong> <pre><code class="language-java"> 027 * @JStache 028 * public record HelloModel(String message){} 029 * 030 * @GetMapping(value = "/") 031 * @ResponseBody 032 * public HelloModel hello() { 033 * return new HelloModel("Spring Boot is now JStachioed!"); 034 * } 035 * </code> </pre> 036 * 037 * @author agentgt 038 * 039 */ 040public class JStachioHttpMessageConverter extends AbstractHttpMessageConverter<Object> { 041 042 private final JStachio jstachio; 043 044 /** 045 * Create http converter from jstachio 046 * @param jstachio an instance usually created by spring 047 */ 048 public JStachioHttpMessageConverter(JStachio jstachio) { 049 super(StandardCharsets.UTF_8, MediaType.TEXT_HTML); 050 this.jstachio = jstachio; 051 } 052 053 @Override 054 protected boolean supports(Class<?> clazz) { 055 return jstachio.supportsType(clazz); 056 } 057 058 @Override 059 public boolean canRead(Class<?> clazz, @SuppressWarnings("exports") MediaType mediaType) { 060 return false; 061 } 062 063 @Override 064 protected Object readInternal(Class<? extends Object> clazz, HttpInputMessage inputMessage) 065 throws IOException, HttpMessageNotReadableException { 066 throw new HttpMessageNotReadableException("Input not supported by JStachio", inputMessage); 067 068 } 069 070 @Override 071 protected void writeInternal(Object t, HttpOutputMessage outputMessage) 072 throws IOException, HttpMessageNotWritableException { 073 Charset charset = getDefaultCharset(); 074 if (charset == null) { 075 charset = StandardCharsets.UTF_8; 076 } 077 try (Writer writer = new BufferedWriter(new OutputStreamWriter(outputMessage.getBody(), charset))) { 078 jstachio.execute(t, writer); 079 } 080 } 081 082}