I'm trying to configure Spring5 and Thymeleaf3 togheter.
I'm working on Eclipse, I build with clean install and run the app with springboot:run.
I've setup a controller and a couple of template and css but it seems that thymeleaf cannot find the css, in the browser it shows the template (es. 'panda.html') without loading the css but if I open manually the .html the browser load also the .css . What i need to add to my code?
this is the mapping
#Controller
public class MyController {
#Autowired
UtentiRepository utentiRepository;
#GetMapping("/gab")
public String panda(Model model) {
return "panda";
}
and this is the template resolver
#Bean
public SpringResourceTemplateResolver templatecssResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/static/css/");
templateResolver.setSuffix(".css");
return templateResolver;
}
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("classpath:/templates/");
templateResolver.setSuffix(".html");
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(templatecssResolver());
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
registry.viewResolver(resolver);
}
You've to override the addResourceHandlers(..) method of the you calls that implements the WebMvcConfigurerAdapter not as a bean (SpringResourceTemplateResolver )
SO just add the overiding method
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**")
.addResourceLocations("classpath:/static/css/");
}
in your template use
<link href="<c:url value="/css/style.css" />" rel="stylesheet">
or using themleaf
<link th:href="#{/css/style.css}" />" rel="stylesheet">
Related
How if one can use ThymeleafViewResolver as a defalt view resolver.
Currentely my WebMvcConfig looks like this
#Configuration
#ComponentScan(basePackages="com.greatLearning.ticketAPI.controller")
public class WebMvcConfig implements WebMvcConfigurer {
#Autowired
ApplicationContext applicationContext;
// #Override
// public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
// configurer.enable();
// }
public InternalResourceViewResolver resolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
//Thymeleaf ViewResolver
#Bean
public SpringResourceTemplateResolver templateResolver(){
// SpringResourceTemplateResolver automatically integrates with Spring's own
// resource resolution infrastructure, which is highly recommended.
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setPrefix("/WEB-INF/views/");
templateResolver.setSuffix(".html");
// HTML is the default value, added here for the sake of clarity.
templateResolver.setTemplateMode(TemplateMode.HTML);
// Template cache is true by default. Set to false if you want
// templates to be automatically updated when modified.
templateResolver.setCacheable(true);
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine(){
// SpringTemplateEngine automatically applies SpringStandardDialect and
// enables Spring's own MessageSource message resolution mechanisms.
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
// Enabling the SpringEL compiler with Spring 4.2.4 or newer can
// speed up execution in most scenarios, but might be incompatible
// with specific cases when expressions in one template are reused
// across different data types, so this flag is "false" by default
// for safer backwards compatibility.
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
#Bean
public ThymeleafViewResolver viewResolver(){
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
// NOTE 'order' and 'viewNames' are optional
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[] {".html", ".xhtml"});
return viewResolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
}
for *.jsp view it is working just fine, but I want to use Thymeleaf to resolve my .html templates becasue I don't want to use *.jsp .
One thing to note is that in my controller
TestController.java
#RequestMapping("/hello")
public String method1() {
return "hello";
}
#RequestMapping("/hello2")
#ResponseBody
public String method2() {
return "hello"; //This works fine
}
when I hit /hello api this is what I get
How do I configre viewResolver so that spring picks up ThymeleafViewResolver to resolve html rather than jsp
Problem Solved!!!!!
Here is what I did after an hour of debugging the libraries
in WebMvcConfig.java I revomed the public InternalResourceViewResolver resolver() method as it is sed to configure jsp.
Now in ThymeleafViewResolver viewResolver() remove these two:
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[] {".html", ".xhtml"});
got help through debgging and [this post](Problem Solved!!!!!
Here is what I did after an hour of debugging the libraries
in WebMvcConfig.java I revomed the public InternalResourceViewResolver resolver() method as it is sed to configure jsp.
Now in ThymeleafViewResolver viewResolver() remove these two:
viewResolver.setOrder(1);
viewResolver.setViewNames(new String[] {".html", ".xhtml"});
got help through debgging and this post.
As to why I will answer if anyone is interested. :)
I have a camel rest in my project and a servlet is configured for it. At the moment I'm trying to add a regular RestController without camel. Can two types of rest be in the same project?
For example
#Override
public void configure() throws Exception {
rest("/dictionary/get-dictionary")
.get()
.param().name("dictionary").required(true).type(RestParamType.query).endParam()
.param().name("name").required(true).type(RestParamType.query).endParam()
.....
.endRest();
CamelServlet implemented for camel
#RestController
#RequestMapping("/createOrder")
#RequiredArgsConstructor
public class OrderController {
private final OrderService OrderService;
#PostMapping
public void createForm(#RequestBody App app) {
orderService.createFullOrder(app);
}
}
When I request createOrder, I always get 404. How can I make both types of controllers work?
Thank in advice
Solution
#Configuration
public class AppConfig {
#Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
#SuppressWarnings("rawtypes")
#Bean
public ServletRegistrationBean axisServletRegistrationBean() {
#SuppressWarnings("unchecked")
ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet(), "/createOrder");
registration.addUrlMappings("/createOrder");
return registration;
}
}
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.package.package")
public class WebConfig {
}
I'm using custom crudrespository to persist data in redis. However, I'm unable to autowire custom repository.
All the configuration seems correct and redis is running on my local.
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;
#Repository
public interface CustomRepository extends CrudRepository<String,
Long> {
String get(String key);
void put(String key, String value);
}
//////////
public class StorageServiceImpl implements IStorageService {
#Autowired
private CustomRepository respository;
#Override
public void saveParameter() {
this.respository.put("key1","value1");
}
#Override
public String getParameter() {
return this.respository.get("key1");
}
/////
#Service
public interface IStorageService {
void saveParameter();
String getParameter();
}
///////
#SpringBootApplication(scanBasePackages = {"com.example.cache"})
#EnableRedisRepositories(basePackages = {"com.example.cache.repository"})
public class ApplicationConfiguration {
public static void main(String[] args){
SpringApplication.run(ApplicationConfiguration.class, args);
new StorageServiceImpl().saveParameter();
System.out.println(new StorageServiceImpl().getParameter());
}
}
When I try running this application using gradle bootRun, I get
Exception in thread "main" java.lang.NullPointerException
at com.example.cache.impl.StorageServiceImpl.saveParameter(StorageServiceImpl.java:16)
at com.example.cache.ApplicationConfiguration.main(ApplicationConfiguration.java:17)
Not sure what's wrong?
You can't use new on any bean, you need to #Autowire it. The annotations only work with spring managed beans at every level.
Add a new bean with a a storage service and a method that makes your call after it is created.
Also, I can't remember if the spring-boot creates the bean if there is only one implementation but I believe your StorageServiceImpl needs the #Service annotation, not the interface.
Delete this from your ApplicationConfiguration class.
new StorageServiceImpl().saveParameter();
System.out.println(new StorageServiceImpl().getParameter());
Then add this new class.
#Service
public class Startup {
#Autowired
IStorageService storageService;
#PostConstruct
public void init(){
storageService.saveParameter();
System.out.println(storageService().getParameter());
}
}
And you need a config
#Configuration
#EnableRedisRepositories
public class ApplicationConfig {
#Bean
public RedisConnectionFactory connectionFactory() {
return new JedisConnectionFactory();
}
#Bean
public RedisTemplate<?, ?> redisTemplate() {
RedisTemplate<byte[], byte[]> template = new RedisTemplate<byte[], byte[]>();
return template;
}
}
How can I add a custom resource location that is on for example my D drive in folder called Resources.
#Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
registry.addResourceHandler("/**").addResourceLocations("D:/Resources/");
}
}
This doesn't work.
This is my application class and the only other configuration file.
#SpringBootApplication
public class Application {
public static void main(String args[]){
SpringApplication.run(Application.class, args);
}
#Bean // for websocket endpoints
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
#Bean
public PasswordEncoder bcryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
You should state your location using the file prefix, check more here . So it should be
registry.addResourceHandler("/**").addResourceLocations("file:///D:/Resources/");
Try /D:/Resources/. Absolute path must start with /
I want to use Swagger with Spring MVC. I have following entries in the build.gradle file
compile 'com.mangofactory:swagger-springmvc:0.9.4'
compile 'com.wordnik:swagger-annotations:1.3.12'
compile 'org.webjars:swagger-ui:2.0.12'
I have enable it using #EnableSwagger annotation.
#EnableAutoConfiguration(exclude = {EmbeddedServletContainerAutoConfiguration.EmbeddedJetty.class, LiquibaseAutoConfiguration.class, org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class})
#EnableSwagger
#EnableWebMvc
#Configuration
public class App extends WebMvcConfigurerAdapter{
#Bean
ProtobufHttpMessageConverter protobufHttpMessageConverter() {
return new ProtobufHttpMessageConverter();
}
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
private SpringSwaggerConfig springSwaggerConfig;
#SuppressWarnings("SpringJavaAutowiringInspection")
#Autowired
public void setSpringSwaggerConfig(SpringSwaggerConfig springSwaggerConfig) {
this.springSwaggerConfig = springSwaggerConfig;
}
#Bean
public SwaggerSpringMvcPlugin customImplementation(){
return new SwaggerSpringMvcPlugin(this.springSwaggerConfig)
.apiInfo(apiInfo())
.includePatterns(".*feed.*"); // assuming the API lives at something like http://myapp/api
}
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo(
"My Project's REST API",
"This is a description of your API.",
"API TOS",
"me#wherever.com",
"API License",
"API License URL"
);
return apiInfo;
}
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("*.html").addResourceLocations("/");
}
}
But when run the application using spring boot and hit the endpoint http://localhost:8080/api-docs, I just see the response in Json,
{"apiVersion":"1.0","apis":[{"description":"Basic Error Controller","path":"/default/basic-error-controller","position":0},{"description":"Manage people","path":"/default/people","position":0}],"authorizations":{},"info":{"contact":"Contact Email","description":"Api Description","license":"Licence Type","licenseUrl":"License URL","termsOfServiceUrl":"Api terms of service","title":"default Title"},"swaggerVersion":"1.2"}
I copied the static files from swagger-ui and copied it to my /main/webapp/doc
I am still missing fancy UI.