Merge pull request #8154 from sjmillington/rest-move-2

[BAEL-18365] Spring rest move 2
This commit is contained in:
Josh Cummings 2019-11-23 12:20:53 -07:00 committed by GitHub
commit fbf857ce85
65 changed files with 1022 additions and 24 deletions

View File

@ -8,3 +8,4 @@ This module contains articles about Spring Boot with Spring Data
- [Rendering Exceptions in JSON with Spring](https://www.baeldung.com/spring-exceptions-json) - [Rendering Exceptions in JSON with Spring](https://www.baeldung.com/spring-exceptions-json)
- [Disable Spring Data Auto Configuration](https://www.baeldung.com/spring-data-disable-auto-config) - [Disable Spring Data Auto Configuration](https://www.baeldung.com/spring-data-disable-auto-config)
- [Repositories with Multiple Spring Data Modules](https://www.baeldung.com/spring-multiple-data-modules) - [Repositories with Multiple Spring Data Modules](https://www.baeldung.com/spring-multiple-data-modules)
- [Spring Custom Property Editor](https://www.baeldung.com/spring-mvc-custom-property-editor)

View File

@ -8,3 +8,7 @@ This module contains articles about administering a Spring Boot runtime
- [Logging HTTP Requests with Spring Boot Actuator HTTP Tracing](https://www.baeldung.com/spring-boot-actuator-http) - [Logging HTTP Requests with Spring Boot Actuator HTTP Tracing](https://www.baeldung.com/spring-boot-actuator-http)
- [How to Disable Console Logging in Spring Boot](https://www.baeldung.com/spring-boot-disable-console-logging) - [How to Disable Console Logging in Spring Boot](https://www.baeldung.com/spring-boot-disable-console-logging)
- [Spring Boot Embedded Tomcat Logs](https://www.baeldung.com/spring-boot-embedded-tomcat-logs) - [Spring Boot Embedded Tomcat Logs](https://www.baeldung.com/spring-boot-embedded-tomcat-logs)
- [How to Change the Default Port in Spring Boot](https://www.baeldung.com/spring-boot-change-port)
- [Project Configuration with Spring](https://www.baeldung.com/project-configuration-with-spring)
- [CORS with Spring](https://www.baeldung.com/spring-cors)
- [Spring Log Incoming Requests](https://www.baeldung.com/spring-http-logging)

View File

@ -32,6 +32,12 @@
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
@ -57,6 +63,10 @@
<artifactId>spring-boot-admin-starter-client</artifactId> <artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin-starter-client.version}</version> <version>${spring-boot-admin-starter-client.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.h2database</groupId> <groupId>com.h2database</groupId>

View File

@ -0,0 +1,15 @@
package com.baeldung.sampleapp.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@EnableAutoConfiguration
@ComponentScan("com.baeldung.sampleapp")
public class MainApplication implements WebMvcConfigurer {
public static void main(final String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.sampleapp.config;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;
import com.baeldung.sampleapp.interceptors.RestTemplateHeaderModifierInterceptor;
@Configuration
public class RestClientConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
List<ClientHttpRequestInterceptor> interceptors = restTemplate.getInterceptors();
if (CollectionUtils.isEmpty(interceptors)) {
interceptors = new ArrayList<ClientHttpRequestInterceptor>();
}
interceptors.add(new RestTemplateHeaderModifierInterceptor());
restTemplate.setInterceptors(interceptors);
return restTemplate;
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.sampleapp.config;
import java.text.SimpleDateFormat;
import java.util.List;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/*
* Please note that main web configuration is in src/main/webapp/WEB-INF/api-servlet.xml
*/
@Configuration
@EnableWebMvc
@ComponentScan({ "com.baeldung.sampleapp.web" })
public class WebConfig implements WebMvcConfigurer {
public WebConfig() {
super();
}
/*
@Override
public void configureMessageConverters(final List<HttpMessageConverter<?>> messageConverters) {
final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.indentOutput(true)
.dateFormat(new SimpleDateFormat("dd-MM-yyyy hh:mm"));
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
// messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
// messageConverters.add(new MappingJackson2HttpMessageConverter());
// messageConverters.add(new ProtobufHttpMessageConverter());
}
*/
}

View File

@ -0,0 +1,18 @@
package com.baeldung.sampleapp.interceptors;
import java.io.IOException;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
public class RestTemplateHeaderModifierInterceptor implements ClientHttpRequestInterceptor {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
ClientHttpResponse response = execution.execute(request, body);
response.getHeaders().add("Foo", "bar");
return response;
}
}

View File

@ -0,0 +1,28 @@
package com.baeldung.sampleapp.repository;
import java.util.Map;
import com.baeldung.sampleapp.web.dto.HeavyResource;
import com.baeldung.sampleapp.web.dto.HeavyResourceAddressOnly;
public class HeavyResourceRepository {
public void save(HeavyResource heavyResource) {
}
public void save(HeavyResourceAddressOnly partialUpdate) {
}
public void save(Map<String, Object> updates, String id) {
}
public void save(HeavyResource heavyResource, String id) {
}
public void save(HeavyResourceAddressOnly partialUpdate, String id) {
}
}

View File

@ -0,0 +1,47 @@
package com.baeldung.sampleapp.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping(value = "/ex")
public class BarMappingExamplesController {
public BarMappingExamplesController() {
super();
}
// API
// with @RequestParam
@RequestMapping(value = "/bars")
@ResponseBody
public String getBarBySimplePathWithRequestParam(@RequestParam("id") final long id) {
return "Get a specific Bar with id=" + id;
}
@RequestMapping(value = "/bars", params = "id")
@ResponseBody
public String getBarBySimplePathWithExplicitRequestParam(@RequestParam("id") final long id) {
return "Get a specific Bar with id=" + id;
}
@RequestMapping(value = "/bars", params = { "id", "second" })
@ResponseBody
public String getBarBySimplePathWithExplicitRequestParams(@RequestParam("id") final long id) {
return "Get a specific Bar with id=" + id;
}
// with @PathVariable
@RequestMapping(value = "/bars/{numericId:[\\d]+}")
@ResponseBody
public String getBarsBySimplePathWithPathVariable(@PathVariable final long numericId) {
return "Get a specific Bar with id=" + numericId;
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.sampleapp.web.controller;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.sampleapp.web.dto.Company;
@RestController
public class CompanyController {
@RequestMapping(value = "/companyRest", produces = MediaType.APPLICATION_JSON_VALUE)
public Company getCompanyRest() {
final Company company = new Company(1, "Xpto");
return company;
}
}

View File

@ -0,0 +1,85 @@
package com.baeldung.sampleapp.web.controller;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
@RestController
public class DeferredResultController {
private final static Logger LOG = LoggerFactory.getLogger(DeferredResultController.class);
@GetMapping("/async-deferredresult")
public DeferredResult<ResponseEntity<?>> handleReqDefResult(Model model) {
LOG.info("Received request");
DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();
deferredResult.onCompletion(() -> LOG.info("Processing complete"));
CompletableFuture.supplyAsync(() -> {
LOG.info("Processing in separate thread");
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "OK";
})
.whenCompleteAsync((result, exc) -> deferredResult.setResult(ResponseEntity.ok(result)));
LOG.info("Servlet thread freed");
return deferredResult;
}
@GetMapping("/process-blocking")
public ResponseEntity<?> handleReqSync(Model model) {
// ...
return ResponseEntity.ok("ok");
}
@GetMapping("/async-deferredresult-timeout")
public DeferredResult<ResponseEntity<?>> handleReqWithTimeouts(Model model) {
LOG.info("Received async request with a configured timeout");
DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>(500l);
deferredResult.onTimeout(() -> deferredResult.setErrorResult(ResponseEntity.status(HttpStatus.REQUEST_TIMEOUT)
.body("Request timeout occurred.")));
CompletableFuture.supplyAsync(() -> {
LOG.info("Processing in separate thread");
try {
Thread.sleep(6000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "error";
})
.whenCompleteAsync((result, exc) -> deferredResult.setResult(ResponseEntity.ok(result)));
LOG.info("servlet thread freed");
return deferredResult;
}
@GetMapping("/async-deferredresult-error")
public DeferredResult<ResponseEntity<?>> handleAsyncFailedRequest(Model model) {
LOG.info("Received async request with a configured error handler");
DeferredResult<ResponseEntity<?>> deferredResult = new DeferredResult<>();
deferredResult.onError(new Consumer<Throwable>() {
@Override
public void accept(Throwable t) {
deferredResult.setErrorResult(ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An error occurred."));
}
});
LOG.info("servlet thread freed");
return deferredResult;
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.sampleapp.web.controller;
import java.util.Map;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
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.RestController;
import com.baeldung.sampleapp.repository.HeavyResourceRepository;
import com.baeldung.sampleapp.web.dto.HeavyResource;
import com.baeldung.sampleapp.web.dto.HeavyResourceAddressOnly;
@RestController
public class HeavyResourceController {
private HeavyResourceRepository heavyResourceRepository = new HeavyResourceRepository();
@RequestMapping(value = "/heavyresource/{id}", method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> saveResource(@RequestBody HeavyResource heavyResource, @PathVariable("id") String id) {
heavyResourceRepository.save(heavyResource, id);
return ResponseEntity.ok("resource saved");
}
@RequestMapping(value = "/heavyresource/{id}", method = RequestMethod.PATCH, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> partialUpdateName(@RequestBody HeavyResourceAddressOnly partialUpdate, @PathVariable("id") String id) {
heavyResourceRepository.save(partialUpdate, id);
return ResponseEntity.ok("resource address updated");
}
@RequestMapping(value = "/heavyresource2/{id}", method = RequestMethod.PATCH, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> partialUpdateGeneric(@RequestBody Map<String, Object> updates,
@PathVariable("id") String id) {
heavyResourceRepository.save(updates, id);
return ResponseEntity.ok("resource updated");
}
}

View File

@ -0,0 +1,39 @@
package com.baeldung.sampleapp.web.controller;
import java.util.Date;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.sampleapp.web.dto.Item;
import com.baeldung.sampleapp.web.dto.ItemManager;
import com.baeldung.sampleapp.web.dto.Views;
import com.fasterxml.jackson.annotation.JsonView;
@RestController
public class ItemController {
@JsonView(Views.Public.class)
@RequestMapping("/items/{id}")
public Item getItemPublic(@PathVariable final int id) {
return ItemManager.getById(id);
}
@JsonView(Views.Internal.class)
@RequestMapping("/items/internal/{id}")
public Item getItemInternal(@PathVariable final int id) {
return ItemManager.getById(id);
}
@RequestMapping("/date")
public Date getCurrentDate() throws Exception {
return new Date();
}
@RequestMapping("/delay/{seconds}")
public void getCurrentTime(@PathVariable final int seconds) throws Exception {
Thread.sleep(seconds * 1000);
}
}

View File

@ -0,0 +1,85 @@
package com.baeldung.sampleapp.web.controller;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
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.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import com.baeldung.sampleapp.web.dto.Foo;
import com.baeldung.sampleapp.web.exception.ResourceNotFoundException;
@Controller
@RequestMapping(value = "/foos")
public class MyFooController {
private final Map<Long, Foo> myfoos;
public MyFooController() {
super();
myfoos = new HashMap<Long, Foo>();
myfoos.put(1L, new Foo(1L, "sample foo"));
}
// API - read
@RequestMapping(method = RequestMethod.GET, produces = { "application/json" })
@ResponseBody
public Collection<Foo> findAll() {
return myfoos.values();
}
@RequestMapping(method = RequestMethod.GET, value = "/{id}", produces = { "application/json" })
@ResponseBody
public Foo findById(@PathVariable final long id) {
final Foo foo = myfoos.get(id);
if (foo == null) {
throw new ResourceNotFoundException();
}
return foo;
}
// API - write
@RequestMapping(method = RequestMethod.PUT, value = "/{id}")
@ResponseStatus(HttpStatus.OK)
@ResponseBody
public Foo updateFoo(@PathVariable("id") final long id, @RequestBody final Foo foo) {
myfoos.put(id, foo);
return foo;
}
@RequestMapping(method = RequestMethod.PATCH, value = "/{id}")
@ResponseStatus(HttpStatus.OK)
public void updateFoo2(@PathVariable("id") final long id, @RequestBody final Foo foo) {
myfoos.put(id, foo);
}
@RequestMapping(method = RequestMethod.POST)
@ResponseStatus(HttpStatus.CREATED)
@ResponseBody
public Foo createFoo(@RequestBody final Foo foo, HttpServletResponse response) {
myfoos.put(foo.getId(), foo);
response.setHeader("Location", ServletUriComponentsBuilder.fromCurrentRequest()
.path("/" + foo.getId())
.toUriString());
return foo;
}
@RequestMapping(method = RequestMethod.DELETE, value = "/{id}")
@ResponseStatus(HttpStatus.OK)
public void deleteById(@PathVariable final long id) {
myfoos.remove(id);
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.sampleapp.web.controller;
import java.util.ArrayList;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import com.baeldung.sampleapp.web.dto.PactDto;
@RestController
public class PactController {
List<PactDto> pacts = new ArrayList<>();
@GetMapping(value = "/pact", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public PactDto getPact() {
return new PactDto(true, "tom");
}
@PostMapping("/pact")
@ResponseStatus(HttpStatus.CREATED)
public void createPact(PactDto pact) {
pacts.add(pact);
}
}

View File

@ -0,0 +1,74 @@
package com.baeldung.sampleapp.web.controller;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
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.RestController;
import org.springframework.web.multipart.MultipartFile;
import com.baeldung.sampleapp.web.dto.Foo;
// used to test HttpClientPostingTest
@RestController
public class SimplePostController {
@RequestMapping(value = "/users", method = RequestMethod.POST)
public String postUser(@RequestParam final String username, @RequestParam final String password) {
return "Success" + username;
}
@RequestMapping(value = "/users/detail", method = RequestMethod.POST)
public String postUserDetail(@RequestBody final Foo entity) {
return "Success" + entity.getId();
}
@RequestMapping(value = "/users/multipart", method = RequestMethod.POST)
public String uploadFile(@RequestParam final String username, @RequestParam final String password, @RequestParam("file") final MultipartFile file) {
if (!file.isEmpty()) {
try {
final DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH.mm.ss");
final String fileName = dateFormat.format(new Date());
final File fileServer = new File(fileName);
fileServer.createNewFile();
final byte[] bytes = file.getBytes();
final BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(fileServer));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + username;
} catch (final Exception e) {
return "You failed to upload " + e.getMessage();
}
} else {
return "You failed to upload because the file was empty.";
}
}
@RequestMapping(value = "/users/upload", method = RequestMethod.POST)
public String postMultipart(@RequestParam("file") final MultipartFile file) {
if (!file.isEmpty()) {
try {
final DateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH.mm.ss");
final String fileName = dateFormat.format(new Date());
final File fileServer = new File(fileName);
fileServer.createNewFile();
final byte[] bytes = file.getBytes();
final BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(fileServer));
stream.write(bytes);
stream.close();
return "You successfully uploaded ";
} catch (final Exception e) {
return "You failed to upload " + e.getMessage();
}
} else {
return "You failed to upload because the file was empty.";
}
}
}

View File

@ -0,0 +1,25 @@
package com.baeldung.sampleapp.web.controller.mediatypes;
import org.springframework.web.bind.annotation.PathVariable;
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.bind.annotation.RestController;
import com.baeldung.sampleapp.web.dto.BaeldungItem;
import com.baeldung.sampleapp.web.dto.BaeldungItemV2;
@RestController
@RequestMapping(value = "/", produces = "application/vnd.baeldung.api.v1+json")
public class CustomMediaTypeController {
@RequestMapping(method = RequestMethod.GET, value = "/public/api/items/{id}", produces = "application/vnd.baeldung.api.v1+json")
public @ResponseBody BaeldungItem getItem(@PathVariable("id") String id) {
return new BaeldungItem("itemId1");
}
@RequestMapping(method = RequestMethod.GET, value = "/public/api/items/{id}", produces = "application/vnd.baeldung.api.v2+json")
public @ResponseBody BaeldungItemV2 getItemSecondAPIVersion(@PathVariable("id") String id) {
return new BaeldungItemV2("itemName");
}
}

View File

@ -0,0 +1,68 @@
package com.baeldung.sampleapp.web.controller.redirect;
import javax.servlet.http.HttpServletRequest;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
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;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.view.RedirectView;
@Controller
@RequestMapping("/")
public class RedirectController {
@RequestMapping(value = "/redirectWithXMLConfig", method = RequestMethod.GET)
public ModelAndView redirectWithUsingXMLConfig(final ModelMap model) {
model.addAttribute("attribute", "redirectWithXMLConfig");
return new ModelAndView("RedirectedUrl", model);
}
@RequestMapping(value = "/redirectWithRedirectPrefix", method = RequestMethod.GET)
public ModelAndView redirectWithUsingRedirectPrefix(final ModelMap model) {
model.addAttribute("attribute", "redirectWithRedirectPrefix");
return new ModelAndView("redirect:/redirectedUrl", model);
}
@RequestMapping(value = "/redirectWithRedirectAttributes", method = RequestMethod.GET)
public RedirectView redirectWithRedirectAttributes(final RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("flashAttribute", "redirectWithRedirectAttributes");
redirectAttributes.addAttribute("attribute", "redirectWithRedirectAttributes");
return new RedirectView("redirectedUrl");
}
@RequestMapping(value = "/redirectWithRedirectView", method = RequestMethod.GET)
public RedirectView redirectWithUsingRedirectView(final ModelMap model) {
model.addAttribute("attribute", "redirectWithRedirectView");
return new RedirectView("redirectedUrl");
}
@RequestMapping(value = "/forwardWithForwardPrefix", method = RequestMethod.GET)
public ModelAndView forwardWithUsingForwardPrefix(final ModelMap model) {
model.addAttribute("attribute", "redirectWithForwardPrefix");
return new ModelAndView("forward:/redirectedUrl", model);
}
@RequestMapping(value = "/redirectedUrl", method = RequestMethod.GET)
public ModelAndView redirection(final ModelMap model, @ModelAttribute("flashAttribute") final Object flashAttribute) {
model.addAttribute("redirectionAttribute", flashAttribute);
return new ModelAndView("redirection", model);
}
@RequestMapping(value = "/redirectPostToPost", method = RequestMethod.POST)
public ModelAndView redirectPostToPost(HttpServletRequest request) {
request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.TEMPORARY_REDIRECT);
return new ModelAndView("redirect:/redirectedPostToPost");
}
@RequestMapping(value = "/redirectedPostToPost", method = RequestMethod.POST)
public ModelAndView redirectedPostToPost() {
return new ModelAndView("redirection");
}
}

View File

@ -0,0 +1,13 @@
package com.baeldung.sampleapp.web.dto;
public class BaeldungItem {
private final String itemId;
public BaeldungItem(String itemId) {
this.itemId = itemId;
}
public String getItemId() {
return itemId;
}
}

View File

@ -0,0 +1,14 @@
package com.baeldung.sampleapp.web.dto;
public class BaeldungItemV2 {
private final String itemName;
public BaeldungItemV2(String itemName) {
this.itemName = itemName;
}
public String getItemName() {
return itemName;
}
}

View File

@ -0,0 +1,38 @@
package com.baeldung.sampleapp.web.dto;
public class Company {
private long id;
private String name;
public Company() {
super();
}
public Company(final long id, final String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public void setName(final String name) {
this.name = name;
}
public long getId() {
return id;
}
public void setId(final long id) {
this.id = id;
}
@Override
public String toString() {
return "Company [id=" + id + ", name=" + name + "]";
}
}

View File

@ -0,0 +1,42 @@
package com.baeldung.sampleapp.web.dto;
public class Foo {
private long id;
private String name;
public Foo() {
super();
}
public Foo(final String name) {
super();
this.name = name;
}
public Foo(final long id, final String name) {
super();
this.id = id;
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;
}
}

View File

@ -0,0 +1,62 @@
package com.baeldung.sampleapp.web.dto;
public class HeavyResource {
private Integer id;
private String name;
private String surname;
private Integer age;
private String address;
public HeavyResource() {
}
public HeavyResource(Integer id, String name, String surname, Integer age, String address) {
this.id = id;
this.name = name;
this.surname = surname;
this.age = age;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.sampleapp.web.dto;
public class HeavyResourceAddressOnly {
private Integer id;
private String address;
public HeavyResourceAddressOnly() {
}
public HeavyResourceAddressOnly(Integer id, String address) {
this.id = id;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

View File

@ -0,0 +1,31 @@
package com.baeldung.sampleapp.web.dto;
public class HeavyResourceAddressPartialUpdate {
private Integer id;
private String address;
public HeavyResourceAddressPartialUpdate() {
}
public HeavyResourceAddressPartialUpdate(Integer id, String address) {
this.id = id;
this.address = address;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.sampleapp.web.dto;
import com.fasterxml.jackson.annotation.JsonView;
public class Item {
@JsonView(Views.Public.class)
public int id;
@JsonView(Views.Public.class)
public String itemName;
@JsonView(Views.Internal.class)
public String ownerName;
public Item() {
super();
}
public Item(final int id, final String itemName, final String ownerName) {
this.id = id;
this.itemName = itemName;
this.ownerName = ownerName;
}
public int getId() {
return id;
}
public String getItemName() {
return itemName;
}
public String getOwnerName() {
return ownerName;
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.sampleapp.web.dto;
public class ItemManager {
public static Item getById(final int id) {
final Item item = new Item(2, "book", "John");
return item;
}
}

View File

@ -0,0 +1,33 @@
package com.baeldung.sampleapp.web.dto;
public class PactDto {
private boolean condition;
private String name;
public PactDto() {
}
public PactDto(boolean condition, String name) {
super();
this.condition = condition;
this.name = name;
}
public boolean isCondition() {
return condition;
}
public void setCondition(boolean condition) {
this.condition = condition;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,9 @@
package com.baeldung.sampleapp.web.dto;
public class Views {
public static class Public {
}
public static class Internal extends Public {
}
}

View File

@ -0,0 +1,8 @@
package com.baeldung.sampleapp.web.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
}

View File

@ -11,6 +11,7 @@ import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.context.annotation.PropertySource;
import com.baeldung.web.log.config.CustomeRequestLoggingFilter; import com.baeldung.web.log.config.CustomeRequestLoggingFilter;
@ -18,6 +19,7 @@ import org.springframework.boot.web.servlet.support.SpringBootServletInitializer
@EnableAutoConfiguration @EnableAutoConfiguration
@ComponentScan("com.baeldung.web.log") @ComponentScan("com.baeldung.web.log")
@PropertySource("application-log.properties")
@SpringBootApplication @SpringBootApplication
public class Application extends SpringBootServletInitializer { public class Application extends SpringBootServletInitializer {

View File

@ -0,0 +1,2 @@
server.port=8082
server.servlet.context-path=/spring-rest

View File

@ -20,3 +20,4 @@ spring.application.name=spring-boot-management
server.port=8081 server.port=8081

View File

@ -7,14 +7,17 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import com.baeldung.web.log.app.Application; import com.baeldung.web.log.app.Application;
import com.baeldung.web.log.data.TaxiRide; import com.baeldung.web.log.data.TaxiRide;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = { Application.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(classes = { Application.class, TaxiFareControllerIntegrationTest.SecurityConfig.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class TaxiFareControllerIntegrationTest { public class TaxiFareControllerIntegrationTest {
@LocalServerPort @LocalServerPort
@ -23,6 +26,7 @@ public class TaxiFareControllerIntegrationTest {
@Test @Test
public void givenRequest_whenFetchTaxiFareRateCard_thanOK() { public void givenRequest_whenFetchTaxiFareRateCard_thanOK() {
System.out.println(port);
String URL = "http://localhost:" + port + "/spring-rest"; String URL = "http://localhost:" + port + "/spring-rest";
TestRestTemplate testRestTemplate = new TestRestTemplate(); TestRestTemplate testRestTemplate = new TestRestTemplate();
TaxiRide taxiRide = new TaxiRide(true, 10l); TaxiRide taxiRide = new TaxiRide(true, 10l);
@ -32,4 +36,17 @@ public class TaxiFareControllerIntegrationTest {
assertThat(fare, equalTo("200")); assertThat(fare, equalTo("200"));
} }
@Configuration
static class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
System.out.println("security being set");
http
.authorizeRequests()
.anyRequest().permitAll()
.and()
.csrf().disable();
}
}
} }

View File

@ -10,7 +10,6 @@ The "Learn Spring Security" Classes: http://github.learnspringsecurity.com
### Relevant Articles: ### Relevant Articles:
- [Integration Testing with the Maven Cargo plugin](https://www.baeldung.com/integration-testing-with-the-maven-cargo-plugin) - [Integration Testing with the Maven Cargo plugin](https://www.baeldung.com/integration-testing-with-the-maven-cargo-plugin)
- [Project Configuration with Spring](https://www.baeldung.com/project-configuration-with-spring)
- [Metrics for your Spring REST API](https://www.baeldung.com/spring-rest-api-metrics) - [Metrics for your Spring REST API](https://www.baeldung.com/spring-rest-api-metrics)
### Build the Project ### Build the Project

View File

@ -9,5 +9,4 @@ This module contains articles about REST APIs in Spring
- [Spring RequestMapping](https://www.baeldung.com/spring-requestmapping) - [Spring RequestMapping](https://www.baeldung.com/spring-requestmapping)
- [Spring and Apache FileUpload](https://www.baeldung.com/spring-apache-file-upload) - [Spring and Apache FileUpload](https://www.baeldung.com/spring-apache-file-upload)
- [Test a REST API with curl](https://www.baeldung.com/curl-rest) - [Test a REST API with curl](https://www.baeldung.com/curl-rest)
- [CORS with Spring](https://www.baeldung.com/spring-cors)
- [Best Practices for REST API Error Handling](https://www.baeldung.com/rest-api-error-handling-best-practices) - [Best Practices for REST API Error Handling](https://www.baeldung.com/rest-api-error-handling-best-practices)

View File

@ -4,7 +4,7 @@
/target /target
/neoDb* /neoDb*
/data /data
/src/main/webapp/WEB-INF/classes /spring-boot-runtime/src/main/webapp/WEB-INF/classes
*/META-INF/* */META-INF/*
# Packaged files # # Packaged files #

View File

@ -12,9 +12,6 @@ The "REST With Spring" Classes: http://bit.ly/restwithspring
- [Guide to UriComponentsBuilder in Spring](https://www.baeldung.com/spring-uricomponentsbuilder) - [Guide to UriComponentsBuilder in Spring](https://www.baeldung.com/spring-uricomponentsbuilder)
- [A Custom Media Type for a Spring REST API](https://www.baeldung.com/spring-rest-custom-media-type) - [A Custom Media Type for a Spring REST API](https://www.baeldung.com/spring-rest-custom-media-type)
- [HTTP PUT vs HTTP PATCH in a REST API](https://www.baeldung.com/http-put-patch-difference-spring) - [HTTP PUT vs HTTP PATCH in a REST API](https://www.baeldung.com/http-put-patch-difference-spring)
- [Spring Log Incoming Requests](https://www.baeldung.com/spring-http-logging)
- [How to Change the Default Port in Spring Boot](https://www.baeldung.com/spring-boot-change-port)
- [Guide to DeferredResult in Spring](https://www.baeldung.com/spring-deferred-result) - [Guide to DeferredResult in Spring](https://www.baeldung.com/spring-deferred-result)
- [Spring Custom Property Editor](https://www.baeldung.com/spring-mvc-custom-property-editor)
- [How to Set a Header on a Response with Spring 5](https://www.baeldung.com/spring-response-header) - [How to Set a Header on a Response with Spring 5](https://www.baeldung.com/spring-response-header)
- [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file) - [Download an Image or a File with Spring MVC](https://www.baeldung.com/spring-controller-return-image-file)

View File

@ -5,17 +5,13 @@ import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.changeport.CustomApplication;
import com.baeldung.produceimage.ImageApplication; import com.baeldung.produceimage.ImageApplication;
import com.baeldung.propertyeditor.PropertyEditorApplication;
import com.baeldung.responseheaders.ResponseHeadersApplication; import com.baeldung.responseheaders.ResponseHeadersApplication;
import com.baeldung.sampleapp.config.MainApplication;
import com.baeldung.web.log.app.Application;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = { CustomApplication.class, ImageApplication.class, PropertyEditorApplication.class, @SpringBootTest(classes = { ImageApplication.class,
ResponseHeadersApplication.class, Application.class, com.baeldung.web.upload.app.UploadApplication.class, ResponseHeadersApplication.class, com.baeldung.web.upload.app.UploadApplication.class,
MainApplication.class}) })
public class SpringContextIntegrationTest { public class SpringContextIntegrationTest {
@Test @Test

View File

@ -5,17 +5,14 @@ import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.junit4.SpringRunner;
import com.baeldung.changeport.CustomApplication;
import com.baeldung.produceimage.ImageApplication; import com.baeldung.produceimage.ImageApplication;
import com.baeldung.propertyeditor.PropertyEditorApplication;
import com.baeldung.responseheaders.ResponseHeadersApplication; import com.baeldung.responseheaders.ResponseHeadersApplication;
import com.baeldung.sampleapp.config.MainApplication;
import com.baeldung.web.log.app.Application;
@RunWith(SpringRunner.class) @RunWith(SpringRunner.class)
@SpringBootTest(classes = { CustomApplication.class, ImageApplication.class, PropertyEditorApplication.class, @SpringBootTest(classes = { ImageApplication.class,
ResponseHeadersApplication.class, Application.class, com.baeldung.web.upload.app.UploadApplication.class, ResponseHeadersApplication.class,
MainApplication.class}) com.baeldung.web.upload.app.UploadApplication.class,
})
public class SpringContextTest { public class SpringContextTest {
@Test @Test