US01: Make it possible for the user to add a horse through the API
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class WendysRennpferdeApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(WendysRennpferdeApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,14 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**").allowedMethods("GET", "POST", "OPTION", "HEAD", "DELETE", "PUT", "PATCH");
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.endpoint;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.HorseDto;
|
||||
import at.ac.tuwien.sepm.assignment.individual.endpoint.mapper.HorseMapper;
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Horse;
|
||||
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
||||
import at.ac.tuwien.sepm.assignment.individual.service.HorseService;
|
||||
import at.ac.tuwien.sepm.assignment.individual.util.ValidationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(at.ac.tuwien.sepm.assignment.individual.endpoint.HorseEndpoint.BASE_URL)
|
||||
public class HorseEndpoint {
|
||||
|
||||
static final String BASE_URL = "/horses";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private final HorseService horseService;
|
||||
private final HorseMapper horseMapper;
|
||||
|
||||
@Autowired
|
||||
public HorseEndpoint(HorseService horseService, HorseMapper horseMapper) {
|
||||
this.horseService = horseService;
|
||||
this.horseMapper = horseMapper;
|
||||
}
|
||||
|
||||
@GetMapping(value = "/{id}")
|
||||
public HorseDto getOneById(@PathVariable("id") Long id) {
|
||||
LOGGER.info("GET " + BASE_URL + "/{}", id);
|
||||
try {
|
||||
return horseMapper.entityToDto(horseService.findOneById(id));
|
||||
} catch (NotFoundException e) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Error during reading horse", e);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
public HorseDto addHorse(@RequestBody HorseDto horse) {
|
||||
LOGGER.info("POST " + BASE_URL);
|
||||
try {
|
||||
Horse horseEntity = horseMapper.dtoToEntity(horse);
|
||||
return horseMapper.entityToDto(horseService.addHorse(horseEntity));
|
||||
} catch (ValidationException e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
"Error during adding new horse: " + e.getMessage(), e);
|
||||
} catch (DataAccessException e) {
|
||||
LOGGER.error(e.getMessage());
|
||||
throw new ResponseStatusException(HttpStatus.UNPROCESSABLE_ENTITY,
|
||||
"Something went wrong during the communication with the database", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.endpoint;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.OwnerDto;
|
||||
import at.ac.tuwien.sepm.assignment.individual.endpoint.mapper.OwnerMapper;
|
||||
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
||||
import at.ac.tuwien.sepm.assignment.individual.service.OwnerService;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(OwnerEndpoint.BASE_URL)
|
||||
public class OwnerEndpoint {
|
||||
|
||||
static final String BASE_URL = "/owners";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private final OwnerService ownerService;
|
||||
private final OwnerMapper ownerMapper;
|
||||
|
||||
@Autowired
|
||||
public OwnerEndpoint(OwnerService ownerService, OwnerMapper ownerMapper) {
|
||||
this.ownerService = ownerService;
|
||||
this.ownerMapper = ownerMapper;
|
||||
}
|
||||
|
||||
@GetMapping(value = "/{id}")
|
||||
public OwnerDto getOneById(@PathVariable("id") Long id) {
|
||||
LOGGER.info("GET " + BASE_URL + "/{}", id);
|
||||
try {
|
||||
return ownerMapper.entityToDto(ownerService.findOneById(id));
|
||||
} catch (NotFoundException e) {
|
||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Error during reading owner", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.endpoint.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
abstract class BaseDto {
|
||||
|
||||
private Long id;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
protected BaseDto() {
|
||||
}
|
||||
|
||||
public BaseDto(Long id, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||
this.id = id;
|
||||
this.createdAt = createdAt;
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof BaseDto)) return false;
|
||||
BaseDto baseDto = (BaseDto) o;
|
||||
return Objects.equals(id, baseDto.id) &&
|
||||
Objects.equals(createdAt, baseDto.createdAt) &&
|
||||
Objects.equals(updatedAt, baseDto.updatedAt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, createdAt, updatedAt);
|
||||
}
|
||||
|
||||
protected String fieldsString() {
|
||||
return "id=" + id +
|
||||
", createdAt=" + createdAt +
|
||||
", updatedAt=" + updatedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BaseDto{ " + fieldsString() + " }";
|
||||
}
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.endpoint.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
import java.sql.Date;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
public class HorseDto extends BaseDto {
|
||||
private String name;
|
||||
private String description;
|
||||
private short score;
|
||||
private Date birthday;
|
||||
private long owner;
|
||||
|
||||
public HorseDto() {}
|
||||
|
||||
public HorseDto(String name, String description, short score, Date birthday, Long owner) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.score = score;
|
||||
this.birthday = birthday;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public HorseDto(Long id, String name, String description, short score, Date birthday, LocalDateTime created, LocalDateTime updated, Long owner) {
|
||||
super(id, created, updated);
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.score = score;
|
||||
this.birthday = birthday;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public short getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(short score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public Date getBirthday() {
|
||||
return birthday;
|
||||
}
|
||||
|
||||
public void setBirthday(Date birthday) {
|
||||
this.birthday = birthday;
|
||||
}
|
||||
|
||||
public Long getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(Long owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof HorseDto)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
HorseDto horseDto = (HorseDto) o;
|
||||
return Objects.equals(name, horseDto.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fieldsString() {
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
return super.fieldsString() + ", name='" + name + '\'' +
|
||||
"description='" + description + '\'' +
|
||||
"score='" + score + '\'' +
|
||||
"birthday='" + df.format(birthday) + '\'' +
|
||||
"owner_id='" + owner + '\'';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HorseDto{ " + fieldsString() + " }";
|
||||
}
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.endpoint.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
public class OwnerDto extends BaseDto {
|
||||
|
||||
private String name;
|
||||
|
||||
public OwnerDto() {
|
||||
}
|
||||
|
||||
public OwnerDto(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public OwnerDto(Long id, String name, LocalDateTime created, LocalDateTime updated) {
|
||||
super(id, created, updated);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof OwnerDto)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
OwnerDto ownerDto = (OwnerDto) o;
|
||||
return Objects.equals(name, ownerDto.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fieldsString() {
|
||||
return super.fieldsString() + ", name='" + name + '\'';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OwnerDto{ " + fieldsString() + " }";
|
||||
}
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.endpoint.mapper;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.HorseDto;
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Horse;
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class HorseMapper {
|
||||
public HorseDto entityToDto(Horse horse) {
|
||||
return new HorseDto(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getCreatedAt(), horse.getUpdatedAt(), horse.getOwner());
|
||||
}
|
||||
|
||||
public Horse dtoToEntity(HorseDto horse) {
|
||||
return new Horse(horse.getId(), horse.getName(), horse.getDescription(), horse.getScore(), horse.getBirthday(), horse.getOwner());
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.endpoint.mapper;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.OwnerDto;
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class OwnerMapper {
|
||||
|
||||
public OwnerDto entityToDto(Owner owner) {
|
||||
return new OwnerDto(owner.getId(), owner.getName(), owner.getCreatedAt(), owner.getUpdatedAt());
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.entity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
abstract class BaseEntity {
|
||||
|
||||
private Long id;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
protected BaseEntity() {
|
||||
}
|
||||
|
||||
protected BaseEntity(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
protected BaseEntity(Long id, LocalDateTime createdAt, LocalDateTime updatedAt) {
|
||||
this.id = id;
|
||||
this.createdAt = createdAt;
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(LocalDateTime createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public LocalDateTime getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
|
||||
public void setUpdatedAt(LocalDateTime updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof BaseEntity)) return false;
|
||||
BaseEntity that = (BaseEntity) o;
|
||||
return Objects.equals(id, that.id) &&
|
||||
Objects.equals(createdAt, that.createdAt) &&
|
||||
Objects.equals(updatedAt, that.updatedAt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(id, createdAt, updatedAt);
|
||||
}
|
||||
|
||||
protected String fieldsString() {
|
||||
return "id=" + id +
|
||||
", createdAt=" + createdAt +
|
||||
", updatedAt=" + updatedAt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BaseEntity{ " + fieldsString() + " }";
|
||||
}
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.entity;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.sql.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Horse extends BaseEntity {
|
||||
private String name;
|
||||
private String description;
|
||||
private short score;
|
||||
private Date birthday;
|
||||
private Long owner;
|
||||
|
||||
public Horse() {}
|
||||
|
||||
public Horse(String name, String description, short score, Date birthday, Long owner) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.score = score;
|
||||
this.birthday = birthday;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Horse(Long id, String name, String description, short score, Date birthday, Long owner) {
|
||||
super(id);
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.score = score;
|
||||
this.birthday = birthday;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Horse(Long id, String name, String description, short score, Date birthday, Long owner, LocalDateTime created, LocalDateTime updated) {
|
||||
super(id, created, updated);
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.score = score;
|
||||
this.birthday = birthday;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public short getScore() {
|
||||
return score;
|
||||
}
|
||||
|
||||
public void setScore(short score) {
|
||||
this.score = score;
|
||||
}
|
||||
|
||||
public Date getBirthday() {
|
||||
return birthday;
|
||||
}
|
||||
|
||||
public void setBirthday(Date birthday) {
|
||||
this.birthday = birthday;
|
||||
}
|
||||
|
||||
public Long getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(Long owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Horse)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
Horse Horse = (Horse) o;
|
||||
return Objects.equals(name, Horse.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fieldsString() {
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
return super.fieldsString() + ", name='" + name + '\'' +
|
||||
"description='" + description + '\'' +
|
||||
"score='" + score + '\'' +
|
||||
"birthday='" + df.format(birthday) + '\'' +
|
||||
"owner='" + owner + '\'';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Horse{ " + fieldsString() + " }";
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.entity;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Owner extends BaseEntity {
|
||||
|
||||
private String name;
|
||||
|
||||
public Owner() {
|
||||
}
|
||||
|
||||
public Owner(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Owner(Long id, String name) {
|
||||
super(id);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Owner(Long id, String name, LocalDateTime created, LocalDateTime updated) {
|
||||
super(id, created, updated);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Owner)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
Owner owner = (Owner) o;
|
||||
return Objects.equals(name, owner.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String fieldsString() {
|
||||
return super.fieldsString() + ", name='" + name + '\'';
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Owner{ " + fieldsString() +" }";
|
||||
}
|
||||
}
|
@@ -0,0 +1,8 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.exception;
|
||||
|
||||
public class NotFoundException extends RuntimeException {
|
||||
|
||||
public NotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.persistence;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.sql.DataSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.jdbc.datasource.init.ScriptUtils;
|
||||
|
||||
/**
|
||||
* This component is only created, if the profile {@code datagen} is active
|
||||
* You can activate this profile by adding {@code -Dspring.profiles.active=datagen} to your maven command line
|
||||
*/
|
||||
@Configuration
|
||||
@Profile("datagen")
|
||||
public class DataGeneratorBean {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private DataSource source;
|
||||
|
||||
public DataGeneratorBean(DataSource source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed once when the component is instantiated. Inserts some dummy data.
|
||||
*/
|
||||
@PostConstruct
|
||||
void insertDummyData() {
|
||||
try {
|
||||
ScriptUtils.executeSqlScript(source.getConnection(), new ClassPathResource("sql/insertData.sql"));
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Error inserting test data", e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.persistence;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Horse;
|
||||
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
public interface HorseDao {
|
||||
|
||||
/**
|
||||
* @param id of the horse to find.
|
||||
* @return the horse with the specified id.
|
||||
* @throws DataAccessException will be thrown if something goes wrong during the database access.
|
||||
* @throws NotFoundException will be thrown if the horse could not be found in the database.
|
||||
*/
|
||||
Horse findOneById(Long id);
|
||||
|
||||
/**
|
||||
* @param horse that specifies the horse to add
|
||||
* @return the newly created horse
|
||||
* @throws DataAccessException will be thrown if something goes wrong during the database access.
|
||||
*/
|
||||
Horse addHorse(Horse horse);
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.persistence;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
|
||||
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
|
||||
public interface OwnerDao {
|
||||
|
||||
/**
|
||||
* @param id of the owner to find.
|
||||
* @return the owner with the specified id.
|
||||
* @throws DataAccessException will be thrown if something goes wrong during the database access.
|
||||
* @throws NotFoundException will be thrown if the owner could not be found in the database.
|
||||
*/
|
||||
Owner findOneById(Long id);
|
||||
|
||||
}
|
@@ -0,0 +1,104 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.persistence.impl;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Horse;
|
||||
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
||||
import at.ac.tuwien.sepm.assignment.individual.persistence.HorseDao;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.support.GeneratedKeyHolder;
|
||||
import org.springframework.jdbc.support.KeyHolder;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public class HorseJdbcDao implements HorseDao {
|
||||
private static final String TABLE_NAME = "horse";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
|
||||
public HorseJdbcDao(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Horse findOneById(Long id) {
|
||||
LOGGER.trace("Get horse with id {}", id);
|
||||
final String sql = "SELECT * FROM " + TABLE_NAME + " WHERE id=?";
|
||||
List<Horse> horses = jdbcTemplate.query(sql, new Object[] { id }, this::mapRow);
|
||||
|
||||
if (horses.isEmpty()) throw new NotFoundException("Could not find horse with id " + id);
|
||||
|
||||
return horses.get(0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Horse addHorse(Horse horse) throws DataAccessException {
|
||||
LOGGER.trace("Add horse {}", horse.toString());
|
||||
String sql = "INSERT INTO " + TABLE_NAME + "(name, description, score, birthday, owner_id, created_at, updated_at) VALUES(?, ?, ?, ?, ?, ?, ?)";
|
||||
|
||||
try {
|
||||
LocalDateTime currentTime = LocalDateTime.now();
|
||||
|
||||
horse.setCreatedAt(currentTime);
|
||||
horse.setUpdatedAt(currentTime);
|
||||
|
||||
// Create a key holder to get the key of the new record
|
||||
KeyHolder keyHolder = new GeneratedKeyHolder();
|
||||
|
||||
int changes = jdbcTemplate.update(connection -> {
|
||||
PreparedStatement ps = connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
|
||||
ps.setString(1, horse.getName());
|
||||
ps.setString(2, horse.getDescription());
|
||||
ps.setInt(3, horse.getScore());
|
||||
ps.setDate(4, horse.getBirthday());
|
||||
|
||||
if(horse.getOwner() == 0)
|
||||
ps.setNull(5, Types.NULL);
|
||||
else
|
||||
ps.setObject(5, horse.getOwner());
|
||||
|
||||
ps.setObject(6, horse.getCreatedAt());
|
||||
ps.setObject(7, horse.getUpdatedAt());
|
||||
return ps;
|
||||
}, keyHolder);
|
||||
|
||||
if (changes == 0)
|
||||
throw new NotFoundException("Creating horse failed, no rows affected");
|
||||
|
||||
horse.setId(((Number)keyHolder.getKeys().get("id")).longValue());
|
||||
return horse;
|
||||
|
||||
} catch (DataAccessException e) {
|
||||
// We are doing this in order to not change the exception type
|
||||
throw new DataAccessException("Adding new records failed", e) {};
|
||||
} catch(NotFoundException e){
|
||||
throw new DataRetrievalFailureException("No new records added", e);
|
||||
}
|
||||
}
|
||||
|
||||
private Horse mapRow(ResultSet resultSet, int i) throws SQLException {
|
||||
final Horse horse = new Horse();
|
||||
horse.setId(resultSet.getLong("id"));
|
||||
horse.setName(resultSet.getString("name"));
|
||||
horse.setDescription(resultSet.getString("description"));
|
||||
horse.setScore(resultSet.getShort("score"));
|
||||
horse.setBirthday(resultSet.getDate("birthday"));
|
||||
horse.setOwner(resultSet.getLong("owner_id"));
|
||||
|
||||
return horse;
|
||||
}
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.persistence.impl;
|
||||
|
||||
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.persistence.OwnerDao;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class OwnerJdbcDao implements OwnerDao {
|
||||
|
||||
private static final String TABLE_NAME = "Owner";
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
|
||||
|
||||
@Autowired
|
||||
public OwnerJdbcDao(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
|
||||
this.jdbcTemplate = jdbcTemplate;
|
||||
this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Owner findOneById(Long id) {
|
||||
LOGGER.trace("Get owner with id {}", id);
|
||||
final String sql = "SELECT * FROM " + TABLE_NAME + " WHERE id=?";
|
||||
List<Owner> owners = jdbcTemplate.query(sql, new Object[] { id }, this::mapRow);
|
||||
|
||||
if (owners.isEmpty()) throw new NotFoundException("Could not find owner with id " + id);
|
||||
|
||||
return owners.get(0);
|
||||
}
|
||||
|
||||
|
||||
private Owner mapRow(ResultSet resultSet, int i) throws SQLException {
|
||||
final Owner owner = new Owner();
|
||||
owner.setId(resultSet.getLong("id"));
|
||||
owner.setName(resultSet.getString("name"));
|
||||
owner.setCreatedAt(resultSet.getTimestamp("created_at").toLocalDateTime());
|
||||
owner.setUpdatedAt(resultSet.getTimestamp("updated_at").toLocalDateTime());
|
||||
return owner;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,22 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.service;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Horse;
|
||||
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
||||
|
||||
public interface HorseService {
|
||||
/**
|
||||
* @param id of the horse to find.
|
||||
* @return the horse with the specified id.
|
||||
* @throws RuntimeException will be thrown if something goes wrong during data processing.
|
||||
* @throws NotFoundException will be thrown if the horse could not be found in the system.
|
||||
*/
|
||||
Horse findOneById(Long id);
|
||||
|
||||
/**
|
||||
* @param horse to add.
|
||||
* @return the horse with the specified id.
|
||||
* @throws RuntimeException will be thrown if something goes wrong during data processing.
|
||||
* @throws NotFoundException will be thrown if the horse could not be found in the system.
|
||||
*/
|
||||
Horse addHorse(Horse horse);
|
||||
}
|
@@ -0,0 +1,17 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.service;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
|
||||
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
||||
|
||||
public interface OwnerService {
|
||||
|
||||
|
||||
/**
|
||||
* @param id of the owner to find.
|
||||
* @return the owner with the specified id.
|
||||
* @throws RuntimeException will be thrown if something goes wrong during data processing.
|
||||
* @throws NotFoundException will be thrown if the owner could not be found in the system.
|
||||
*/
|
||||
Owner findOneById(Long id);
|
||||
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.service.impl;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Horse;
|
||||
import at.ac.tuwien.sepm.assignment.individual.persistence.HorseDao;
|
||||
import at.ac.tuwien.sepm.assignment.individual.service.HorseService;
|
||||
import at.ac.tuwien.sepm.assignment.individual.util.ValidationException;
|
||||
import at.ac.tuwien.sepm.assignment.individual.util.Validator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
@Service
|
||||
public class SimpleHorseService implements HorseService {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private final HorseDao horseDao;
|
||||
private final Validator validator;
|
||||
|
||||
@Autowired
|
||||
public SimpleHorseService(HorseDao horseDao, Validator validator) {
|
||||
this.horseDao = horseDao;
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Horse findOneById(Long id) {
|
||||
LOGGER.trace("findOneById({})", id);
|
||||
return horseDao.findOneById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Horse addHorse(Horse horse) throws ValidationException, DataAccessException {
|
||||
LOGGER.trace("addHorse({})", horse.toString());
|
||||
this.validator.validateNewHorse(horse);
|
||||
return horseDao.addHorse(horse);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.service.impl;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
|
||||
import at.ac.tuwien.sepm.assignment.individual.persistence.OwnerDao;
|
||||
import at.ac.tuwien.sepm.assignment.individual.service.OwnerService;
|
||||
import at.ac.tuwien.sepm.assignment.individual.util.Validator;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class SimpleOwnerService implements OwnerService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private final OwnerDao ownerDao;
|
||||
private final Validator validator;
|
||||
|
||||
@Autowired
|
||||
public SimpleOwnerService(OwnerDao ownerDao, Validator validator) {
|
||||
this.ownerDao = ownerDao;
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Owner findOneById(Long id) {
|
||||
LOGGER.trace("findOneById({})", id);
|
||||
return ownerDao.findOneById(id);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.util;
|
||||
|
||||
public class ValidationException extends RuntimeException {
|
||||
|
||||
public ValidationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.util;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Horse;
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class Validator {
|
||||
|
||||
|
||||
|
||||
public void validateNewOwner(Owner owner) throws ValidationException {
|
||||
}
|
||||
|
||||
public void validateUpdateOwner(Owner owner) throws ValidationException {
|
||||
}
|
||||
|
||||
public void validateNewHorse(Horse horse) throws ValidationException {
|
||||
if(horse.getScore() > 5 || horse.getScore() < 1) {
|
||||
throw new ValidationException("Score value " + horse.getScore() + " not allowed. The score must be an integer between 1 and 5");
|
||||
}
|
||||
}
|
||||
}
|
0
backend/src/main/resources/application-test.yml
Normal file
0
backend/src/main/resources/application-test.yml
Normal file
19
backend/src/main/resources/application.yml
Normal file
19
backend/src/main/resources/application.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
logging:
|
||||
level:
|
||||
root: INFO
|
||||
file:
|
||||
name: ./log/wendys-friends.log
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: wendys-friends
|
||||
datasource:
|
||||
url: "jdbc:h2:./wendydb;INIT=RUNSCRIPT FROM 'classpath:sql/createSchema.sql'"
|
||||
username: "sa"
|
||||
password: ""
|
||||
driver-class-name: "org.h2.Driver"
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
server:
|
||||
port: 8080
|
21
backend/src/main/resources/sql/createSchema.sql
Normal file
21
backend/src/main/resources/sql/createSchema.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
CREATE TABLE IF NOT EXISTS owner
|
||||
(
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS horse
|
||||
(
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
score TINYINT NOT NULL CHECK(score >= 1 AND score <= 5),
|
||||
birthday DATE NOT NULL,
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE horse ADD IF NOT EXISTS owner_id BIGINT NULL;
|
||||
ALTER TABLE horse ADD CONSTRAINT IF NOT EXISTS FL_OWNER FOREIGN KEY (owner_id) REFERENCES owner(id);
|
7
backend/src/main/resources/sql/insertData.sql
Normal file
7
backend/src/main/resources/sql/insertData.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- insert initial test data
|
||||
-- the id is hardcode to enable references between further test data
|
||||
INSERT INTO owner (ID, NAME, CREATED_AT, UPDATED_AT)
|
||||
VALUES (1, 'Fred', CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()),
|
||||
(2, 'Julia', CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP()),
|
||||
(3, 'Kim', CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP());
|
||||
|
@@ -0,0 +1,30 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.base;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.entity.Owner;
|
||||
|
||||
public interface TestData {
|
||||
|
||||
/**
|
||||
* URI Data
|
||||
*/
|
||||
String BASE_URL = "http://localhost:";
|
||||
String HORSE_URL = "/horses";
|
||||
String OWNER_URL = "/owners";
|
||||
|
||||
/**
|
||||
* Owner Data
|
||||
*/
|
||||
static Owner getNewOwner() {
|
||||
return new Owner("Owner");
|
||||
}
|
||||
|
||||
static Owner getNewOwner(String name) {
|
||||
return new Owner(name);
|
||||
}
|
||||
|
||||
static Owner getNewOwnerWithId() {
|
||||
return new Owner(1L, "Owner");
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.unit.persistence;
|
||||
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.DefaultTransactionDefinition;
|
||||
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("test")
|
||||
public class OwnerDaoJdbcTest extends OwnerDaoTestBase {
|
||||
|
||||
@Autowired
|
||||
PlatformTransactionManager txm;
|
||||
|
||||
TransactionStatus txstatus;
|
||||
|
||||
@BeforeEach
|
||||
public void setupDBTransaction() {
|
||||
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
|
||||
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
|
||||
txstatus = txm.getTransaction(def);
|
||||
assumeTrue(txstatus.isNewTransaction());
|
||||
txstatus.setRollbackOnly();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void tearDownDBData() {
|
||||
txm.rollback(txstatus);
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
package at.ac.tuwien.sepm.assignment.individual.unit.persistence;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import at.ac.tuwien.sepm.assignment.individual.exception.NotFoundException;
|
||||
import at.ac.tuwien.sepm.assignment.individual.persistence.OwnerDao;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
public abstract class OwnerDaoTestBase {
|
||||
|
||||
@Autowired
|
||||
OwnerDao ownerDao;
|
||||
|
||||
@Test
|
||||
@DisplayName("Finding owner by non-existing ID should throw NotFoundException")
|
||||
public void findingOwnerById_nonExisting_shouldThrowNotFoundException() {
|
||||
assertThrows(NotFoundException.class,
|
||||
() -> ownerDao.findOneById(1L));
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user