How to send mail using spring boot? - spring-boot

i'm trying to sent mail in my spring boot application using mailtrap to test that and this is my code:
pom.xml :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
application.properties: i took this credentials from my account on mailtrap.io :
spring.mail.host=smtp.mailtrap.io
spring.mail.port=2525
spring.mail.username=2d9a7d89fcc8f8
spring.mail.password=9bb8e9090abd96
EmailCfg :
#Component
public class EmailCfg {
#Value("${spring.mail.host}")
private String host;
#Value("${spring.mail.port}")
private int port;
#Value("${spring.mail.username}")
private String username;
#Value("${spring.mail.password}")
private String password;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
EmailMsg :
public class EmailMsg {
#NotNull
private String name;
#NotNull
#Email
private String email;
#NotNull
#Min(10)
private String feedback;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getFeedback() {
return feedback;
}
public void setFeedback(String feedback) {
this.feedback = feedback;
}
}
Controller :
#CrossOrigin(origins = StringsConstants.FRONT_BASE_URL, maxAge = 3600)
#Api("Events Controller")
#RestController
#RequestMapping(StringsConstants.EVENTS_URL)
public class EventsController {
#Autowired
private EmailCfg emailCfg;
#PostMapping(value = "/sendMail")
#PreAuthorize("hasRole('USER')")
public void sendFeedback(#RequestBody EmailMsg feedback,
BindingResult bindingResult){
if(bindingResult.hasErrors()){
throw new ValidationException("Feedback is not valid");
}
// Create a mail sender
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(this.emailCfg.getHost());
mailSender.setPort(this.emailCfg.getPort());
mailSender.setUsername(this.emailCfg.getUsername());
mailSender.setPassword(this.emailCfg.getPassword());
// Create an email instance
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setFrom(feedback.getEmail());
mailMessage.setTo("rc#feedback.com");
mailMessage.setSubject("New feedback from " + feedback.getName());
mailMessage.setText(feedback.getFeedback());
// Send mail
mailSender.send(mailMessage);
}
}
It's not working and im not getting any error !!! on postman im getting this
{
"timestamp": "2021-04-11T09:52:43.286+0000",
"status": 404,
"error": "Not Found",
"message": "No message available",
"path": "/api/events/sendEmail"
}
any ideas? please !

Related

Spring Boot; passing user's First Name to welcome.jsp after logging in

A lot of the articles online for Spring Boot deals with Spring Security and it does not help me in the slightest. I am trying to implement a registration and login page and once the user successfully logins, it will take them to a welcome page where it should display their first name, something like "Welcome first name or Welcome username". I have tried passing the first name through a
model.addAttribute("firstName", accountInstance.getFirstName());
but that doesn't seem to work. Any hints to achieve this would be much appreciated
Login Controller
#Controller
public class LoginController {
#Autowired
private AccountRepository accountRepo;
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String showLoginPage(ModelMap model) {
model.addAttribute("login", new AccountEntity());
return "login";
}
#RequestMapping(value = "/login", method = RequestMethod.POST)
public Object submitLoginIn(#ModelAttribute("login") AccountEntity accountForm, Model model) {
AccountEntity accountInstance = accountRepo.findByEmail(accountForm.getEmail().toLowerCase());
// Password Verifier using Argon2
Argon2PasswordEncoder argon2PasswordEncoder = new Argon2PasswordEncoder();
boolean passwordMatch = argon2PasswordEncoder.matches(accountForm.getPassword(), accountInstance.getPassword());
// issue where if i use caps email, throws null pointer exception
if (accountInstance == null || !passwordMatch) {
System.out.println("Invalid Email or Password");
// return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
return "login";
} else if (accountInstance.isEnabled() == false) {
System.out.println("Cant login cause not verified");
return "login";
} else {
System.out.println("account exist");
model.addAttribute("firstName", accountInstance.getFirstName());
return "redirect:welcome"; // Change later
}
}
}
Account Repository
public interface AccountRepository extends CrudRepository<AccountEntity, Long> {
// Optional<AccountEntity> findById(Long Id);
AccountEntity findByUserName(String userName);
AccountEntity findByPassword(String password);
AccountEntity findByEmail(String email);
AccountEntity findByVerificationCode(String verificationCode);
}
Account Entity
#Entity(name = "user")
public class AccountEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String userName;
private String email;
private String password;
// private String gender;
private Integer age;
private Date createdDate;
private boolean enabled;
#Column(updatable = false)
private String verificationCode;
// Getters and Setters
public void setId(Long id) {
this.id = id;
}
public Long getId() {
return id;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
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 getGender() { return gender; }
*
* public void setGender(String gender) { this.gender = gender; }
*/
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getVerificationCode() {
return verificationCode;
}
public void setVerificationCode(String verificationCode) {
this.verificationCode = verificationCode;
}
public Date getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
Welcome.jsp
<p> Welcome, ${firstName.firstName} </p>
<!-- <p> Welcome, ${firstName} </p> -->
SO #Bollywood was correct with the redirecting:welcome. Doing so didn't pass the value I wanted to the jsp. Changing it to return "welcome" instead of return "redirect:welcome" worked!

Why all properties of a Model passed from AOP to controller with other arguments are null

AOP
#Around(
"execution(* net.inter.warp.bridge.controller.*.*(.., net.inter.warp.bridge.model.User)) && " +
"args(.., authenticatedUser)"
)
public Object withAuthenticatedUser(ProceedingJoinPoint joinPoint, User authenticatedUser) throws Throwable {
System.out.println(joinPoint + " -> " + authenticatedUser);
User user = null;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null)
user = (User) userService.loadUserByUsername(authentication.getName());
else
throw new UnauthorizedException("err 1");
if (user == null)
throw new UnauthorizedException("err 2");
return joinPoint.proceed(new Object[]{user});
}
Controller (all properties of authenticatedUser are null)
package net.inter.warp.bridge.controller;
#GetMapping("/boxes/{id}")
public ResponseEntity<Box> getBoxById(#PathVariable(value = "id") Long boxId, User authenticatedUser)
throws NoDynamicTableFoundException, ResourceNotFoundException {}
Controller (This works as there is no more parameters except for authenticatedUser)
package net.inter.warp.bridge.controller;
#GetMapping("/boxes/{id}")
public ResponseEntity<Box> getBoxById(User authenticatedUser)
throws NoDynamicTableFoundException, ResourceNotFoundException {}
AOP seems to hate other paramethers... authenticatedUser is not null, every property of authenticatedUser is null.
Model (I am not sure this issue is related to this)
#Entity
#Table(name="users")
#ToString
public class User extends AuthEntity implements UserDetails
{
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
String[] userRoles = this.roles.stream().map((role) -> role.getName()).toArray(String[]::new);
Collection<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList(userRoles);
return authorities;
}
#Override
public String getUsername() {
return this.email;
}
#Override
public boolean isAccountNonExpired() {
return true;
}
#Override
public boolean isAccountNonLocked() {
return true;
}
#Override
public boolean isCredentialsNonExpired() {
return true;
}
#Override
public boolean isEnabled() {
return true;
}
#Column(nullable=false)
#NotNull(message = "")
private String name;
#Column(nullable=false, unique=true)
#Email
//#NotBlank(message = "")
private String email;
#Column
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
#JsonIgnore
private String password;
#Column(length = 20, columnDefinition ="bigint")
//#NotNull(message = "")
private Long organization_id;
#ManyToOne(optional=false)
#JoinColumn(name = "organization_id",referencedColumnName="id", insertable=false, updatable=false)
//#JsonIgnore
private Organization organization;
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
//#Fetch(org.hibernate.annotations.FetchMode.SELECT)
#JoinTable(
name="user_role",
joinColumns={#JoinColumn(name="user_id")},
inverseJoinColumns={#JoinColumn(name="role_id")})
private List<Role> roles;
/*
#ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
//#Fetch(org.hibernate.annotations.FetchMode.SELECT)
#Fetch(value = FetchMode.SUBSELECT)
#JoinTable(
name="hyperbridge_resource.user_workspace",
joinColumns={#JoinColumn(name="user_id")},
inverseJoinColumns={#JoinColumn(name="workspace_id")})
private List<Workspace> workspaces;
*/
#Column(length = 1, columnDefinition ="char")
private String active;
#Column(name = "reset_token")
#JsonIgnore
private String resetToken;
#Column(name = "reset_token_time")
#DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss")
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss", timezone = "Asia/Seoul")
private LocalDateTime resetTokenTime;
public String getName() {
return name;
}
public void setName(String name) {
this.name = 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 Long getOrganization_id() {
return organization_id;
}
public void setOrganization_id(Long organization_id) {
this.organization_id = organization_id;
}
public Organization getOrganization() {
return organization;
}
public void setOrganization(Organization organization) {
this.organization = organization;
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
/* public List<Workspace> getWorkspaces() {
return workspaces;
}
public void setWorkspaces(List<Workspace> workspaces) {
this.workspaces = workspaces;
}*/
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public String getResetToken() {
return resetToken;
}
public void setResetToken(String resetToken) {
this.resetToken = resetToken;
}
public LocalDateTime getResetTokenTime() {
return resetTokenTime;
}
public void setResetTokenTime(LocalDateTime resetTokenTime) {
this.resetTokenTime = resetTokenTime;
}
}
Try this, doc:
#Around(
"execution(* net.inter.warp.bridge.controller.*.*(..) && " +
"args(authenticatedUser,..)"

Spring Data: Could not determine type for: java.util.List, at table: user, for columns: [org.hibernate.mapping.Column(roles)]

I am new to Spring, and I was following this tutorial Spring Rest Services
to understand how oAuth works with REST APIs.
Prior to this, my app was running smoothly.
While working with the tutorial, it required me to have my User entity implement UserDetails. And I had to add an extra List<String> roles because it is used in my UserDetailsImpl service which implements UserDetailsService.
And now when I run mvn spring-boot:run I get the error that's mentioned in the title.
I looked up online, but most of the issues were related to table associations via a particular column, but in my code, there is no type of association mapped to/from roles column.
Here is my User entity:
#Entity
public class User implements UserDetails {
#Id
private UUID id;
private String name;
private String email;
private String password;
private List<String> roles;
public User (){
}
public User (String email, String name, String password, UUID id, List<String> roles){
this.email = email;
this.name = name;
this.password = password;
this.id = id;
this.roles = roles;
}
public String getEmail() {
return email;
}
public String getName() {
return name;
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
#Override
public String getPassword() {
return password;
}
#Override
public String getUsername() {
return email;
}
#Override
public boolean isAccountNonExpired() {
return false;
}
#Override
public boolean isAccountNonLocked() {
return false;
}
#Override
public boolean isCredentialsNonExpired() {
return false;
}
#Override
public boolean isEnabled() {
return false;
}
public UUID getId() {
return id;
}
List<String> getRoles() {
return roles;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
public void setName(String name) {
this.name = name;
}
public void setId(UUID id) {
this.id = id;
}
}
And this my UserDetailsImp service:
#Service
public class UserDetailsImp implements UserDetailsService {
#Autowired
UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userRepository.getOneByEmail(email);
UserBuilder builder = null;
if( user != null){
builder.username(user.getEmail()).password(user.getPassword()).roles(String.join("",user.getRoles()));
} else {
throw new UsernameNotFoundException("User not found");
}
return builder.build();
}
}
Any help would be hugely appreciated.
The field private List<String> roles has unknown type in the DB.
Try using #ElementCollection annotation.
https://docs.oracle.com/javaee/6/api/javax/persistence/ElementCollection.html

Error: No string encryptor registered for hibernate with name "hibernateStringEncryptor" in with jasypt

I have a problem with Jasyt with Spring Boot and Hibernate.
When i try to write encrypted password into database i got an error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'receptionistController': Invocation of init method failed; nested exception is org.jasypt.exceptions.EncryptionInitializationException: No string encryptor registered for hibernate with name "hibernateStringEncryptor"
hibernateStringEncryptor is registred in Configuration class
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = "medical.center")
public class HibernateConfig {
#Bean
public void Test(){
System.out.println("Test");
}
public EnvironmentStringPBEConfig encryptorConfiguration(){
EnvironmentStringPBEConfig encryptor = new EnvironmentStringPBEConfig();
encryptor.setAlgorithm("PBEWithMD5AndDES");
encryptor.setPasswordSysPropertyName("beaver.encryption.password");
return encryptor;
}
public StandardPBEStringEncryptor standardStringEncryptor(){
StandardPBEStringEncryptor stringEncryptor = new StandardPBEStringEncryptor();
stringEncryptor.setConfig(encryptorConfiguration());
return stringEncryptor;
}
#Bean
#Autowired
public HibernatePBEStringEncryptor hibernateStringEncryptor(){
HibernatePBEStringEncryptor stringEncryptor = new HibernatePBEStringEncryptor();
stringEncryptor.setEncryptor(standardStringEncryptor());
stringEncryptor.setRegisteredName("hibernateStringEncryptor");
return stringEncryptor;
}
And User Class:
#Entity
#TypeDef(
name="encryptedString",
typeClass=EncryptedStringType.class,
parameters={#Parameter(name="encryptorRegisteredName",
value="hibernateStringEncryptor")}
public class User {
#Id
#GeneratedValue
private Long id;
private String login;
#Autowired
#Type(type="encryptedString")
private String password;
private String firstName;
private String lastName;
#Column(nullable=true)
private String email;
#Column(nullable=true)
private String phone;
#Column(nullable=true)
private LocalDate bornDate;
#CreatedDate
private LocalDateTime createTime;
#LastModifiedDate
private LocalDateTime modDate;
#Transient
private final static String[] rolesArray = { "Admin", "Doctor", "Patient", "Receptionist" };
private int role;
#Autowired(required=false)
#OneToMany(cascade = CascadeType.ALL)
#Column(nullable = true)
private List<UserMessage> userMessagesRecive;
#Autowired(required=false)
#OneToMany(cascade = CascadeType.ALL)
#Column(nullable = true)
private List<UserMessage> userMessagesSend;
public static String[] getRolesArray() {
return rolesArray;
}
public void setCreateTime(LocalDateTime createTime) {
this.createTime = createTime;
}
public void setModDate(LocalDateTime modDate) {
this.modDate = modDate;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstMame) {
this.firstName = firstMame;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public LocalDate getBornDate() {
return bornDate;
}
public void setBornDate(LocalDate bornDate) {
this.bornDate = bornDate;
}
public int getRole() {
return role;
}
public void setRole(int role) {
this.role = role;
}
public String[] getRoles() {
return rolesArray;
}
public List<UserMessage> getUserMessagesRecive() {
return userMessagesRecive;
}
public void setUserMessagesRecive(List<UserMessage> userMessagesRecive) {
this.userMessagesRecive = userMessagesRecive;
}
public List<UserMessage> getUserMessagesSend() {
return userMessagesSend;
}
public void setUserMessagesSend(List<UserMessage> userMessagesSend) {
this.userMessagesSend = userMessagesSend;
}
public String getRoleByName(int role) {
return rolesArray[role];
}
}
And main method:
#SpringBootApplication
#EnableJpaRepositories("medical.center")
#ComponentScan(basePackages = "medical.center")
#EntityScan("medical.center")
#EnableTransactionManagement
public class MedicalCenterApplication {
public static void main(String[] args) {
SpringApplication.run(MedicalCenterApplication.class, args);
and Receptionist Class:
#RestController
public class ReceptionistController {
#Autowired
private final ReceptionistRepository receptionistRepository;
private final ReceptionistGenerator receptionistGenerator;
private static final Logger logger = Logger.getLogger(ReceptionistController.class);
public ReceptionistController(ReceptionistRepository receptionistRepository,
ReceptionistGenerator receptionistGenerator) {
this.receptionistRepository = receptionistRepository;
this.receptionistGenerator = receptionistGenerator;
}
#PostConstruct
public void runAtStart() {
receptionistRepository.save(receptionistGenerator.generate());
}
#GetMapping("/getRecepcionist")
public Receptionist getReceptionist() {
logger.info("Get Receptionist");
return receptionistRepository.getOne(1L);
}
}
Please help.
Lukasz

Empty field Data Type in springfox swagger ui

I have a Spring Web MVC application with rest services and I try to use Springfox for automated docs for it.
I use
io.springfox:springfox-swagger2:2.5.0
io.springfox:springfox-swagger-ui:2.5.0
org.webjars:swagger-ui:2.1.4
My SwaggerConfig:
#Configuration
#EnableSwagger2
#Profile("dev")
public class SwaggerConfig {
#Bean
public Docket api() {
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build().apiInfo(apiInfo());
return docket;
}
}
And:
#Configuration
#EnableWebMvc
#Profile("dev")
public class SwaggerWebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
I have a rest controller:
#Api
#RestController
#RequestMapping(RegistrationRestController.ROOT_PATH)
public class RegistrationRestController {
private final static Logger log = LogManager.getLogger(RegistrationRestController.class);
public static final String ROOT_PATH = "/rest/registration";
private final ResponseUtil responseUtil;
private final UserService userService;
#Autowired
public RegistrationRestController(ResponseUtil responseUtil, UserService userService) {
log.debug("Instantiate RegistrationRestController bean");
this.responseUtil = Objects.requireNonNull(responseUtil);
this.userService = Objects.requireNonNull(userService);
}
#RequestMapping(value = {""}, method = RequestMethod.POST)
#ApiResponses({
#ApiResponse(code = 200, message = "Create new user and authorize them. Returns access token", response = AccessTokenDTO.class)
})
#ApiOperation(value = "Create new user", response = AccessTokenDTO.class)
public ResponseDTO newUserRegistration(#Valid #ApiParam(required = true) RegistrationDTO registrationDTO) {
log.debug("POST {} with registrationDTO='{}'", ROOT_PATH, registrationDTO.toString());
AccessTokenDTO accessToken = userService.createUserAndAuthorize(registrationDTO);
return responseUtil.wrapResult(accessToken);
}
}
And RegistrationDTO:
#ApiModel
public class RegistrationDTO {
#NotNull(message = "registrationDTO.phone.notNull.fail")
#Pattern(regexp = "[0-9]{10}", message = "registrationDTO.phone.pattern.fail")
private String phone;
#NotNull(message = "registrationDTO.email.notNull.fail")
#Email(message = "registrationDTO.email.pattern.fail")
private String email;
#NotNull(message = "registrationDTO.lastName.notNull.fail")
#Size(min = 1, message = "registrationDTO.lastName.size.fail")
private String lastName;
#NotNull(message = "registrationDTO.firstName.notNull.fail")
#Size(min = 1, message = "registrationDTO.firstName.size.fail")
private String firstName;
#NotNull(message = "registrationDTO.password.notNull.fail")
#Size(min = 6, message = "registrationDTO.password.size.fail")
private String password;
#NotNull(message = "registrationDTO.passwordConfirmation.notNull.fail")
#Size(min = 6, message = "registrationDTO.passwordConfirmation.size.fail")
private String passwordConfirmation;
#AssertTrue(message = "registrationDTO.isPasswordMatch.fail")
public boolean isPasswordMatch() {
return Objects.equals(password, passwordConfirmation);
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPasswordConfirmation() {
return passwordConfirmation;
}
public void setPasswordConfirmation(String passwordConfirmation) {
this.passwordConfirmation = passwordConfirmation;
}
#Override
public String toString() {
return "RegistrationDTO{" +
"phone='" + phone + '\'' +
", email='" + email + '\'' +
", lastName='" + lastName + '\'' +
", firstName='" + firstName + '\'' +
'}';
}
}
But when I'm opening localhost:8080/swagger-ui.html I see an empty Data type for RegistrationDTO parameter.
What I'm doing wrong? :(
Need to specify #RequestBody before method parameter

Resources