US07: Add an owner update endpoint to the API

This commit is contained in:
Ivaylo Ivanov 2020-03-24 15:05:22 +01:00
parent 123c9badaa
commit 62bbb0644b
9 changed files with 185 additions and 4 deletions

View File

@ -43,7 +43,7 @@ public class OwnerEndpoint {
@PostMapping @PostMapping
@ResponseStatus(HttpStatus.CREATED) @ResponseStatus(HttpStatus.CREATED)
public OwnerDto addHorse(@RequestBody OwnerDto owner) { public OwnerDto addOwner(@RequestBody OwnerDto owner) {
LOGGER.info("POST " + BASE_URL); LOGGER.info("POST " + BASE_URL);
try { try {
Owner ownerEntity = ownerMapper.dtoToEntity(owner); Owner ownerEntity = ownerMapper.dtoToEntity(owner);
@ -58,4 +58,27 @@ public class OwnerEndpoint {
"Something went wrong during the communication with the database"); "Something went wrong during the communication with the database");
} }
} }
@PutMapping(value = "/{id}")
@ResponseStatus(HttpStatus.OK)
public OwnerDto updateOwner(@PathVariable("id") Long id, @RequestBody OwnerDto owner) {
LOGGER.info("PUT " + BASE_URL + "/{}", id);
try {
Owner ownerEntity = ownerMapper.dtoToEntity(owner);
ownerEntity.setId(id);
return ownerMapper.entityToDto((ownerService.updateOwner(ownerEntity)));
} catch (ValidationException e) {
LOGGER.error(e.getMessage());
throw new ResponseStatusException(HttpStatus.BAD_REQUEST,
"Error during updating owner with id " + id + ": " + e.getMessage());
} catch (DataAccessException e) {
LOGGER.error(e.getMessage());
throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY,
"Something went wrong during the communication with the database");
} catch (NotFoundException e) {
LOGGER.error(e.getMessage());
throw new ResponseStatusException(HttpStatus.NOT_FOUND,
"The requested owner could not be found");
}
}
} }

View File

@ -4,6 +4,8 @@ import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException; import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import java.io.IOException;
public interface OwnerDao { public interface OwnerDao {
/** /**
@ -16,9 +18,15 @@ public interface OwnerDao {
/** /**
* @param owner that specifies the owner to add * @param owner that specifies the owner to add
* @return the newly created horse * @return the newly created owner
* @throws DataAccessException will be thrown if something goes wrong during the database access. * @throws DataAccessException will be thrown if something goes wrong during the database access.
*/ */
Owner addOwner(Owner owner); Owner addOwner(Owner owner);
/**
* @param owner that specifies the new owner values alongside with the id of the owner to update
* @return the updated owner
* @throws DataAccessException will be thrown if something goes wrong during the database access.
*/
Owner updateOwner(Owner owner) throws DataAccessException;
} }

View File

@ -7,6 +7,7 @@ import java.lang.invoke.MethodHandles;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -84,6 +85,44 @@ public class OwnerJdbcDao implements OwnerDao {
} }
} }
@Override
public Owner updateOwner(Owner owner) throws DataAccessException {
LOGGER.trace("Update owner {}", owner.toString());
String sql = "UPDATE " + TABLE_NAME + " SET name=?, updated_at=? WHERE id=?";
try {
if(owner.getId() == null || owner.getId() == 0)
throw new DataIntegrityViolationException("Horse Id missing or 0");
this.validateOwner(owner);
Owner oldOwner = findOneById(owner.getId());
LocalDateTime currentTime = LocalDateTime.now();
owner.setUpdatedAt(currentTime);
int changes = jdbcTemplate.update(connection -> {
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, owner.getName());
ps.setObject(2, owner.getUpdatedAt());
ps.setObject(3, owner.getId());
return ps;
});
if (changes == 0)
throw new DataAccessException("Updating owner failed, no rows affected") {};
owner.setCreatedAt(oldOwner.getCreatedAt());
return owner;
} catch(DataAccessException e) {
// We are doing this in order to not change the exception type
throw new DataAccessException("Updating records failed", e) {};
}
}
private void validateOwner(Owner owner) throws DataIntegrityViolationException { private void validateOwner(Owner owner) throws DataIntegrityViolationException {
if(owner.getName() == null || owner.getName().isEmpty()) if(owner.getName() == null || owner.getName().isEmpty())
throw new DataIntegrityViolationException("Required parameters for owner missing"); throw new DataIntegrityViolationException("Required parameters for owner missing");

View File

@ -5,6 +5,8 @@ import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
import at.ac.tuwien.sepm.assignment.individual.util.ValidationException; import at.ac.tuwien.sepm.assignment.individual.util.ValidationException;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import java.io.IOException;
public interface OwnerService { public interface OwnerService {
@ -20,8 +22,15 @@ public interface OwnerService {
* @param owner to create * @param owner to create
* @return the new owner * @return the new owner
* @throws ValidationException will be thrown if something goes wrong during verification. * @throws ValidationException will be thrown if something goes wrong during verification.
* @throws DataAccessException will be thrown if the horse could not be saved in the database. * @throws DataAccessException will be thrown if the owner could not be saved in the database.
*/ */
Owner addOwner(Owner owner) throws ValidationException, DataAccessException; Owner addOwner(Owner owner) throws ValidationException, DataAccessException;
/**
* @param owner that specifies the new owner values alongside with the id of the owner to update
* @return the updated owner
* @throws ValidationException will be thrown if something goes wrong during verification.
* @throws DataAccessException will be thrown if the owner could not be saved in the database.
*/
Owner updateOwner(Owner owner) throws ValidationException, DataAccessException;
} }

View File

@ -37,4 +37,11 @@ public class SimpleOwnerService implements OwnerService {
this.validator.validateNewOwner(owner); this.validator.validateNewOwner(owner);
return ownerDao.addOwner(owner); return ownerDao.addOwner(owner);
} }
@Override
public Owner updateOwner(Owner owner) throws ValidationException, DataAccessException {
LOGGER.trace("updateOwner({})", owner);
this.validator.validateUpdateOwner(owner);
return ownerDao.updateOwner(owner);
}
} }

View File

@ -21,6 +21,12 @@ public class Validator {
} }
public void validateUpdateOwner(Owner owner) throws ValidationException { public void validateUpdateOwner(Owner owner) throws ValidationException {
if(owner.getId() == null || owner.getId() == 0) {
throw new ValidationException("Owner Id cannot be null or 0");
}
if(owner.getName() == null || owner.getName().isEmpty()) {
throw new ValidationException("Required value for owner missing: name");
}
} }
public void validateNewHorse(Horse horse) throws ValidationException { public void validateNewHorse(Horse horse) throws ValidationException {

View File

@ -38,5 +38,29 @@ public class OwnerEndpointTest {
assertEquals(response.getStatusCode(), HttpStatus.CREATED); assertEquals(response.getStatusCode(), HttpStatus.CREATED);
assertEquals(newOwner.getName(), response.getBody().getName()); assertEquals(newOwner.getName(), response.getBody().getName());
} }
@Test
@DisplayName("Updating a owner with the correct parameters will return 200 and the new OwnerDto")
public void updatingNewOwner_correctParameters_shouldReturnStatus200AndOwner() {
OwnerDto newOwner = new OwnerDto("Chad");
// Create a new owner
HttpEntity<OwnerDto> request = new HttpEntity<>(newOwner);
ResponseEntity<OwnerDto> response = REST_TEMPLATE
.exchange(BASE_URL + port + OWNER_URL, HttpMethod.POST, request, OwnerDto.class);
// Update the owner
newOwner.setId(response.getBody().getId());
newOwner.setName("Gigachad");
request = new HttpEntity<>(newOwner);
response = REST_TEMPLATE
.exchange(BASE_URL + port + OWNER_URL + '/' + newOwner.getId(), HttpMethod.PUT, request, OwnerDto.class);
// Compare everything except timestamps
assertEquals(response.getStatusCode(), HttpStatus.OK);
assertEquals(newOwner.getId(), response.getBody().getId());
assertEquals(newOwner.getName(), response.getBody().getName());
}
} }

View File

@ -10,6 +10,9 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import java.io.IOException;
import java.sql.Date;
public abstract class OwnerDaoTestBase { public abstract class OwnerDaoTestBase {
@Autowired @Autowired
@ -31,9 +34,40 @@ public abstract class OwnerDaoTestBase {
} }
@Test @Test
@DisplayName("Adding a new horse with the incorrect parameters should throw DataAccessException") @DisplayName("Adding a new owner with the incorrect parameters should throw DataAccessException")
public void addingNewOwner_incorrectParameters_shouldThrowDataAccess() { public void addingNewOwner_incorrectParameters_shouldThrowDataAccess() {
Owner newOwner = new Owner(""); Owner newOwner = new Owner("");
assertThrows(DataAccessException.class, () -> ownerDao.addOwner(newOwner)); assertThrows(DataAccessException.class, () -> ownerDao.addOwner(newOwner));
} }
@Test
@DisplayName("Updating a owner with the correct parameters should return the owner")
public void updatingOwner_correctParameters_shouldReturnOwner() throws IOException {
// Create owner
Owner newOwner = new Owner("Chad");
Owner savedOwner = ownerDao.addOwner(newOwner);
// Update owner
newOwner.setId(savedOwner.getId());
newOwner.setName("Gigachad");
Owner updatedOwner = ownerDao.updateOwner(newOwner);
// Compare everything except updated timestamp
assertEquals(updatedOwner.getId(), newOwner.getId());
assertEquals(updatedOwner.getName(), newOwner.getName());
assertEquals(updatedOwner.getCreatedAt(), newOwner.getCreatedAt());
}
@Test
@DisplayName("Updating a owner with the incorrect parameters should throw DataAccessException")
public void updatingOwner_incorrectParameters_shouldThrowDataAccess() {
// Create owner
Owner newOwner = new Owner("Chad");
Owner savedOwner = ownerDao.addOwner(newOwner);
// Update owner
newOwner.setId(savedOwner.getId());
newOwner.setName("");
assertThrows(DataAccessException.class, () -> ownerDao.updateOwner(newOwner));
}
} }

View File

@ -36,4 +36,35 @@ public class OwnerServiceTest {
Owner newOwner = new Owner(""); Owner newOwner = new Owner("");
assertThrows(ValidationException.class, () -> ownerService.addOwner(newOwner)); assertThrows(ValidationException.class, () -> ownerService.addOwner(newOwner));
} }
@Test
@DisplayName("Updating a owner with the correct parameters will return the new owner")
public void updatingOwner_correctParameters_shouldReturnOwner() {
// Create owner
Owner newOwner = new Owner("Chad");
Owner savedOwner = ownerService.addOwner(newOwner);
// Update owner
newOwner.setId(savedOwner.getId());
newOwner.setName("Chad");
Owner updatedOwner = ownerService.updateOwner(newOwner);
// Compare everything except updated timestamp
assertEquals(updatedOwner.getId(), newOwner.getId());
assertEquals(updatedOwner.getName(), newOwner.getName());
assertEquals(updatedOwner.getCreatedAt(), newOwner.getCreatedAt());
}
@Test
@DisplayName("Updating a owner with the incorrect parameters will return the new owner")
public void updatingOwner_incorrectParameters_shouldThrowValidation() {
// Create owner
Owner newOwner = new Owner("Chad");
Owner savedOwner = ownerService.addOwner(newOwner);
// Update owner
newOwner.setId(savedOwner.getId());
newOwner.setName("");
assertThrows(ValidationException.class, () -> ownerService.updateOwner(newOwner));
}
} }