Merge branch 'master' into JAVA-3533

This commit is contained in:
Loredana Crusoveanu
2021-01-01 22:55:21 +02:00
committed by GitHub
109 changed files with 958 additions and 875 deletions
+2
View File
@@ -22,9 +22,11 @@
<module>spring-mvc-forms-jsp</module>
<module>spring-mvc-views</module>
<module>spring-mvc-webflow</module>
<module>spring-mvc-xml</module>
<module>spring-rest-angular</module>
<module>spring-rest-http</module>
<module>spring-rest-http-2</module>
<module>spring-rest-query-language</module>
<module>spring-resttemplate-2</module>
<module>spring-thymeleaf</module>
<module>spring-thymeleaf-2</module>
@@ -0,0 +1,13 @@
*.class
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
# Packaged files #
*.jar
*.war
*.ear
@@ -0,0 +1,24 @@
## Spring MVC XML
This module contains articles about Spring MVC with XML configuration
### The Course
The "REST With Spring" Classes: http://bit.ly/restwithspring
### Relevant Articles:
- [Java Session Timeout](https://www.baeldung.com/servlet-session-timeout)
- [Returning Image/Media Data with Spring MVC](https://www.baeldung.com/spring-mvc-image-media-data)
- [Geolocation by IP in Java](https://www.baeldung.com/geolocation-by-ip-with-maxmind)
- [Guide to JavaServer Pages (JSP)](https://www.baeldung.com/jsp)
- [Exploring SpringMVCs Form Tag Library](https://www.baeldung.com/spring-mvc-form-tags)
- [web.xml vs Initializer with Spring](https://www.baeldung.com/spring-xml-vs-java-config)
- [A Java Web Application Without a web.xml](https://www.baeldung.com/java-web-app-without-web-xml)
- [Validating RequestParams and PathVariables in Spring](https://www.baeldung.com/spring-validate-requestparam-pathvariable)
- [Debugging the Spring MVC 404 “No mapping found for HTTP request” Error](https://www.baeldung.com/spring-mvc-404-error)
- [Introduction to Servlets and Servlet Containers](https://www.baeldung.com/java-servlets-containers-intro)
## Spring MVC with XML Configuration Example Project
- access a sample jsp page at: `http://localhost:8080/spring-mvc-xml/sample.html`
+176
View File
@@ -0,0 +1,176 @@
<?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>
<artifactId>spring-mvc-xml</artifactId>
<version>0.1-SNAPSHOT</version>
<name>spring-mvc-xml</name>
<packaging>war</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<!-- web -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>${hibernate-validator.version}</version>
</dependency>
<!-- Json conversion -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- IO -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>com.maxmind.geoip2</groupId>
<artifactId>geoip2</artifactId>
<version>${geoip2.version}</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>${javax.el.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
</dependency>
<!-- CRaSH Dependency -->
<dependency>
<groupId>org.crashub</groupId>
<artifactId>crash.embed.spring</artifactId>
<version>${crash.version}</version>
</dependency>
<dependency>
<groupId>org.crashub</groupId>
<artifactId>crash.cli</artifactId>
<version>${crash.version}</version>
</dependency>
<dependency>
<groupId>org.crashub</groupId>
<artifactId>crash.connectors.telnet</artifactId>
<version>${crash.version}</version>
<exclusions>
<exclusion>
<artifactId>log4j</artifactId>
<groupId>log4j</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- Groovy -->
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
</dependency>
</dependencies>
<build>
<finalName>spring-mvc-xml</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>${maven-war-plugin.version}</version>
</plugin>
</plugins>
</build>
<properties>
<!-- Spring -->
<org.springframework.version>5.0.2.RELEASE</org.springframework.version>
<spring-boot.version>1.5.10.RELEASE</spring-boot.version>
<!-- persistence -->
<mysql-connector-java.version>5.1.40</mysql-connector-java.version>
<!-- http -->
<httpcore.version>4.4.5</httpcore.version>
<httpclient.version>4.5.2</httpclient.version>
<!-- various -->
<hibernate-validator.version>6.0.10.Final</hibernate-validator.version>
<javax.el.version>3.0.1-b08</javax.el.version>
<!-- util -->
<guava.version>19.0</guava.version>
<geoip2.version>2.8.0</geoip2.version>
<!-- Maven plugins -->
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
<crash.version>1.3.2</crash.version>
<groovy.version>3.0.0-rc-3</groovy.version>
</properties>
</project>
@@ -0,0 +1,21 @@
package com.baeldung.jsp;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ExampleOne extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE html><html>" + "<head>" + "<meta charset=\"UTF-8\" />" + "<title>HTML Rendered by Servlet</title>" + "</head>" + "<body>" + "<h1>HTML Rendered by Servlet</h1></br>" + "<p>This page was rendered by the ExampleOne Servlet!</p>"
+ "</body>" + "</html>");
}
}
@@ -0,0 +1,24 @@
package com.baeldung.jsp;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name = "ExampleThree", description = "JSP Servlet With Annotations", urlPatterns = { "/ExampleThree" })
public class ExampleThree extends HttpServlet {
private static final long serialVersionUID = 1L;
private String instanceMessage;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String message = request.getParameter("message");
instanceMessage = request.getParameter("message");
request.setAttribute("text", message);
request.setAttribute("unsafeText", instanceMessage);
request.getRequestDispatcher("/jsp/ExampleThree.jsp").forward(request, response);
}
}
@@ -0,0 +1,19 @@
package com.baeldung.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ImportResource("classpath:webMvcConfig.xml")
@Configuration
@ComponentScan
public class ClientWebConfig implements WebMvcConfigurer {
public ClientWebConfig() {
super();
}
// API
}
@@ -0,0 +1,62 @@
package com.baeldung.spring;
import java.util.Locale;
import java.util.ResourceBundle;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
//@EnableWebMvc
//@Configuration
@ComponentScan("com.baeldung.spring")
public class ClientWebConfigJava implements WebMvcConfigurer {
public ClientWebConfigJava() {
super();
}
@Bean
public MessageSource messageSource() {
final ResourceBundleMessageSource ms = new ResourceBundleMessageSource();
ms.setBasenames("messages");
return ms;
}
@Bean
public ResourceBundle getBeanResourceBundle() {
final Locale locale = Locale.getDefault();
return new MessageSourceResourceBundle(messageSource(), locale);
}
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/sample.html");
}
@Bean
public ViewResolver viewResolver() {
final InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/view/");
bean.setSuffix(".jsp");
return bean;
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
@@ -0,0 +1,21 @@
package com.baeldung.spring.controller;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import javax.validation.ConstraintViolationException;
@ControllerAdvice
public class ConstraintViolationExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = {ConstraintViolationException.class})
protected ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException e, WebRequest request) {
return handleExceptionInternal(e, e.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
}
@@ -0,0 +1,51 @@
package com.baeldung.spring.controller;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class ErrorController {
@RequestMapping(value = "500Error", method = RequestMethod.GET)
public void throwRuntimeException() {
throw new NullPointerException("Throwing a null pointer exception");
}
@RequestMapping(value = "errors", method = RequestMethod.GET)
public ModelAndView renderErrorPage(HttpServletRequest httpRequest) {
ModelAndView errorPage = new ModelAndView("errorPage");
String errorMsg = "";
int httpErrorCode = getErrorCode(httpRequest);
switch (httpErrorCode) {
case 400: {
errorMsg = "Http Error Code : 400 . Bad Request";
break;
}
case 401: {
errorMsg = "Http Error Code : 401. Unauthorized";
break;
}
case 404: {
errorMsg = "Http Error Code : 404. Resource not found";
break;
}
// Handle other 4xx error codes.
case 500: {
errorMsg = "Http Error Code : 500. Internal Server Error";
break;
}
// Handle other 5xx error codes.
}
errorPage.addObject("errorMsg", errorMsg);
return errorPage;
}
private int getErrorCode(HttpServletRequest httpRequest) {
return (Integer) httpRequest.getAttribute("javax.servlet.error.status_code");
}
}
@@ -0,0 +1,29 @@
package com.baeldung.spring.controller;
import java.io.IOException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.baeldung.spring.form.GeoIP;
import com.baeldung.spring.service.RawDBDemoGeoIPLocationService;
//@Controller
//add db file and uncomment to see the working example
public class GeoIPTestController {
private RawDBDemoGeoIPLocationService locationService;
public GeoIPTestController() throws IOException {
locationService = new RawDBDemoGeoIPLocationService();
}
@RequestMapping(value = "/GeoIPTest", method = RequestMethod.POST)
@ResponseBody
public GeoIP getLocation(@RequestParam(value = "ipAddress", required = true) String ipAddress) throws Exception {
return locationService.getLocation(ipAddress);
}
}
@@ -0,0 +1,16 @@
package com.baeldung.spring.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@Controller
public class GreetingController {
@RequestMapping(value = "/greeting", method = RequestMethod.GET)
public String get(ModelMap model) {
model.addAttribute("message", "Hello, World!");
return "greeting";
}
}
@@ -0,0 +1,18 @@
package com.baeldung.spring.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class HelloController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView model = new ModelAndView("helloworld");
model.addObject("msg", "Welcome to Baeldung's Spring Handler Mappings Guide.<br>This request was mapped" + " using SimpleUrlHandlerMapping.");
return model;
}
}
@@ -0,0 +1,17 @@
package com.baeldung.spring.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class HelloGuestController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView model = new ModelAndView("helloworld");
model.addObject("msg", "Welcome to Baeldung's Spring Handler Mappings Guide.<br>This request was mapped" + " using ControllerClassNameHandlerMapping.");
return model;
}
}
@@ -0,0 +1,17 @@
package com.baeldung.spring.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class HelloWorldController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView model = new ModelAndView("helloworld");
model.addObject("msg", "Welcome to Baeldung's Spring Handler Mappings Guide.<br>This request was mapped" + " using BeanNameUrlHandlerMapping.");
return model;
}
}
@@ -0,0 +1,61 @@
package com.baeldung.spring.controller;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.support.ServletContextResource;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
@Controller
public class ImageController {
@Autowired
private ServletContext servletContext;
@RequestMapping(value = "/image-view", method = RequestMethod.GET)
public String imageView() throws IOException {
return "image-download";
}
@RequestMapping(value = "/image-manual-response", method = RequestMethod.GET)
public void getImageAsByteArray(HttpServletResponse response) throws IOException {
final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg");
response.setContentType(MediaType.IMAGE_JPEG_VALUE);
IOUtils.copy(in, response.getOutputStream());
}
@RequestMapping(value = "/image-byte-array", method = RequestMethod.GET)
@ResponseBody
public byte[] getImageAsByteArray() throws IOException {
final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg");
return IOUtils.toByteArray(in);
}
@RequestMapping(value = "/image-response-entity", method = RequestMethod.GET)
public ResponseEntity<byte[]> getImageAsResponseEntity() throws IOException {
ResponseEntity<byte[]> responseEntity;
final HttpHeaders headers = new HttpHeaders();
final InputStream in = servletContext.getResourceAsStream("/WEB-INF/images/image-example.jpg");
byte[] media = IOUtils.toByteArray(in);
headers.setCacheControl(CacheControl.noCache().getHeaderValue());
responseEntity = new ResponseEntity<>(media, headers, HttpStatus.OK);
return responseEntity;
}
@RequestMapping(value = "/image-resource", method = RequestMethod.GET)
@ResponseBody
public ResponseEntity<Resource> getImageAsResource() {
final HttpHeaders headers = new HttpHeaders();
Resource resource = new ServletContextResource(servletContext, "/WEB-INF/images/image-example.jpg");
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
}
@@ -0,0 +1,83 @@
package com.baeldung.spring.controller;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import com.baeldung.spring.form.Person;
import com.baeldung.spring.validator.PersonValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
@Controller
public class PersonController {
@Autowired
PersonValidator validator;
@RequestMapping(value = "/person", method = RequestMethod.GET)
public ModelAndView showForm(final Model model) {
initData(model);
return new ModelAndView("personForm", "person", new Person());
}
@RequestMapping(value = "/addPerson", method = RequestMethod.POST)
public String submit(@Valid @ModelAttribute("person") final Person person, final BindingResult result, final ModelMap modelMap, final Model model) {
validator.validate(person, result);
if (result.hasErrors()) {
initData(model);
return "personForm";
}
modelMap.addAttribute("person", person);
return "personView";
}
private void initData(final Model model) {
final List<String> favouriteLanguageItem = new ArrayList<String>();
favouriteLanguageItem.add("Java");
favouriteLanguageItem.add("C++");
favouriteLanguageItem.add("Perl");
model.addAttribute("favouriteLanguageItem", favouriteLanguageItem);
final List<String> jobItem = new ArrayList<String>();
jobItem.add("Full time");
jobItem.add("Part time");
model.addAttribute("jobItem", jobItem);
final Map<String, String> countryItems = new LinkedHashMap<String, String>();
countryItems.put("US", "United Stated");
countryItems.put("IT", "Italy");
countryItems.put("UK", "United Kingdom");
countryItems.put("FR", "Grance");
model.addAttribute("countryItems", countryItems);
final List<String> fruit = new ArrayList<String>();
fruit.add("Banana");
fruit.add("Mango");
fruit.add("Apple");
model.addAttribute("fruit", fruit);
final List<String> books = new ArrayList<String>();
books.add("The Great Gatsby");
books.add("Nineteen Eighty-Four");
books.add("The Lord of the Rings");
model.addAttribute("books", books);
}
}
@@ -0,0 +1,31 @@
package com.baeldung.spring.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.*;
@Controller
@RequestMapping("/public/api/1")
@Validated
public class RequestAndPathVariableValidationController {
@GetMapping("/name-for-day")
public String getNameOfDayByNumberRequestParam(@RequestParam @Min(1) @Max(7) Integer dayOfWeek) {
return dayOfWeek + "";
}
@GetMapping("/name-for-day/{dayOfWeek}")
public String getNameOfDayByPathVariable(@PathVariable("dayOfWeek") @Min(1) @Max(7) Integer dayOfWeek) {
return dayOfWeek + "";
}
@GetMapping("/valid-name")
public void validStringRequestParam(@RequestParam @NotBlank @Size(max = 10) @Pattern(regexp = "^[A-Z][a-zA-Z0-9]+$") String name) {
}
}
@@ -0,0 +1,18 @@
package com.baeldung.spring.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class WelcomeController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {
ModelAndView model = new ModelAndView("welcome");
model.addObject("msg", " Baeldung's Spring Handler Mappings Guide.<br>This request was mapped" + " using SimpleUrlHandlerMapping.");
return model;
}
}
@@ -0,0 +1,56 @@
package com.baeldung.spring.form;
public class GeoIP {
private String ipAddress;
private String city;
private String latitude;
private String longitude;
public GeoIP() {
}
public GeoIP(String ipAddress) {
this.ipAddress = ipAddress;
}
public GeoIP(String ipAddress, String city, String latitude, String longitude) {
this.ipAddress = ipAddress;
this.city = city;
this.latitude = latitude;
this.longitude = longitude;
}
public String getIpAddress() {
return ipAddress;
}
public void setIpAddress(String ipAddress) {
this.ipAddress = ipAddress;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
}
@@ -0,0 +1,153 @@
package com.baeldung.spring.form;
import java.util.List;
import javax.validation.constraints.NotEmpty;
import org.springframework.web.multipart.MultipartFile;
public class Person {
private long id;
private String name;
private String email;
private String dateOfBirth;
@NotEmpty
private String password;
private String sex;
private String country;
private String book;
private String job;
private boolean receiveNewsletter;
private String[] hobbies;
private List<String> favouriteLanguage;
private List<String> fruit;
private String notes;
private MultipartFile file;
public Person() {
super();
}
public long getId() {
return id;
}
public void setId(final long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(final String email) {
this.email = email;
}
public String getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(final String dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
public String getPassword() {
return password;
}
public void setPassword(final String password) {
this.password = password;
}
public String getSex() {
return sex;
}
public void setSex(final String sex) {
this.sex = sex;
}
public String getCountry() {
return country;
}
public void setCountry(final String country) {
this.country = country;
}
public String getJob() {
return job;
}
public void setJob(final String job) {
this.job = job;
}
public boolean isReceiveNewsletter() {
return receiveNewsletter;
}
public void setReceiveNewsletter(final boolean receiveNewsletter) {
this.receiveNewsletter = receiveNewsletter;
}
public String[] getHobbies() {
return hobbies;
}
public void setHobbies(final String[] hobbies) {
this.hobbies = hobbies;
}
public List<String> getFavouriteLanguage() {
return favouriteLanguage;
}
public void setFavouriteLanguage(final List<String> favouriteLanguage) {
this.favouriteLanguage = favouriteLanguage;
}
public String getNotes() {
return notes;
}
public void setNotes(final String notes) {
this.notes = notes;
}
public List<String> getFruit() {
return fruit;
}
public void setFruit(final List<String> fruit) {
this.fruit = fruit;
}
public String getBook() {
return book;
}
public void setBook(final String book) {
this.book = book;
}
public MultipartFile getFile() {
return file;
}
public void setFile(final MultipartFile file) {
this.file = file;
}
}
@@ -0,0 +1,29 @@
package com.baeldung.spring.service;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import com.baeldung.spring.form.GeoIP;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
public class RawDBDemoGeoIPLocationService {
private DatabaseReader dbReader;
public RawDBDemoGeoIPLocationService() throws IOException {
File database = new File("your-path-to-db-file");
dbReader = new DatabaseReader.Builder(database).build();
}
public GeoIP getLocation(String ip) throws IOException, GeoIp2Exception {
InetAddress ipAddress = InetAddress.getByName(ip);
CityResponse response = dbReader.city(ipAddress);
String cityName = response.getCity().getName();
String latitude = response.getLocation().getLatitude().toString();
String longitude = response.getLocation().getLongitude().toString();
return new GeoIP(ip, cityName, latitude, longitude);
}
}
@@ -0,0 +1,22 @@
package com.baeldung.spring.validator;
import com.baeldung.spring.form.Person;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
@Component
public class PersonValidator implements Validator {
@Override
public boolean supports(final Class calzz) {
return Person.class.isAssignableFrom(calzz);
}
@Override
public void validate(final Object obj, final Errors errors) {
ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "required.name");
}
}
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager" />
<context:component-scan base-package="com.baeldung.spring.controller" />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:view-controller path="/sample.html" view-name="sample" />
<!-- Content strategy using path extension -->
<bean id="contentNegotiationManager"
class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false" />
<property name="favorParameter" value="true"/>
<property name="parameterName" value="mediaType"/>
<property name="ignoreAcceptHeader" value="true" />
<property name="defaultContentType" value="application/json" />
<property name="useJaf" value="false" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
</map>
</property>
</bean>
</beans>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,2 @@
required.name = Name is required!
NotEmpty.person.password = Password is required!
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"
>
<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>image/jpeg</value>
<value>image/png</value>
</list>
</property>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<context:component-scan base-package="com.baeldung.spring.controller"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/"/>
<property name="suffix" value=".jsp"/>
</bean>
<mvc:view-controller path="/sample.html" view-name="sample"/>
<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource">
<property name="basename" value="messages" />
</bean>
</beans>
@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Geo IP Test</title>
<!--jquery dep -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready (function () {
// getting the public ip address from api and setting on text box
// ip api : https://www.ipify.org/
$.get( "https://api.ipify.org?format=json", function( data ) {
console.log(data);
$("#ip").val(data.ip) ;
});
function showLocationOnMap (location) {
var map;
map = new google.maps.Map(document.getElementById('map'), {
center: {lat: Number(location.latitude), lng: Number(location.longitude)},
zoom: 15
});
var marker = new google.maps.Marker({
position: {lat: Number(location.latitude), lng: Number(location.longitude)},
map: map,
title: "Public IP:"+location.ipAddress+" @ "+location.city
});
}
$( "#ipForm" ).submit(function( event ) {
event.preventDefault();
$.ajax({
url: "GeoIPTest",
type: "POST",
contentType: "application/x-www-form-urlencoded; charset=UTF-8", // send as JSON
data: $.param( {ipAddress : $("#ip").val()} ),
complete: function(data) {
console.log ("Request complete");
},
success: function(data) {
$("#status").html(JSON.stringify(data));
if (data.ipAddress !=null) {
console.log ("Success:"+data.ipAddress);
showLocationOnMap(data);
}
},
error: function(err) {
console.log(err);
$("#status").html("Error:"+JSON.stringify(data));
},
});
});
});
</script>
</head>
<body>
<form id="ipForm" action="GeoIPTest" method="POST">
<input type="text" name = "ipAddress" id = "ip"/>
<input type="submit" name="submit" value="submit" />
</form>
<div id="status"></div>
<div id="map" style="height: 500px; width:100%; position:absolute"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR-MAPS-API-KEY"
async defer></script>
</body>
</html>
@@ -0,0 +1,14 @@
import org.crsh.cli.Command;
import org.crsh.cli.Usage;
import org.crsh.cli.Option;
class message {
@Usage("show my own message")
@Command
Object main(@Usage("custom message") @Option(names=["m","message"]) String message) {
if (message == null)
message = "No message given...";
return message;
}
}
@@ -0,0 +1,14 @@
import org.crsh.command.BaseCommand;
import org.crsh.cli.Usage;
import org.crsh.cli.Command;
import org.crsh.cli.Option;
public class message2 extends BaseCommand {
@Usage("show my own message using java")
@Command
public Object main(@Usage("custom message") @Option(names = { "m", "message" }) String message) {
if (message == null)
message = "No message given...";
return message;
}
}
@@ -0,0 +1 @@
crash.telnet.port=50001
@@ -0,0 +1,65 @@
############################
# Telnet daemon properties #
############################
#####################
# Terminals Section #
#####################
# List of terminals available and defined below
terminals=vt100,ansi,windoof,xterm
# vt100 implementation and aliases
term.vt100.class=net.wimpi.telnetd.io.terminal.vt100
term.vt100.aliases=default,vt100-am,vt102,dec-vt100
# ansi implementation and aliases
term.ansi.class=net.wimpi.telnetd.io.terminal.ansi
term.ansi.aliases=color-xterm,xterm-color,vt320,vt220,linux,screen
# windoof implementation and aliases
term.windoof.class=net.wimpi.telnetd.io.terminal.Windoof
term.windoof.aliases=
# xterm implementation and aliases
term.xterm.class=net.wimpi.telnetd.io.terminal.xterm
term.xterm.aliases=
##################
# Shells Section #
##################
# List of shells available and defined below
shells=simple
# shell implementations
shell.simple.class=org.crsh.telnet.term.TelnetHandler
#####################
# Listeners Section #
#####################
listeners=std
# std listener specific properties
#Basic listener and connection management settings (port is commented because CRaSH configures it)
# std.port=5000
std.floodprotection=5
std.maxcon=25
# Timeout Settings for connections (ms)
std.time_to_warning=3600000
std.time_to_timedout=60000
# Housekeeping thread active every 1 secs
std.housekeepinginterval=1000
std.inputmode=character
# Login shell
std.loginshell=simple
# Connection filter class
std.connectionfilter=none
Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.baeldung.spring.controller"/>
<!-- Start: Mapping by bean name (BeanNameUrlHandlerMapping) -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="order" value="1"/>
</bean>
<bean name="/hello*.htm" class="com.baeldung.spring.controller.HelloWorldController"/>
<!-- End: Mapping by bean name (BeanNameUrlHandlerMapping) -->
<!-- Start: Mapping by SimpleUrlHandlerMapping -->
<!-- Method 1 Using Value -->
<!-- <bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings"> <value> /welcome.htm=welcomeController /welcome*=welcomeController
</value> </property> <property name="order" value="2" /> </bean> -->
<!-- Method 2 Using prop key -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/welcome.htm">welcomeController</prop>
<prop key="/welcome*">welcomeController</prop>
<prop key="/hello*">helloController</prop>
</props>
</property>
<property name="order" value="2"/>
</bean>
<bean id="welcomeController" class="com.baeldung.spring.controller.WelcomeController"></bean>
<bean id="helloController" class="com.baeldung.spring.controller.HelloController"/>
<!-- End: Mapping by SimpleUrlHandlerMapping -->
<bean class="com.baeldung.spring.controller.HelloGuestController"/>
<!-- End: Mapping by ControllerClassNameHandlerMapping -->
<!-- Start: Mapping by ControllerClassNameHandlerMapping with prefix -->
<!-- <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
<property name="caseSensitive" value="true" /> <property name="order" value="0"
/> <property name="pathPrefix" value="/login" /> </bean> <bean class="com.baeldung.spring.controller.HelloGuestController"
/> -->
<!-- End: Mapping by ControllerClassNameHandlerMapping with prefix -->
<bean class="org.crsh.spring.SpringWebBootstrap">
<property name="cmdMountPointConfig"
value="war:/WEB-INF/crash/commands/" />
<property name="confMountPointConfig"
value="war:/WEB-INF/crash/" />
<property name="config">
<props>
<prop key="crash.telnet.port">5000</prop>
</props>
</property>
</bean>
</beans>
@@ -0,0 +1,20 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>SpringMVCExample</title>
</head>
<body>
<h3>Pleas enter the correct details</h3>
<table>
<tr>
<td><a href="employee">Retry</a></td>
</tr>
</table>
</body>
</html>
@@ -0,0 +1,10 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page session="false"%>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>${errorMsg}</h1>
</body>
</html>
@@ -0,0 +1,9 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Greeting</title>
</head>
<body>
<h2>${message}</h2>
</body>
</html>
@@ -0,0 +1,15 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hello World</title>
</head>
<body>
<h2>Hello ${msg}</h2>
<br>
<p>
<a href="spring-handler-index.jsp">Go to spring handler mappings homepage</a>
</body>
</html>
@@ -0,0 +1,15 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Hello World</title>
</head>
<body>
<h2>Hello World ${msg}</h2>
<br>
<p>
<a href="spring-handler-index.jsp">Go to spring handler mappings homepage</a>
</body>
</html>
@@ -0,0 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Image download examples</title>
</head>
<body>
<h1>Image download examples</h1>
<ul>
<li><a href="<c:url value="/image-manual-response" />">Image manually add to response</a></li>
<li><a href="<c:url value="/image-byte-array.jpg" />">Image Download <i>byte[]</i> Example</a></li>
<li><a href="<c:url value="/image-response-entity.jpg" />">Image Download <i>ResponseEntity</i> Example</a></li>
<li><a href="<c:url value="/image-resource.jpg" />">Image Download <i>Resource</i> Example</a></li>
</ul>
</body>
</html>
@@ -0,0 +1,120 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Form Example - Register a Person</title>
</head>
<style>
.error {
color: #ff0000;
}
.errorbox {
background-color: #ffEEEE;
border: 2px solid #ff0000;
}
</style>
<body>
<h3>Welcome, Enter the Person Details</h3>
<form:form method="POST" action="/spring-mvc-xml/addPerson" modelAttribute="person">
<form:errors path="*" cssClass="errorbox" element="div" />
<table>
<tr>
<td><form:label path="name">Name</form:label></td>
<td><form:input path="name" /></td>
<td><form:errors path="name" cssClass="error" element="div"/></td>
</tr>
<tr>
<td><form:label path="email">E-mail</form:label></td>
<td><form:input type="email" path="email" /></td>
<td><form:errors path="email" cssClass="error" /></td>
</tr>
<tr>
<td><form:label path="dateOfBirth">Date of birth</form:label></td>
<td><form:input type="date" path="dateOfBirth" /></td>
</tr>
<tr>
<td><form:label path="password">Password</form:label></td>
<td><form:password path="password" /></td>
<td><form:errors path="password" cssClass="error" /></td>
</tr>
<tr>
<td><form:label path="sex">Sex</form:label></td>
<td>
Male: <form:radiobutton path="sex" value="M"/> <br/>
Female: <form:radiobutton path="sex" value="F"/>
</td>
</tr>
<tr>
<td><form:label path="job">Job</form:label></td>
<td>
<form:radiobuttons items="${jobItem}" path="job" />
</td>
</tr>
<tr>
<td><form:label path="country">Country</form:label></td>
<td>
<form:select path="country" items="${countryItems}" />
</td>
</tr>
<tr>
<td><form:label path="book">Book</form:label></td>
<td>
<form:select path="book">
<form:option value="-" label="--Please Select"/>
<form:options items="${books}" />
</form:select>
</td>
</tr>
<tr>
<td><form:label path="fruit">Fruit</form:label></td>
<td>
<form:select path="fruit" items="${fruit}" multiple="true"/>
</td>
</tr>
<tr>
<td><form:label path="receiveNewsletter">Receive newsletter</form:label></td>
<td><form:checkbox path="receiveNewsletter" rows="3" cols="20"/></td>
</tr>
<tr>
<td><form:label path="hobbies">Hobbies</form:label></td>
<td>
Bird watching: <form:checkbox path="hobbies" value="Bird watching"/>
Astronomy: <form:checkbox path="hobbies" value="Astronomy"/>
Snowboarding: <form:checkbox path="hobbies" value="Snowboarding"/>
</td>
</tr>
<tr>
<td><form:label path="favouriteLanguage">Favourite languages</form:label></td>
<td>
<form:checkboxes items="${favouriteLanguageItem}" path="favouriteLanguage" />
</td>
</tr>
<tr>
<td><form:label path="notes">Notes</form:label></td>
<td><form:textarea path="notes" rows="3" cols="20"/></td>
</tr>
<tr>
<td><form:hidden path="id" value="12345"/></td>
</tr>
<tr>
<td><input type="submit" value="Submit" /></td>
</tr>
</table>
</form:form>
</body>
</html>
@@ -0,0 +1,65 @@
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Spring MVC Form Handling</title>
</head>
<body>
<h2>Submitted Person Information</h2>
<table>
<tr>
<td>Id :</td>
<td>${person.id}</td>
</tr>
<tr>
<td>Name :</td>
<td>${person.name}</td>
</tr>
<tr>
<td>Date of birth :</td>
<td>${person.dateOfBirth}</td>
</tr>
<tr>
<td>Password :</td>
<td>${person.password}</td>
</tr>
<tr>
<td>Sex :</td>
<td>${person.sex}</td>
</tr>
<tr>
<td>Job :</td>
<td>${person.job}</td>
</tr>
<tr>
<td>Country :</td>
<td>${person.country}</td>
</tr>
<tr>
<td>Fruit :</td>
<td><c:forEach items="${person.fruit}" var="current">[<c:out value="${current}" />]</c:forEach></td>
</tr>
<tr>
<td>Book :</td>
<td>${person.book}</td>
</tr>
<tr>
<td>Receive Newsletter :</td>
<td>${person.receiveNewsletter}</td>
</tr>
<tr>
<td>Hobbies :</td>
<td><c:forEach items="${person.hobbies}" var="current">[<c:out value="${current}" />]</c:forEach></td>
</tr>
<tr>
<td>Favourite Languages :</td>
<td><c:forEach items="${person.favouriteLanguage}" var="current">[<c:out value="${current}" />]</c:forEach></td>
</tr>
<tr>
<td>Notes :</td>
<td>${person.notes}</td>
</tr>
</table>
</body>
</html>
@@ -0,0 +1,7 @@
<html>
<head></head>
<body>
<h1>This is the body of the sample view</h1>
</body>
</html>
@@ -0,0 +1,15 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome Page</title>
</head>
<body>
<h2>Welcome to ${msg}</h2>
<br>
<p>
<a href="spring-handler-index.jsp">Go to spring handler mappings homepage</a>
</body>
</html>
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1"
>
<display-name>Spring MVC XML Application</display-name>
<!-- Spring root -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.baeldung.spring</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.crsh.plugin.WebPluginLifeCycle</listener-class>
</listener>
<!-- Spring child -->
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- JSP Servlet -->
<servlet>
<servlet-name>ExampleOne</servlet-name>
<servlet-class>com.baeldung.jsp.ExampleOne</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ExampleOne</servlet-name>
<url-pattern>/jsp/ExampleOne</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ExampleThree</servlet-name>
<servlet-class>com.baeldung.jsp.ExampleThree</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ExampleThree</servlet-name>
<url-pattern>/jsp/ExampleThree</url-pattern>
</servlet-mapping>
<!-- additional config -->
<session-config>
<session-timeout>10</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<error-page>
<location>/errors</location>
</error-page>
</web-app>
@@ -0,0 +1,20 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring MVC Examples</title>
</head>
<body>
<h1>Spring MVC Examples</h1>
<ul>
<li><a href="employee">Welcome Page</a></li>
<li><a href="spring-handler-index.jsp">Spring Handler Mapping Examples</a></li>
<li><a href="image-view">Image Download Examples</a></li>
</ul>
</body>
</html>
@@ -0,0 +1,10 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<head>
<title>Java Binding Example</title>
</head>
<body>
<h1>Bound Value</h1>
<p>You said: ${text}</p>
</body>
</html>
@@ -0,0 +1,13 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<head>
<title>Java in Static Page Example</title>
</head>
<body>
<h1>Java in Static Page Example</h1>
<% String[] arr = {"What's up?", "Hello", "It's a nice day today!"};
String greetings = arr[(int)(Math.random() * arr.length)];
%>
<p><%= greetings %></p>
</body>
</html>
@@ -0,0 +1,12 @@
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>JSP Examples</title>
</head>
<body>
<h1>Simple JSP Examples</h1>
<p>Invoke HTML rendered by Servlet: <a href="ExampleOne" target="_blank">here</a></p>
<p>Java in static page: <a href="ExampleTwo.jsp" target="_blank">here</a></p>
<p>Java injected by Servlet: <a href="ExampleThree?message=hello!" target="_blank">here</a></p>
</body>
</html>
@@ -0,0 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome</title>
</head>
<body>
<h2>Spring Handler Mapping Examples</h2>
<h3>Click each link below to see how the request is mapped using the specified mapping:
</h3>
<ol>
<li><a href="helloWorld.html">BeanNameUrlHandlerMapping - Mapping by bean name</a></li>
<li><a href="welcome.html">SimpleUrlHandlerMapping</a></li>
<li><a href="helloGuest.html">ControllerClassNameHandlerMapping - Mapping by controller name</a></li>
</ol>
<a href="index.jsp">Home</a>
</body>
</html>
@@ -0,0 +1,19 @@
package com.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.baeldung.spring.ClientWebConfig;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ClientWebConfig.class)
@WebAppConfiguration
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}
@@ -0,0 +1,32 @@
package com.baeldung.geoip;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import org.junit.Test;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.GeoIp2Exception;
import com.maxmind.geoip2.model.CityResponse;
public class GeoIpIntegrationTest {
@Test
public void givenIP_whenFetchingCity_thenReturnsCityData() throws IOException, GeoIp2Exception {
ClassLoader classLoader = getClass().getClassLoader();
File database = new File(classLoader.getResource("GeoLite2-City.mmdb").getFile());
DatabaseReader dbReader = new DatabaseReader.Builder(database).build();
InetAddress ipAddress = InetAddress.getByName("google.com");
CityResponse response = dbReader.city(ipAddress);
String countryName = response.getCountry().getName();
String cityName = response.getCity().getName();
String postal = response.getPostal().getCode();
String state = response.getLeastSpecificSubdivision().getName();
}
}
@@ -0,0 +1,73 @@
package com.baeldung.spring.controller;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import com.baeldung.spring.ClientWebConfig;
import com.baeldung.spring.ClientWebConfigJava;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ClientWebConfigJava.class)
@WebAppConfiguration
public class RequestAndPathVariableValidationControllerIntegrationTest {
private MockMvc mockMvc;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void getNameOfDayByNumberRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception {
mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(5)))
.andExpect(status().isOk());
}
@Test
public void getNameOfDayByNumberRequestParam_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception {
mockMvc.perform(get("/public/api/1/name-for-day").param("dayOfWeek", Integer.toString(15)))
.andExpect(status().isBadRequest());
}
@Test
public void getNameOfDayByPathVariable_whenGetWithProperRequestParam_thenReturn200() throws Exception {
mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(5))).andExpect(status().isOk());
}
@Test
public void getNameOfDayByPathVariable_whenGetWithRequestParamOutOfRange_thenReturn400() throws Exception {
mockMvc.perform(get("/public/api/1/name-for-day/{dayOfWeek}", Integer.toString(15)))
.andExpect(status().isBadRequest());
}
@Test
public void validStringRequestParam_whenGetWithProperRequestParam_thenReturn200() throws Exception {
mockMvc.perform(get("/public/api/1/valid-name").param("name", "John")).andExpect(status().isOk());
}
@Test
public void validStringRequestParam_whenGetWithTooLongRequestParam_thenReturn400() throws Exception {
mockMvc.perform(get("/public/api/1/valid-name").param("name", "asdfghjklqw"))
.andExpect(status().isBadRequest());
}
@Test
public void validStringRequestParam_whenGetWithLowerCaseRequestParam_thenReturn400() throws Exception {
mockMvc.perform(get("/public/api/1/valid-name").param("name", "john")).andExpect(status().isBadRequest());
}
}
@@ -0,0 +1,13 @@
*.class
#folders#
/target
/neoDb*
/data
/src/main/webapp/WEB-INF/classes
*/META-INF/*
# Packaged files #
*.jar
*.war
*.ear
@@ -0,0 +1,32 @@
## Spring REST Query Language
This module contains articles about the REST query language with Spring
### Courses
The "REST With Spring" Classes: http://bit.ly/restwithspring
The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles:
- [REST Query Language with Spring and JPA Criteria](https://www.baeldung.com/rest-search-language-spring-jpa-criteria)
- [REST Query Language with Spring Data JPA Specifications](https://www.baeldung.com/rest-api-search-language-spring-data-specifications)
- [REST Query Language with Spring Data JPA and QueryDSL](https://www.baeldung.com/rest-api-search-language-spring-data-querydsl)
- [REST Query Language Advanced Search Operations](https://www.baeldung.com/rest-api-query-search-language-more-operations)
- [REST Query Language with RSQL](https://www.baeldung.com/rest-api-search-language-rsql-fiql)
- [REST Query Language Implementing OR Operation](https://www.baeldung.com/rest-api-query-search-or-operation)
### Build the Project
```
mvn clean install
```
### Set up MySQL
```
mysql -u root -p
> CREATE USER 'tutorialuser'@'localhost' IDENTIFIED BY 'tutorialmy5ql';
> GRANT ALL PRIVILEGES ON *.* TO 'tutorialuser'@'localhost';
> FLUSH PRIVILEGES;
```
@@ -0,0 +1,359 @@
<?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>
<artifactId>spring-rest-query-language</artifactId>
<version>0.1-SNAPSHOT</version>
<name>spring-rest-query-language</name>
<packaging>war</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>
<!-- Spring Boot Dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<!-- deployment -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!-- Querydsl -->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<!-- Rsql -->
<dependency>
<groupId>cz.jirutka.rsql</groupId>
<artifactId>rsql-parser</artifactId>
<version>${rsql.version}</version>
</dependency>
<!-- web -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-logging</artifactId>
<groupId>commons-logging</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
</dependency>
<!-- persistence -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
<version>${xml-apis.version}</version>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>${javassist.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- web -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<scope>runtime</scope>
</dependency>
<!-- marshalling -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<!-- util -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<!-- test scoped -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>spring-rest-query-language</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<version>${cargo-maven2-plugin.version}</version>
<configuration>
<wait>true</wait>
<container>
<containerId>jetty8x</containerId>
<type>embedded</type>
<systemProperties>
<!-- <provPersistenceTarget>cargo</provPersistenceTarget> -->
</systemProperties>
</container>
<configuration>
<properties>
<cargo.servlet.port>8082</cargo.servlet.port>
</properties>
</configuration>
</configuration>
</plugin>
<!-- Querydsl and Specifications -->
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>${apt-maven-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>live</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<excludes>
<exclude>**/*IntegrationTest.java</exclude>
<exclude>**/*IntTest.java</exclude>
</excludes>
<includes>
<include>**/*LiveTest.java</include>
</includes>
</configuration>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<test.mime>json</test.mime>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<wait>false</wait>
</configuration>
<executions>
<execution>
<id>start-server</id>
<phase>pre-integration-test</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>stop-server</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<properties>
<!-- persistence -->
<rsql.version>2.1.0</rsql.version>
<!-- various -->
<xstream.version>1.4.9</xstream.version>
<javassist.version>3.21.0-GA</javassist.version>
<xml-apis.version>1.4.01</xml-apis.version>
<!-- util -->
<guava.version>19.0</guava.version>
<!-- Maven plugins -->
<cargo-maven2-plugin.version>1.7.0</cargo-maven2-plugin.version>
<apt-maven-plugin.version>1.1.3</apt-maven-plugin.version>
</properties>
</project>
@@ -0,0 +1,100 @@
package com.baeldung.persistence.dao;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.data.jpa.domain.Specification;
import com.baeldung.web.util.SearchOperation;
import com.baeldung.web.util.SpecSearchCriteria;
public class GenericSpecificationsBuilder<U> {
private final List<SpecSearchCriteria> params;
public GenericSpecificationsBuilder() {
this.params = new ArrayList<>();
}
public final GenericSpecificationsBuilder<U> with(final String key, final String operation, final Object value, final String prefix, final String suffix) {
return with(null, key, operation, value, prefix, suffix);
}
public final GenericSpecificationsBuilder<U> with(final String precedenceIndicator, final String key, final String operation, final Object value, final String prefix, final String suffix) {
SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0));
if (op != null) {
if (op == SearchOperation.EQUALITY) // the operation may be complex operation
{
final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX);
final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX);
if (startWithAsterisk && endWithAsterisk) {
op = SearchOperation.CONTAINS;
} else if (startWithAsterisk) {
op = SearchOperation.ENDS_WITH;
} else if (endWithAsterisk) {
op = SearchOperation.STARTS_WITH;
}
}
params.add(new SpecSearchCriteria(precedenceIndicator, key, op, value));
}
return this;
}
public Specification<U> build(Function<SpecSearchCriteria, Specification<U>> converter) {
if (params.size() == 0) {
return null;
}
final List<Specification<U>> specs = params.stream()
.map(converter)
.collect(Collectors.toCollection(ArrayList::new));
Specification<U> result = specs.get(0);
for (int idx = 1; idx < specs.size(); idx++) {
result = params.get(idx)
.isOrPredicate()
? Specification.where(result)
.or(specs.get(idx))
: Specification.where(result)
.and(specs.get(idx));
}
return result;
}
public Specification<U> build(Deque<?> postFixedExprStack, Function<SpecSearchCriteria, Specification<U>> converter) {
Deque<Specification<U>> specStack = new LinkedList<>();
Collections.reverse((List<?>) postFixedExprStack);
while (!postFixedExprStack.isEmpty()) {
Object mayBeOperand = postFixedExprStack.pop();
if (!(mayBeOperand instanceof String)) {
specStack.push(converter.apply((SpecSearchCriteria) mayBeOperand));
} else {
Specification<U> operand1 = specStack.pop();
Specification<U> operand2 = specStack.pop();
if (mayBeOperand.equals(SearchOperation.AND_OPERATOR))
specStack.push(Specification.where(operand1)
.and(operand2));
else if (mayBeOperand.equals(SearchOperation.OR_OPERATOR))
specStack.push(Specification.where(operand1)
.or(operand2));
}
}
return specStack.pop();
}
}
@@ -0,0 +1,12 @@
package com.baeldung.persistence.dao;
import java.util.List;
import com.baeldung.persistence.model.User;
import com.baeldung.web.util.SearchCriteria;
public interface IUserDAO {
List<User> searchUser(List<SearchCriteria> params);
void save(User entity);
}
@@ -0,0 +1,57 @@
package com.baeldung.persistence.dao;
import com.baeldung.persistence.model.MyUser;
import com.baeldung.web.util.SearchCriteria;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.NumberPath;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.core.types.dsl.StringPath;
public class MyUserPredicate {
private SearchCriteria criteria;
public MyUserPredicate(final SearchCriteria criteria) {
this.criteria = criteria;
}
public BooleanExpression getPredicate() {
final PathBuilder<MyUser> entityPath = new PathBuilder<>(MyUser.class, "myUser");
if (isNumeric(criteria.getValue().toString())) {
final NumberPath<Integer> path = entityPath.getNumber(criteria.getKey(), Integer.class);
final int value = Integer.parseInt(criteria.getValue().toString());
switch (criteria.getOperation()) {
case ":":
return path.eq(value);
case ">":
return path.goe(value);
case "<":
return path.loe(value);
}
} else {
final StringPath path = entityPath.getString(criteria.getKey());
if (criteria.getOperation().equalsIgnoreCase(":")) {
return path.containsIgnoreCase(criteria.getValue().toString());
}
}
return null;
}
public SearchCriteria getCriteria() {
return criteria;
}
public void setCriteria(final SearchCriteria criteria) {
this.criteria = criteria;
}
public static boolean isNumeric(final String str) {
try {
Integer.parseInt(str);
} catch (final NumberFormatException e) {
return false;
}
return true;
}
}
@@ -0,0 +1,58 @@
package com.baeldung.persistence.dao;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import com.baeldung.web.util.SearchCriteria;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
public final class MyUserPredicatesBuilder {
private final List<SearchCriteria> params;
public MyUserPredicatesBuilder() {
params = new ArrayList<>();
}
public MyUserPredicatesBuilder with(final String key, final String operation, final Object value) {
params.add(new SearchCriteria(key, operation, value));
return this;
}
public BooleanExpression build() {
if (params.size() == 0) {
return null;
}
final List<BooleanExpression> predicates = params.stream().map(param -> {
MyUserPredicate predicate = new MyUserPredicate(param);
return predicate.getPredicate();
}).filter(Objects::nonNull).collect(Collectors.toList());
BooleanExpression result = Expressions.asBoolean(true).isTrue();
for (BooleanExpression predicate : predicates) {
result = result.and(predicate);
}
return result;
}
static class BooleanExpressionWrapper {
private BooleanExpression result;
public BooleanExpressionWrapper(final BooleanExpression result) {
super();
this.result = result;
}
public BooleanExpression getResult() {
return result;
}
public void setResult(BooleanExpression result) {
this.result = result;
}
}
}
@@ -0,0 +1,22 @@
package com.baeldung.persistence.dao;
import com.baeldung.persistence.model.QMyUser;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.querydsl.QuerydslPredicateExecutor;
import org.springframework.data.querydsl.binding.QuerydslBinderCustomizer;
import org.springframework.data.querydsl.binding.QuerydslBindings;
import org.springframework.data.querydsl.binding.SingleValueBinding;
import com.baeldung.persistence.model.MyUser;
import com.querydsl.core.types.dsl.StringExpression;
import com.querydsl.core.types.dsl.StringPath;
public interface MyUserRepository extends JpaRepository<MyUser, Long>, QuerydslPredicateExecutor<MyUser>, QuerydslBinderCustomizer<QMyUser> {
@Override
default public void customize(final QuerydslBindings bindings, final QMyUser root) {
bindings.bind(String.class)
.first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
bindings.excluding(root.email);
}
}
@@ -0,0 +1,43 @@
package com.baeldung.persistence.dao;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.stereotype.Repository;
import com.baeldung.persistence.model.User;
import com.baeldung.web.util.SearchCriteria;
@Repository
public class UserDAO implements IUserDAO {
@PersistenceContext
private EntityManager entityManager;
@Override
public List<User> searchUser(final List<SearchCriteria> params) {
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<User> query = builder.createQuery(User.class);
final Root r = query.from(User.class);
Predicate predicate = builder.conjunction();
UserSearchQueryCriteriaConsumer searchConsumer = new UserSearchQueryCriteriaConsumer(predicate, builder, r);
params.stream().forEach(searchConsumer);
predicate = searchConsumer.getPredicate();
query.where(predicate);
return entityManager.createQuery(query).getResultList();
}
@Override
public void save(final User entity) {
entityManager.persist(entity);
}
}
@@ -0,0 +1,10 @@
package com.baeldung.persistence.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import com.baeldung.persistence.model.User;
public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}
@@ -0,0 +1,43 @@
package com.baeldung.persistence.dao;
import java.util.function.Consumer;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import com.baeldung.web.util.SearchCriteria;
public class UserSearchQueryCriteriaConsumer implements Consumer<SearchCriteria>{
private Predicate predicate;
private CriteriaBuilder builder;
private Root r;
public UserSearchQueryCriteriaConsumer(Predicate predicate, CriteriaBuilder builder, Root r) {
super();
this.predicate = predicate;
this.builder = builder;
this.r= r;
}
@Override
public void accept(SearchCriteria param) {
if (param.getOperation().equalsIgnoreCase(">")) {
predicate = builder.and(predicate, builder.greaterThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
} else if (param.getOperation().equalsIgnoreCase("<")) {
predicate = builder.and(predicate, builder.lessThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
} else if (param.getOperation().equalsIgnoreCase(":")) {
if (r.get(param.getKey()).getJavaType() == String.class) {
predicate = builder.and(predicate, builder.like(r.get(param.getKey()), "%" + param.getValue() + "%"));
} else {
predicate = builder.and(predicate, builder.equal(r.get(param.getKey()), param.getValue()));
}
}
}
public Predicate getPredicate() {
return predicate;
}
}
@@ -0,0 +1,50 @@
package com.baeldung.persistence.dao;
import org.springframework.data.jpa.domain.Specification;
import com.baeldung.persistence.model.User;
import com.baeldung.web.util.SpecSearchCriteria;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
public class UserSpecification implements Specification<User> {
private SpecSearchCriteria criteria;
public UserSpecification(final SpecSearchCriteria criteria) {
super();
this.criteria = criteria;
}
public SpecSearchCriteria getCriteria() {
return criteria;
}
@Override
public Predicate toPredicate(final Root<User> root, final CriteriaQuery<?> query, final CriteriaBuilder builder) {
switch (criteria.getOperation()) {
case EQUALITY:
return builder.equal(root.get(criteria.getKey()), criteria.getValue());
case NEGATION:
return builder.notEqual(root.get(criteria.getKey()), criteria.getValue());
case GREATER_THAN:
return builder.greaterThan(root.get(criteria.getKey()), criteria.getValue().toString());
case LESS_THAN:
return builder.lessThan(root.get(criteria.getKey()), criteria.getValue().toString());
case LIKE:
return builder.like(root.get(criteria.getKey()), criteria.getValue().toString());
case STARTS_WITH:
return builder.like(root.get(criteria.getKey()), criteria.getValue() + "%");
case ENDS_WITH:
return builder.like(root.get(criteria.getKey()), "%" + criteria.getValue());
case CONTAINS:
return builder.like(root.get(criteria.getKey()), "%" + criteria.getValue() + "%");
default:
return null;
}
}
}
@@ -0,0 +1,70 @@
package com.baeldung.persistence.dao;
import java.util.ArrayList;
import java.util.List;
import org.springframework.data.jpa.domain.Specification;
import com.baeldung.persistence.model.User;
import com.baeldung.web.util.SearchOperation;
import com.baeldung.web.util.SpecSearchCriteria;
public final class UserSpecificationsBuilder {
private final List<SpecSearchCriteria> params;
public UserSpecificationsBuilder() {
params = new ArrayList<>();
}
// API
public final UserSpecificationsBuilder with(final String key, final String operation, final Object value, final String prefix, final String suffix) {
return with(null, key, operation, value, prefix, suffix);
}
public final UserSpecificationsBuilder with(final String orPredicate, final String key, final String operation, final Object value, final String prefix, final String suffix) {
SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0));
if (op != null) {
if (op == SearchOperation.EQUALITY) { // the operation may be complex operation
final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX);
final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX);
if (startWithAsterisk && endWithAsterisk) {
op = SearchOperation.CONTAINS;
} else if (startWithAsterisk) {
op = SearchOperation.ENDS_WITH;
} else if (endWithAsterisk) {
op = SearchOperation.STARTS_WITH;
}
}
params.add(new SpecSearchCriteria(orPredicate, key, op, value));
}
return this;
}
public Specification<User> build() {
if (params.size() == 0)
return null;
Specification<User> result = new UserSpecification(params.get(0));
for (int i = 1; i < params.size(); i++) {
result = params.get(i).isOrPredicate()
? Specification.where(result).or(new UserSpecification(params.get(i)))
: Specification.where(result).and(new UserSpecification(params.get(i)));
}
return result;
}
public final UserSpecificationsBuilder with(UserSpecification spec) {
params.add(spec.getCriteria());
return this;
}
public final UserSpecificationsBuilder with(SpecSearchCriteria criteria) {
params.add(criteria);
return this;
}
}
@@ -0,0 +1,33 @@
package com.baeldung.persistence.dao.rsql;
import org.springframework.data.jpa.domain.Specification;
import cz.jirutka.rsql.parser.ast.AndNode;
import cz.jirutka.rsql.parser.ast.ComparisonNode;
import cz.jirutka.rsql.parser.ast.OrNode;
import cz.jirutka.rsql.parser.ast.RSQLVisitor;
public class CustomRsqlVisitor<T> implements RSQLVisitor<Specification<T>, Void> {
private GenericRsqlSpecBuilder<T> builder;
public CustomRsqlVisitor() {
builder = new GenericRsqlSpecBuilder<T>();
}
@Override
public Specification<T> visit(final AndNode node, final Void param) {
return builder.createSpecification(node);
}
@Override
public Specification<T> visit(final OrNode node, final Void param) {
return builder.createSpecification(node);
}
@Override
public Specification<T> visit(final ComparisonNode node, final Void params) {
return builder.createSpecification(node);
}
}
@@ -0,0 +1,53 @@
package com.baeldung.persistence.dao.rsql;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.data.jpa.domain.Specification;
import cz.jirutka.rsql.parser.ast.ComparisonNode;
import cz.jirutka.rsql.parser.ast.LogicalNode;
import cz.jirutka.rsql.parser.ast.LogicalOperator;
import cz.jirutka.rsql.parser.ast.Node;
public class GenericRsqlSpecBuilder<T> {
public Specification<T> createSpecification(final Node node) {
if (node instanceof LogicalNode) {
return createSpecification((LogicalNode) node);
}
if (node instanceof ComparisonNode) {
return createSpecification((ComparisonNode) node);
}
return null;
}
public Specification<T> createSpecification(final LogicalNode logicalNode) {
List<Specification<T>> specs = logicalNode.getChildren()
.stream()
.map(node -> createSpecification(node))
.filter(Objects::nonNull)
.collect(Collectors.toList());
Specification<T> result = specs.get(0);
if (logicalNode.getOperator() == LogicalOperator.AND) {
for (int i = 1; i < specs.size(); i++) {
result = Specification.where(result).and(specs.get(i));
}
}
else if (logicalNode.getOperator() == LogicalOperator.OR) {
for (int i = 1; i < specs.size(); i++) {
result = Specification.where(result).or(specs.get(i));
}
}
return result;
}
public Specification<T> createSpecification(final ComparisonNode comparisonNode) {
return Specification.where(new GenericRsqlSpecification<T>(comparisonNode.getSelector(), comparisonNode.getOperator(), comparisonNode.getArguments()));
}
}
@@ -0,0 +1,92 @@
package com.baeldung.persistence.dao.rsql;
import java.util.List;
import java.util.stream.Collectors;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import org.springframework.data.jpa.domain.Specification;
import cz.jirutka.rsql.parser.ast.ComparisonOperator;
public class GenericRsqlSpecification<T> implements Specification<T> {
private String property;
private ComparisonOperator operator;
private List<String> arguments;
public GenericRsqlSpecification(final String property, final ComparisonOperator operator, final List<String> arguments) {
super();
this.property = property;
this.operator = operator;
this.arguments = arguments;
}
@Override
public Predicate toPredicate(final Root<T> root, final CriteriaQuery<?> query, final CriteriaBuilder builder) {
final List<Object> args = castArguments(root);
final Object argument = args.get(0);
switch (RsqlSearchOperation.getSimpleOperator(operator)) {
case EQUAL: {
if (argument instanceof String) {
return builder.like(root.get(property), argument.toString().replace('*', '%'));
} else if (argument == null) {
return builder.isNull(root.get(property));
} else {
return builder.equal(root.get(property), argument);
}
}
case NOT_EQUAL: {
if (argument instanceof String) {
return builder.notLike(root.<String> get(property), argument.toString().replace('*', '%'));
} else if (argument == null) {
return builder.isNotNull(root.get(property));
} else {
return builder.notEqual(root.get(property), argument);
}
}
case GREATER_THAN: {
return builder.greaterThan(root.<String> get(property), argument.toString());
}
case GREATER_THAN_OR_EQUAL: {
return builder.greaterThanOrEqualTo(root.<String> get(property), argument.toString());
}
case LESS_THAN: {
return builder.lessThan(root.<String> get(property), argument.toString());
}
case LESS_THAN_OR_EQUAL: {
return builder.lessThanOrEqualTo(root.<String> get(property), argument.toString());
}
case IN:
return root.get(property).in(args);
case NOT_IN:
return builder.not(root.get(property).in(args));
}
return null;
}
// === private
private List<Object> castArguments(final Root<T> root) {
final Class<? extends Object> type = root.get(property).getJavaType();
final List<Object> args = arguments.stream().map(arg -> {
if (type.equals(Integer.class)) {
return Integer.parseInt(arg);
} else if (type.equals(Long.class)) {
return Long.parseLong(arg);
} else {
return arg;
}
}).collect(Collectors.toList());
return args;
}
}
@@ -0,0 +1,27 @@
package com.baeldung.persistence.dao.rsql;
import cz.jirutka.rsql.parser.ast.ComparisonOperator;
import cz.jirutka.rsql.parser.ast.RSQLOperators;
import java.util.Arrays;
public enum RsqlSearchOperation {
EQUAL(RSQLOperators.EQUAL), NOT_EQUAL(RSQLOperators.NOT_EQUAL), GREATER_THAN(RSQLOperators.GREATER_THAN), GREATER_THAN_OR_EQUAL(RSQLOperators.GREATER_THAN_OR_EQUAL), LESS_THAN(RSQLOperators.LESS_THAN), LESS_THAN_OR_EQUAL(
RSQLOperators.LESS_THAN_OR_EQUAL), IN(RSQLOperators.IN), NOT_IN(RSQLOperators.NOT_IN);
private ComparisonOperator operator;
RsqlSearchOperation(final ComparisonOperator operator) {
this.operator = operator;
}
public static RsqlSearchOperation getSimpleOperator(final ComparisonOperator operator) {
return Arrays.stream(values())
.filter(operation -> operation.getOperator() == operator)
.findAny().orElse(null);
}
public ComparisonOperator getOperator() {
return operator;
}
}
@@ -0,0 +1,107 @@
package com.baeldung.persistence.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
// used for Querydsl test
@Entity
public class MyUser {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String email;
private int age;
public MyUser() {
super();
}
public MyUser(final String firstName, final String lastName, final String email, final int age) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.age = age;
}
//
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(final String username) {
email = username;
}
public int getAge() {
return age;
}
public void setAge(final int age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((email == null) ? 0 : email.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final MyUser user = (MyUser) obj;
if (!email.equals(user.email))
return false;
return true;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("MyUser [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[username").append(email).append("]");
return builder.toString();
}
}
@@ -0,0 +1,94 @@
package com.baeldung.persistence.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String firstName;
private String lastName;
private String email;
private int age;
public User() {
super();
}
public Long getId() {
return id;
}
public void setId(final Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(final String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(final String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(final String username) {
email = username;
}
public int getAge() {
return age;
}
public void setAge(final int age) {
this.age = age;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((email == null) ? 0 : email.hashCode());
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final User user = (User) obj;
return email.equals(user.email);
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("User [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[username").append(email).append("]");
return builder.toString();
}
}
@@ -0,0 +1,13 @@
package com.baeldung.persistence.model;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.StaticMetamodel;
@StaticMetamodel(User.class)
public class User_ {
public static volatile SingularAttribute<User, Long> id;
public static volatile SingularAttribute<User, String> firstName;
public static volatile SingularAttribute<User, String> lastName;
public static volatile SingularAttribute<User, Integer> age;
public static volatile SingularAttribute<User, String> email;
}
@@ -0,0 +1,40 @@
package com.baeldung.spring;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.web.context.request.RequestContextListener;
/**
* Main Application Class - uses Spring Boot. Just run this as a normal Java
* class to run up a Jetty Server (on http://localhost:8082/spring-rest-query-language)
*
*/
@EnableScheduling
@EnableAutoConfiguration
@ComponentScan("com.baeldung")
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(Application.class);
}
@Override
public void onStartup(ServletContext sc) throws ServletException {
// Manages the lifecycle of the root application context
sc.addListener(new RequestContextListener());
}
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
}
@@ -0,0 +1,85 @@
package com.baeldung.spring;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.google.common.base.Preconditions;
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-${envTarget:h2}.properties" })
@ComponentScan({ "com.baeldung.persistence" })
// @ImportResource("classpath*:springDataPersistenceConfig.xml")
@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
public class PersistenceConfig {
@Autowired
private Environment env;
public PersistenceConfig() {
super();
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com.baeldung.persistence.model" });
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
// vendorAdapter.set
em.setJpaVendorAdapter(vendorAdapter);
em.setJpaProperties(additionalProperties());
return em;
}
@Bean
public DataSource dataSource() {
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(Preconditions.checkNotNull(env.getProperty("jdbc.driverClassName")));
dataSource.setUrl(Preconditions.checkNotNull(env.getProperty("jdbc.url")));
dataSource.setUsername(Preconditions.checkNotNull(env.getProperty("jdbc.user")));
dataSource.setPassword(Preconditions.checkNotNull(env.getProperty("jdbc.pass")));
return dataSource;
}
@Bean
public PlatformTransactionManager transactionManager() {
final JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
final Properties additionalProperties() {
final Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
// hibernateProperties.setProperty("hibernate.globally_quoted_identifiers", "true");
return hibernateProperties;
}
}
@@ -0,0 +1,31 @@
package com.baeldung.spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@ComponentScan("com.baeldung.web")
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
final InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
// API
@Override
public void addViewControllers(final ViewControllerRegistry registry) {
registry.addViewController("/homepage.html");
}
}
@@ -0,0 +1,14 @@
package com.baeldung.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping(value = "/")
public class HomeController {
public String index() {
return "homepage";
}
}
@@ -0,0 +1,171 @@
package com.baeldung.web.controller;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.querydsl.binding.QuerydslPredicate;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import com.baeldung.persistence.dao.GenericSpecificationsBuilder;
import com.baeldung.persistence.dao.IUserDAO;
import com.baeldung.persistence.dao.MyUserPredicatesBuilder;
import com.baeldung.persistence.dao.MyUserRepository;
import com.baeldung.persistence.dao.UserRepository;
import com.baeldung.persistence.dao.UserSpecification;
import com.baeldung.persistence.dao.UserSpecificationsBuilder;
import com.baeldung.persistence.dao.rsql.CustomRsqlVisitor;
import com.baeldung.persistence.model.MyUser;
import com.baeldung.persistence.model.User;
import com.baeldung.web.util.CriteriaParser;
import com.baeldung.web.util.SearchCriteria;
import com.baeldung.web.util.SearchOperation;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import cz.jirutka.rsql.parser.RSQLParser;
import cz.jirutka.rsql.parser.ast.Node;
//@EnableSpringDataWebSupport
@Controller
@RequestMapping(value = "/auth/")
public class UserController {
@Autowired
private IUserDAO service;
@Autowired
private UserRepository dao;
@Autowired
private MyUserRepository myUserRepository;
public UserController() {
super();
}
// API - READ
@RequestMapping(method = RequestMethod.GET, value = "/users")
@ResponseBody
public List<User> search(@RequestParam(value = "search", required = false) String search) {
List<SearchCriteria> params = new ArrayList<SearchCriteria>();
if (search != null) {
Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
params.add(new SearchCriteria(matcher.group(1), matcher.group(2), matcher.group(3)));
}
}
return service.searchUser(params);
}
@RequestMapping(method = RequestMethod.GET, value = "/users/spec")
@ResponseBody
public List<User> findAllBySpecification(@RequestParam(value = "search") String search) {
UserSpecificationsBuilder builder = new UserSpecificationsBuilder();
String operationSetExper = Joiner.on("|")
.join(SearchOperation.SIMPLE_OPERATION_SET);
Pattern pattern = Pattern.compile("(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2), matcher.group(4), matcher.group(3), matcher.group(5));
}
Specification<User> spec = builder.build();
return dao.findAll(spec);
}
@GetMapping(value = "/users/espec")
@ResponseBody
public List<User> findAllByOrPredicate(@RequestParam(value = "search") String search) {
Specification<User> spec = resolveSpecification(search);
return dao.findAll(spec);
}
@GetMapping(value = "/users/spec/adv")
@ResponseBody
public List<User> findAllByAdvPredicate(@RequestParam(value = "search") String search) {
Specification<User> spec = resolveSpecificationFromInfixExpr(search);
return dao.findAll(spec);
}
protected Specification<User> resolveSpecificationFromInfixExpr(String searchParameters) {
CriteriaParser parser = new CriteriaParser();
GenericSpecificationsBuilder<User> specBuilder = new GenericSpecificationsBuilder<>();
return specBuilder.build(parser.parse(searchParameters), UserSpecification::new);
}
protected Specification<User> resolveSpecification(String searchParameters) {
UserSpecificationsBuilder builder = new UserSpecificationsBuilder();
String operationSetExper = Joiner.on("|")
.join(SearchOperation.SIMPLE_OPERATION_SET);
Pattern pattern = Pattern.compile("(\\p{Punct}?)(\\w+?)(" + operationSetExper + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?),");
Matcher matcher = pattern.matcher(searchParameters + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(5), matcher.group(4), matcher.group(6));
}
return builder.build();
}
@RequestMapping(method = RequestMethod.GET, value = "/myusers")
@ResponseBody
public Iterable<MyUser> findAllByQuerydsl(@RequestParam(value = "search") String search) {
MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder();
if (search != null) {
Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),");
Matcher matcher = pattern.matcher(search + ",");
while (matcher.find()) {
builder.with(matcher.group(1), matcher.group(2), matcher.group(3));
}
}
BooleanExpression exp = builder.build();
return myUserRepository.findAll(exp);
}
@RequestMapping(method = RequestMethod.GET, value = "/users/rsql")
@ResponseBody
public List<User> findAllByRsql(@RequestParam(value = "search") String search) {
Node rootNode = new RSQLParser().parse(search);
Specification<User> spec = rootNode.accept(new CustomRsqlVisitor<User>());
return dao.findAll(spec);
}
@RequestMapping(method = RequestMethod.GET, value = "/api/myusers")
@ResponseBody
public Iterable<MyUser> findAllByWebQuerydsl(@QuerydslPredicate(root = MyUser.class) Predicate predicate) {
return myUserRepository.findAll(predicate);
}
// API - WRITE
@RequestMapping(method = RequestMethod.POST, value = "/users")
@ResponseStatus(HttpStatus.CREATED)
public void create(@RequestBody User resource) {
Preconditions.checkNotNull(resource);
dao.save(resource);
}
@RequestMapping(method = RequestMethod.POST, value = "/myusers")
@ResponseStatus(HttpStatus.CREATED)
public void addMyUser(@RequestBody MyUser resource) {
Preconditions.checkNotNull(resource);
myUserRepository.save(resource);
}
}
@@ -0,0 +1,85 @@
package com.baeldung.web.error;
import javax.persistence.EntityNotFoundException;
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
import com.baeldung.web.exception.MyResourceNotFoundException;
@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
public RestResponseEntityExceptionHandler() {
super();
}
// API
// 400
@ExceptionHandler({ ConstraintViolationException.class })
public ResponseEntity<Object> handleBadRequest(final ConstraintViolationException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
@ExceptionHandler({ DataIntegrityViolationException.class })
public ResponseEntity<Object> handleBadRequest(final DataIntegrityViolationException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request);
}
@Override
protected ResponseEntity<Object> handleHttpMessageNotReadable(final HttpMessageNotReadableException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
// ex.getCause() instanceof JsonMappingException, JsonParseException // for additional information later on
return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
}
@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(final MethodArgumentNotValidException ex, final HttpHeaders headers, final HttpStatus status, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, headers, HttpStatus.BAD_REQUEST, request);
}
// 404
@ExceptionHandler(value = { EntityNotFoundException.class, MyResourceNotFoundException.class })
protected ResponseEntity<Object> handleNotFound(final RuntimeException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
// 409
@ExceptionHandler({ InvalidDataAccessApiUsageException.class, DataAccessException.class })
protected ResponseEntity<Object> handleConflict(final RuntimeException ex, final WebRequest request) {
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.CONFLICT, request);
}
// 412
// 500
@ExceptionHandler({ NullPointerException.class, IllegalArgumentException.class, IllegalStateException.class })
/*500*/public ResponseEntity<Object> handleInternal(final RuntimeException ex, final WebRequest request) {
logger.error("500 Status Code", ex);
final String bodyOfResponse = "This should be application specific";
return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR, request);
}
}
@@ -0,0 +1,21 @@
package com.baeldung.web.exception;
public final class MyResourceNotFoundException extends RuntimeException {
public MyResourceNotFoundException() {
super();
}
public MyResourceNotFoundException(final String message, final Throwable cause) {
super(message, cause);
}
public MyResourceNotFoundException(final String message) {
super(message);
}
public MyResourceNotFoundException(final Throwable cause) {
super(cause);
}
}
@@ -0,0 +1,77 @@
package com.baeldung.web.util;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Joiner;
public class CriteriaParser {
private static Map<String, Operator> ops;
private static Pattern SpecCriteraRegex = Pattern.compile("^(\\w+?)(" + Joiner.on("|")
.join(SearchOperation.SIMPLE_OPERATION_SET) + ")(\\p{Punct}?)(\\w+?)(\\p{Punct}?)$");
private enum Operator {
OR(1), AND(2);
final int precedence;
Operator(int p) {
precedence = p;
}
}
static {
Map<String, Operator> tempMap = new HashMap<>();
tempMap.put("AND", Operator.AND);
tempMap.put("OR", Operator.OR);
tempMap.put("or", Operator.OR);
tempMap.put("and", Operator.AND);
ops = Collections.unmodifiableMap(tempMap);
}
private static boolean isHigerPrecedenceOperator(String currOp, String prevOp) {
return (ops.containsKey(prevOp) && ops.get(prevOp).precedence >= ops.get(currOp).precedence);
}
public Deque<?> parse(String searchParam) {
Deque<Object> output = new LinkedList<>();
Deque<String> stack = new LinkedList<>();
Arrays.stream(searchParam.split("\\s+")).forEach(token -> {
if (ops.containsKey(token)) {
while (!stack.isEmpty() && isHigerPrecedenceOperator(token, stack.peek()))
output.push(stack.pop()
.equalsIgnoreCase(SearchOperation.OR_OPERATOR) ? SearchOperation.OR_OPERATOR : SearchOperation.AND_OPERATOR);
stack.push(token.equalsIgnoreCase(SearchOperation.OR_OPERATOR) ? SearchOperation.OR_OPERATOR : SearchOperation.AND_OPERATOR);
} else if (token.equals(SearchOperation.LEFT_PARANTHESIS)) {
stack.push(SearchOperation.LEFT_PARANTHESIS);
} else if (token.equals(SearchOperation.RIGHT_PARANTHESIS)) {
while (!stack.peek()
.equals(SearchOperation.LEFT_PARANTHESIS))
output.push(stack.pop());
stack.pop();
} else {
Matcher matcher = SpecCriteraRegex.matcher(token);
while (matcher.find()) {
output.push(new SpecSearchCriteria(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4), matcher.group(5)));
}
}
});
while (!stack.isEmpty())
output.push(stack.pop());
return output;
}
}
@@ -0,0 +1,44 @@
package com.baeldung.web.util;
public class SearchCriteria {
private String key;
private String operation;
private Object value;
public SearchCriteria() {
}
public SearchCriteria(final String key, final String operation, final Object value) {
super();
this.key = key;
this.operation = operation;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(final String key) {
this.key = key;
}
public String getOperation() {
return operation;
}
public void setOperation(final String operation) {
this.operation = operation;
}
public Object getValue() {
return value;
}
public void setValue(final Object value) {
this.value = value;
}
}
@@ -0,0 +1,36 @@
package com.baeldung.web.util;
public enum SearchOperation {
EQUALITY, NEGATION, GREATER_THAN, LESS_THAN, LIKE, STARTS_WITH, ENDS_WITH, CONTAINS;
public static final String[] SIMPLE_OPERATION_SET = { ":", "!", ">", "<", "~" };
public static final String OR_PREDICATE_FLAG = "'";
public static final String ZERO_OR_MORE_REGEX = "*";
public static final String OR_OPERATOR = "OR";
public static final String AND_OPERATOR = "AND";
public static final String LEFT_PARANTHESIS = "(";
public static final String RIGHT_PARANTHESIS = ")";
public static SearchOperation getSimpleOperation(final char input) {
switch (input) {
case ':':
return EQUALITY;
case '!':
return NEGATION;
case '>':
return GREATER_THAN;
case '<':
return LESS_THAN;
case '~':
return LIKE;
default:
return null;
}
}
}
@@ -0,0 +1,82 @@
package com.baeldung.web.util;
public class SpecSearchCriteria {
private String key;
private SearchOperation operation;
private Object value;
private boolean orPredicate;
public SpecSearchCriteria() {
}
public SpecSearchCriteria(final String key, final SearchOperation operation, final Object value) {
super();
this.key = key;
this.operation = operation;
this.value = value;
}
public SpecSearchCriteria(final String orPredicate, final String key, final SearchOperation operation, final Object value) {
super();
this.orPredicate = orPredicate != null && orPredicate.equals(SearchOperation.OR_PREDICATE_FLAG);
this.key = key;
this.operation = operation;
this.value = value;
}
public SpecSearchCriteria(String key, String operation, String prefix, String value, String suffix) {
SearchOperation op = SearchOperation.getSimpleOperation(operation.charAt(0));
if (op != null) {
if (op == SearchOperation.EQUALITY) { // the operation may be complex operation
final boolean startWithAsterisk = prefix != null && prefix.contains(SearchOperation.ZERO_OR_MORE_REGEX);
final boolean endWithAsterisk = suffix != null && suffix.contains(SearchOperation.ZERO_OR_MORE_REGEX);
if (startWithAsterisk && endWithAsterisk) {
op = SearchOperation.CONTAINS;
} else if (startWithAsterisk) {
op = SearchOperation.ENDS_WITH;
} else if (endWithAsterisk) {
op = SearchOperation.STARTS_WITH;
}
}
}
this.key = key;
this.operation = op;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(final String key) {
this.key = key;
}
public SearchOperation getOperation() {
return operation;
}
public void setOperation(final SearchOperation operation) {
this.operation = operation;
}
public Object getValue() {
return value;
}
public void setValue(final Object value) {
this.value = value;
}
public boolean isOrPredicate() {
return orPredicate;
}
public void setOrPredicate(boolean orPredicate) {
this.orPredicate = orPredicate;
}
}
@@ -0,0 +1,2 @@
server.port=8082
server.servlet.context-path=/spring-rest-query-language
@@ -0,0 +1,5 @@
insert into User (id, firstName, lastName, email, age) values (1, 'john', 'doe', 'john@doe.com', 22);
insert into User (id, firstName, lastName, email, age) values (2, 'tom', 'doe', 'tom@doe.com', 26);
insert into MyUser (id, firstName, lastName, email, age) values (1, 'john', 'doe', 'john@doe.com', 22);
insert into MyUser (id, firstName, lastName, email, age) values (2, 'tom', 'doe', 'tom@doe.com', 26);
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,22 @@
## jdbc.X
#jdbc.driverClassName=com.mysql.jdbc.Driver
#jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate4_01?createDatabaseIfNotExist=true
#jdbc.user=tutorialuser
#jdbc.pass=tutorialmy5ql
#
## hibernate.X
#hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
#hibernate.show_sql=false
#hibernate.hbm2ddl.auto=create-drop
# jdbc.X
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:security_permission;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
jdbc.user=sa
jdbc.pass=
# hibernate.X
hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
@@ -0,0 +1,10 @@
# jdbc.X
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_hibernate4_01?createDatabaseIfNotExist=true
jdbc.user=tutorialuser
jdbc.pass=tutorialmy5ql
# hibernate.X
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql=false
hibernate.hbm2ddl.auto=create-drop
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
>
<jpa:repositories base-package="com.baeldung.persistence.dao"/>
</beans>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd" >
</beans>
@@ -0,0 +1,7 @@
<html>
<head></head>
<body>
<h1>This is the body of the sample view</h1>
</body>
</html>
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"
>
<display-name>Spring REST Query language Application</display-name>
<!-- Spring root -->
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>com.baeldung.spring</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Spring child -->
<servlet>
<servlet-name>api</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>api</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
</web-app>
@@ -0,0 +1,21 @@
package com.baeldung;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.spring.Application;
/**
* Note: In the IDE, remember to generate query type classes before running the Integration Test (e.g. in Eclipse right-click on the project > Run As > Maven generate sources)
*
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class SpringContextTest {
@Test
public void whenSpringContextIsBootstrapped_thenNoExceptions() {
}
}
@@ -0,0 +1,109 @@
package com.baeldung.persistence.query;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsIn.isIn;
import static org.hamcrest.core.IsNot.not;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.baeldung.persistence.dao.IUserDAO;
import com.baeldung.persistence.model.User;
import com.baeldung.spring.PersistenceConfig;
import com.baeldung.web.util.SearchCriteria;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { PersistenceConfig.class })
@Transactional
@Rollback
public class JPACriteriaQueryIntegrationTest {
@Autowired
private IUserDAO userApi;
private User userJohn;
private User userTom;
@Before
public void init() {
userJohn = new User();
userJohn.setFirstName("john");
userJohn.setLastName("doe");
userJohn.setEmail("john@doe.com");
userJohn.setAge(22);
userApi.save(userJohn);
userTom = new User();
userTom.setFirstName("tom");
userTom.setLastName("doe");
userTom.setEmail("tom@doe.com");
userTom.setAge(26);
userApi.save(userTom);
}
@Test
public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() {
final List<SearchCriteria> params = new ArrayList<SearchCriteria>();
params.add(new SearchCriteria("firstName", ":", "john"));
params.add(new SearchCriteria("lastName", ":", "doe"));
final List<User> results = userApi.searchUser(params);
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenLast_whenGettingListOfUsers_thenCorrect() {
final List<SearchCriteria> params = new ArrayList<SearchCriteria>();
params.add(new SearchCriteria("lastName", ":", "doe"));
final List<User> results = userApi.searchUser(params);
assertThat(userJohn, isIn(results));
assertThat(userTom, isIn(results));
}
@Test
public void givenLastAndAge_whenGettingListOfUsers_thenCorrect() {
final List<SearchCriteria> params = new ArrayList<SearchCriteria>();
params.add(new SearchCriteria("lastName", ":", "doe"));
params.add(new SearchCriteria("age", ">", "25"));
final List<User> results = userApi.searchUser(params);
assertThat(userTom, isIn(results));
assertThat(userJohn, not(isIn(results)));
}
@Test
public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect() {
final List<SearchCriteria> params = new ArrayList<SearchCriteria>();
params.add(new SearchCriteria("firstName", ":", "adam"));
params.add(new SearchCriteria("lastName", ":", "fox"));
final List<User> results = userApi.searchUser(params);
assertThat(userJohn, not(isIn(results)));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenPartialFirst_whenGettingListOfUsers_thenCorrect() {
final List<SearchCriteria> params = new ArrayList<SearchCriteria>();
params.add(new SearchCriteria("firstName", ":", "jo"));
final List<User> results = userApi.searchUser(params);
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
}
@@ -0,0 +1,98 @@
package com.baeldung.persistence.query;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsEmptyIterable.emptyIterable;
import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
import static org.hamcrest.core.IsNot.not;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.baeldung.persistence.dao.MyUserPredicatesBuilder;
import com.baeldung.persistence.dao.MyUserRepository;
import com.baeldung.persistence.model.MyUser;
import com.baeldung.spring.PersistenceConfig;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { PersistenceConfig.class })
@Transactional
@Rollback
public class JPAQuerydslIntegrationTest {
@Autowired
private MyUserRepository repo;
private MyUser userJohn;
private MyUser userTom;
@Before
public void init() {
userJohn = new MyUser();
userJohn.setFirstName("john");
userJohn.setLastName("doe");
userJohn.setEmail("john@doe.com");
userJohn.setAge(22);
repo.save(userJohn);
userTom = new MyUser();
userTom.setFirstName("tom");
userTom.setLastName("doe");
userTom.setEmail("tom@doe.com");
userTom.setAge(26);
repo.save(userTom);
}
@Test
public void givenLast_whenGettingListOfUsers_thenCorrect() {
final MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder().with("lastName", ":", "doe");
final Iterable<MyUser> results = repo.findAll(builder.build());
assertThat(results, containsInAnyOrder(userJohn, userTom));
}
@Test
public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() {
final MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder().with("firstName", ":", "john").with("lastName", ":", "doe");
final Iterable<MyUser> results = repo.findAll(builder.build());
assertThat(results, contains(userJohn));
assertThat(results, not(contains(userTom)));
}
@Test
public void givenLastAndAge_whenGettingListOfUsers_thenCorrect() {
final MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder().with("lastName", ":", "doe").with("age", ">", "25");
final Iterable<MyUser> results = repo.findAll(builder.build());
assertThat(results, contains(userTom));
assertThat(results, not(contains(userJohn)));
}
@Test
public void givenWrongFirstAndLast_whenGettingListOfUsers_thenCorrect() {
final MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder().with("firstName", ":", "adam").with("lastName", ":", "fox");
final Iterable<MyUser> results = repo.findAll(builder.build());
assertThat(results, emptyIterable());
}
@Test
public void givenPartialFirst_whenGettingListOfUsers_thenCorrect() {
final MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder().with("firstName", ":", "jo");
final Iterable<MyUser> results = repo.findAll(builder.build());
assertThat(results, contains(userJohn));
assertThat(results, not(contains(userTom)));
}
}
@@ -0,0 +1,180 @@
package com.baeldung.persistence.query;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.baeldung.persistence.dao.GenericSpecificationsBuilder;
import com.baeldung.persistence.dao.UserRepository;
import com.baeldung.persistence.dao.UserSpecification;
import com.baeldung.persistence.dao.UserSpecificationsBuilder;
import com.baeldung.persistence.model.User;
import com.baeldung.spring.PersistenceConfig;
import com.baeldung.web.util.CriteriaParser;
import com.baeldung.web.util.SearchOperation;
import com.baeldung.web.util.SpecSearchCriteria;
import java.util.List;
import java.util.function.Function;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.hamcrest.collection.IsIn.isIn;
import static org.hamcrest.core.IsNot.not;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { PersistenceConfig.class })
@Transactional
@Rollback
public class JPASpecificationIntegrationTest {
@Autowired
private UserRepository repository;
private User userJohn;
private User userTom;
private User userPercy;
@Before
public void init() {
userJohn = new User();
userJohn.setFirstName("john");
userJohn.setLastName("doe");
userJohn.setEmail("john@doe.com");
userJohn.setAge(22);
repository.save(userJohn);
userTom = new User();
userTom.setFirstName("tom");
userTom.setLastName("doe");
userTom.setEmail("tom@doe.com");
userTom.setAge(26);
repository.save(userTom);
userPercy = new User();
userPercy.setFirstName("percy");
userPercy.setLastName("blackney");
userPercy.setEmail("percy@blackney.com");
userPercy.setAge(30);
repository.save(userPercy);
}
@Test
public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() {
final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john"));
final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("lastName", SearchOperation.EQUALITY, "doe"));
final List<User> results = repository.findAll(Specification
.where(spec)
.and(spec1));
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() {
UserSpecificationsBuilder builder = new UserSpecificationsBuilder();
SpecSearchCriteria spec = new SpecSearchCriteria("firstName", SearchOperation.EQUALITY, "john");
SpecSearchCriteria spec1 = new SpecSearchCriteria("'","lastName", SearchOperation.EQUALITY, "doe");
List<User> results = repository.findAll(builder
.with(spec)
.with(spec1)
.build());
assertThat(results, hasSize(2));
assertThat(userJohn, isIn(results));
assertThat(userTom, isIn(results));
}
@Test
public void givenFirstOrLastNameAndAgeGenericBuilder_whenGettingListOfUsers_thenCorrect() {
GenericSpecificationsBuilder<User> builder = new GenericSpecificationsBuilder<>();
Function<SpecSearchCriteria, Specification<User>> converter = UserSpecification::new;
CriteriaParser parser=new CriteriaParser();
List<User> results = repository.findAll(builder.build(parser.parse("( lastName:doe OR firstName:john ) AND age:22"), converter));
assertThat(results, hasSize(1));
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenFirstOrLastNameGenericBuilder_whenGettingListOfUsers_thenCorrect() {
GenericSpecificationsBuilder<User> builder = new GenericSpecificationsBuilder<>();
Function<SpecSearchCriteria, Specification<User>> converter = UserSpecification::new;
builder.with("firstName", ":", "john", null, null);
builder.with("'", "lastName", ":", "doe", null, null);
List<User> results = repository.findAll(builder.build(converter));
assertThat(results, hasSize(2));
assertThat(userJohn, isIn(results));
assertThat(userTom, isIn(results));
}
@Test
public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() {
final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.NEGATION, "john"));
final List<User> results = repository.findAll(Specification.where(spec));
assertThat(userTom, isIn(results));
assertThat(userJohn, not(isIn(results)));
}
@Test
public void givenMinAge_whenGettingListOfUsers_thenCorrect() {
final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "25"));
final List<User> results = repository.findAll(Specification.where(spec));
assertThat(userTom, isIn(results));
assertThat(userJohn, not(isIn(results)));
}
@Test
public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() {
final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.STARTS_WITH, "jo"));
final List<User> results = repository.findAll(spec);
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() {
final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.ENDS_WITH, "n"));
final List<User> results = repository.findAll(spec);
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() {
final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("firstName", SearchOperation.CONTAINS, "oh"));
final List<User> results = repository.findAll(spec);
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenAgeRange_whenGettingListOfUsers_thenCorrect() {
final UserSpecification spec = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.GREATER_THAN, "20"));
final UserSpecification spec1 = new UserSpecification(new SpecSearchCriteria("age", SearchOperation.LESS_THAN, "25"));
final List<User> results = repository.findAll(Specification
.where(spec)
.and(spec1));
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
}
@@ -0,0 +1,147 @@
package com.baeldung.persistence.query;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.junit.Before;
import org.junit.Test;
import org.springframework.test.context.ActiveProfiles;
import com.baeldung.persistence.model.User;
//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = { ConfigTest.class,
// PersistenceConfig.class }, loader = AnnotationConfigContextLoader.class)
@ActiveProfiles("test")
public class JPASpecificationLiveTest {
// @Autowired
// private UserRepository repository;
private User userJohn;
private User userTom;
private final String URL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/spec?search=";
@Before
public void init() {
userJohn = new User();
userJohn.setFirstName("john");
userJohn.setLastName("doe");
userJohn.setEmail("john@doe.com");
userJohn.setAge(22);
// repository.save(userJohn);
userTom = new User();
userTom.setFirstName("tom");
userTom.setLastName("doe");
userTom.setEmail("tom@doe.com");
userTom.setAge(26);
// repository.save(userTom);
}
private final String EURL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/espec?search=";
@Test
public void givenFirstOrLastName_whenGettingListOfUsers_thenCorrect() {
final Response response = RestAssured.get(EURL_PREFIX + "firstName:john,'lastName:doe");
final String result = response.body()
.asString();
assertTrue(result.contains(userJohn.getEmail()));
assertTrue(result.contains(userTom.getEmail()));
}
@Test
public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() {
final Response response = RestAssured.get(URL_PREFIX + "firstName:john,lastName:doe");
final String result = response.body()
.asString();
assertTrue(result.contains(userJohn.getEmail()));
assertFalse(result.contains(userTom.getEmail()));
}
@Test
public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() {
final Response response = RestAssured.get(URL_PREFIX + "firstName!john");
final String result = response.body()
.asString();
assertTrue(result.contains(userTom.getEmail()));
assertFalse(result.contains(userJohn.getEmail()));
}
@Test
public void givenMinAge_whenGettingListOfUsers_thenCorrect() {
final Response response = RestAssured.get(URL_PREFIX + "age>25");
final String result = response.body()
.asString();
assertTrue(result.contains(userTom.getEmail()));
assertFalse(result.contains(userJohn.getEmail()));
}
@Test
public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() {
final Response response = RestAssured.get(URL_PREFIX + "firstName:jo*");
final String result = response.body()
.asString();
assertTrue(result.contains(userJohn.getEmail()));
assertFalse(result.contains(userTom.getEmail()));
}
@Test
public void givenFirstNameSuffix_whenGettingListOfUsers_thenCorrect() {
final Response response = RestAssured.get(URL_PREFIX + "firstName:*n");
final String result = response.body()
.asString();
assertTrue(result.contains(userJohn.getEmail()));
assertFalse(result.contains(userTom.getEmail()));
}
@Test
public void givenFirstNameSubstring_whenGettingListOfUsers_thenCorrect() {
final Response response = RestAssured.get(URL_PREFIX + "firstName:*oh*");
final String result = response.body()
.asString();
assertTrue(result.contains(userJohn.getEmail()));
assertFalse(result.contains(userTom.getEmail()));
}
@Test
public void givenAgeRange_whenGettingListOfUsers_thenCorrect() {
final Response response = RestAssured.get(URL_PREFIX + "age>20,age<25");
final String result = response.body()
.asString();
assertTrue(result.contains(userJohn.getEmail()));
assertFalse(result.contains(userTom.getEmail()));
}
private final String ADV_URL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/users/spec/adv?search=";
@Test
public void givenFirstOrLastName_whenGettingAdvListOfUsers_thenCorrect() {
final Response response = RestAssured.get(ADV_URL_PREFIX + "firstName:john OR lastName:doe");
final String result = response.body()
.asString();
assertTrue(result.contains(userJohn.getEmail()));
assertTrue(result.contains(userTom.getEmail()));
}
@Test
public void givenFirstOrFirstNameAndAge_whenGettingAdvListOfUsers_thenCorrect() {
final Response response = RestAssured.get(ADV_URL_PREFIX + "( firstName:john OR firstName:tom ) AND age>22");
final String result = response.body()
.asString();
assertFalse(result.contains(userJohn.getEmail()));
assertTrue(result.contains(userTom.getEmail()));
}
}
@@ -0,0 +1,106 @@
package com.baeldung.persistence.query;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsIn.isIn;
import static org.hamcrest.core.IsNot.not;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import com.baeldung.persistence.dao.UserRepository;
import com.baeldung.persistence.dao.rsql.CustomRsqlVisitor;
import com.baeldung.persistence.model.User;
import com.baeldung.spring.PersistenceConfig;
import cz.jirutka.rsql.parser.RSQLParser;
import cz.jirutka.rsql.parser.ast.Node;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { PersistenceConfig.class })
@Transactional
@Rollback
public class RsqlIntegrationTest {
@Autowired
private UserRepository repository;
private User userJohn;
private User userTom;
@Before
public void init() {
userJohn = new User();
userJohn.setFirstName("john");
userJohn.setLastName("doe");
userJohn.setEmail("john@doe.com");
userJohn.setAge(22);
repository.save(userJohn);
userTom = new User();
userTom.setFirstName("tom");
userTom.setLastName("doe");
userTom.setEmail("tom@doe.com");
userTom.setAge(26);
repository.save(userTom);
}
@Test
public void givenFirstAndLastName_whenGettingListOfUsers_thenCorrect() {
final Node rootNode = new RSQLParser().parse("firstName==john;lastName==doe");
final Specification<User> spec = rootNode.accept(new CustomRsqlVisitor<User>());
final List<User> results = repository.findAll(spec);
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenFirstNameInverse_whenGettingListOfUsers_thenCorrect() {
final Node rootNode = new RSQLParser().parse("firstName!=john");
final Specification<User> spec = rootNode.accept(new CustomRsqlVisitor<User>());
final List<User> results = repository.findAll(spec);
assertThat(userTom, isIn(results));
assertThat(userJohn, not(isIn(results)));
}
@Test
public void givenMinAge_whenGettingListOfUsers_thenCorrect() {
final Node rootNode = new RSQLParser().parse("age>25");
final Specification<User> spec = rootNode.accept(new CustomRsqlVisitor<User>());
final List<User> results = repository.findAll(spec);
assertThat(userTom, isIn(results));
assertThat(userJohn, not(isIn(results)));
}
@Test
public void givenFirstNamePrefix_whenGettingListOfUsers_thenCorrect() {
final Node rootNode = new RSQLParser().parse("firstName==jo*");
final Specification<User> spec = rootNode.accept(new CustomRsqlVisitor<User>());
final List<User> results = repository.findAll(spec);
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
@Test
public void givenListOfFirstName_whenGettingListOfUsers_thenCorrect() {
final Node rootNode = new RSQLParser().parse("firstName=in=(john,jack)");
final Specification<User> spec = rootNode.accept(new CustomRsqlVisitor<User>());
final List<User> results = repository.findAll(spec);
assertThat(userJohn, isIn(results));
assertThat(userTom, not(isIn(results)));
}
}
@@ -0,0 +1,51 @@
package com.baeldung.web;
import static org.junit.Assert.assertEquals;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import io.restassured.specification.RequestSpecification;
import org.junit.Test;
import org.springframework.test.context.ActiveProfiles;
import com.baeldung.persistence.model.MyUser;
@ActiveProfiles("test")
public class MyUserLiveTest {
private final MyUser userJohn = new MyUser("john", "doe", "john@doe.com", 11);
private String URL_PREFIX = "http://localhost:8082/spring-rest-query-language/auth/api/myusers";
@Test
public void whenGettingListOfUsers_thenCorrect() {
final Response response = givenAuth().get(URL_PREFIX);
final MyUser[] result = response.as(MyUser[].class);
assertEquals(result.length, 2);
}
@Test
public void givenFirstName_whenGettingListOfUsers_thenCorrect() {
final Response response = givenAuth().get(URL_PREFIX + "?firstName=john");
final MyUser[] result = response.as(MyUser[].class);
assertEquals(result.length, 1);
assertEquals(result[0].getEmail(), userJohn.getEmail());
}
@Test
public void givenPartialLastName_whenGettingListOfUsers_thenCorrect() {
final Response response = givenAuth().get(URL_PREFIX + "?lastName=do");
final MyUser[] result = response.as(MyUser[].class);
assertEquals(result.length, 2);
}
@Test
public void givenEmail_whenGettingListOfUsers_thenIgnored() {
final Response response = givenAuth().get(URL_PREFIX + "?email=john");
final MyUser[] result = response.as(MyUser[].class);
assertEquals(result.length, 2);
}
private RequestSpecification givenAuth() {
return RestAssured.given().auth().preemptive().basic("user1", "user1Pass");
}
}

Some files were not shown because too many files have changed in this diff Show More