uvod - dio prvi
Hrvoje Šimić
hsimic@[Link]
Cilj
UI REST API
(kasnije)
frontend backend
stvori
grupu
dodaj
studenta
student-
koordinator
admin
uključi
studenta
u grupu
sustav za formiranje projektnih grupa student
Instalirat ćemo...
Java 13 IntelliJ IDEA Postman
Kodificira najbolje prakse
Convention over configuration
Automatsko podešavanje
infrastrukture
Postavljanje Spring Boot
projekta
i m u m
min a n
e ri r
gen a
k o d
og
Domenski model i ORM
Kreirajmo domensku klasu
Student
n i za c i j a paketa
orga a, ali
ro iz v o lj n
je p d a svi
c ij a j e
konven d
budu ispo
osnovnog
@Entity
Entitet "student" public class Student {
ID studenta, @Id
surogatni primarni @GeneratedValue
ključ private Long id;
private String jmbag;
private String
givenName;
private String
familyName;
Uključivanje admin konzole
za bazu
[Link]: true
većina globalne
konfiguracije ide
u ovu datoteku
Tomcat started on port(s): 8080 (http) with context path ''
Started OppApplication in 7.858 seconds (JVM running for
8.852)
/h2-console
in-memory baza
samo kliknemo
Connect
@Entity
Entitet "student" public class Student {
ID studenta, @Id
surogatni primarni @GeneratedValue
ključ private Long id;
JMBAG je jedinstven, @Column(unique=true)
@NotNull
obavezan,
@Size(min=10, max=10)
duljine 10 znakova private String jmbag;
0036324986 private String
givenName;
t o o ls
dev a
a d -
relo i j
k a c
apli
u
Shema se
promijenila
@Size(min=10, max=10)
@NotNull
@Column(unique=true)
Tri sloja aplikacije
REST poslovna data
API logika access
Controlle Repositor
Service
r y
HTTP, JSON Java Java SQL
«interface»
Controller Service
«interface»
Service Repository
Repository
Spring Data repository
public interface StudentRepository
extends JpaRepository<Student, Long>
{
} tip entiteta, tip ID-a
public interface StudentService {
List<Student> listAll();
}
@Service
public class StudentServiceJpa implements
StudentService {
samoožičavanj @Autowired
e private StudentRepository studentRepo;
@Override
public List<Student> listAll() {
return [Link]();
}
}
kod je organiziran u
komponente
žice
komponente
Java source Spring konfiguracija
aplikacijski kontekst
aplikacijski kontekst = konfigurirane i spojene komponente
Student
Repositor
Student y
Controlle impl
r
Student
ServiceJp
a
Dependency injection
@Autowired
private StudentRepository studentRepo;
ry
to
si
po
Re
nt
de
tu
S
StudentServiceJpa
REST
Controller
@RestController
@RequestMapping("/students")
public class StudentController {
@Autowired
private StudentService studentService; Repositor
Service
y
@GetMapping("")
GET public List<Student> listStudents() {
/students return [Link]();
}
}
Poziv REST servisa
Postman
@RestController @Service
@RequestMapping("/students") public class StudentServiceJpa
public class StudentController { implements StudentService {
@Autowired @Autowired
private StudentService studentService; private StudentRepository studentRepo;
@GetMapping("") @Override
public List<Student> listStudents() { public List<Student> listAll() {
return [Link](); return [Link]();
} }
} }
?
public interface StudentRepository extends JpaRepository<Student, Long> {
}
Metode JpaRepository:
count delete
existsById deleteAll (2)
findAll (5) deleteAllInBatch
findAllById deleteById
findById flush
getOne save
saveAll
saveAndFlush
SELECT
GET listAll() findAll() FROM
/students student
List<Student List<Student SQL
JSON
> > resultset
Podaci iz JSON-a i u JSON
dodaj
studenta
sustav za formiranje projektnih grupa
/**
* Creates new student in the system.
* @param student object to create, with ID set to
null
* @return created student object in the system with
«interface»
ID set
Student * @throws IllegalArgumentException if given student
Service is null
* or its ID is not null
*/
Student createStudent(Student student);
@Override
public Student createStudent(Student student) {
Student [Link](student, "Student object must be given");
ServiceJp [Link]([Link](),
a "Student ID must be null, not" + [Link]()
);
return [Link](student);
}
REST servis za dodavanje
studenta
@PostMapping("")
public Student createStudent(@RequestBody Student student) {
return [Link](student);
}
POST /students
{
"jmbag": "1000000000", objekt
"givenName": "Ivica", Student
"familyName": "Ivić"
}
Naši upiti nad bazom
e š k a!
š a gr
= n a
500
???
@Override
public Student createStudent(Student student) {
[Link](student, "Student object must be given");
[Link]([Link](),
"Student ID must be null, not" + [Link]()
);
if ([Link]([Link]()) > 0)
throw new RequestDeniedException(
"Student with JMBAG " + [Link]() + " already exists
);
return [Link](student);
}
Metode JpaRepository:
count delete
existsById deleteAll (2)
in g) ?
findAll (5) S t r
deleteAllInBatch
g(
y Jm ba
o u n tB
findAllById deleteById
c
findById flush
getOne save
saveAll
saveAndFlush
public interface StudentRepository extends JpaRepository<Student, Long> {
int countByJmbag(String jmbag); gdje je
implementacija?
}
count By Jmbag
select count(*) from student s where [Link]=?
D a t a
pr i ng
S samo
treba etode
a zi v m
n
Exception handling
Obrada iznimki
@Override
public Student createStudent(Student student) {
[Link](student, "Student object must be given");
[Link]([Link](),
"Student ID must be null, not" + [Link]()
);
if ([Link]([Link]()) > 0)
throw new RequestDeniedException(
"Student with JMBAG " + [Link]() + " already exists
);
return [Link](student);
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class RequestDeniedException extends RuntimeException {
public RequestDeniedException(String message) {
super(message);
}
}
TransactionSystemException: Could not commit JPA transaction
ConstraintViolationException: Validation failed for classes
[[Link]]
'size must be between 10 and 10', propertyPath=jmbag
private static final String JMBAG_FORMAT = "[0-9]{10}";
Student
ServiceJp
a @Override
public Student createStudent(Student student) {
[Link](student, "Student object must be given");
[Link]([Link](),
"Student ID must be null, not" + [Link]()
);
String jmbag = [Link]();
[Link](jmbag, "JMBAG must be given");
[Link]([Link](JMBAG_FORMAT),
"JMBAG must have 10 digits, not '" + jmbag + "'"
);
if ([Link]([Link]()) > 0)
throw new ActionForbiddenException(
"Student with JMBAG " + [Link]() + " already exists
);
return [Link](student);
}
Svejedno 500 Internal Server
Error
Exception handler
Order(Ordered.HIGHEST_PRECEDENCE)
ControllerAdvice
ublic class RestExceptionHandler {
@ExceptionHandler([Link])
protected ResponseEntity<?> handleIllegalArgument(Exception e, WebRequest req)
Map<String, String> props = new HashMap<>();
[Link]("message", [Link]());
[Link]("status", "400");
[Link]("error", "Bad Request");
return new ResponseEntity<>(props, HttpStatus.BAD_REQUEST);
}
Pravi status odgovora je 400
Validacija podataka na tri
mjesta:
C S R
frontend servisni sloj baza