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