001package io.jstach.opt.spring.example.hello;
002
003import java.io.IOException;
004import java.io.Writer;
005
006import org.springframework.beans.factory.annotation.Autowired;
007import org.springframework.http.ResponseEntity;
008import org.springframework.stereotype.Component;
009import org.springframework.stereotype.Controller;
010import org.springframework.web.bind.annotation.GetMapping;
011import org.springframework.web.bind.annotation.ResponseBody;
012import org.springframework.web.servlet.ModelAndView;
013import org.springframework.web.servlet.View;
014
015import io.jstach.jstache.JStacheInterfaces;
016import io.jstach.jstachio.Template;
017import io.jstach.jstachio.TemplateModel;
018import io.jstach.opt.spring.web.JStachioHttpMessageConverter;
019import io.jstach.opt.spring.webmvc.JStachioModelView;
020
021/**
022 * Example hello world controller using different ways to use JStachio for web
023 * development.
024 *
025 * @author agentgt
026 */
027@Controller
028public class HelloController {
029
030        /**
031         * Placate JDK 18 Javadoc
032         */
033        public HelloController() {
034        }
035
036        /**
037         * Spring will inject this as the templates are component scanned as this projects
038         * module {@link io.jstach.opt.spring.example/ } has a config that will add @
039         * {@link Component} to all generated code.
040         */
041        @Autowired(required = true)
042        public Template<HelloModel> view;
043
044        /**
045         * Here we use JStachio runtime to resolve the renderer (in this case we are calling
046         * them Views) via Springs Http Message Converter.
047         * @apiNote Notice that the method has to be annotated with
048         * <code>&#64;ResponseBody</code>.
049         * @return the model that will be used to find the correct view and then rendered
050         * using that view
051         * @see JStachioHttpMessageConverter
052         */
053        @GetMapping(value = "/")
054        @ResponseBody
055        public HelloModel hello() {
056                return new HelloModel("Spring Boot is now JStachioed!");
057        }
058
059        /**
060         * Here we use the generated code directly and return a {@link TemplateModel} which is
061         * analogous to {@link ModelAndView}.
062         *
063         * @apiNote Notice that the method has to be annotated with
064         * <code>&#64;ResponseBody</code>.
065         * @return the template model pair that already has the template found.
066         * @see JStachioHttpMessageConverter
067         */
068        @GetMapping(value = "/templateModel")
069        @ResponseBody
070        public TemplateModel templateModel() {
071                return HelloModelView.of().model(new HelloModel("Spring Boot is using JStachio TemplateModel!"));
072        }
073
074        /**
075         * Here we use a {@link ResponseEntity} which allows use to set status codes with our
076         * model to be rendered.
077         * @return a response entity.
078         * @see JStachioHttpMessageConverter
079         */
080        @GetMapping(value = "/responseEntity")
081        public ResponseEntity<HelloModel> entity() {
082                return ResponseEntity.badRequest().body(new HelloModel("Spring Boot is using JStachio ResponseEntity. "
083                                + "This is a 400 http error code but is not an actual error!"));
084        }
085
086        /**
087         * Here we could use {@link JStacheInterfaces} to make our model implement
088         * {@link JStachioModelView} to support the traditional servlet MVC approach. The
089         * model will use the static jstachio singleton that will be the spring one.
090         * <p>
091         * This approach has pros and cons. It makes your models slightly coupled to Spring
092         * MVC but allows you to return different views if say you had to redirect on some
093         * inputs ({@link org.springframework.web.servlet.view.RedirectView}).
094         *
095         * @apiNote Notice that the return type is {@link View}.
096         * @return the model and view that will be used as View (see
097         * {@link HelloModelAndView}).
098         * @see JStachioHttpMessageConverter
099         * @see HelloModelAndView
100         */
101        @SuppressWarnings("exports")
102        @GetMapping(value = "/mvc")
103        public View mvc() {
104                return new HelloModelAndView("Spring Boot MVC is now JStachioed!");
105        }
106
107        /**
108         * Here we use the {@linkplain #view wired renderer} that does not have filtering and
109         * thus cannot use JMustache for dynamic editing of templates.
110         * @param writer spring will inject the servlet output
111         * @throws IOException an error while writing to the output
112         */
113        @GetMapping(value = "/wired")
114        public void wired(Writer writer) throws IOException {
115                var model = new HelloModel("JStachioed is wired!");
116                view.execute(model, writer);
117        }
118
119}