PAN-48 Created the AccountController and created the copyNonNullProperties method

This commit is contained in:
2019-02-24 19:14:17 -07:00
parent 8c9f2bbd9c
commit b77a750c30
4 changed files with 189 additions and 6 deletions
@@ -2,11 +2,22 @@ package edu.msudenver.tsp.persistence.controller;
import edu.msudenver.tsp.persistence.dto.AccountsDto;
import edu.msudenver.tsp.persistence.repository.AccountsRepository;
import edu.msudenver.tsp.utilities.PersistenceUtilities;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StopWatch;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.groups.Default;
import java.util.List;
import java.util.Optional;
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/accounts")
@@ -14,13 +25,157 @@ public class AccountController {
private final AccountsRepository accountsRepository;
@GetMapping("/")
public @ResponseBody Iterable<AccountsDto> getListOfAccounts() {
return accountsRepository.findAll();
public @ResponseBody
ResponseEntity<Iterable<AccountsDto>> getListOfAccounts() {
LOG.info("Received request to list all accounts");
LOG.debug("Querying for list of accounts");
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final List<AccountsDto> listOfAccounts = (List<AccountsDto>) accountsRepository.findAll();
stopWatch.stop();
LOG.debug("Successfully completed query. Query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
LOG.info("Returning list of all accounts with size of " + listOfAccounts.size());
return new ResponseEntity<>(listOfAccounts, HttpStatus.OK);
}
@GetMapping("/{id}")
public @ResponseBody
Optional<AccountsDto> getAccountById(@PathVariable("id") final Integer id) {
return accountsRepository.findById(id);
ResponseEntity<AccountsDto> getAccountById(@PathVariable("id") final Integer id) {
LOG.info("Received request to query for account with id " + id);
if (id == null) {
LOG.error("ERROR: ID was null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Querying for account with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final Optional<AccountsDto> account = accountsRepository.findById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return account.map(accountDto -> {
LOG.info("Returning account with id " + id);
return new ResponseEntity<>(accountDto, HttpStatus.OK);
}).orElseGet(
() -> {
LOG.warn("No account was found with id " + id);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
);
}
@PostMapping("/")
@Validated({AccountsDto.Insert.class, Default.class})
public @ResponseBody ResponseEntity<AccountsDto> insertAccount(
@Valid @RequestBody final AccountsDto accountsDto, final BindingResult bindingResult) {
LOG.info("Received request to insert a new account");
if (bindingResult.hasErrors()) {
LOG.error("Binding result is unprocessable");
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (accountsDto == null) {
LOG.error("Passed account is unprocessable");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Saving new account");
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final AccountsDto savedAccount = accountsRepository.save(accountsDto);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
LOG.info("Returning the newly created account");
return new ResponseEntity<>(savedAccount, HttpStatus.CREATED);
}
@PatchMapping("/{id}")
public @ResponseBody ResponseEntity<AccountsDto> updateAccount(
@PathVariable("id") final Integer id,
@RequestBody final AccountsDto accountsDto, final BindingResult bindingResult) {
LOG.info("Received request to update an account");
if (bindingResult.hasErrors()) {
LOG.error("Binding result is unprocessable");
return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY);
}
if (accountsDto == null) {
LOG.error("Passed entity is null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
if (id == null) {
LOG.error("Account ID must be specified");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Checking for existence of account with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
final Optional<AccountsDto> existingAccount = accountsRepository.findById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
if (!existingAccount.isPresent()) {
LOG.error("No account associated with id " + id);
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
PersistenceUtilities.copyNonNullProperties(accountsDto, existingAccount.get());
existingAccount.get().setVersion(existingAccount.get().getVersion()+ 1);
LOG.info("Updating account with id " + id);
LOG.debug("Querying for account with ID " + id);
stopWatch.start();
final AccountsDto updatedAccount = accountsRepository.save(existingAccount.get());
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return new ResponseEntity<>(updatedAccount, HttpStatus.OK);
}
@DeleteMapping("/{id}")
public @ResponseBody ResponseEntity<Void> deleteAccountById(@PathVariable("id") final Integer id) {
LOG.info("Received request to delete account with id " + id);
if (id == null) {
LOG.error("Specified Id is null");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
LOG.debug("Deleting account with id " + id);
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
accountsRepository.deleteById(id);
stopWatch.stop();
LOG.debug("Received response from server: query took " + stopWatch.getTotalTimeMillis() + "ms to complete");
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
}
@@ -27,5 +27,5 @@ public class AccountsDto extends BaseDto implements Serializable {
public static final long serialVersionUID = 7095627971593953734L;
interface Insert {}
public interface Insert {}
}
@@ -18,6 +18,7 @@ repositories {
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile fileTree(dir: 'lib', include: '**/*.jar')
testCompile group: 'junit', name: 'junit', version: '4.12'
}
@@ -0,0 +1,27 @@
package edu.msudenver.tsp.utilities;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import java.beans.FeatureDescriptor;
import java.util.stream.Stream;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class PersistenceUtilities {
private static String[] getNullPropertyNames(final Object source) {
final BeanWrapper wrappedSource = new BeanWrapperImpl(source);
return Stream.of(wrappedSource.getPropertyDescriptors())
.map(FeatureDescriptor::getName)
.filter(propertyName -> wrappedSource.getPropertyValue(propertyName) == null
|| propertyName.equals("id"))
.toArray(String[]::new);
}
public static void copyNonNullProperties(final Object source, final Object target) {
BeanUtils.copyProperties(source, target, getNullPropertyNames(source));
}
}