So I have a class and a field that is list of strings and I want to validate every one of them, but it's not working, I tried this and this didn't work out:
public class Info {
#NotNull
#NotEmpty
private List<#Email(message = "uncorrect email") String> emails;
}
I also tried this and it didn't work:
public class Info {
#NotNull
#NotEmpty
private #Valid List<#Email(message = "uncorrect email") String> emails;
}
But when it's just one String it works fine.
public class Info {
#NotNull
#NotEmpty
private #Email(message = "uncorrect email") String email;
}
How can I achieve what I want?
Latest versions of hibernate validator support it. You can go with the following changes to achieve the desired validation behaviour.
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.0</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
</dependencies>
Java Bean
import java.util.List;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
public class Info {
#NotNull
#NotEmpty
private List<#Email(message = "List contain atleast one incorrect email") String> emails;
#NotNull
#NotEmpty
#Email(message = "incorrect email")
private String email;
public List<String> getEmails() {
return emails;
}
public void setEmails(List<String> emails) {
this.emails = emails;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#Override
public String toString() {
return "Info [emails=" + emails + ", email=" + email + "]";
}
}
Adding the #Valid
#PostMapping("/post")
public void post(#RequestBody #Valid Info info) {
System.out.println(info);
}
Related
I follow a spring boot tutorial and I can't solve this problem because the tutorial is not detailed enough
this is the User model class code :
package com.example.user;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import java.util.Date;
import java.util.List;
public class User {
private Integer id;
#Size(min=2, message="Name should have atleast 2 characters")
private String name;
private Date birthDate;
protected User() {
}
public User(Integer id, String name, Date birthDate) {
super();
this.id = id;
this.name = name;
this.birthDate = birthDate;
}
//getters and setters
}
this is the userResource code for the post mapping method :
#PostMapping("/users")
public ResponseEntity<Object> createUser(#Valid #RequestBody User user) {
User savedUser = service.save(user);
URI location = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(savedUser.getId()).toUri();
return ResponseEntity.created(location).build();
}
I solve the problem :
The hibernate validator dependacy was missed so I add it to the POM and everything works fine
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.12.Final</version>
</dependency>
I am trying to set up lombok in my sts.
So far I have done these steps:
I downloaded the lambok jar file.
I ran the file and specified the path for sts.exe and then clicked on install.
I have added the required dependencies in my pom.xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
I have also edited my sts.ini file. After installation of lambok.jar following line was already there at the end pf the file
-javaagent:E:\JAVA SOFTWARES\spring-tool-suite-3.9.8.RELEASE-e4.11.0-win32-x86_64\sts-bundle\sts-
3.9.8.RELEASE\lombok.jar
so I moved it next to
-vmargs
Then, I cleaned my project. I have also updated my project. Closed sts and then ran my application again. But it is still not recognizing the getters in my file. It produces the following error.
The method getFirstname() is undefined for the type Student
Student.java:
package com.crud.msstudent.models;
import java.io.Serializable;
import javax.persistence.*;
import javax.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;
#Getter
#Setter
#Accessors(chain=true)
#NoArgsConstructor
#AllArgsConstructor
#Entity
#Table(name = "student")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#NotEmpty(message = "First name is required")
private String firstname;
#NotEmpty(message = "Last name is required")
private String lastname;
#Column(nullable = true, name = "email")
private String email;
}
The error is being shown in my StudentController.java file. Following is some of the code:
#PutMapping(value="/students/{id}")
public Student updateStudent(#PathVariable("id") #Min(1) int id, #Valid
#RequestBody Student newstd) {
Student stdu = studentservice.findById(id)
.orElseThrow(()->new
StudentNotFoundException("Student with "+id+" is Not Found!"));
stdu.setFirstname(newstd.getFirstname());
stdu.setLastname(newstd.getLastname());
stdu.setEmail(newstd.getEmail());
return studentservice.save(stdu);
}
#DeleteMapping(value="/students/{id}")
public String deleteStudent(#PathVariable("id") #Min(1) int id) {
Student std = studentservice.findById(id)
.orElseThrow(()->new
StudentNotFoundException("Student with "+id+" is Not Found!"));
studentservice.deleteById(std.getId());
return "Student with ID :"+id+" is deleted";
}
Please tell me what am I missing?
If you're using STS you might be missing the plugin required for it. For further details please refer to the Lombok site on how to install it.
If mvnw.cmd clean compile command works normally, try project reloading.
Right click your project folder in Package Explorer > Maven > Update Project
Does this help (source):
To include lombok as a 'provided' dependency, add it to your block like so:
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
</dependencies>
JDK9+ with module-info.java
The configuration of the compiler plug-in should contain the following:
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</path>
</annotationProcessorPaths>
are you using Eclipse IDE? in some case, you have to update the project explicitly in eclipse.
better to go without using lombok
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
#NotEmpty(message = "First name is required")
private String firstname;
#NotEmpty(message = "Last name is required")
private String lastname;
#Column(nullable = true, name = "email")
private String email;
public Student()
{
}
public Student(int id,String firstname,String lastname,String email)
{
this.id=id;
this.firstname=firstname;
this.lastname=lastname;
this.email=email
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id=id;
}
public String getFirstname()
{
return firstname;
}
public void setFirstname(String firstname)
{
this.firstname=firstname;
}
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;
}
I have this controller
#Controller
public class EmpleadoController {
#Autowired
private EmpleadoService servicio;
#PostMapping("/empleado/new/submit")
public String nuevoEmpleadoSubmit(#Valid #ModelAttribute("empleadoForm") Empleado empleadoForm, BindingResult bindingResult) {
if(bindingResult.hasErrors()) {
return "formulario";
}else {
servicio.add(empleadoForm);
return "redirect:/empleado/list";
}
}
}
With this model
package com.alexotero.spring.model;
import javax.validation.constraints.Email;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
public class Empleado {
#Min(0)
private long id;
#NotEmpty
private String nombre;
#Email
private String email;
private String telefono;
//Constructors getters setters and stuff
I've also added this dependency to the pom.xml
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
It doesn't matter what i introduce in the form, the controller never detects any error. Always adds the object to the List(in the service) and redirects to the list.html. I cannot find where is the problem.
For my case, I removed this dependency
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
and added
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
I think they both conflict with each other.
EDIT: still currently getting this as an error:
2019-08-08 15:12:50.876 WARN 3164 --- [io-8080-exec-10] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type '' not supported]
I'm not really sure why it's saying Content type ' ' not supported...
Also it works from postman but doesn't show xml, just shows json, even though I have selected application/xml for the header type
I'm trying to get my basic spring rest service to respond with XML. I've annotated all the elements and put headers that are supposed to accept XML. For some reason my client still gets the error "unsupported media type".
I tried putting #ResponseBody next to the methods in EmployeeService, but it ended up giving me a different error which was: [org.springframework.web.HttpMediaTypeNotSupportedException: Content type '' not supported]
Employee.java
public class Employee implements Serializable {
#XmlAttribute
private String id;
#XmlElement
private String name;
#XmlElement
private String description;
//private List<Team> teams;
public Employee() {
super();
}
public Employee(String id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
//this.teams = teams;
}
#XmlAttribute
public String getId() {
return id;
}
#XmlAttribute
public void setId(String id) {
this.id = id;
}
#XmlElement
public String getName() {
return name;
}
#XmlElement
public void setName(String name) {
this.name = name;
}
#XmlElement
public String getDescription() {
return description;
}
// public List<Team> getTeam() {
// return teams;
// }
#XmlElement
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return String.format(
"employee [id=%s, name=%s, description=%s]", id,
name, description);
}
}
EmployeeController.java
#RestController
public class EmployeeController {
#Autowired
private EmployeeService employeeService;
#GetMapping(path = "/employees", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public #ResponseBody HashMap<String, Employee> retrieveEmployees() {
return employeeService.retrieveAllEmployees();
}
#GetMapping(path = "/employees/{employeeId}",produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE}, consumes = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public #ResponseBody Employee retrievebyId(#PathVariable String employeeId) {
return employeeService.retrieveEmployee(employeeId);
}
#PostMapping(path="/employees")
public ResponseEntity<Void> registeremployee(#RequestBody Employee newemployee) {
Employee employee = employeeService.addEmployee(newemployee.getId(),newemployee.getName(), newemployee.getDescription());
if (employee == null)
return ResponseEntity.noContent().build();
URI location = ServletUriComponentsBuilder.fromCurrentRequest().path(
"/{id}").buildAndExpand(employee.getId()).toUri();
return ResponseEntity.created(location).build();
}
}
EmployeeService.java
#Component
public class EmployeeService {
static HashMap<String, Employee> employees = new HashMap<>();
static {
//Initialize Data
Team team1 = new Team("t1", "Java team", "Java Dev Team");
Employee Joe = new Employee("employee1", "Joe Smith","Human Resources");
Employee Bob = new Employee("employee2", "Bob Jones",
"Developer");
employees.put("employee1", Joe);
employees.put("employee2", Bob);
}
public HashMap<String, Employee> retrieveAllEmployees() {
return employees;
}
public Employee retrieveEmployee(String employeeId) {
return employees.get(employeeId);
}
//private SecureRandom random = new SecureRandom();
public Employee addEmployee(String id, String name, String description) {
//String randomId = new BigInteger(130, random).toString(32);
Employee employee = new Employee(id, name, description);
employees.put(id, employee);
return employee;
}
}
RestClient.java
public class RestClient {
public static void getJsonEmployee(String id) throws JSONException, IOException {
String uri = "http://localhost:8080/employees/" + id;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = restTemplate.headForHeaders(uri);
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_XML));
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
}
public static void postJsonEmployee(String id, String name, String description) {
final String uri = "http://localhost:8080/employees/";
Employee newemp = new Employee(id, name, description);
RestTemplate restTemplate = new RestTemplate();
HttpHeaders httpHeaders = restTemplate.headForHeaders(uri);
httpHeaders.setContentType(MediaType.APPLICATION_XML);
Employee result = restTemplate.postForObject( uri, newemp, Employee.class);
httpHeaders.setContentType(MediaType.APPLICATION_XML);
}
public static void main(String[] args) throws IOException, JSONException {
System.out.println("GET or POST?");
BufferedReader getpost = new BufferedReader(new InputStreamReader(System.in));
String selection = getpost.readLine();
switch(selection) {
case "GET":
System.out.println("Type in the employee's ID");
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String employeeid = reader.readLine();
getJsonEmployee(employeeid);
break;
case "POST":
System.out.println("Type in the employee's ID");
Scanner scan = new Scanner(System.in);
String newid = scan.nextLine();
System.out.println("Type in the employee's name");
String newname = scan.nextLine();
System.out.println("Type in the employee's description");
String newdesc = scan.nextLine();
postJsonEmployee(newid, newname, newdesc);
break;
}
}
}
10:00:37.986 [main] DEBUG org.springframework.web.client.RestTemplate - HTTP HEAD http://localhost:8080/employees/
10:00:38.293 [main] DEBUG org.springframework.web.client.RestTemplate - Response 415 UNSUPPORTED_MEDIA_TYPE
Exception in thread "main"
org.springframework.web.client.HttpClientErrorException$UnsupportedMediaType: 415 null
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:95)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:122)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:102)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:778)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:736)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:670)
at org.springframework.web.client.RestTemplate.headForHeaders(RestTemplate.java:362)
at com.client.clientmodel.RestClient.getJsonEmployee(RestClient.java:52)
at com.client.clientmodel.RestClient.main(RestClient.java:104)
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.springboot</groupId>
<artifactId>employee-model</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>employee-model</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
The 405 indicates your client is sending a bad request. You are issuing an HTTP HEAD request in your client. Try just "newing" HttpHeaders.
Also can't set headers on a request after sending the request.
Http status code series 4xx means a client-side problem. 415 means Unsupported media type.
I am not a java guy but I faced exactly this issue before at ajax call.
To solve this issue I add a headder which is Accept: "*/*" this solution is for ajax request. For java, I believe it will be
public static void getJsonEmployee(String id) throws JSONException, IOException {
String uri = "http://localhost:8080/employees/" + id;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = restTemplate.headForHeaders(uri);
headers.add("Accept", "*/*");
String result = restTemplate.getForObject(uri, String.class);
System.out.println(result);
}
Can you try with the following code. I have modified only getJsonEmployee() method.
public static void getJsonEmployee(String id) throws JSONException, IOException {
String uri = "http://localhost:8080/employees/" + id;
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity entity = new HttpEntity(headers)
ResponseEntity<String> response = restTemplate.exchange(uri, HttpMethod.GET, entity, String.class);
String result = response.getBody();
System.out.println(result);
}
Besides, I see that your Employee class to generate XML is not right, I provide below the proposed Employee class and there is a main method also so that you can run to test the generation of XML structure.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
#XmlRootElement
public class Employee implements Serializable {
private String id;
private String name;
private String description;
// private List<Team> teams;
public Employee() {
super();
}
public Employee(String id, String name, String description) {
this.id = id;
this.name = name;
this.description = description;
// this.teams = teams;
}
#XmlAttribute
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
#Override
public String toString() {
return String.format("employee [id=%s, name=%s, description=%s]", id, name, description);
}
public static void main(String[] args) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(Employee.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Employee emp = new Employee("id1", "name-1", "desc-1");
marshaller.marshal(emp, System.out);
}
}
error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'searchController' method
public java.lang.String softuniBlog.controller.SearchController.search(java.lang.String,org.springframework.ui.Model)
to {[/search]}: There is already 'searchController' bean method
public java.lang.String softuniBlog.controller.SearchController.index() mapped.
**I`m trying to build search engine for my blog and have 3 questions.
1) Why In application properties last 3 rows are "can not resolve"
2) How can I fix the error I have, app is working but when try url /search?q=someText it trows exception:
[Handler dispatch failed; nested exception is java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionDelegatorBaseImpl.(Lorg/hibernate/engine/spi/SessionImplementor;)V] with root cause
java.lang.NoSuchMethodError: org.hibernate.engine.spi.SessionDelegatorBaseImpl.(Lorg/hibernate/engine/spi/SessionImplementor;)V
3) How can take search query from input form instead from url
please check the code:
search input box
<div id="wrap">
<form action="" autocomplete="on">
<input id="search" name="search" type="text" placeholder="What're we looking for ?"></input>
<input id="search_submit" value="Rechercher" type="submit"></input>
</form>
</div>
Article controller
package softuniBlog.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import softuniBlog.bindingModel.ArticleBindingModel;
import softuniBlog.entity.Article;
import softuniBlog.entity.User;
import softuniBlog.repository.ArticleRepository;
import softuniBlog.repository.UserRepository;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
#Controller
public class ArticleConstroller {
#Autowired
private ArticleRepository articleRepository;
#Autowired
private UserRepository userRepository;
#GetMapping("/article/create")
#PreAuthorize("isAuthenticated()")
public String create(Model model){
model.addAttribute("view", "/article/create");
return "base-layout";
}
#PostMapping("/article/create")
#PreAuthorize("isAuthenticated()")
public String createProcess(ArticleBindingModel articleBindingModel){
UserDetails user = (UserDetails) SecurityContextHolder
.getContext()
.getAuthentication()
.getPrincipal();
User userEntity = this.userRepository.findByEmail(user.getUsername());
String databasePathImage = null;
String[] allowedContentTypes = {
"image/png",
"image/jpg",
"image/jpeg"
};
boolean isContentTypeAllowed =
Arrays.asList(allowedContentTypes)
.contains(articleBindingModel.getImage().getContentType());
if(isContentTypeAllowed){
String imagesPath = "\\src\\main\\resources\\static\\img\\";
String imagePathRoot = System.getProperty("user.dir");
String imageSaveDirectory = imagePathRoot + imagesPath;
String fileName = articleBindingModel.getImage().getOriginalFilename();
String savePath = imageSaveDirectory + fileName;
File imageFile = new File(savePath);
try {
articleBindingModel.getImage().transferTo(imageFile);
databasePathImage = "/img/" + fileName;
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
Article articleEntity = new Article(
articleBindingModel.getTitle(),
articleBindingModel.getContent(),
userEntity,
databasePathImage
);
this.articleRepository.saveAndFlush(articleEntity);
return "redirect:/";
}
#GetMapping("/article/edit/{id}")
#PreAuthorize("isAuthenticated()")
public String edit(#PathVariable Integer id, Model model){
if(!this.articleRepository.exists(id)){
return "redirect:/";
}
Article article = this.articleRepository.findOne(id);
if(!this.isUserAuthorOrAdmin(article)){
return "redirect:/";
}
model.addAttribute("view", "article/edit");
model.addAttribute("article", article);
return "base-layout";
}
#GetMapping("/article/{id}")
public String details(Model model, #PathVariable Integer id) {
if(!this.articleRepository.exists(id)){
return "redirect:/";
}
if(!(SecurityContextHolder.getContext().getAuthentication()
instanceof AnonymousAuthenticationToken)){
UserDetails principal = (UserDetails) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal();
User entityUser = this.userRepository.findByEmail(principal.getUsername());
model.addAttribute("user", entityUser);
}
Article article = this.articleRepository.findOne(id);
model.addAttribute("view", "article/details");
model.addAttribute("article", article);
return "base-layout";
}
#PostMapping("/article/edit/{id}")
#PreAuthorize("isAuthenticated()")
public String editProcess(#PathVariable Integer id, ArticleBindingModel articleBindingModel) {
if(!this.articleRepository.exists(id)){
return "redirect:/";
}
Article article = this.articleRepository.findOne(id);
if(!this.isUserAuthorOrAdmin(article)){
return "redirect:/";
}
article.setTitle(articleBindingModel.getTitle());
article.setContent(articleBindingModel.getContent());
this.articleRepository.saveAndFlush(article);
return "redirect:/article/" + article.getId();
}
#GetMapping("/article/delete/{id}")
#PreAuthorize("isAuthenticated()")
public String delete(#PathVariable Integer id, Model model){
if(!this.articleRepository.exists(id)){
return "redirect:/";
}
Article article = this.articleRepository.findOne(id);
if(!this.isUserAuthorOrAdmin(article)){
return "redirect:/";
}
model.addAttribute("article", article);
model.addAttribute("view", "article/delete");
return "base-layout";
}
#PostMapping("/article/delete/{id}")
#PreAuthorize("isAuthenticated()")
public String deleteProcess(#PathVariable Integer id) {
if(!this.articleRepository.exists(id)){
return "redirect:/";
}
Article article = this.articleRepository.findOne(id);
if(!this.isUserAuthorOrAdmin(article)){
return "redirect:/";
}
this.articleRepository.delete(article);
return "redirect:/";
}
private boolean isUserAuthorOrAdmin(Article article){
UserDetails user = (UserDetails) SecurityContextHolder
.getContext()
.getAuthentication()
.getPrincipal();
User userEntity = this.userRepository.findByEmail(user.getUsername());
return userEntity.isAdmin() || userEntity.isAuthor(article);
}
}
Article model
import javax.validation.constraints.NotNull;
import javax.persistence.*;
import java.util.Date;
#Entity
#Indexed
#Table(name = "articles")
public class Article {
private Integer id;
#Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
#NotNull
private String title;
#Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
#NotNull
private String content;
private Date date;
private User author;
private String imagePath;
public Article(String title, String content, User author, String imagePath) {
this.title = title;
this.content = content;
this.author = author;
this.imagePath = imagePath;
this.date = new Date();
}
public Article(){
}
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
#Column(name = "title", nullable = false)
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
#Column(name = "content", nullable = false, columnDefinition = "text")
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
#Column(name = "date", nullable = true)
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
#ManyToOne()
#JoinColumn(nullable = false, name = "authorId")
public User getAuthor() {
return author;
}
public void setAuthor(User author) {
this.author = author;
}
#Transient
public String getSummary(){
return this.getContent().substring(0, this.getContent().length()/2) + "...";
}
public String getImagePath() {
return imagePath;
}
public void setImagePath(String imagePath) {
this.imagePath = imagePath;
}
}
Application properties
# Database connection with the given database name
spring.datasource.url = jdbc:mysql://localhost:3306/javablog
# Username and password
spring.datasource.username = root
spring.datasource.password =
# Show or not log for each sql query
spring.jpa.show-sql = true
# Hibernate ddl auto (create, create-drop, update): with "update" the database
# schema will be automatically updated accordingly to java entities found in
# the project
# Using "create" will delete and recreate the tables every time the project is started
spring.jpa.hibernate.ddl-auto = update
# Naming strategy
spring.jpa.hibernate.naming.strategy = org.hibernate.cfg.ImprovedNamingStrategy
# Allows Hibernate to generate SQL optimized for a particular DBMS
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
spring.jpa.properties.hibernate.search.default.directory_provider = filesystem
# Using the filesystem DirectoryProvider you also have to specify the default
# base directory for all indexes (make sure that the application have write
# permissions on such directory)
spring.jpa.properties.hibernate.search.default.indexBase = ../java/softuniBlog/lucene/indexes
#Turn off Thymeleaf cache
spring.thymeleaf.cache = false
POM XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>softuni.blog</groupId>
<artifactId>blog</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>Blog</name>
<description>Blog Project from the Software Technologies Course</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-orm</artifactId>
<version>5.7.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-infinispan</artifactId>
<version>5.7.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-elasticsearch</artifactId>
<version>5.7.0.Final</version>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-directory-provider</artifactId>
<version>8.2.4.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.0.Alpha2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>`enter code here`
</project>
I honestly don't understand you other questions (and you probably should ask them separately), but for question 2 I can tell you that a NoSuchMethodError is very likely to be caused by your using an incompatible version of Hibernate ORM with Hibernate Search.
To sum up:
Hibernate Search 5.7.0 and later should be used with Hibernate ORM 5.2.3 or later.
Hibernate Search 5.6.x and earlier should be used with Hibernate ORM 5.1.x or earlier.
EDIT: Your pom appears to contain a dependency to hibernate-entitymanager, and you didn't set the version for this dependency, so I suspect you're getting some older version. hibernate-entitymanager isn't required to use JPA starting with Hibernate ORM 5.2, so you should try to remove it.