Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Wendys Racing Horses
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
tu-wien
Wendys Racing Horses
Commits
0f5f0d22
Commit
0f5f0d22
authored
Mar 19, 2020
by
Ivaylo Ivanov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
US02: Make it possible to upload a picture through the API
parent
f9a8d501
Changes
17
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
267 additions
and
29 deletions
+267
-29
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/HorseEndpoint.java
...en/sepm/assignment/individual/endpoint/HorseEndpoint.java
+20
-1
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java
...ien/sepm/assignment/individual/endpoint/dto/HorseDto.java
+15
-2
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java
...pm/assignment/individual/endpoint/mapper/HorseMapper.java
+2
-2
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java
...at/ac/tuwien/sepm/assignment/individual/entity/Horse.java
+17
-3
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/FileDao.java
...uwien/sepm/assignment/individual/persistence/FileDao.java
+13
-0
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseFileDao.java
.../assignment/individual/persistence/impl/HorseFileDao.java
+52
-0
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java
.../assignment/individual/persistence/impl/HorseJdbcDao.java
+10
-6
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/HorseService.java
...wien/sepm/assignment/individual/service/HorseService.java
+9
-0
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleHorseService.java
...ssignment/individual/service/impl/SimpleHorseService.java
+17
-6
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java
.../ac/tuwien/sepm/assignment/individual/util/Validator.java
+14
-0
backend/src/main/resources/application.yml
backend/src/main/resources/application.yml
+7
-0
backend/src/main/resources/sql/createSchema.sql
backend/src/main/resources/sql/createSchema.sql
+1
-0
backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java
.../assignment/individual/integration/HorseEndpointTest.java
+36
-5
backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java
...ignment/individual/unit/persistence/HorseDaoTestBase.java
+2
-2
backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseFileDaoTest.java
...ignment/individual/unit/persistence/HorseFileDaoTest.java
+50
-0
backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java
.../assignment/individual/unit/service/HorseServiceTest.java
+2
-2
backend/src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg
...c/tuwien/sepm/assignment/individual/integration/horse.jpg
+0
-0
No files found.
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/HorseEndpoint.java
View file @
0f5f0d22
...
@@ -12,8 +12,10 @@ import org.springframework.beans.factory.annotation.Autowired;
...
@@ -12,8 +12,10 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.dao.DataAccessException
;
import
org.springframework.dao.DataAccessException
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.multipart.MultipartFile
;
import
org.springframework.web.server.ResponseStatusException
;
import
org.springframework.web.server.ResponseStatusException
;
import
java.io.IOException
;
import
java.lang.invoke.MethodHandles
;
import
java.lang.invoke.MethodHandles
;
@RestController
@RestController
...
@@ -50,7 +52,7 @@ public class HorseEndpoint {
...
@@ -50,7 +52,7 @@ public class HorseEndpoint {
return
horseMapper
.
entityToDto
(
horseService
.
addHorse
(
horseEntity
));
return
horseMapper
.
entityToDto
(
horseService
.
addHorse
(
horseEntity
));
}
catch
(
ValidationException
e
)
{
}
catch
(
ValidationException
e
)
{
LOGGER
.
error
(
e
.
getMessage
());
LOGGER
.
error
(
e
.
getMessage
());
throw
new
ResponseStatusException
(
HttpStatus
.
UNPROCESSABLE_ENTITY
,
throw
new
ResponseStatusException
(
HttpStatus
.
BAD_REQUEST
,
"Error during adding new horse: "
+
e
.
getMessage
(),
e
);
"Error during adding new horse: "
+
e
.
getMessage
(),
e
);
}
catch
(
DataAccessException
e
)
{
}
catch
(
DataAccessException
e
)
{
LOGGER
.
error
(
e
.
getMessage
());
LOGGER
.
error
(
e
.
getMessage
());
...
@@ -58,4 +60,21 @@ public class HorseEndpoint {
...
@@ -58,4 +60,21 @@ public class HorseEndpoint {
"Something went wrong during the communication with the database"
,
e
);
"Something went wrong during the communication with the database"
,
e
);
}
}
}
}
@PostMapping
(
value
=
"/upload"
)
@ResponseStatus
(
HttpStatus
.
CREATED
)
public
void
addImage
(
@RequestParam
(
"file"
)
MultipartFile
image
)
{
LOGGER
.
info
(
"POST "
+
BASE_URL
+
"/upload"
);
try
{
horseService
.
saveImage
(
image
);
}
catch
(
ValidationException
e
)
{
LOGGER
.
error
(
e
.
getMessage
());
throw
new
ResponseStatusException
(
HttpStatus
.
BAD_REQUEST
,
"Unsupported file type provided. Supported file types are jpg and png."
);
}
catch
(
IOException
e
)
{
LOGGER
.
error
(
e
.
getMessage
());
throw
new
ResponseStatusException
(
HttpStatus
.
UNPROCESSABLE_ENTITY
,
"Something went wrong while uploading the file"
);
}
}
}
}
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/dto/HorseDto.java
View file @
0f5f0d22
...
@@ -14,26 +14,29 @@ public class HorseDto extends BaseDto {
...
@@ -14,26 +14,29 @@ public class HorseDto extends BaseDto {
private
short
score
;
private
short
score
;
private
ERace
race
;
private
ERace
race
;
private
Date
birthday
;
private
Date
birthday
;
private
String
imagePath
;
private
Long
owner
;
private
Long
owner
;
public
HorseDto
()
{}
public
HorseDto
()
{}
public
HorseDto
(
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
Long
owner
)
{
public
HorseDto
(
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
String
imagePath
,
Long
owner
)
{
this
.
name
=
name
;
this
.
name
=
name
;
this
.
description
=
description
;
this
.
description
=
description
;
this
.
score
=
score
;
this
.
score
=
score
;
this
.
birthday
=
birthday
;
this
.
birthday
=
birthday
;
this
.
race
=
race
;
this
.
race
=
race
;
this
.
imagePath
=
imagePath
;
this
.
owner
=
owner
;
this
.
owner
=
owner
;
}
}
public
HorseDto
(
Long
id
,
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
LocalDateTime
created
,
LocalDateTime
updated
,
Long
owner
)
{
public
HorseDto
(
Long
id
,
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
String
imagePath
,
LocalDateTime
created
,
LocalDateTime
updated
,
Long
owner
)
{
super
(
id
,
created
,
updated
);
super
(
id
,
created
,
updated
);
this
.
name
=
name
;
this
.
name
=
name
;
this
.
description
=
description
;
this
.
description
=
description
;
this
.
score
=
score
;
this
.
score
=
score
;
this
.
birthday
=
birthday
;
this
.
birthday
=
birthday
;
this
.
race
=
race
;
this
.
race
=
race
;
this
.
imagePath
=
imagePath
;
this
.
owner
=
owner
;
this
.
owner
=
owner
;
}
}
...
@@ -77,6 +80,14 @@ public class HorseDto extends BaseDto {
...
@@ -77,6 +80,14 @@ public class HorseDto extends BaseDto {
this
.
race
=
race
;
this
.
race
=
race
;
}
}
public
String
getImagePath
()
{
return
imagePath
;
}
public
void
setImagePath
(
String
imagePath
)
{
this
.
imagePath
=
imagePath
;
}
public
Long
getOwner
()
{
public
Long
getOwner
()
{
return
owner
;
return
owner
;
}
}
...
@@ -96,6 +107,7 @@ public class HorseDto extends BaseDto {
...
@@ -96,6 +107,7 @@ public class HorseDto extends BaseDto {
Objects
.
equals
(
score
,
h
.
score
)
&&
Objects
.
equals
(
score
,
h
.
score
)
&&
Objects
.
equals
(
birthday
,
h
.
birthday
)
&&
Objects
.
equals
(
birthday
,
h
.
birthday
)
&&
Objects
.
equals
(
race
,
h
.
race
)
&&
Objects
.
equals
(
race
,
h
.
race
)
&&
Objects
.
equals
(
imagePath
,
h
.
imagePath
)
&&
Objects
.
equals
(
owner
,
h
.
owner
);
Objects
.
equals
(
owner
,
h
.
owner
);
}
}
...
@@ -113,6 +125,7 @@ public class HorseDto extends BaseDto {
...
@@ -113,6 +125,7 @@ public class HorseDto extends BaseDto {
", score='"
+
score
+
'\''
+
", score='"
+
score
+
'\''
+
", birthday='"
+
df
.
format
(
birthday
)
+
'\''
+
", birthday='"
+
df
.
format
(
birthday
)
+
'\''
+
", race='"
+
race
+
'\''
+
", race='"
+
race
+
'\''
+
", imagePath='"
+
imagePath
+
'\''
+
", owner_id='"
+
owner
+
'\''
;
", owner_id='"
+
owner
+
'\''
;
}
}
...
...
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/endpoint/mapper/HorseMapper.java
View file @
0f5f0d22
...
@@ -8,10 +8,10 @@ import org.springframework.stereotype.Component;
...
@@ -8,10 +8,10 @@ import org.springframework.stereotype.Component;
@Component
@Component
public
class
HorseMapper
{
public
class
HorseMapper
{
public
HorseDto
entityToDto
(
Horse
horse
)
{
public
HorseDto
entityToDto
(
Horse
horse
)
{
return
new
HorseDto
(
horse
.
getId
(),
horse
.
getName
(),
horse
.
getDescription
(),
horse
.
getScore
(),
horse
.
getBirthday
(),
horse
.
getRace
(),
horse
.
getCreatedAt
(),
horse
.
getUpdatedAt
(),
horse
.
getOwner
());
return
new
HorseDto
(
horse
.
getId
(),
horse
.
getName
(),
horse
.
getDescription
(),
horse
.
getScore
(),
horse
.
getBirthday
(),
horse
.
getRace
(),
horse
.
get
ImagePath
(),
horse
.
get
CreatedAt
(),
horse
.
getUpdatedAt
(),
horse
.
getOwner
());
}
}
public
Horse
dtoToEntity
(
HorseDto
horse
)
{
public
Horse
dtoToEntity
(
HorseDto
horse
)
{
return
new
Horse
(
horse
.
getId
(),
horse
.
getName
(),
horse
.
getDescription
(),
horse
.
getScore
(),
horse
.
getBirthday
(),
horse
.
getRace
(),
horse
.
getOwner
());
return
new
Horse
(
horse
.
getId
(),
horse
.
getName
(),
horse
.
getDescription
(),
horse
.
getScore
(),
horse
.
getBirthday
(),
horse
.
getRace
(),
horse
.
get
ImagePath
(),
horse
.
get
Owner
());
}
}
}
}
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/entity/Horse.java
View file @
0f5f0d22
...
@@ -13,36 +13,40 @@ public class Horse extends BaseEntity {
...
@@ -13,36 +13,40 @@ public class Horse extends BaseEntity {
private
short
score
;
private
short
score
;
private
ERace
race
;
private
ERace
race
;
private
Date
birthday
;
private
Date
birthday
;
private
String
imagePath
;
private
Long
owner
;
private
Long
owner
;
public
Horse
()
{}
public
Horse
()
{}
public
Horse
(
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
Long
owner
)
{
public
Horse
(
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
String
imagePath
,
Long
owner
)
{
this
.
name
=
name
;
this
.
name
=
name
;
this
.
description
=
description
;
this
.
description
=
description
;
this
.
score
=
score
;
this
.
score
=
score
;
this
.
birthday
=
birthday
;
this
.
birthday
=
birthday
;
this
.
race
=
race
;
this
.
race
=
race
;
this
.
imagePath
=
imagePath
;
this
.
owner
=
owner
;
this
.
owner
=
owner
;
}
}
public
Horse
(
Long
id
,
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
Long
owner
)
{
public
Horse
(
Long
id
,
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
String
imagePath
,
Long
owner
)
{
super
(
id
);
super
(
id
);
this
.
name
=
name
;
this
.
name
=
name
;
this
.
description
=
description
;
this
.
description
=
description
;
this
.
score
=
score
;
this
.
score
=
score
;
this
.
birthday
=
birthday
;
this
.
birthday
=
birthday
;
this
.
race
=
race
;
this
.
race
=
race
;
this
.
imagePath
=
imagePath
;
this
.
owner
=
owner
;
this
.
owner
=
owner
;
}
}
public
Horse
(
Long
id
,
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
Long
owner
,
LocalDateTime
created
,
LocalDateTime
updated
)
{
public
Horse
(
Long
id
,
String
name
,
String
description
,
short
score
,
Date
birthday
,
ERace
race
,
String
imagePath
,
Long
owner
,
LocalDateTime
created
,
LocalDateTime
updated
)
{
super
(
id
,
created
,
updated
);
super
(
id
,
created
,
updated
);
this
.
name
=
name
;
this
.
name
=
name
;
this
.
description
=
description
;
this
.
description
=
description
;
this
.
score
=
score
;
this
.
score
=
score
;
this
.
birthday
=
birthday
;
this
.
birthday
=
birthday
;
this
.
race
=
race
;
this
.
race
=
race
;
this
.
imagePath
=
imagePath
;
this
.
owner
=
owner
;
this
.
owner
=
owner
;
}
}
...
@@ -86,6 +90,14 @@ public class Horse extends BaseEntity {
...
@@ -86,6 +90,14 @@ public class Horse extends BaseEntity {
this
.
race
=
race
;
this
.
race
=
race
;
}
}
public
String
getImagePath
()
{
return
imagePath
;
}
public
void
setImagePath
(
String
imagePath
)
{
this
.
imagePath
=
imagePath
;
}
public
Long
getOwner
()
{
public
Long
getOwner
()
{
return
owner
;
return
owner
;
}
}
...
@@ -105,6 +117,7 @@ public class Horse extends BaseEntity {
...
@@ -105,6 +117,7 @@ public class Horse extends BaseEntity {
Objects
.
equals
(
score
,
h
.
score
)
&&
Objects
.
equals
(
score
,
h
.
score
)
&&
Objects
.
equals
(
birthday
,
h
.
birthday
)
&&
Objects
.
equals
(
birthday
,
h
.
birthday
)
&&
Objects
.
equals
(
race
,
h
.
race
)
&&
Objects
.
equals
(
race
,
h
.
race
)
&&
Objects
.
equals
(
imagePath
,
h
.
imagePath
)
&&
Objects
.
equals
(
owner
,
h
.
owner
);
Objects
.
equals
(
owner
,
h
.
owner
);
}
}
...
@@ -122,6 +135,7 @@ public class Horse extends BaseEntity {
...
@@ -122,6 +135,7 @@ public class Horse extends BaseEntity {
", score='"
+
score
+
'\''
+
", score='"
+
score
+
'\''
+
", birthday='"
+
df
.
format
(
birthday
)
+
'\''
+
", birthday='"
+
df
.
format
(
birthday
)
+
'\''
+
", race='"
+
race
+
'\''
+
", race='"
+
race
+
'\''
+
", imagePath='"
+
imagePath
+
'\''
+
", owner='"
+
owner
+
'\''
;
", owner='"
+
owner
+
'\''
;
}
}
...
...
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/FileDao.java
0 → 100644
View file @
0f5f0d22
package
at.ac.tuwien.sepm.assignment.individual.persistence
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.IOException
;
public
interface
FileDao
{
/**
* Used for saving files on the local file system
* @param file file to save
*/
void
save
(
MultipartFile
file
)
throws
IOException
;
}
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseFileDao.java
0 → 100644
View file @
0f5f0d22
package
at.ac.tuwien.sepm.assignment.individual.persistence.impl
;
import
at.ac.tuwien.sepm.assignment.individual.persistence.FileDao
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Repository
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.File
;
import
java.io.IOException
;
import
java.lang.invoke.MethodHandles
;
import
java.nio.file.FileSystemException
;
import
java.nio.file.Files
;
@Repository
public
class
HorseFileDao
implements
FileDao
{
@Value
(
"${spring.upload.path}"
)
private
String
FILE_BASE_PATH
;
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
MethodHandles
.
lookup
().
lookupClass
());
public
HorseFileDao
()
{};
@Override
public
void
save
(
MultipartFile
file
)
throws
IOException
{
if
(
file
==
null
||
file
.
getOriginalFilename
()
==
null
||
file
.
isEmpty
())
throw
new
IOException
(
"Cannot save an empty file"
);
if
(!
file
.
getContentType
().
equals
(
"image/jpeg"
)
&&
!
file
.
getContentType
().
equals
(
"image/png"
))
throw
new
IOException
(
"Unsupported file type"
);
String
fileName
=
file
.
getOriginalFilename
();
LOGGER
.
trace
(
"Writing file to "
+
FILE_BASE_PATH
+
fileName
);
try
{
// Create directory if it doesn't exist
File
uploadDir
=
new
File
(
FILE_BASE_PATH
);
if
(!
uploadDir
.
exists
())
uploadDir
.
mkdir
();
// Save the file
if
(
uploadDir
.
exists
())
{
File
target
=
new
File
(
FILE_BASE_PATH
+
fileName
);
Files
.
write
(
target
.
toPath
(),
file
.
getBytes
());
}
else
{
throw
new
FileSystemException
(
"Base upload directory "
+
FILE_BASE_PATH
+
" does not exist"
);
}
}
catch
(
Exception
e
)
{
LOGGER
.
error
(
e
.
getMessage
());
throw
new
IOException
(
"Saving the file failed"
);
}
}
}
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/persistence/impl/HorseJdbcDao.java
View file @
0f5f0d22
...
@@ -50,11 +50,11 @@ public class HorseJdbcDao implements HorseDao {
...
@@ -50,11 +50,11 @@ public class HorseJdbcDao implements HorseDao {
@Override
@Override
public
Horse
addHorse
(
Horse
horse
)
throws
DataAccessException
{
public
Horse
addHorse
(
Horse
horse
)
throws
DataAccessException
{
LOGGER
.
trace
(
"Add horse {}"
,
horse
.
toString
());
LOGGER
.
trace
(
"Add horse {}"
,
horse
.
toString
());
String
sql
=
"INSERT INTO "
+
TABLE_NAME
+
"(name, description, score, birthday, race,
owner_id, created_at, updated_at) VALUES(
?, ?, ?, ?, ?, ?, ?, ?)"
;
String
sql
=
"INSERT INTO "
+
TABLE_NAME
+
"(name, description, score, birthday, race,
image_path, owner_id, created_at, updated_at) VALUES(?,
?, ?, ?, ?, ?, ?, ?, ?)"
;
try
{
try
{
// Check if the constraints are violated
// Check if the constraints are violated
if
(
horse
.
getName
()
==
null
||
horse
.
getScore
()
==
0
||
horse
.
getBirthday
()
==
null
||
horse
.
getRace
()
==
null
)
if
(
horse
.
getName
()
==
null
||
horse
.
getScore
()
==
0
||
horse
.
getBirthday
()
==
null
||
horse
.
getRace
()
==
null
||
horse
.
getImagePath
()
==
null
)
throw
new
DataIntegrityViolationException
(
"Required parameters for horse missing"
);
throw
new
DataIntegrityViolationException
(
"Required parameters for horse missing"
);
LocalDateTime
currentTime
=
LocalDateTime
.
now
();
LocalDateTime
currentTime
=
LocalDateTime
.
now
();
...
@@ -74,13 +74,15 @@ public class HorseJdbcDao implements HorseDao {
...
@@ -74,13 +74,15 @@ public class HorseJdbcDao implements HorseDao {
ps
.
setDate
(
4
,
horse
.
getBirthday
());
ps
.
setDate
(
4
,
horse
.
getBirthday
());
ps
.
setString
(
5
,
horse
.
getRace
().
toString
());
// Convert to string to be able to save in DB
ps
.
setString
(
5
,
horse
.
getRace
().
toString
());
// Convert to string to be able to save in DB
ps
.
setString
(
6
,
horse
.
getImagePath
());
if
(
horse
.
getOwner
()
==
null
||
horse
.
getOwner
()
==
0
)
if
(
horse
.
getOwner
()
==
null
||
horse
.
getOwner
()
==
0
)
ps
.
setNull
(
6
,
Types
.
NULL
);
ps
.
setNull
(
7
,
Types
.
NULL
);
else
else
ps
.
setObject
(
6
,
horse
.
getOwner
());
ps
.
setObject
(
7
,
horse
.
getOwner
());
ps
.
setObject
(
7
,
horse
.
getCreatedAt
());
ps
.
setObject
(
8
,
horse
.
getCreatedAt
());
ps
.
setObject
(
8
,
horse
.
getUpdatedAt
());
ps
.
setObject
(
9
,
horse
.
getUpdatedAt
());
return
ps
;
return
ps
;
},
keyHolder
);
},
keyHolder
);
...
@@ -98,6 +100,7 @@ public class HorseJdbcDao implements HorseDao {
...
@@ -98,6 +100,7 @@ public class HorseJdbcDao implements HorseDao {
}
}
}
}
private
Horse
mapRow
(
ResultSet
resultSet
,
int
i
)
throws
SQLException
{
private
Horse
mapRow
(
ResultSet
resultSet
,
int
i
)
throws
SQLException
{
final
Horse
horse
=
new
Horse
();
final
Horse
horse
=
new
Horse
();
horse
.
setId
(
resultSet
.
getLong
(
"id"
));
horse
.
setId
(
resultSet
.
getLong
(
"id"
));
...
@@ -107,6 +110,7 @@ public class HorseJdbcDao implements HorseDao {
...
@@ -107,6 +110,7 @@ public class HorseJdbcDao implements HorseDao {
horse
.
setBirthday
(
resultSet
.
getDate
(
"birthday"
));
horse
.
setBirthday
(
resultSet
.
getDate
(
"birthday"
));
horse
.
setRace
(
ERace
.
valueOf
(
resultSet
.
getString
(
"race"
)));
// Convert to Enum for usage in objects
horse
.
setRace
(
ERace
.
valueOf
(
resultSet
.
getString
(
"race"
)));
// Convert to Enum for usage in objects
horse
.
setOwner
(
resultSet
.
getLong
(
"owner_id"
));
horse
.
setOwner
(
resultSet
.
getLong
(
"owner_id"
));
horse
.
setImagePath
(
resultSet
.
getString
(
"image_path"
));
horse
.
setCreatedAt
(
resultSet
.
getTimestamp
(
"created_at"
).
toLocalDateTime
());
horse
.
setCreatedAt
(
resultSet
.
getTimestamp
(
"created_at"
).
toLocalDateTime
());
horse
.
setUpdatedAt
(
resultSet
.
getTimestamp
(
"updated_at"
).
toLocalDateTime
());
horse
.
setUpdatedAt
(
resultSet
.
getTimestamp
(
"updated_at"
).
toLocalDateTime
());
return
horse
;
return
horse
;
...
...
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/HorseService.java
View file @
0f5f0d22
...
@@ -2,6 +2,9 @@ package at.ac.tuwien.sepm.assignment.individual.service;
...
@@ -2,6 +2,9 @@ package at.ac.tuwien.sepm.assignment.individual.service;
import
at.ac.tuwien.sepm.assignment.individual.entity.Horse
;
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.exception.NotFoundException
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.IOException
;
public
interface
HorseService
{
public
interface
HorseService
{
/**
/**
...
@@ -19,4 +22,10 @@ public interface HorseService {
...
@@ -19,4 +22,10 @@ public interface HorseService {
* @throws NotFoundException will be thrown if the horse could not be found in the system.
* @throws NotFoundException will be thrown if the horse could not be found in the system.
*/
*/
Horse
addHorse
(
Horse
horse
);
Horse
addHorse
(
Horse
horse
);
/**
* @param img image to upload
* @throws IOException will be thrown if something goes wrong with saving the file
*/
void
saveImage
(
MultipartFile
img
)
throws
IOException
;
}
}
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/service/impl/SimpleHorseService.java
View file @
0f5f0d22
package
at.ac.tuwien.sepm.assignment.individual.service.impl
;
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.entity.Horse
;
import
at.ac.tuwien.sepm.assignment.individual.persistence.FileDao
;
import
at.ac.tuwien.sepm.assignment.individual.persistence.HorseDao
;
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.service.HorseService
;
import
at.ac.tuwien.sepm.assignment.individual.util.ValidationException
;
import
at.ac.tuwien.sepm.assignment.individual.util.ValidationException
;
...
@@ -10,32 +11,42 @@ import org.slf4j.LoggerFactory;
...
@@ -10,32 +11,42 @@ import org.slf4j.LoggerFactory;
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
org.springframework.stereotype.Service
;
import
org.springframework.stereotype.Service
;
import
org.springframework.web.multipart.MultipartFile
;
import
java.io.IOException
;
import
java.lang.invoke.MethodHandles
;
import
java.lang.invoke.MethodHandles
;
import
java.text.SimpleDateFormat
;
@Service
@Service
public
class
SimpleHorseService
implements
HorseService
{
public
class
SimpleHorseService
implements
HorseService
{
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
MethodHandles
.
lookup
().
lookupClass
());
private
static
final
Logger
LOGGER
=
LoggerFactory
.
getLogger
(
MethodHandles
.
lookup
().
lookupClass
());
private
final
HorseDao
horseDao
;
private
final
HorseDao
horseJdbcDao
;
private
final
FileDao
horseFileDao
;
private
final
Validator
validator
;
private
final
Validator
validator
;
@Autowired
@Autowired
public
SimpleHorseService
(
HorseDao
horseDao
,
Validator
validator
)
{
public
SimpleHorseService
(
HorseDao
horseJdbcDao
,
FileDao
horseFileDao
,
Validator
validator
)
{
this
.
horseDao
=
horseDao
;
this
.
horseJdbcDao
=
horseJdbcDao
;
this
.
horseFileDao
=
horseFileDao
;
this
.
validator
=
validator
;
this
.
validator
=
validator
;
}
}
@Override
@Override
public
Horse
findOneById
(
Long
id
)
{
public
Horse
findOneById
(
Long
id
)
{
LOGGER
.
trace
(
"findOneById({})"
,
id
);
LOGGER
.
trace
(
"findOneById({})"
,
id
);
return
horseDao
.
findOneById
(
id
);
return
horse
Jdbc
Dao
.
findOneById
(
id
);
}
}
@Override
@Override
public
Horse
addHorse
(
Horse
horse
)
throws
ValidationException
,
DataAccessException
{
public
Horse
addHorse
(
Horse
horse
)
throws
ValidationException
,
DataAccessException
{
this
.
validator
.
validateNewHorse
(
horse
);
this
.
validator
.
validateNewHorse
(
horse
);
LOGGER
.
trace
(
"addHorse({})"
,
horse
.
toString
());
LOGGER
.
trace
(
"addHorse({})"
,
horse
.
toString
());
return
horseDao
.
addHorse
(
horse
);
return
horseJdbcDao
.
addHorse
(
horse
);
}
@Override
public
void
saveImage
(
MultipartFile
img
)
throws
ValidationException
,
IOException
{
this
.
validator
.
validateHorseImage
(
img
);
LOGGER
.
trace
(
"saveImage({})"
,
img
.
getName
());
horseFileDao
.
save
(
img
);
}
}
}
}
backend/src/main/java/at/ac/tuwien/sepm/assignment/individual/util/Validator.java
View file @
0f5f0d22
...
@@ -3,6 +3,7 @@ package at.ac.tuwien.sepm.assignment.individual.util;
...
@@ -3,6 +3,7 @@ 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.Horse
;
import
at.ac.tuwien.sepm.assignment.individual.entity.Owner
;
import
at.ac.tuwien.sepm.assignment.individual.entity.Owner
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.multipart.MultipartFile
;
@Component
@Component
public
class
Validator
{
public
class
Validator
{
...
@@ -22,5 +23,18 @@ public class Validator {
...
@@ -22,5 +23,18 @@ public class Validator {
if
(
horse
.
getScore
()
>
5
||
horse
.
getScore
()
<
1
)
{
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"
);
throw
new
ValidationException
(
"Score value "
+
horse
.
getScore
()
+
" not allowed. The score must be an integer between 1 and 5"
);
}
}
if
(!
horse
.
getImagePath
().
endsWith
(
".png"
)
&&
!
horse
.
getImagePath
().
endsWith
(
".jpg"
)
&&
!
horse
.
getImagePath
().
endsWith
(
".jpeg"
))
{
throw
new
ValidationException
(
"Unsupported file type supplied. Supported file types are jpg and png"
);
}
}
public
void
validateHorseImage
(
MultipartFile
image
)
throws
ValidationException
{
if
(
image
==
null
||
image
.
getContentType
()
==
null
||
image
.
isEmpty
())
{
throw
new
ValidationException
(
"No image supplied"
);
}
if
(!
image
.
getContentType
().
equals
(
"image/png"
)
&&
!
image
.
getContentType
().
equals
(
"image/jpeg"
))
{
throw
new
ValidationException
(
"Unsupported file type supplied: "
+
image
.
getContentType
());
}
}
}
}
}
backend/src/main/resources/application.yml
View file @
0f5f0d22
...
@@ -15,5 +15,12 @@ spring:
...
@@ -15,5 +15,12 @@ spring:
h2
:
h2
:
console
:
console
:
enabled
:
true
enabled
:
true
upload
:
path
:
/tmp/uploads/
servlet
:
multipart
:
enabled
:
true
max-file-size
:
10MB
max-request-size
:
15MB
server
:
server
:
port
:
8080
port
:
8080
backend/src/main/resources/sql/createSchema.sql
View file @
0f5f0d22
...
@@ -17,6 +17,7 @@ CREATE TABLE IF NOT EXISTS horse
...
@@ -17,6 +17,7 @@ CREATE TABLE IF NOT EXISTS horse
score
TINYINT
NOT
NULL
CHECK
(
score
>=
1
AND
score
<=
5
),
score
TINYINT
NOT
NULL
CHECK
(
score
>=
1
AND
score
<=
5
),
birthday
DATE
NOT
NULL
,
birthday
DATE
NOT
NULL
,
race
RACE
NOT
NULL
,
race
RACE
NOT
NULL
,
image_path
VARCHAR
(
255
)
NOT
NULL
,
created_at
DATETIME
NOT
NULL
,
created_at
DATETIME
NOT
NULL
,
updated_at
DATETIME
NOT
NULL
updated_at
DATETIME
NOT
NULL
);
);
...
...
backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/integration/HorseEndpointTest.java
View file @
0f5f0d22
...
@@ -6,20 +6,25 @@ import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.HorseDto;
...
@@ -6,20 +6,25 @@ import at.ac.tuwien.sepm.assignment.individual.endpoint.dto.HorseDto;
import
at.ac.tuwien.sepm.assignment.individual.enums.ERace
;
import
at.ac.tuwien.sepm.assignment.individual.enums.ERace
;
import
org.junit.jupiter.api.DisplayName
;
import
org.junit.jupiter.api.DisplayName
;
import
org.junit.jupiter.api.Test
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.boot.web.server.LocalServerPort
;
import
org.springframework.boot.web.server.LocalServerPort
;
import
org.springframework.http.HttpEntity
;
import
org.springframework.core.io.ClassPathResource
;
import
org.springframework.http.HttpMethod
;
import
org.springframework.http.*
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.test.context.ActiveProfiles
;
import
org.springframework.test.context.ActiveProfiles
;
import
org.springframework.test.context.event.annotation.AfterTestMethod
;
import
org.springframework.util.LinkedMultiValueMap
;
import
org.springframework.util.MultiValueMap
;
import
org.springframework.web.client.RestTemplate
;
import
org.springframework.web.client.RestTemplate
;
import
java.io.File
;
import
java.sql.Date
;
import
java.sql.Date
;
@SpringBootTest
(
webEnvironment
=
SpringBootTest
.
WebEnvironment
.
RANDOM_PORT
)
@SpringBootTest
(
webEnvironment
=
SpringBootTest
.
WebEnvironment
.
RANDOM_PORT
)
@ActiveProfiles
(
"test"
)
@ActiveProfiles
(
"test"
)
public
class
HorseEndpointTest
{
public
class
HorseEndpointTest
{
@Value
(
"${spring.upload.path}"
)
private
String
FILE_BASE_PATH
;
private
static
final
RestTemplate
REST_TEMPLATE
=
new
RestTemplate
();
private
static
final
RestTemplate
REST_TEMPLATE
=
new
RestTemplate
();
private
static
final
String
BASE_URL
=
"http://localhost:"
;
private
static
final
String
BASE_URL
=
"http://localhost:"
;
private
static
final
String
HORSE_URL
=
"/horses"
;
private
static
final
String
HORSE_URL
=
"/horses"
;
...
@@ -31,7 +36,7 @@ public class HorseEndpointTest {
...
@@ -31,7 +36,7 @@ public class HorseEndpointTest {
@DisplayName
(
"Adding a new horse with the correct parameters will return HTTP 201 and the new HorseDto"
)
@DisplayName
(
"Adding a new horse with the correct parameters will return HTTP 201 and the new HorseDto"
)
public
void
addingNewHorse_correctParameters_shouldReturnStatus201AndHorse
()
{
public
void
addingNewHorse_correctParameters_shouldReturnStatus201AndHorse
()
{
String
birthday
=
"2020-01-01"
;
String
birthday
=
"2020-01-01"
;
HorseDto
newHorse
=
new
HorseDto
(
"Zephyr"
,
"Nice horse"
,
(
short
)
4
,
Date
.
valueOf
(
birthday
),
ERace
.
APPALOOSA
,
null
);
HorseDto
newHorse
=
new
HorseDto
(
"Zephyr"
,
"Nice horse"
,
(
short
)
4
,
Date
.
valueOf
(
birthday
),
ERace
.
APPALOOSA
,
"files/test.png"
,
null
);
HttpEntity
<
HorseDto
>
request
=
new
HttpEntity
<>(
newHorse
);
HttpEntity
<
HorseDto
>
request
=
new
HttpEntity
<>(
newHorse
);
ResponseEntity
<
HorseDto
>
response
=
REST_TEMPLATE
ResponseEntity
<
HorseDto
>
response
=
REST_TEMPLATE
...
@@ -43,6 +48,32 @@ public class HorseEndpointTest {
...
@@ -43,6 +48,32 @@ public class HorseEndpointTest {
assertEquals
(
newHorse
.
getDescription
(),
response
.
getBody
().
getDescription
());
assertEquals
(
newHorse
.
getDescription
(),
response
.
getBody
().
getDescription
());
assertEquals
(
newHorse
.
getScore
(),
response
.
getBody
().
getScore
());
assertEquals
(
newHorse
.
getScore
(),
response
.
getBody
().
getScore
());
assertEquals
(
newHorse
.
getBirthday
().
toString
(),
response
.
getBody
().
getBirthday
().
toString
());
assertEquals
(
newHorse
.
getBirthday
().
toString
(),
response
.
getBody
().
getBirthday
().
toString
());
assertEquals
(
newHorse
.
getImagePath
(),
response
.
getBody
().
getImagePath
());
assertEquals
(
newHorse
.
getOwner
(),
response
.
getBody
().
getOwner
());
assertEquals
(
newHorse
.
getOwner
(),
response
.
getBody
().
getOwner
());
}
}
@Test
@DisplayName
(
"Uploading an image in the correct format will return HTTP 201"
)
public
void
addingNewImage_correctFormat_shouldReturnStatus201
()
{
try
{
// More information:
// https://www.baeldung.com/spring-rest-template-multipart-upload
// https://github.com/spring-guides/gs-uploading-files/blob/master/complete/src/test/java/com/example/uploadingfiles/FileUploadIntegrationTests.java
// Get the file
ClassPathResource
image
=
new
ClassPathResource
(
"horse.jpg"
,
getClass
());
// Set the body
MultiValueMap
<
String
,
Object
>
body
=
new
LinkedMultiValueMap
<>();
body
.
add
(
"file"
,
image
);
// Create the HTTP Entity
HttpEntity
<
MultiValueMap
<
String
,
Object
>>
request
=
new
HttpEntity
<>(
body
);
ResponseEntity
<
String
>
response
=
REST_TEMPLATE
.
postForEntity
(
BASE_URL
+
port
+
HORSE_URL
+
"/upload"
,
request
,
String
.
class
);
assertEquals
(
HttpStatus
.
CREATED
,
response
.
getStatusCode
());
}
finally
{
new
File
(
FILE_BASE_PATH
+
"horse.jpg"
).
delete
();
}
}
}
}
backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseDaoTestBase.java
View file @
0f5f0d22
...
@@ -21,7 +21,7 @@ public abstract class HorseDaoTestBase {
...
@@ -21,7 +21,7 @@ public abstract class HorseDaoTestBase {
@DisplayName
(
"Adding a new horse with the correct parameters should return the horse"
)
@DisplayName
(
"Adding a new horse with the correct parameters should return the horse"
)
public
void
addingNewHorse_correctParameters_shouldReturnHorse
()
{
public
void
addingNewHorse_correctParameters_shouldReturnHorse
()
{
String
birthday
=
"2020-01-01"
;
String
birthday
=
"2020-01-01"
;
Horse
newHorse
=
new
Horse
(
"Zephyr"
,
"Nice horse"
,
(
short
)
4
,
Date
.
valueOf
(
birthday
),
ERace
.
APPALOOSA
,
null
);
Horse
newHorse
=
new
Horse
(
"Zephyr"
,
"Nice horse"
,
(
short
)
4
,
Date
.
valueOf
(
birthday
),
ERace
.
APPALOOSA
,
"files/test.png"
,
null
);
Horse
savedHorse
=
horseDao
.
addHorse
(
newHorse
);
Horse
savedHorse
=
horseDao
.
addHorse
(
newHorse
);
assertEquals
(
newHorse
,
savedHorse
);
assertEquals
(
newHorse
,
savedHorse
);
}
}
...
@@ -30,7 +30,7 @@ public abstract class HorseDaoTestBase {
...
@@ -30,7 +30,7 @@ public abstract class HorseDaoTestBase {
@DisplayName
(
"Adding a new horse with the incorrect parameters should throw DataAccessException"
)
@DisplayName
(
"Adding a new horse with the incorrect parameters should throw DataAccessException"
)
public
void
addingNewHorse_incorrectParameters_shouldThrowDataAccess
()
{
public
void
addingNewHorse_incorrectParameters_shouldThrowDataAccess
()
{
String
birthday
=
"2020-01-01"
;
String
birthday
=
"2020-01-01"
;
Horse
newHorse
=
new
Horse
(
"Zephyr"
,
"Nice horse"
,
(
short
)
80
,
Date
.
valueOf
(
birthday
),
null
,
null
);
Horse
newHorse
=
new
Horse
(
"Zephyr"
,
"Nice horse"
,
(
short
)
80
,
Date
.
valueOf
(
birthday
),
null
,
null
,
null
);
assertThrows
(
DataAccessException
.
class
,
()
->
horseDao
.
addHorse
(
newHorse
));
assertThrows
(
DataAccessException
.
class
,
()
->
horseDao
.
addHorse
(
newHorse
));
}
}
...
...
backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/persistence/HorseFileDaoTest.java
0 → 100644
View file @
0f5f0d22
package
at.ac.tuwien.sepm.assignment.individual.unit.persistence
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.*;
import
at.ac.tuwien.sepm.assignment.individual.persistence.impl.HorseFileDao
;
import
org.junit.jupiter.api.AfterEach
;
import
org.junit.jupiter.api.DisplayName
;
import
org.junit.jupiter.api.Test
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
org.springframework.http.MediaType
;
import
org.springframework.mock.web.MockMultipartFile
;
import
org.springframework.test.context.ActiveProfiles
;
import
java.io.File
;
import
java.io.FileInputStream
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
@SpringBootTest
@ActiveProfiles
(
"test"
)
public
class
HorseFileDaoTest
{
@Value
(
"${spring.upload.path}"
)
private
String
FILE_BASE_PATH
;
@Autowired
HorseFileDao
horseFileDao
;
@Test
@DisplayName
(
"Creating a file with the correct type should result in a saved file"
)
public
void
savingFile_correctType_shouldWriteFile
()
throws
FileNotFoundException
,
IOException
{
File
image
=
new
File
(
"src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg"
);
horseFileDao
.
save
(
new
MockMultipartFile
(
"file"
,
image
.
getName
(),
MediaType
.
IMAGE_JPEG_VALUE
,
new
FileInputStream
(
image
)));
File
savedImage
=
new
File
(
FILE_BASE_PATH
+
"horse.jpg"
);
assertTrue
(
savedImage
.
exists
());
assertTrue
(
savedImage
.
isFile
());
}
@Test
@DisplayName
(
"Creating a file with the correct type should result in a saved file"
)
public
void
savingFile_incorrectType_shouldThrowIOException
()
throws
FileNotFoundException
,
IOException
{
File
image
=
new
File
(
"src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg"
);
assertThrows
(
IOException
.
class
,
()
->
horseFileDao
.
save
(
new
MockMultipartFile
(
"file"
,
image
.
getName
(),
MediaType
.
TEXT_HTML_VALUE
,
new
FileInputStream
(
image
))));
}
@AfterEach
public
void
cleanup
()
{
new
File
(
FILE_BASE_PATH
+
"horse.jpg"
).
delete
();
}
}
backend/src/test/java/at/ac/tuwien/sepm/assignment/individual/unit/service/HorseServiceTest.java
View file @
0f5f0d22
...
@@ -29,7 +29,7 @@ public class HorseServiceTest {
...
@@ -29,7 +29,7 @@ public class HorseServiceTest {
@DisplayName
(
"Adding a new horse with the correct parameters will return the new horse"
)
@DisplayName
(
"Adding a new horse with the correct parameters will return the new horse"
)
public
void
addingNewHorse_correctParameters_shouldReturnHorse
()
{
public
void
addingNewHorse_correctParameters_shouldReturnHorse
()
{
String
birthday
=
"2020-01-01"
;
String
birthday
=
"2020-01-01"
;
Horse
newHorse
=
new
Horse
(
"Zephyr"
,
"Nice horse"
,
(
short
)
4
,
Date
.
valueOf
(
birthday
),
ERace
.
APPALOOSA
,
null
);
Horse
newHorse
=
new
Horse
(
"Zephyr"
,
"Nice horse"
,
(
short
)
4
,
Date
.
valueOf
(
birthday
),
ERace
.
APPALOOSA
,
"files/test.png"
,
null
);
Horse
savedHorse
=
horseService
.
addHorse
(
newHorse
);
Horse
savedHorse
=
horseService
.
addHorse
(
newHorse
);
assertEquals
(
newHorse
,
savedHorse
);
assertEquals
(
newHorse
,
savedHorse
);
}
}
...
@@ -38,7 +38,7 @@ public class HorseServiceTest {
...
@@ -38,7 +38,7 @@ public class HorseServiceTest {
@DisplayName
(
"Adding a new horse with the incorrect parameters will throw a ValidationException"
)
@DisplayName
(
"Adding a new horse with the incorrect parameters will throw a ValidationException"
)
public
void
addingNewHorse_incorrectParameters_shouldThrowValidation
()
{
public
void
addingNewHorse_incorrectParameters_shouldThrowValidation
()
{
String
birthday
=
"2020-01-01"
;
String
birthday
=
"2020-01-01"
;
Horse
newHorse
=
new
Horse
(
"Zephyr"
,
"Nice horse"
,
(
short
)
80
,
Date
.
valueOf
(
birthday
),
null
,
null
);
Horse
newHorse
=
new
Horse
(
"Zephyr"
,
"Nice horse"
,
(
short
)
80
,
Date
.
valueOf
(
birthday
),
null
,
null
,
null
);
assertThrows
(
ValidationException
.
class
,
()
->
horseService
.
addHorse
(
newHorse
));
assertThrows
(
ValidationException
.
class
,
()
->
horseService
.
addHorse
(
newHorse
));
}
}
}
}
backend/src/test/resources/at/ac/tuwien/sepm/assignment/individual/integration/horse.jpg
0 → 100644
View file @
0f5f0d22
53.6 KB
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment