Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Annotated a class with @Configuration and @Controller. Need help in refactoring

Below is my class in which i had to use both @Configuration and @Controller as there should be only one instance of Thymeleaf in the entire application else i get exceptions for that. My other classes are annotated with @RequestScope so i cannot use a singleton scoped bean. So i had a mixup of Configuration and Controller to get the result, but i feel it is a bad practice. I would appreciate any help to refactor the code and remove the bad practice.

UPDATE

I am using spring-boot 1.5.14. I am using the following approach to process a template and keep the processed template as string.

@Controller
@Configuration
@EnableWebMvc
@ApplicationScope
public class MyThymeleafConfig {

    @GetMapping("/view-template")
    @ResponseBody
    public void viewTemplates() {

        Context context = new Context();
        context.setVariable("mydata", "this is it");

        String html = templateEngine().process("templates/view-to-process.html", context);
        System.out.println(html);
    }


    /*

    configuration for thymeleaf and template processing

    */

    @Bean
    public SpringTemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setTemplateResolver(thymeleafTemplateResolver());
        return templateEngine;
    }

    @Bean
    public SpringResourceTemplateResolver thymeleafTemplateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setPrefix("classpath:");
        templateResolver.setSuffix(".html");
        templateResolver.setCacheable(false);
        templateResolver.setTemplateMode(TemplateMode.HTML);
        return templateResolver;
    }

    @Bean
    public ThymeleafViewResolver thymeleafViewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(templateEngine());
        return viewResolver;
    }
}

To serve static resources the following config:

@Configuration
@EnableWebMvc
public class StaticResourceConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
                .addResourceHandler("/**")
                .addResourceLocations("/static/", "classpath:static/");
    }
}

UPDATE

I have also mentioned the reasons why i couldn't accept the below mentioned answers as my other classes have request scopes.

UPDATE

I have other classes with @RequestScopelike below:

@RequestScope
@Controller
public class SecondController {

    @GetMapping("/viewPage")
    public String viewPage(Model model) {
        model.addAttribute("mydata", "sjfbsdf");
        model.addAttribute("somedata", "sjdfksfjhshgdfbskdfj");
        return "templates/view-to-process.html";
    }
}
like image 663
sam Avatar asked Aug 01 '18 14:08

sam


People also ask

What happens when a class is annotated with the @controller annotation?

The @Controller annotation indicates that a particular class serves the role of a controller. There is no need to extend any controller base class or reference the Servlet API.

What is @configuration annotation used for?

@Configuration annotation indicates that a class declares one or more @Bean methods and may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.

What is the use of @configuration annotation in spring boot?

One of the most important annotations in spring is @Configuration annotation which indicates that the class has @Bean definition methods. So Spring container can process the class and generate Spring Beans to be used in the application. This annotation is part of the spring core framework.

Which of the following is correct about the @controller annotation?

Answer: The @Controller annotation indicates that a particular class serves the role of a controller. It does not require you to extend any controller base class or reference the Servlet API. Is This Question Helpful?


1 Answers

Don't put request mappings inside configuration classes, it violates the principal of separation of concerns. You can go for a approach like below.

All the application wide beans are setup in Application class which is present in the root of the classpath. Application class in the best place to have your thymeleaf and static resource configurations too, since the Application class have application-scope.

@SpringBootApplication
@EnableWebMvc
public class Application{

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Bean
    public ViewResolver viewResolver() {
       ThymeleafViewResolver resolver = new ThymeleafViewResolver();
       resolver.setTemplateEngine(templateEngine());
       resolver.setCharacterEncoding("UTF-8");
       resolver.setCache(false);
       return resolver;
    }

   @Bean
   public TemplateEngine templateEngine() {
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();
        templateEngine.setEnableSpringELCompiler(true);
        templateEngine.addDialect(new LayoutDialect());
        templateEngine.addDialect(new Java8TimeDialect());
        templateEngine.setTemplateResolver(templateResolver());
        return templateEngine;
   }

   private ITemplateResolver templateResolver() {
       SpringResourceTemplateResolver resolver = new 
            SpringResourceTemplateResolver();
       resolver.setApplicationContext(applicationContext);
       resolver.setPrefix("classpath:/templates/");
       resolver.setTemplateMode(TemplateMode.HTML);
       return resolver;
   }
}

If you put the static resources inside a folder named static or public in the classpath, springboot identify that as the location for static resources. Then you don't need to override addResourceHandlers method. If you really want to do it, you can do it inside the Application class extending WebMvcConfigurerAdapter. You don't need separate class to configure just static resource paths.

Don't put request mappings inside configuration classes, put them in separate controller classes like:

@Controller
public class MyController {
   @GetMapping("/view-template")
   @ResponseBody
   public void viewTemplates() {
         Context context = new Context();
         context.setVariable("mydata", "this is it");

         String html = templateEngine().process("templates/view-to-process.html", context);
         System.out.println(html);
    }
}

Of cause, springboot allows you to do it the way you like, but you'd better stick to a general approach.

like image 68
Johna Avatar answered Sep 18 '22 14:09

Johna