001package io.jstach.opt.spring.example.hello; 002 003import org.springframework.http.ResponseEntity; 004import org.springframework.stereotype.Controller; 005import org.springframework.web.bind.annotation.GetMapping; 006import org.springframework.web.bind.annotation.RequestParam; 007import org.springframework.web.bind.annotation.ResponseBody; 008import org.springframework.web.servlet.ModelAndView; 009import org.springframework.web.servlet.View; 010 011import io.jstach.jstache.JStacheInterfaces; 012import io.jstach.jstachio.JStachio; 013import io.jstach.jstachio.Template; 014import io.jstach.jstachio.TemplateModel; 015import io.jstach.opt.spring.web.JStachioHttpMessageConverter; 016import io.jstach.opt.spring.webmvc.JStachioModelView; 017 018/** 019 * Example hello world controller using different ways to use JStachio for web 020 * development. 021 * 022 * @author agentgt 023 */ 024@Controller 025public class HelloController { 026 027 /** 028 * Placate JDK 18 Javadoc 029 * @param jstachio spring powered jstachio 030 * @param view wired in template 031 */ 032 public HelloController(JStachio jstachio, Template<HelloModel> view) { 033 this.jstachio = jstachio; 034 this.view = view; 035 } 036 037 /** 038 * (Optional) Spring will inject this template as the templates are either component 039 * scanned or loaded by the ServiceLoader into Spring's context. 040 * 041 * This is usually not needed as just returning the models is good enough. 042 */ 043 public final Template<HelloModel> view; 044 045 /** 046 * Although not needed You can also wire in JStachio directly 047 */ 048 public final JStachio jstachio; 049 050 /** 051 * Here we use JStachio runtime to resolve the renderer (in this case we are calling 052 * them Views) via Springs Http Message Converter. 053 * @apiNote Notice that the method has to be annotated with 054 * <code>@ResponseBody</code>. 055 * @return the model that will be used to find the correct view and then rendered 056 * using that view 057 * @see JStachioHttpMessageConverter 058 */ 059 @GetMapping(value = "/") 060 @ResponseBody 061 public HelloModel hello() { 062 return new HelloModel("Spring Boot is now JStachioed!"); 063 } 064 065 /** 066 * Here we use the generated code directly and return a {@link TemplateModel} which is 067 * analogous to {@link ModelAndView}. 068 * 069 * @apiNote Notice that the method has to be annotated with 070 * <code>@ResponseBody</code>. 071 * @return the template model pair that already has the template found. 072 * @see JStachioHttpMessageConverter 073 */ 074 @GetMapping(value = "/templateModel") 075 @ResponseBody 076 public TemplateModel templateModel() { 077 return HelloModelView.of().model(new HelloModel("Spring Boot is using JStachio TemplateModel!")); 078 } 079 080 /** 081 * Here we use a {@link ResponseEntity} which allows use to set status codes with our 082 * model to be rendered. 083 * @return a response entity. 084 * @see JStachioHttpMessageConverter 085 */ 086 @GetMapping(value = "/responseEntity") 087 public ResponseEntity<HelloModel> entity() { 088 return ResponseEntity.badRequest().body(new HelloModel("Spring Boot is using JStachio ResponseEntity. " 089 + "This is a 400 http error code but is not an actual error!")); 090 } 091 092 /** 093 * Here we could use {@link JStacheInterfaces} to make our model implement 094 * {@link JStachioModelView} to support the traditional servlet MVC approach. The 095 * model will use the static jstachio singleton that will be the spring one. 096 * <p> 097 * This approach has pros and cons. It makes your models slightly coupled to Spring 098 * MVC but allows you to return different views if say you had to redirect on some 099 * inputs ({@link org.springframework.web.servlet.view.RedirectView}). 100 * 101 * @apiNote Notice that the return type is {@link View}. 102 * @return the model and view that will be used as View (see 103 * {@link HelloModelAndView}). 104 * @see JStachioHttpMessageConverter 105 * @see HelloModelAndView 106 */ 107 @GetMapping(value = "/mvc") 108 @SuppressWarnings("exports") 109 public View mvc() { 110 return new HelloModelAndView("Spring Boot MVC is now JStachioed!"); 111 } 112 113 /** 114 * Here we use the {@linkplain #view wired renderer}. 115 * @return template model pair derived from {@link Template#model(Object)}. 116 */ 117 @GetMapping(value = "/wired") 118 @ResponseBody 119 public TemplateModel wired() { 120 var model = new HelloModel("JStachioed is wired!"); 121 return view.model(model); 122 } 123 124 /** 125 * Here we could use {@link JStacheInterfaces} to make our model implement 126 * {@link JStachioModelView} to support the traditional servlet MVC approach. The 127 * model will use the static jstachio singleton that will be the spring one. 128 * <p> 129 * This approach has pros and cons. It makes your models slightly coupled to Spring 130 * MVC but allows you to return different views if say you had to redirect on some 131 * inputs ({@link org.springframework.web.servlet.view.RedirectView}). 132 * <p> 133 * 134 * This controller method is to test buffering. Ignore. 135 * 136 * @apiNote Notice that the return type is {@link View}. 137 * @param size size of output 138 * @return the model and view that will be used as View (see 139 * {@link HelloModelAndView}). 140 * @see JStachioHttpMessageConverter 141 * @see HelloModelAndView 142 * @hidden 143 */ 144 @GetMapping(value = "/long/mvc") 145 @SuppressWarnings("exports") 146 public View longMvc(@RequestParam(name = "size", defaultValue = "0") int size) { 147 if (size <= 0) { 148 size = 1024 * 16; 149 } 150 StringBuilder sb = new StringBuilder(); 151 for (int i = 0; i < size; i++) { 152 int j = (i % 64) + 48; 153 char c = (char) j; 154 sb.append(c); 155 } 156 return new HelloModelAndView(sb.toString()); 157 } 158 159}