So I can't make these default messages change to the ones I want. In all the JSP files they work great, but I can't make them work inside a form.
Here is my UserController:
#RequestMapping(path = "/user/profile", method = RequestMethod.POST)
public ModelAndView userProfilePost(#ModelAttribute("userForm") #Valid UserForm userForm, BindingResult result) {
if(result.hasErrors()){
return userProfileGet(userForm);
}
User user = us.findByEmail(SecurityContextHolder.getContext().getAuthentication().getName());
user = userHelper.update(userForm, us ,user);
userForm = new UserForm();
userForm.setName(user.getName());
userForm.setEmail(user.getEmail());
return userProfileGet(userForm);
}
Then we have my WebConfig:
#Bean
public LocalValidatorFactoryBean localValidatorFactoryBean() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
#Bean
public MessageSource messageSource()
{
final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:languages_i18n/messages", "classpath:languages_i18n/validation");
messageSource.setDefaultEncoding(StandardCharsets.UTF_8.displayName());
messageSource.setCacheSeconds(5);
return messageSource;
}
My UserForm:
public class UserForm {
#Email()
private String email;
#Size(max=100 , min=3)
private String password;
#Size(max=100 , min =3)
private String name;
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
Here I tried also doing (which didn't work of course haha):
#Email(message = "{Email.UserForm.email}")
private String email;
#Size(max=100 , min=3, message = "{Size.UserForm.password}")
private String password;
#Size(max=100 , min =3, message = "{Size.UserForm.name}")
private String name;
Here is my validation_en.properties:
Email.UserForm.email = Your e-mail format is not valid
Size.UserForm.password = Your password must have between {min} and {max} characters
Size.UserForm.name = Your name must have between {min} and {max} characters
I know that when I do it right, the lines in the .properties file should get colored but they are still grey, so clearly I am not reaching them correctly.
Any comment will be well received, thank you in advance.
Apparently the solution was that the first letter of the form should be lower case, like this (I do not know why):
Size.userForm.password = Your password must have between {2} and {1} characters
Size.userForm.name = Your name must have between {2} and {1} characters
After that we have to add what Tung Phan said that was also correct because parameters are object array, so {min} and {max} were wrong.
Hope this is useful for anyone in the future.
Parameters are an Object array.
The {0} is field name, other fields are in alphabatical order, max and then min.
So it should be:
Size.UserForm.password = Your password must have between {2} and {1} characters
Size.UserForm.name = Your name must have between {2} and {1} characters
Related
I have 3 different method in controller for get requests.
-the 1st one to get a user by id with a path variable:
#GetMapping(path="/{id}")
public ResponseEntity<UserInfoDTO> getUserById(#PathVariable Long id)
The 2nd gets a user based on the username parameter:
public ResponseEntity<UserInfoDTO> getUserByUsername(#RequestParam String username)
And finally another one to get all users
public ResponseEntity<List<UserInfoDTO>> getAllUsers()
What should be the #GetMapping for the 2nd and 3rd method?
For exemple #GetMapping for all users and #GetMapping(path="/") for a user by username?
Or whatever...
Thanks.
Defining the Mappings purely depends on the context of your application and its usecases.
We can define a context prefixed by users and modified mappings are show in the snippet below and at the time of invocation it can be called like mentioned in the comments,
#GetMapping(path="/users/")
public ResponseEntity<UserInfoDTO> getUserByUsername(#RequestParam String username) {
}
// GET: <protocol>://<hostUrl>/users?username=<username>
#GetMapping(path="/users")
public ResponseEntity<List<UserInfoDTO>> getAllUsers() {
}
// GET: <protocol>://<hostUrl>/users
#GetMapping(path="/users/{id}")
public ResponseEntity<UserInfoDTO> getUserById(#PathVariable Long id)
// GET: <protocol>://<hostUrl>/users/<userid>
For example, optional username param:
#GetMapping(path = "/")
public ResponseEntity<?> getUserByUsername(#RequestParam(required = false) final String username) {
if (username != null) {
// http://localhost:8080/?username=myname
return new ResponseEntity<>(new UserInfoDTO("by username: " + username), HttpStatus.OK);
} else {
// http://localhost:8080/
return getAllUsers();
}
}
private ResponseEntity<List<UserInfoDTO>> getAllUsers() {
return new ResponseEntity<>(List.of(new UserInfoDTO("user1-of-all"), new UserInfoDTO("user2-of-all")),
HttpStatus.OK);
}
public static class UserInfoDTO {
public UserInfoDTO(final String name) {
this.name = name;
}
private final String name;
public String getName() {
return name;
}
}
I'm pulling my hair out over this. I have a simple User entity like this
#Entity
public class User {
private static final PasswordEncoder pwEncoder = new BCryptPasswordEncoder();
#Id
#GeneratedValue
private long id;
#NotNull(message = "FIELD_IS_NULL")
#NotEmpty(message = "FIELD_IS_REQUIRED")
#Length(min = 3, message = "FIELD_MUST_HAVE_AT_LEAST_3_CHARACTERS")
private String username;
#NotNull(message = "FIELD_IS_NULL")
#NotEmpty(message = "FIELD_IS_REQUIRED")
#Length(min = 6, message = "FIELD_MUST_HAVE_AT_LEAST_6_CHARACTERS")
#Pattern(regexp = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,128}$", message="PW_MIN_6_MAX_128_1_UPPER_1_LOWER_1_NUMERIC")
private String password;
public User(String username, String password){
this.username = username;
this.password = pwEncoder.encode(password);
}
/* getters and setters */
}
This works fine except that the password hashing happens before any validation, which means that the hashed password is validated instead of the unhashed.
I'm using a PagingAndSortingRepository for all my repository needs and I'd really like to avoid implementing a controller just for this case.
I'm feeling like I'm missing something really big there...
If you using this constructor
public User(String username, String password){
this.username = username;
this.password = pwEncoder.encode(password);
}
you'll have encoded password instead of original value
you can make #PrePersist method like this:
#PrePersist
public void prePersist(){
password = pwEncoder.encode(password);
}
class SingIn {
private String login;
private String password;
public SingIn(String login, String password) {
this.login = login;
this.password = password;
}
public String getLogin() {
return login;
}
public String getPassword() {
return password;
}
}
Login property could be an email(pattern ".+#.+") or a phone number(pattern "\+\d+").
Is it possible somehow with javax annotation to validate the login property?
Yes, it's possible by composing 2 #Pattern annotations with logical OR:
#ConstraintComposition(OR)
#Pattern(regexp = ".+#.+")
#Pattern(regexp = "\+\d+")
#ReportAsSingleViolation
#Target({ METHOD, FIELD })
#Retention(RUNTIME)
#Constraint(validatedBy = { })
public #interface EmailOrPhone {
See also the topic Boolean composition of constraints in the Hibernate Validator documentation.
My entity class
public class User {
String name;
String userName;
String password;
String[] roles;
static class ROLES {
static String ADMIN="ADMINISTRATOR";
static String USER="USER";
}
public User(){
}
public User(String name, String userName, String password, String... roles) {
this.name = name;
this.userName = userName;
this.password = password;
this.roles = roles;
}
}
Format of the properties file
user[0].name=Sujal Mandal
user[0].userName=sujal12
user[0].password=sujal123
user[0].roles=ADMIN,USER,SUPER_USER
user[1].name=Busra Ercelik
user[1].userName=busra12
user[1].password=busra123
user[1].roles=USER
I would like to write an util class which will read the properties file & return me the objects of Users
What would be the best way of doing this in Java/Spring boot enviornment?
The simplest solution is shown below where in you need to use #ConfigurationProperties:
#Component
#ConfigurationProperties("myproject")
public class UsersPopulator {
private List<User> users;//all users will be populated from application.properties
//add getter method
}
Your application.properties file looks like the below:
myproject.users[0].name=Sujal Mandal
myproject.users[0].userName=sujal12
myproject.users[0].password=sujal123
myproject.users[0].roles=ADMIN,USER,SUPER USER
myproject.users[1].name=Busra Ercelik
myproject.users[1].userName=busra12
myproject.users[1].password=busra123
myproject.users[1].roles=USER
You need to ensure that #EnableConfigurationProperties is added to the launcher class file.
I have created a route
#RequestMapping( value = "login" , method = RequestMethod.POST , consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE )
public void greet( #RequestBody Login l){
System.out.println(l.getName());
}
class Login{
public void setName(String name) {
this.name = name;
}
public void setPassword(String password) {
this.password = password;
}
private String name;
private String password;
public String getName() {
return name;
}
public String getPassword() {
return password;
}
public Login(){};
}
And i am using postman to send data to it:
headers:
'Accept':application/x-www-form-urlencoded
Content-Type:application/x-www-form-urlencoded
data:
name:Greet
password:Me
Yet i keep getting erorr:
"message": "Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported",
I have read various questions and post about this but i fail to find solution to fix this.
All help is appreciated, thanks.
Whenever we use MediaType.APPLICATION_FORM_URLENCODED_VALUE Spring does not understand it as a RequestBody. So remove RequestBody and do like this
#RequestMapping( value = "login" , method = RequestMethod.POST , consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE )
public void greet(Login l ){
if(l != null /*or whatever you want to do*/)
System.out.println(l.getName());
}
In Spring don't use #RequestBody annotation when consuming API with Content-type: 'application/x-www-form-urlencoded'.
You have to use MultiValueMap in case of application/x-www-form-urlencoded.