Overriding default ValidationMessages.properties from hibernate-validation - spring

I'm trying to override the ValidationMessages.properties from default hibernate-validation (5.0.2 version) in a Spring MVC application.
But it keeps using the internal ValidationMessages.properties from jar.
UPDATE: it works (but it should be another way) when I copy the *.properties files to org\hibernate\validator ...
This is my configuration:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.blueliv.search.*"} )
public class WebConfig extends WebMvcConfigurerAdapter {
static Logger log =LoggerFactory.getLogger(WebMvcConfigurerAdapter.class);
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new GsonHttpMessageConverter());
//converters.add(new MappingJackson2HttpMessageConverter());
}
#Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
#Bean
public ExceptionHandlerExceptionResolver exceptionResolver() {
return new ExceptionHandlerExceptionResolver();
}
#Bean
public LocalValidatorFactoryBean validator() {
LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean();
validatorFactoryBean.setValidationMessageSource(getBundle());
return validatorFactoryBean;
}
public ReloadableResourceBundleMessageSource getBundle(){
log.debug("get bundle!");
ReloadableResourceBundleMessageSource bundle = new ReloadableResourceBundleMessageSource();
bundle.setBasenames("classpath:/i18n/validation/ValidatonMessages");
return bundle;
}
#Override
public Validator getValidator() {
return validator();
}

Related

Spring MVC controllers configure for thymeleaf views

I've tried to configure controllers for thymeleaf views resolver, but it doesn't work. I made controller test and they passed so i think it is servlets configuration problem.
My WebConfig looks like this:
#Configuration
#EnableWebMvc
#ComponentScan("springmvccommerce.web")
public class WebConfig implements WebMvcConfigurer{
#Bean
ViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
return viewResolver;
}
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCacheable(true);
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
Edit:
HomeController:
#Controller
public class HomeController {
#GetMapping("/")
public String home() {
return "home";
}
}
And productController:
#Controller
public class ProductController {
#Autowired
private ProductRepository productRepository;
#GetMapping("/products")
public String products(Model model) {
model.addAttribute("productList", productRepository.findProduct(Long.MAX_VALUE, 20));
return "products";
}
}
If it is not enough, I've added link to repo in comment.
It seems spring boot haven't support for tomcat 10 due to the jakarta namespace, switch to tomcat 9 and retry.
Here are some links related:
https://github.com/spring-projects/spring-framework/issues/25354
Deploying Spring 5.x on Tomcat 10.x with jakarta.* package

Spring JPA Custom Validator Bean Inyection

Any bean inyected into CustomValidator Implementation are always null. Im using Spring Boot 2, the applciation is a REST API, i'm not using MVC.
I have tried everything I have read about this with no luck so far.
this topic here for example did not work for me
Should I validate otherwise?, I've been stuck with this for 2 days already.
This is my Config class:
#Configuration
public class Beans {
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:idiomas/idioma");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleResolver localeResolver() {
AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
resolver.setDefaultLocale(new Locale("es"));
return resolver;
}
#Bean
public LocalValidatorFactoryBean getValidator() {
LocalValidatorFactoryBean validatorFactoryBean = new LocalValidatorFactoryBean();
validatorFactoryBean.setValidationMessageSource(messageSource());
return validatorFactoryBean;
}
#Bean
public CommonsRequestLoggingFilter logFilter() {
CommonsRequestLoggingFilter filter = new CommonsRequestLoggingFilter();
filter.setIncludeQueryString(true);
filter.setIncludePayload(true);
filter.setMaxPayloadLength(10000);
filter.setIncludeHeaders(true);
filter.setAfterMessagePrefix("REQUEST: ");
return filter;
}
}
My CustomValidator looks like this:
public class AlmacenValidator implements ConstraintValidator {
#Autowired
private AlmacenService servicio;
#Autowired
private ApplicationContext contexto;
#Override
public void initialize(AlmacenValido constraintAnnotation) {
}
#Override
public boolean isValid(Almacen item, ConstraintValidatorContext context) {
//Database calls
}
JPA Entity:
#Entity
#AlmacenValido
#Table(name = "almacenes")
public class Almacen {
//Entity fields
}
The Annotation:
#Documented
#Retention(RUNTIME)
#Target({ TYPE, FIELD, ANNOTATION_TYPE, PARAMETER })
#Constraint(validatedBy = AlmacenValidator.class)
public #interface AlmacenValido {
String message() default "{validacion.almacen}";
Class[] groups() default {};
Class[] payload() default {};
}
I've created test example for you. Please check it https://github.com/alex-petrov81/stackoverflow-answers/tree/master/validation-bean-injection

How to solve `No message found under code 'good.morning.message' for locale 'us'`?

I'm trying to test a internationalization but I keep getting the message "No message found under code 'good.morning.message' for locale 'us'." each time I make a GET request.
I'm using Netbeans IDE for my project. Below are my codes
#SpringBootApplication
public class RestfulWebServicesApplication {
public static void main(String[] args) {
SpringApplication.run(RestfulWebServicesApplication.class, args);
}
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setDefaultLocale(Locale.US);
return localeResolver;
}
#Bean
public ReloadableResourceBundleMessageSource bundleMessageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
ControllerClass
#RestController
public class HelloWorldController {
#Autowired
private MessageSource messageSource;
#GetMapping("/hello-world-internationalized")
public String helloWorldInternationalized(#RequestHeader(name="Accept-Language", required=false) Locale locale) {
return messageSource.getMessage("good.morning.message", null, locale);
//return "Good morning";
}
}
Here's my messages.properties file:
good.morning.message=Good Morning
And here's the link to my folder structure
Change bundleMessageSource() name to messageSource().

#Bean Controller not getting picked up by #EnableMVC

Most of my #Controllers are picked up through component scanning. However, a few, such as those I use with Spring Social are created as #Beans. I just migrated from mostly xml to JavaConfig only and upgraded to Spring 4.1.9.
However, the Controller endpoints that are created as #Beans are creating 404s.
Any ideas?
package nl.project.webapp.config;
#Order(1)
public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[]{WebAppConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[]{ServletConfig.class};
}
#Override
protected String[] getServletMappings() {
return new String[]{"/"};
}
[...]
}
package nl.project.webapp.config;
#Configuration
#ComponentScan(basePackages = {"nl.project.webapp"},excludeFilters={
#ComponentScan.Filter(type=FilterType.ANNOTATION,value=Controller.class),
#ComponentScan.Filter(type=FilterType.ANNOTATION,value=RestController.class)
})
#Import({AppConfig.class,JPAConfig.class})
#PropertySource("classpath:msa.properties")
public class WebAppConfig {
[...]
}
package nl.project.webapp.config;
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"nl.project.webapp.controller"},includeFilters={
#ComponentScan.Filter(type=FilterType.ANNOTATION,value=Controller.class),
#ComponentScan.Filter(type=FilterType.ANNOTATION,value=RestController.class)
})
public class ServletConfig extends WebMvcConfigurerAdapter{
[...]
}
package nl.project.webapp.social.config;
#Configuration
public class SocialConfig{
#Bean
public MyConnectController connectController(MessageSource messages, UsorManager userMgr, PhotoManager photoMgr) {
MyConnectController connectController = new MyConnectController(connectionFactoryLocator, connectionRepository);
connectController.setConnectInterceptors(Arrays.asList(new ConnectInterceptor<?>[]{
new TwitterConnectInterceptor(userMgr, photoMgr, messages),
new FacebookConnectInterceptor(userMgr, photoMgr, messages),
new LinkedInConnectInterceptor(userMgr, photoMgr, messages),
new GoogleConnectInterceptor(userMgr, photoMgr, messages),
}));
return connectController;
}
#Bean
public MySignInController signinController(MessageSource messages, UsorManager userMgr, PhotoManager photoMgr){
MySignInController signinController = new MySignInController(connectionFactoryLocator, usersConnectionRepository, new SimpleSigninAdapter(userMgr));
signinController.setSignInInterceptors(Arrays.asList(new ProviderSignInInterceptor<?>[]{
new FacebookSigninInterceptor(userMgr, photoMgr, messages),
new LinkedInSigninInterceptor(userMgr, photoMgr),
new GoogleSigninInterceptor(userMgr, photoMgr)
}));
return signinController;
}
}
package nl.project.webapp.social.controller;
#Controller
#RequestMapping("/signin")
public class MySignInController extends ProviderSignInController {
public MySignInController(
ConnectionFactoryLocator connectionFactoryLocator,
UsersConnectionRepository usersConnectionRepository,
SignInAdapter signInAdapter) {
super(connectionFactoryLocator, usersConnectionRepository, signInAdapter);
this.connectionFactoryLocator = connectionFactoryLocator;
}
[...]
The problem was caused by SocialConfig being imported by the WebAppConfig in stead of the ServletConfig. Although the documentation suggests that any Controller bean available in the context will be picked up by using '#EnableWebMVC', it is not very clear that this does not apply to Controller beans loaded through the webapp context.

How to config #EnableConfigurationProperties, #ConfigurationProperties with WebApplicationInitializer?

I want to read application.properties using
#EnableConfigurationProperties and #ConfigurationProperties.
I am able to do that with the following codes:
Application.java
#SpringBootApplication
#EnableConfigurationProperties(ApplicationConfiguration.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
ApplicationConfiguration.java
#ConfigurationProperties(prefix = "server")
public class ApplicationConfiguration {
private String port;
public String getPort() {
return port;
}
public void setPort(String port) {
this.port = port;
}
}
TestController.java
#Controller
public class TestController {
#Autowired
ApplicationConfiguration applicationConfiguration;
#RequestMapping("/test")
#ResponseBody
public String test() {
if (applicationConfiguration != null) {
return applicationConfiguration.getPort();
}
return "1";
}
}
application.properties
server.port = 8085
Now I want to replace SpringBoot(Application.java) with WebApplicationInitializer so that I can use an external container. Here is my code:
CommonInitializer.java
public class CommonInitializer implements WebApplicationInitializer{
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext annotationConfigWebApplicationContext = new AnnotationConfigWebApplicationContext();
annotationConfigWebApplicationContext.register(WebConfiguration.class);
annotationConfigWebApplicationContext.setServletContext(servletContext);
ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(annotationConfigWebApplicationContext));
servlet.setLoadOnStartup(1);
servlet.addMapping("/");
}
}
WebConfiguration.java
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "hello")
#EnableAutoConfiguration
#EnableConfigurationProperties(ApplicationConfiguration.class)
public class WebConfiguration {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
After doing this, I am not able to get the port(port is null, applicationConfiguration is not null) in application.proerties. Any idea? What am I missing?
Problem solved. I am missing property file location!!
#ConfigurationProperties(prefix = "server", locations = "classpath:application.properties")
Seems spring boot does that for you automatically.

Resources