Professional Documents
Culture Documents
IT Obuka SD BE T4
IT Obuka SD BE T4
Prekvalifikacije za IT 1
TEMA 4:
SLOJ SERVISA
Vladimir Dimitrieski, PhD, dimitrieski@uns.ac.rs
Nebojša Horvat, MSc, horva.n@uns.ac.rs
Aleksandar Ignjatijević, B.Sc., aleksandar.ignjatijevic@uns.ac.rs
Prekvalifikacije za IT 2
Pregled
• Servisni sloj u Springu
• Servisi za rad sa bazom podataka
• HQL
• Servisi za rad sa fajlovima
• Logovanje
• log4j
• Zadaci
1
1/4/2023
Prekvalifikacije za IT 3
SERVISNI SLOJ U
SPRINGU
Prekvalifikacije za IT 4
Servisni sloj
• Servisni sloj u Springu nalazi se ispod Web sloja
• na kojem su smešteni kontroleri koji komuniciraju sa klijentskom
stranom
• Istovremeno komunicira i sa slojem na kojem su smešteni
repozitorijumi
• Na ovom nivou nalaze se metode
• koje implementiraju poslovnu logiku aplikacije
• koje implementiraju komunikaciju sa spoljnim resursima (fajl
sistem)
• koje implementiraju komunikaciju sa email serverima
2
1/4/2023
Prekvalifikacije za IT 5
Servisni sloj
Prekvalifikacije za IT 6
SERVISI ZA RAD SA
BAZOM PODATAKA
HQL
3
1/4/2023
Prekvalifikacije za IT 7
Primer
• Kreirati REST endpoint
• Koji vraća listu adresa na osnovu prosleđenog imena korisnika
• putanja /api/v1/addresses/user/{name}
Prekvalifikacije za IT 8
Primer
• Kreirati nov interfejs u paketu
• desni klik na paket -> new -> interface
• nazvati ga AddressDao
• kreirati novu klasu u paketu
• desni klik na paket -> new -> class
• nazvati je AddressDaoImpl
• klasa AddressDaoImpl implementira interfejs AddressDao
4
1/4/2023
Prekvalifikacije za IT 9
Primer
-----------------------------------------------
@Service
public class AddressDaoImpl implements AddressDao{
Prekvalifikacije za IT 10
Primer
• U interfejs dodati metodu koja vraća listu adresa na
osnovu prosleđenog imena korisnika
10
5
1/4/2023
Prekvalifikacije za IT 11
Primer
@Service
public class AddressDaoImpl implements AddressDao {
@PersistenceContext
private EntityManager em;
@Override
public List<AddressEntity> findAddressesByUserName(String name) {
String sql = "select a " +
"from AddressEntity a " +
"left join fetch a.users u " +
"where u.name = :name ";
11
Prekvalifikacije za IT 12
Primer
12
6
1/4/2023
Prekvalifikacije za IT 13
Primer
@RestController
@RequestMapping(path = "/api/v1/addresses")
public class AddressController {
//………..
@Autowired
private AddressDao addressDao;
//………..
}
13
Prekvalifikacije za IT 14
SERVISI ZA RAD SA
FAJLOVIMA
14
7
1/4/2023
Prekvalifikacije za IT 15
Primer
• Kreirati endpoint
• Koji omogućuje upload fajla
• putanja /api/v1/upload
• Ne koristiti REST već implementirati generisanje
stranica na backend-u
• server-side page generation
• frontend kao deo backend-a
• stranice se nalaze i generišu na backend-u i HTML se šalje frontend-u
samo na prikaz
• skoro identična stuktura kao i REST aplikacija osim web sloja
15
Prekvalifikacije za IT 16
STS projekat
• Kreirati novi spring boot
projekat u STS
• File -> New ->
Spring starter project
• na prvom ekranu popuniti kao
što je dato na slici
• nakon popunjavanja pritisnuti
dugme Next
• na drugom ekranu sve ostaviti
kako jeste
• nisu potrebne dodatne
biblioteke
• pritisnuti dugme Finish
16
8
1/4/2023
Prekvalifikacije za IT 17
STS projekat
• Dodati u pom.xml zavisnost od
• spring-boot-starter-web
• spring-boot-starter-thymeleaf
• spring-boot-devtools
17
Prekvalifikacije za IT 18
Primer
• U resources kreirati folder templates
• Kreirati upload.html
• Za mogućnost odabira i slanja fajla
• Kreirati uploadStatus.html
• Za prikaz statusa poslatog fajla
18
9
1/4/2023
Prekvalifikacije za IT 19
Primer – upload.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
</body>
</html>
19
Prekvalifikacije za IT 20
Primer – uploadStatus.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
<div th:if="${message}">
<h2 th:text="${message}"></h2>
</div>
</body>
</html>
20
10
1/4/2023
Prekvalifikacije za IT 21
Primer
21
Prekvalifikacije za IT 22
Primer
@Controller
@RequestMapping(path = "/")
public class UploadController {
@RequestMapping(method = RequestMethod.GET)
public String index() {
return "upload";
}
22
11
1/4/2023
Prekvalifikacije za IT 23
Primer
23
Prekvalifikacije za IT 24
Primer
public interface FileHandler {
public String singleFileUpload(
MultipartFile file, RedirectAttributes
redirectAttributes) throws IOException;
}
24
12
1/4/2023
Prekvalifikacije za IT 25
Primer
@Service
public class FileHandlerImpl implements FileHandler{
//………
}
25
Prekvalifikacije za IT 26
Primer
@Override
public String singleFileUpload(MultipartFile file, RedirectAttributes redirectAttributes)
throws IOException {
if (file.isEmpty()) {
redirectAttributes.addFlashAttribute("message", "Please select a file to upload");
return "redirect:uploadStatus";
}
try {
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded '" + file.getOriginalFilename() + "'");
} catch (IOException e) {
throw e;
}
return "redirect:/uploadStatus";
}
26
13
1/4/2023
Prekvalifikacije za IT 27
Primer
@Controller
@RequestMapping(path = "/")
public class UploadController {
@Autowired
private FileHandler fileHandler;
27
Prekvalifikacije za IT 28
Primer
28
14
1/4/2023
Prekvalifikacije za IT 29
Primer
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MultipartException.class)
public String handleError1(MultipartException e,
RedirectAttributes redirectAttributes) {
redirectAttributes.addFlashAttribute("message",
e.getCause().getMessage());
return "redirect:/uploadStatus";
29
Prekvalifikacije za IT 30
Primer
• U klasi gde se nalazi main metoda (npr.
UploadExampleApplication) dodati tomcatEmbedded
metodu koja treba da spreči reset tomcat-a
30
15
1/4/2023
Prekvalifikacije za IT 31
Primer
@Bean
public TomcatServletWebServerFactory tomcatEmbedded() {
tomcat.addConnectorCustomizers((TomcatConnectorCustomizer)
connector -> {if ((connector.getProtocolHandler()
instanceof AbstractHttp11Protocol<?>)) {
//-1 means unlimited
((AbstractHttp11Protocol<?>)
connector.getProtocolHandler()).setMaxSwallowSize(-1);
}
});
return tomcat;
31
Prekvalifikacije za IT 32
Primer
• U application.properties fajl dodati:
• spring.servlet.multipart.max-file-size=1MB
• spring.servlet.multipart.max-request-size=1MB
• Pokrenuti aplikaciju
• Kreirati direktorijum C:/temp
• Otici na localhost:8080/
32
16
1/4/2023
Prekvalifikacije za IT 33
LOGOVANJE
log4j
33
Prekvalifikacije za IT 34
Logovanje
• Logovanje predstavlja prikupljanje statističkih podataka o
radu aplikacije
• Primitivan način putem ispisivanja poruka na izlazni
uređaj
• Napredan način putem ispisavanja poruka i pratećih
podataka u odgovarajuće fajlove
34
17
1/4/2023
Prekvalifikacije za IT 35
Log4j
• Apache biblioteka za logovanje u aplikacijama koje su
pisane u Java programskom jeziku
• Dodati u pom.xml zavisnost od
• spring-boot-starter-logging
• spring-boot-starter-log4j2
35
Prekvalifikacije za IT 36
Log4j
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-
logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
36
18
1/4/2023
Prekvalifikacije za IT 37
Log4j
• U application.properties dodati
• logging.level.org.springframework.web=INFO
• logging.level.com.iktpreobuka.uploadexample.controllers=INFO
• logging.level.org.hibernate=ERROR
• logging.file.name=logs/spring-boot-logging.log
• log4j.logger.org.thymeleaf=DEBUG
37
Prekvalifikacije za IT 38
Log4j
• U klasu UploadController dodati instancu Logger-a
38
19
1/4/2023
Prekvalifikacije za IT 39
Log4j
39
Prekvalifikacije za IT 40
Log4j
40
20
1/4/2023
Prekvalifikacije za IT 41
41
Prekvalifikacije za IT 42
42
21
1/4/2023
Prekvalifikacije za IT 43
43
Prekvalifikacije za IT 44
44
22
1/4/2023
Prekvalifikacije za IT 45
45
Prekvalifikacije za IT 46
46
23
1/4/2023
Prekvalifikacije za IT 47
47
Prekvalifikacije za IT 48
48
24
1/4/2023
Prekvalifikacije za IT 49
STS projekat
• Kreirati novi spring boot
projekat u STS
• File -> New ->
Spring starter project
• na prvom ekranu popuniti kao
što je dato na slici
• nakon popunjavanja pritisnuti
dugme Next
• na drugom ekranu sve ostaviti
kako jeste
• nisu potrebne dodatne
biblioteke
• pritisnuti dugme Finish
49
Prekvalifikacije za IT 50
STS projekat
• Dodati u pom.xml zavisnost od
• spring-boot-starter-web
• spring-boot-starter-mail
50
25
1/4/2023
Prekvalifikacije za IT 51
STS projekat
• Nakon dodavanja potrebnih zavisnosti, sledeći korak je
podešavanje svojstva email servera
• u ovom primeru će biti korišćen Gmail SMTP server
51
Prekvalifikacije za IT 52
STS projekat
• U application.properties fajl dodati:
• spring.mail.host=smtp.gmail.com
• spring.mail.port=587
• spring.mail.username=<mejl>
• spring.mail.password=<lozinka>
• spring.mail.properties.mail.smtp.auth=true
• spring.mail.properties.mail.smtp.starttls.enable=true
52
26
1/4/2023
Prekvalifikacije za IT 53
Primer
• kreirati novi paket
• desni klik na postojeći paket -> new -> package
• nazvati ga com.iktpreobuka.email_example.models
• kreirati novu klasu u paketu
• desni klik na paket -> new -> class
• nazvati je EmailObject
53
Prekvalifikacije za IT 54
Primer
public class EmailObject {
public EmailObject() {
super();
}
//TODO add getters and setters
}
54
27
1/4/2023
Prekvalifikacije za IT 55
Primer
• kreirati novi paket
• desni klik na postojeći paket -> new -> package
• nazvati ga com.iktpreobuka.email_example.services
• kreirati novi interfejs u paketu
• desni klik na paket -> new -> interface
• nazvati ga EmailService
• kreirati novu klasu u paketu
• desni klik na paket -> new -> class
• nazvati je EmailServiceImpl
• klasa EmailServiceImpl implementira interfejs EmailService
55
Prekvalifikacije za IT 56
Primer
public interface EmailService {
56
28
1/4/2023
Prekvalifikacije za IT 57
Primer
@Service
public class EmailServiceImpl implements EmailService{
@Autowired
public JavaMailSender emailSender;
@Override
public void sendSimpleMessage(EmailObject object) {
// TODO Auto-generated method stub
}
@Override
public void sendTemplateMessage(EmailObject object) throws Exception {
// TODO Auto-generated method stub
}
@Override
public void sendMessageWithAttachment(EmailObject object, String
pathToAttachment) throws Exception {
// TODO Auto-generated method stub
}
}
57
Prekvalifikacije za IT 58
Primer
@Override
public void sendSimpleMessage(EmailObject object) {
SimpleMailMessage message = new SimpleMailMessage();
message.setTo(object.getTo());
message.setSubject(object.getSubject());
message.setText(object.getText());
emailSender.send(message);
}
58
29
1/4/2023
Prekvalifikacije za IT 59
Primer
@Override
public void sendTemplateMessage(EmailObject object) throws
Exception {
MimeMessage mail = emailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mail,
true);
helper.setTo(object.getTo());
helper.setSubject(object.getSubject());
String text = "<html><body><table "
+ "style='border:2px solid black'>"
+ "<tr><td>" + object.getText() + "</td></tr>"
+ "</table></body></html>";
helper.setText(text, true);
emailSender.send(mail);
59
Prekvalifikacije za IT 60
Primer
@Override
public void sendMessageWithAttachment(EmailObject object,
String pathToAttachment) throws Exception {
MimeMessage mail = emailSender.createMimeMessage();
MimeMessageHelper helper = new
MimeMessageHelper(mail, true);
helper.setTo(object.getTo());
helper.setSubject(object.getSubject());
helper.setText(object.getText(), false);
FileSystemResource file = new FileSystemResource(
new File(pathToAttachment));
helper.addAttachment(file.getFilename(), file);
emailSender.send(mail);
}
60
30
1/4/2023
Prekvalifikacije za IT 61
Primer
• kreirati novi paket
• desni klik na postojeći paket -> new -> package
• nazvati ga com.iktpreobuka.email_example.controllers
• kreirati novu klasu u paketu
• desni klik na paket -> new -> class
• nazvati je EmailController
• u okviru EmailController klase kreirati REST endpoint koji
omogućuje slanje jednostavnog email-a
• putanja /simpleEmail
61
Prekvalifikacije za IT 62
Primer
@RestController
@RequestMapping(path = "/")
public class EmailController {
@Autowired
private EmailService emailService;
private static String PATH_TO_ATTACHMENT = "E://proba//slika.jpg";
emailService.sendSimpleMessage(object);
return "Your mail has been sent!";
}
}
62
31
1/4/2023
Prekvalifikacije za IT 63
Primer
• kreirati REST endpoint koji omogućuje slanje email-a,
tako da je tekst mejla oblikovan vidu html-a
• putanja /templateEmail
• kreirati REST endpoint koji omogućuje slanje email-a sa
prilogom
• putanja /emailWithAttachment
63
Prekvalifikacije za IT 64
Primer
@RequestMapping(method = RequestMethod.POST, value =
"/templateEmail")
public String sendTemplateMessage(@RequestBody EmailObject
object) throws Exception {
if(object==null || object.getTo()==null ||
object.getText()==null) {
return null;
}
emailService.sendTemplateMessage(object);
return "Your mail has been sent!";
}
64
32
1/4/2023
Prekvalifikacije za IT 65
Primer
@RequestMapping(method = RequestMethod.POST, value =
"/emailWithAttachment")
public String sendMessageWithAttachment(@RequestBody EmailObject
object) throws Exception {
if(object==null || object.getTo()==null ||
object.getText()==null) {
return null;
}
emailService.sendMessageWithAttachment(object,
PATH_TO_ATTACHMENT);
return "Your mail has been sent!";
}
65
Prekvalifikacije za IT 66
Primer
• Pokrenuti aplikaciju
• Ukoliko postoje problemi sa slanjem mejla,
• proveriti svoj gmail nalog
• Možda je Google poslao poruku da potvrdite da ste vi slali email aplikativno
66
33
1/4/2023
Prekvalifikacije za IT 67
ZADACI
67
Prekvalifikacije za IT 68
Zadatak 1
• Uraditi sledeće stavke:
• 1.1 omogućiti upload fajla sa listom korisnika gde svaki red u fajlu
sadrži podatke za jednog korisnika (ime i email), gde su podaci
delimitirani zarezom
• 1.2 nakon što je fajl sa korisnicima upload-ovan omogućiti čuvanje
svih korisnika koji se nalaze u fajlu
• 1.3 Prilikom dodavanja novog korisnika ili izmene postojećeg
korisnika omogućiti proveru da li je prosleđena mail adresa
korisnika već uneta u bazu podataka. Ukoliko jeste zabraniti unos
ili izmenu
• 1.4 u klasu UserEntity dodati polje troškovi. Prilikom unosa novog ili
izmene postojećeg korisnika polje troškovi postaviti na vrednost
5000 ukoliko korisnik živi u Novom Sadu, ili 10000 ukoliko korisnik
živi u Beogradu. U svim ostalim situacijama upisati vrednost 0 u
polje troškovi
68
34
1/4/2023
Prekvalifikacije za IT 69
Zadatak 2
• Uraditi sledeće stavke:
• 2.1 Kreirati REST endpoint koji omogućuje download fajla
• 2.2 Kreirati REST endpoint koji omogućuje downolad fajla u kome se nalaze
podaci o svim korisnicima koji se nalaze u bazi podataka. Fajl je potrebno prvo
napraviti na serverskoj strani tako da su podaci o korisnicima razdvojeni
zarezom (csv fajl)
• 2.3 Proširiti zadatak 2.2 tako da REST endpoint prima listu svih atributa klase
UserEntity koje korisnik želi da se nalaze u csv fajlu. Ukoliko se u listi nalazi
atribut koji nije deo UserEntity kase, vratiti odgovarajuću grešku korisniku.
Ukoliko je prosleđena prazna lista, u fajl upisati sve atribute klase UserEntity
69
35