BAEL-20884 Move Spring Boot Rest to Spring Boot Modules

This commit is contained in:
mikr
2020-01-21 10:43:27 +01:00
parent 1200d8777a
commit 65b8a95943
91 changed files with 28 additions and 3 deletions
+3
View File
@@ -0,0 +1,3 @@
## Core Java Modules
This module contains modules about Sprint Boot
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.spring-boot-modules</groupId>
<artifactId>spring-boot-modules</artifactId>
<name>spring-boot-modules</name>
<packaging>pom</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modules>
<module>spring-boot-rest</module>
</modules>
</project>
@@ -0,0 +1,28 @@
## Spring Boot REST
This module contains articles about Spring Boot RESTful APIs.
### Relevant Articles
- [HATEOAS for a Spring REST Service](https://www.baeldung.com/rest-api-discoverability-with-spring)
- [Versioning a REST API](https://www.baeldung.com/rest-versioning)
- [ETags for REST with Spring](https://www.baeldung.com/etags-for-rest-with-spring)
- [Testing REST with multiple MIME types](https://www.baeldung.com/testing-rest-api-with-multiple-media-types)
- [Testing Web APIs with Postman Collections](https://www.baeldung.com/postman-testing-collections)
- [Spring Boot Consuming and Producing JSON](https://www.baeldung.com/spring-boot-json)
- [Error Handling for REST with Spring](https://www.baeldung.com/exception-handling-for-rest-with-spring)
### E-book
These articles are part of the Spring REST E-book:
1. [Bootstrap a Web Application with Spring 5](https://www.baeldung.com/bootstraping-a-web-application-with-spring-and-java-based-configuration)
2. [Build a REST API with Spring and Java Config](https://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration)
3. [Http Message Converters with the Spring Framework](https://www.baeldung.com/spring-httpmessageconverter-rest)
4. [Spring’s RequestBody and ResponseBody Annotations](https://www.baeldung.com/spring-request-response-body)
5. [Entity To DTO Conversion for a Spring REST API](https://www.baeldung.com/entity-to-and-from-dto-for-a-java-spring-application)
6. [Error Handling for REST with Spring](https://www.baeldung.com/exception-handling-for-rest-with-spring)
7. [REST API Discoverability and HATEOAS](https://www.baeldung.com/restful-web-service-discoverability)
8. [An Intro to Spring HATEOAS](https://www.baeldung.com/spring-hateoas-tutorial)
9. [REST Pagination in Spring](https://www.baeldung.com/rest-api-pagination-in-spring)
10. [Test a REST API with Java](https://www.baeldung.com/integration-testing-a-rest-api)
@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.baeldung.web</groupId>
<artifactId>spring-boot-rest</artifactId>
<name>spring-boot-rest</name>
<packaging>war</packaging>
<description>Spring Boot Rest Module</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-boot-2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../../parent-boot-2</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
<!-- We'll need to comment out the jackson-dataformat-xml dependency if we want to use XStream: -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-oxm</artifactId>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<!-- Spring HATEOAS -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
<!-- util -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>${modelmapper.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<properties>
<start-class>com.baeldung.SpringBootRestApplication</start-class>
<guava.version>27.0.1-jre</guava.version>
<xstream.version>1.4.11.1</xstream.version>
<modelmapper.version>2.3.5</modelmapper.version>
</properties>
</project>
@@ -0,0 +1,20 @@
package com.baeldung;
import org.modelmapper.ModelMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
public class SpringBootRestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootRestApplication.class, args);
}
@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
}
@@ -0,0 +1,29 @@
package com.baeldung.persistence;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.domain.Page;
public interface IOperations<T extends Serializable> {
// read - one
T findById(final long id);
// read - all
List<T> findAll();
Page<T> findPaginated(int page, int size);
// write
T create(final T entity);
T update(final T entity);
void delete(final T entity);
void deleteById(final long entityId);
}
@@ -0,0 +1,9 @@
package com.baeldung.persistence.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.baeldung.persistence.model.Foo;
public interface IFooDao extends JpaRepository<Foo, Long> {
}
@@ -0,0 +1,60 @@
package com.baeldung.persistence.model;
import java.util.Map;
import org.springframework.hateoas.ResourceSupport;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@JsonInclude(Include.NON_NULL)
public class Customer extends ResourceSupport {
private String customerId;
private String customerName;
private String companyName;
private Map<String, Order> orders;
public Customer() {
super();
}
public Customer(final String customerId, final String customerName, final String companyName) {
super();
this.customerId = customerId;
this.customerName = customerName;
this.companyName = companyName;
}
public String getCustomerId() {
return customerId;
}
public void setCustomerId(final String customerId) {
this.customerId = customerId;
}
public String getCustomerName() {
return customerName;
}
public void setCustomerName(final String customerName) {
this.customerName = customerName;
}
public String getCompanyName() {
return companyName;
}
public void setCompanyName(final String companyName) {
this.companyName = companyName;
}
public Map<String, Order> getOrders() {
return orders;
}
public void setOrders(final Map<String, Order> orders) {
this.orders = orders;
}
}
@@ -0,0 +1,98 @@
package com.baeldung.persistence.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Version;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("Foo")
@Entity
public class Foo implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@Column(nullable = false)
private String name;
@Version
private long version;
public Foo() {
super();
}
public Foo(final String name) {
super();
this.name = name;
}
// API
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 long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
//
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.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 Foo other = (Foo) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append("Foo [name=").append(name).append("]");
return builder.toString();
}
}
@@ -0,0 +1,50 @@
package com.baeldung.persistence.model;
import org.springframework.hateoas.ResourceSupport;
public class Order extends ResourceSupport {
private String orderId;
private double price;
private int quantity;
public Order() {
super();
}
public Order(final String orderId, final double price, final int quantity) {
super();
this.orderId = orderId;
this.price = price;
this.quantity = quantity;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(final String orderId) {
this.orderId = orderId;
}
public double getPrice() {
return price;
}
public void setPrice(final double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(final int quantity) {
this.quantity = quantity;
}
@Override
public String toString() {
return "Order [orderId=" + orderId + ", price=" + price + ", quantity=" + quantity + "]";
}
}
@@ -0,0 +1,13 @@
package com.baeldung.persistence.service;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.baeldung.persistence.IOperations;
import com.baeldung.persistence.model.Foo;
public interface IFooService extends IOperations<Foo> {
Page<Foo> findPaginated(Pageable pageable);
}
@@ -0,0 +1,62 @@
package com.baeldung.persistence.service.common;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Transactional;
import com.baeldung.persistence.IOperations;
import com.google.common.collect.Lists;
@Transactional
public abstract class AbstractService<T extends Serializable> implements IOperations<T> {
// read - one
@Override
@Transactional(readOnly = true)
public T findById(final long id) {
return getDao().findById(id).orElse(null);
}
// read - all
@Override
@Transactional(readOnly = true)
public List<T> findAll() {
return Lists.newArrayList(getDao().findAll());
}
@Override
public Page<T> findPaginated(final int page, final int size) {
return getDao().findAll(PageRequest.of(page, size));
}
// write
@Override
public T create(final T entity) {
return getDao().save(entity);
}
@Override
public T update(final T entity) {
return getDao().save(entity);
}
@Override
public void delete(final T entity) {
getDao().delete(entity);
}
@Override
public void deleteById(final long entityId) {
getDao().deleteById(entityId);
}
protected abstract PagingAndSortingRepository<T, Long> getDao();
}
@@ -0,0 +1,51 @@
package com.baeldung.persistence.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.baeldung.persistence.dao.IFooDao;
import com.baeldung.persistence.model.Foo;
import com.baeldung.persistence.service.IFooService;
import com.baeldung.persistence.service.common.AbstractService;
import com.google.common.collect.Lists;
@Service
@Transactional
public class FooService extends AbstractService<Foo> implements IFooService {
@Autowired
private IFooDao dao;
public FooService() {
super();
}
// API
@Override
protected PagingAndSortingRepository<Foo, Long> getDao() {
return dao;
}
// custom methods
@Override
public Page<Foo> findPaginated(Pageable pageable) {
return dao.findAll(pageable);
}
// overridden to be secured
@Override
@Transactional(readOnly = true)
public List<Foo> findAll() {
return Lists.newArrayList(getDao().findAll());
}
}
@@ -0,0 +1,37 @@
package com.baeldung.requestresponsebody;
import com.baeldung.services.ExampleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping("/post")
public class ExamplePostController {
private static Logger log = LoggerFactory.getLogger(ExamplePostController.class);
@Autowired ExampleService exampleService;
@PostMapping("/request")
public ResponseEntity postController(@RequestBody LoginForm loginForm) {
log.debug("POST received - serializing LoginForm: " + loginForm.getPassword() + " " + loginForm.getUsername());
exampleService.fakeAuthenticate(loginForm);
return ResponseEntity.ok(HttpStatus.OK);
}
@PostMapping("/response")
@ResponseBody
public ResponseTransfer postResponseController(@RequestBody LoginForm loginForm) {
log.debug("POST received - serializing LoginForm: " + loginForm.getPassword() + " " + loginForm.getUsername());
return new ResponseTransfer("Thanks For Posting!!!");
}
}
@@ -0,0 +1,31 @@
package com.baeldung.requestresponsebody;
public class LoginForm {
private String username;
private String password;
public LoginForm() {
}
public LoginForm(String username, String password) {
super();
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
@@ -0,0 +1,18 @@
package com.baeldung.requestresponsebody;
public class ResponseTransfer {
private String text;
public ResponseTransfer(String text) {
this.setText(text);
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
@@ -0,0 +1,13 @@
package com.baeldung.services;
import java.util.List;
import com.baeldung.persistence.model.Customer;
public interface CustomerService {
List<Customer> allCustomers();
Customer getCustomerDetail(final String id);
}
@@ -0,0 +1,40 @@
package com.baeldung.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.springframework.stereotype.Service;
import com.baeldung.persistence.model.Customer;
@Service
public class CustomerServiceImpl implements CustomerService {
private HashMap<String, Customer> customerMap;
public CustomerServiceImpl() {
customerMap = new HashMap<>();
final Customer customerOne = new Customer("10A", "Jane", "ABC Company");
final Customer customerTwo = new Customer("20B", "Bob", "XYZ Company");
final Customer customerThree = new Customer("30C", "Tim", "CKV Company");
customerMap.put("10A", customerOne);
customerMap.put("20B", customerTwo);
customerMap.put("30C", customerThree);
}
@Override
public List<Customer> allCustomers() {
return new ArrayList<>(customerMap.values());
}
@Override
public Customer getCustomerDetail(final String customerId) {
return customerMap.get(customerId);
}
}
@@ -0,0 +1,13 @@
package com.baeldung.services;
import org.springframework.stereotype.Service;
import com.baeldung.requestresponsebody.LoginForm;
@Service
public class ExampleService {
public boolean fakeAuthenticate(LoginForm lf) {
return true;
}
}
@@ -0,0 +1,13 @@
package com.baeldung.services;
import java.util.List;
import com.baeldung.persistence.model.Order;
public interface OrderService {
List<Order> getAllOrdersForCustomer(String customerId);
Order getOrderByIdForCustomer(String customerId, String orderId);
}
@@ -0,0 +1,59 @@
package com.baeldung.services;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.baeldung.persistence.model.Customer;
import com.baeldung.persistence.model.Order;
@Service
public class OrderServiceImpl implements OrderService {
private HashMap<String, Customer> customerMap;
private HashMap<String, Order> customerOneOrderMap;
private HashMap<String, Order> customerTwoOrderMap;
private HashMap<String, Order> customerThreeOrderMap;
public OrderServiceImpl() {
customerMap = new HashMap<>();
customerOneOrderMap = new HashMap<>();
customerTwoOrderMap = new HashMap<>();
customerThreeOrderMap = new HashMap<>();
customerOneOrderMap.put("001A", new Order("001A", 150.00, 25));
customerOneOrderMap.put("002A", new Order("002A", 250.00, 15));
customerTwoOrderMap.put("002B", new Order("002B", 550.00, 325));
customerTwoOrderMap.put("002B", new Order("002B", 450.00, 525));
final Customer customerOne = new Customer("10A", "Jane", "ABC Company");
final Customer customerTwo = new Customer("20B", "Bob", "XYZ Company");
final Customer customerThree = new Customer("30C", "Tim", "CKV Company");
customerOne.setOrders(customerOneOrderMap);
customerTwo.setOrders(customerTwoOrderMap);
customerThree.setOrders(customerThreeOrderMap);
customerMap.put("10A", customerOne);
customerMap.put("20B", customerTwo);
customerMap.put("30C", customerThree);
}
@Override
public List<Order> getAllOrdersForCustomer(final String customerId) {
return new ArrayList<>(customerMap.get(customerId).getOrders().values());
}
@Override
public Order getOrderByIdForCustomer(final String customerId, final String orderId) {
final Map<String, Order> orders = customerMap.get(customerId).getOrders();
Order selectedOrder = orders.get(orderId);
return selectedOrder;
}
}
@@ -0,0 +1,84 @@
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(basePackages = { "com.baeldung.persistence", "com.baeldung.springpagination" })
@EnableJpaRepositories(basePackages = {"com.baeldung.persistence.dao", "com.baeldung.springpagination.repository"})
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", "com.baeldung.springpagination.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,69 @@
package com.baeldung.spring;
import java.util.List;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MarshallingHttpMessageConverter;
import org.springframework.oxm.xstream.XStreamMarshaller;
import org.springframework.web.filter.ShallowEtagHeaderFilter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
// If we want to enable xml configurations for message-converter:
// @ImportResource("classpath:WEB-INF/api-servlet.xml")
public class WebConfig implements WebMvcConfigurer {
// @Override
// public void configureMessageConverters(final List<HttpMessageConverter<?>> messageConverters) {
// messageConverters.add(new MappingJackson2HttpMessageConverter());
// messageConverters.add(createXmlHttpMessageConverter());
// }
//
// private HttpMessageConverter<Object> createXmlHttpMessageConverter() {
// final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter();
//
// final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller();
// xstreamMarshaller.setAutodetectAnnotations(true);
// xmlConverter.setMarshaller(xstreamMarshaller);
// xmlConverter.setUnmarshaller(xstreamMarshaller);
//
// return xmlConverter;
// }
// Another possibility is to create a bean which will be automatically added to the Spring Boot Autoconfigurations
// @Bean
// public HttpMessageConverter<Object> createXmlHttpMessageConverter() {
// final MarshallingHttpMessageConverter xmlConverter = new MarshallingHttpMessageConverter();
//
// final XStreamMarshaller xstreamMarshaller = new XStreamMarshaller();
// xstreamMarshaller.setAutodetectAnnotations(true);
// xmlConverter.setMarshaller(xstreamMarshaller);
// xmlConverter.setUnmarshaller(xstreamMarshaller);
//
// return xmlConverter;
// }
// Etags
// If we're not using Spring Boot we can make use of
// AbstractAnnotationConfigDispatcherServletInitializer#getServletFilters
@Bean
public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() {
FilterRegistrationBean<ShallowEtagHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<>( new ShallowEtagHeaderFilter());
filterRegistrationBean.addUrlPatterns("/foos/*");
filterRegistrationBean.setName("etagFilter");
return filterRegistrationBean;
}
// We can also just declare the filter directly
// @Bean
// public ShallowEtagHeaderFilter shallowEtagHeaderFilter() {
// return new ShallowEtagHeaderFilter();
// }
}
@@ -0,0 +1,93 @@
package com.baeldung.springpagination.controller;
import com.baeldung.springpagination.dto.PostDto;
import com.baeldung.springpagination.model.Post;
import com.baeldung.springpagination.service.IPostService;
import com.baeldung.springpagination.service.IUserService;
import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import java.text.ParseException;
import java.util.List;
import java.util.stream.Collectors;
@Controller
@RequestMapping("/posts")
public class PostRestController {
@Autowired
private IPostService postService;
@Autowired
private IUserService userService;
@Autowired
private ModelMapper modelMapper;
@GetMapping
@ResponseBody
public List<PostDto> getPosts(
@PathVariable("page") int page,
@PathVariable("size") int size,
@PathVariable("sortDir") String sortDir,
@PathVariable("sort") String sort) {
List<Post> posts = postService.getPostsList(page, size, sortDir, sort);
return posts.stream()
.map(this::convertToDto)
.collect(Collectors.toList());
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public PostDto createPost(@RequestBody PostDto postDto) throws ParseException {
Post post = convertToEntity(postDto);
Post postCreated = postService.createPost(post);
return convertToDto(postCreated);
}
@GetMapping(value = "/{id}")
@ResponseBody
public PostDto getPost(@PathVariable("id") Long id) {
return convertToDto(postService.getPostById(id));
}
@PutMapping(value = "/{id}")
@ResponseStatus(HttpStatus.OK)
public void updatePost(@RequestBody PostDto postDto) throws ParseException {
Post post = convertToEntity(postDto);
postService.updatePost(post);
}
private PostDto convertToDto(Post post) {
PostDto postDto = modelMapper.map(post, PostDto.class);
postDto.setSubmissionDate(post.getSubmissionDate(),
userService.getCurrentUser().getPreference().getTimezone());
return postDto;
}
private Post convertToEntity(PostDto postDto) throws ParseException {
Post post = modelMapper.map(postDto, Post.class);
post.setSubmissionDate(postDto.getSubmissionDateConverted(
userService.getCurrentUser().getPreference().getTimezone()));
if (postDto.getId() != null) {
Post oldPost = postService.getPostById(postDto.getId());
post.setRedditID(oldPost.getRedditID());
post.setSent(oldPost.isSent());
}
return post;
}
}
@@ -0,0 +1,71 @@
package com.baeldung.springpagination.dto;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class PostDto {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
private Long id;
private String title;
private String url;
private String date;
private UserDto user;
public Date getSubmissionDateConverted(String timezone) throws ParseException {
dateFormat.setTimeZone(TimeZone.getTimeZone(timezone));
return dateFormat.parse(this.date);
}
public void setSubmissionDate(Date date, String timezone) {
dateFormat.setTimeZone(TimeZone.getTimeZone(timezone));
this.date = dateFormat.format(date);
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public UserDto getUser() {
return user;
}
public void setUser(UserDto user) {
this.user = user;
}
}
@@ -0,0 +1,14 @@
package com.baeldung.springpagination.dto;
public class UserDto {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@@ -0,0 +1,98 @@
package com.baeldung.springpagination.model;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Post {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String title;
private String url;
private String date;
private String redditID;
private Date submissionDate;
private boolean sent;
private String userName;
public Post() {
}
public boolean isSent() {
return sent;
}
public void setSent(boolean sent) {
this.sent = sent;
}
public String getRedditID() {
return redditID;
}
public void setRedditID(String redditID) {
this.redditID = redditID;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public Date getSubmissionDate() {
return submissionDate;
}
public void setSubmissionDate(Date submissionDate) {
this.submissionDate = submissionDate;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
@@ -0,0 +1,32 @@
package com.baeldung.springpagination.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Preference {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String timezone;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTimezone() {
return timezone;
}
public void setTimezone(String timezone) {
this.timezone = timezone;
}
}
@@ -0,0 +1,37 @@
package com.baeldung.springpagination.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Subject {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(nullable = false)
private String name;
public Subject() {
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@@ -0,0 +1,44 @@
package com.baeldung.springpagination.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@OneToOne
Preference preference;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Preference getPreference() {
return preference;
}
public void setPreference(Preference preference) {
this.preference = preference;
}
}

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