How to use thymeleaf without controller - spring-boot

I want to use thymeleaf templates in my spring boot application. I've some html pages in the src/resources/public directory and I want them to be served wihout writing a controller because I want to write a front end application. I can access the index.html file at http://localhost:8080/index.html but it's not using the thymeleaf syntax. How can I do it?
I've added the thymeleaf dependency, tried writing a SpringResourceTemplateResolver bean but still no luck. Here is what I've done so far:
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#Bean
public SpringResourceTemplateResolver templateResolver(){
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("classpath:/public/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCacheable(true);
return templateResolver;
}
}

Related

WebMvcTest when Multiple TemplateResolver

I have added a second TemplateResolver because I would like to use also Thymeleaf to serve Template for Plain-Text Templates. When starting application it works fine, the Thymeleaf templates are being resolved.
But from now my #WebMvcTests are not working. I says, that:
Error resolving template [disclaimer/view], template might not exist or might not be accessible by any of the configured Template Resolvers
The TemplateResolver are configures like:
#Configuration
public class SitemapViewResolverConfiguration {
#Bean
public ITemplateResolver thymeleafTextTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("/templates/sitemap/");
templateResolver.setCacheable(false);
templateResolver.setSuffix(".txt");
templateResolver.setTemplateMode(TemplateMode.TEXT);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCheckExistence(TRUE);
return templateResolver;
}
}
#Configuration
public class PageViewResolverConfiguration {
#Bean
public ITemplateResolver thymeleafHtmlTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("classpath:/templates/view/");
templateResolver.setCacheable(false);
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCheckExistence(TRUE);
return templateResolver;
}
}
My template structure is as follows:
The test class is:
#RunWith(SpringRunner.class)
#WebMvcTest(DisclaimerController.class)
public class DisclaimerControllerTest {
#Autowired MockMvc mvc;
#Test
public void testGet() throws Exception {
mvc.perform(get("/disclaimer")
.andExpect(status().isOk())
.andExpect(view().name("disclaimer/view"))
;
}
}
Error:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: Error resolving template [disclaimer/view], template might not exist or might not be accessible by any of the configured Template Resolvers
Okay, I found the problem. As I use #WebMvcTest it didn't load my TemplateResolver. As before I relied on Spring Boot automatic resolver, I am using now two selfmade resolver. But they are not picked up by the test, that's why MockMvc could not resolve it.
I fixed it by adding Configuration as Import:
#RunWith(SpringRunner.class)
#WebMvcTest({PageViewResolverConfiguration.class, DisclaimerController.class})
public class DisclaimerControllerTest {
...
}

Spring Boot swagger file without UI

I have a simple service built in Spring Boot that has a simple API. I've added the springfox libraries to use swagger and the swagger UI, but I do not want my application to serve the UI also. I just want to get the definition from from /api/v1/api-docs
How do I switch off the UI part? Not adding swagger-ui library as a dependency doesn't remove the UI for some reason.
You can block the UI and return HTTP code 404. Something similar to below
#Controller //note - this is a spring-boot controller, not #RestController
public class HomeController {
#RequestMapping ("/swagger/api/v1/api-docs")
public String home(HttpServletRequest request) {
throw new ResourceNotFoundException(); //Custom Solution
or
throw new NoSuchRequestHandlingMethodException(request);
}
}
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
...
}
If you are using Spring Boot
#SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
#Bean
RouterFunction<ServerResponse> routerFunction() {
return route(GET("/swagger"), req ->
ServerResponse.temporaryRedirect("<some 404 page>").build());
}
}

Spring boot - executable war also deployable to app server

Let's say I have a spring boot web application - It is runnable via gradle (embedded tomcat).
But I need it also to be possible to deploy war in standard way into app server.
How the app should be configured? Standard web.xml along with xml configuration?
Currently I have something like:
#SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
System.setProperty("spring.profiles.active", "dev");
SpringApplication.run(MyApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
#Configuration
#ConditionalOnWebApplication
public static class WebConfiguration {
#Bean
public ServletListenerRegistrationBean<ServletContextListener> registerClientCookieConfigListener () {
ServletListenerRegistrationBean<ServletContextListener> srb =
new ServletListenerRegistrationBean<>();
srb.setListener(new MyConfigListener());
return srb;
}
#Bean
public ServletListenerRegistrationBean<HttpSessionListener> registerMySessionConfigListener () {
ServletListenerRegistrationBean<HttpSessionListener> srb =
new ServletListenerRegistrationBean<>();
srb.setListener(new MySessionConfigListener());
return srb;
}
#Bean
public FilterRegistrationBean registerLoginFilter() {
FilterRegistrationBean filter = new FilterRegistrationBean(new MyFilter());
filter.setUrlPatterns(Collections.singletonList("/*"));
return filter;
}
#Bean
public ServletRegistrationBean registerSAMLDispatcherServlet() {
ServletRegistrationBean bean = new ServletRegistrationBean(
new DispatcherServlet(), "/test/*");
bean.setLoadOnStartup(1);
return bean;
}
}
}
which is 1:1 mapping to web.xml.
Is it even possible to deploy it to app server without web.xml?
You don't need web.xml to deploy spring boot to standalone tomcat server or any other web server.
spring boot does not rely on xml configurations, it configures an equivalent to the dispatcher servlet automatically.
to deploy a spring boot app to an another server, you need to update your packaging to war in maven
<packaging>war</packaging>
and tell maven that a webserver will be available in the runtime and don't package it with scope provided
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
few documentations
https://www.baeldung.com/spring-boot-war-tomcat-deploy
https://www.mkyong.com/spring-boot/spring-boot-deploy-war-file-to-tomcat/

Spring Boot 2 Thymeleaf Configuration Ignoring 'templates'

I'm migrating an existing application to Spring 5.0.0.M3 & Spring Boot 2.0.0.M3. With Spring Boot I'm also importing the Thymeleaf starter.
The application has 2 template folders mails and templates. If I specify the below configuration for email templates, the templates folder is ignored; e.g. I'm getting FileNotFoundException for templates in this folder.
#Configuration
public class ThymeleafConfiguration {
#SuppressWarnings("unused")
private final Logger log = LoggerFactory.getLogger(ThymeleafConfiguration.class);
#Bean
#Description("Thymeleaf template resolver serving HTML 5 emails")
public ClassLoaderTemplateResolver emailTemplateResolver() {
ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
emailTemplateResolver.setPrefix("mails/");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setTemplateMode("HTML5");
emailTemplateResolver.setCharacterEncoding(CharEncoding.UTF_8);
emailTemplateResolver.setOrder(1);
return emailTemplateResolver;
}
}
I've tried setting the setOrder parameter to 2, 10, etc. which made no difference. If I remove the resolver method, the templates folder is recognized, but the mails folder isn't.
Any ideas what might be going on?
What I understand is you have mails and templates sub-folders under the resources folder.
You can add resource folder as the prefix in your ClassLoaderTemplateResolver. Then add ResourceHandler for both mails and templates sub-folders.
ClassLoaderTemplateResolver
#Bean
#Description("Thymeleaf template resolver serving HTML 5 emails")
public ClassLoaderTemplateResolver emailTemplateResolver() {
ClassLoaderTemplateResolver emailTemplateResolver = new
ClassLoaderTemplateResolver();
emailTemplateResolver.setPrefix("resources/");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setTemplateMode("HTML5");
emailTemplateResolver.setCharacterEncoding(CharEncoding.UTF_8);
emailTemplateResolver.setOrder(1);
return emailTemplateResolver;
}
Place your ResourceHandler method in your application class, which your have annotated with #SpringBootApplication.
ResourceHandler
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/mails/**")) {
registry.addResourceHandler("/mails/**").addResourceLocations("classpath:/resources/mails/");
}
if (!registry.hasMappingForPattern("/templates/**")) {
registry.addResourceHandler("/templates/**").addResourceLocations("classpath:/resources/templates/");
}
}
When you return your view name from any method, it can be like:
return "mails/page1";
or
return "templates/page2";

Spring Boot: Web.xml and embedded server jar

I'm trying to convert a legacy spring-mvc app to Spring boot (in order to have a self contained JAR enabling easier upgrade to Java-8).
I see no reason to use replace my existing web.xml file with code as the code looks like configuration and web.xml is more established.
Is it possible to use my existing web.xml in a Spring Boot application (in embedded JAR mode)?
Edit: I also want to avoid using #EnableAutoConfiguration
Thanks
ok, thanks to Mecon, I'm slightly closer. I had to remove the ContextLoaderListener in the web.xml; also had to import the xml Spring config even though it was referenced in the contextConfigLocation.
#Configuration
#ComponentScan
#EnableAutoConfiguration
#ImportResource(value = {"classpath:/webapp-base.xml"})
public class WebApp {
#Autowired
private ServerProperties serverProperties;
#Autowired
private MediaConfiguration mediaConfig;
#Bean
public EmbeddedServletContainerFactory servletContainer() {
JettyEmbeddedServletContainerFactory factory = new JettyEmbeddedServletContainerFactory();
factory.setContextPath(serverProperties.getContextPath());
factory.addConfigurations(new WebXmlConfiguration());
factory.addServerCustomizers(server -> {
List<Handler> resourceHandlers = getResourceHandlers();
Handler original = server.getHandler();
HandlerList handlerList = new HandlerList();
Handler[] array = getHandlers(original, resourceHandlers);
handlerList.setHandlers(array);
server.setHandler(handlerList);
}
);
return factory;
}
private List<Handler> getResourceHandlers() {
return mediaConfig.getMappings().stream().map(m -> {
ContextHandler contextHandler = new ContextHandler(m.getUrlpath());
ResourceHandler resourceHandler = new ResourceHandler();
resourceHandler.setResourceBase(m.getFilepath());
contextHandler.setHandler(resourceHandler);
return contextHandler;
}).collect(Collectors.toList());
}
private Handler[] getHandlers(Handler original, List<Handler> resourceHandlers) {
ArrayList<Handler> handlers = new ArrayList<>();
handlers.add(original);
handlers.addAll(resourceHandlers);
return handlers.toArray(new Handler[resourceHandlers.size()+1]);
}
public static void main(String[] args) {
SpringApplication.run(WebApp.class, args);
}
}
You don't need Spring-Boot to have a self-contained JAR, all you really need is Embedded Tomcat, or Jetty.
Create a class with public static void main(String[] a), and this Class will be used when the Jar is "executed" by java -jar myWebapp.jar command.
In the main method, you can fire up the Embedded Tomcat or Jetty, and make it load your webapp by referring to existing web.xml.

Resources