You are on page 1of 34

Sadržaj

Poglavlje Broj stranica Težina


Scrum 37 +
Osvnove Web Aplikacije u Javi 18 +
Uvod u Spring 21 +
SpringMVC 12 +
SpringBoot 8 +
Thymeleaf 9 +
Spring Security 24 +
Korištenje baza podataka u 27 +
Java web aplikacijama
Hibernate 32 +
Spring Data JPA 24 +
Git 25 +
I18nt 11 +
Jenkins i Sonar 15 +
jUnit 37 +
Quartz Scheduler 6 +
Spring MVC Rest 15 +
Java I. kolokvij

1. Scrum

Scrum je metodologija za upravljanje tj razvoj produkta. On zamjenjuje tradicionalni waterfall pristup kako bi se
omogućilo češće izdavanje verzija proizvoda i uključilo samog korisnika.

Sastoji se od 7+-2 člana.

Bazira se na Sprintevima koji obično traju 1-2 tjedna a nikako više od 30 dana. Rezultat Sprinta je testirana verzija
produkta.

Uloge u Scrumu:

- Product owner:
o osoba odgovorna za maksimiziranje povrata investicije
o odlučuje o prioritetima zadataka u Product Backlogu
o donosi konačne odluke oko prihvaćanja zahtjeva od korisnika
o prihvaća ili odbija
- Scrum Development Team
o Uključuje eksperte raznih profila (programere. Testere. Analitičare)
o Pregovara o preuzimanju obveza s Product Ownerom
o Najčešća veličina tima je 7+-2 člana
- Scrum Master
o Pazi da se poštuju pravila Scrum metodologije
o Pomaže u rješavanje prepreka (organizira radnu atmosferu) tj. štiti od vanjskih utjecaja
o Osigurava da rezultat Sprinta budu vidljiv
o Odgovoran je za organiziranje sastanaka

Product Backlog sadrži sve zadatke koji se trebaju završiti da bi projekt bio gotov. O prioritetima odlučuje Product
Owner. Svaki od zadataka s Product Backloga kada se preuzme u Sprint detaljno se razradi u Sprint Backlog.
Sprint Planning Meeting

- Organizira ga Product owner s ostatkom tima prije svakog Sprinta


- Odabiru se zadaci s Product Backloga koje će se raditi u tom
Sprintu. Tim je odgovoran za odabir količine posla koju mogu
završiti unuta Sprinta (procjene u satima).
- Product Backlog sadrži sve zadatke koji se trebaju završiti da bi
projekt bio gotov.
- Zadaci koje se izvrše u jednom Sprintu moraju produktirati
funkcionalnoj verziji produkta koji se može isporučiti.

Daily Scrum Sastanak

- Svakog dana 15tak minuta


- Što su radili prošli dan i što će raditi sljedeći dan

Sprint Review Meeting

- Na kraju Sprinta tim prezentira verziju produkta


- Na njemu sudjeluju i krajnji korisnici/naručitelji kako bi bili u toku
s procesom razvoja

Sprint Retrospective sastanak

- Analiziraju se dobre i loše strane u Sprintu te predlažu poboljšanja

Backlog Refinement sastanak

- Kod procjenjivanja trajanja zadataka svaki zadatak s Product Backloga mora biti detaljno raspisan na manje
zadatke
- Zadaci se djele na Epic (modul produkta), Story (jedan Use – Case) i zadatke
- Procjena vrmenea za zadatke: Planning Poker, Fist of five

Definition of Done (DoD)

- Dokument koji opisuje kada je neki zadatak stvarno završen.

Kanban - na japanskom znaci ploča s oznakama

Trello – za organiziranje Scrum

Taiga – kanban Balsamiq – web mock NjinjaMock – web mock inVision – web mock

2. Osnove Web Aplikacije u Javi


Zahtjev sadržava info o samom pregledniku i stranici koju želi dohvatiti. Odgovor sadržava stranicu koja se dohvaća,
info o njoj i info o poslužitelju.

Troslojne Web aplikacije

Web sloj

- služi za obradu podataka koje je unio korisnik vračanje odgovora korisniku


- obrađuje iznimke, mora implementirati autorizaciju i autentifikaciju

Servisni sloj

- sadrži aplikacijse i infrastruktirne servise


o aplikacijski servisi omogućuju koriđtenje javnoh API sučelja i brinu se za implementaciju
transakcijskih emhanizama i autorizaciju korisnika
o infrastrukturin servis sadže programisi kod koji komunicira s vanjskim servisima (baza podatakam
email poslužitelj)

Sloj Repozitorja

- kao najniži sloj služi za komunikaciju aplikacije s podatkovnim repozitorijima


3. Uvod u Spring

Prednosti korištenja Springa:

- Dependency injection – još se naziva i Inversion of Control (IoC) ovisnosti se injektiraju one objekte koji ih
trebaju. Objekti definiranje zavisnosti između objekata.

JavaBeans

- nazivaju se i POJO klase (plain old java object) i predstavljaju temelj Springa
- implementiraju sučelje Seriazable, imaju konstruktor bez ulaznih parametara te omogućavaju pristup
pomoću gettera i settera

Dohvaćanje objekata (beanova) iz contexa moguće je na sljedeći način:

Spring containter

- jezgra Springovog contexta. Korištenjem dependency injection upravlja komponentama tj vezama između
njih
- on hendla cijeli life od objekata, destrukciju i sl.
4. Spring MVC

To je zapravo pristup programiranju tj. odvajanje prezentacijskog djela sa buissnes djela.

Zahtjev poslan od strane korisnika (1) prenosi informacije o tome što korisnik želi (URL koji želi dohvatiti) i ostale
podatke koje je upisao u grafičko sučelje.
Zahtjev dolazi do DispatcherServleta koji prosljeđuje zahtjev do Controllera koji je zadužen za obradu tog zahtjeva
(definiranog URL-om u samom zahtjevu)
Da bi moga točno znati koji Controller je zadužen za obradu kojeg zahtjeva mora konzultirati Handler Mapping (2)
koja mu vraća punu adresu Controllera kojeg treba kontaktirati.
Nakon toga DispatcherServlet šalje zahtjev tome Controlleru (3)
Controller obrađuje zahtjev i podatke u suradnji s ostalim komponentama app i vraća rezultate (podatke) i
informacije o stranici koja se mora prikazati DispatcherServletu (4). Rezultati i podaci se spremaju u Model koji ima
strukturu ključ+vrijednost. Vraća data + ime Viewa (dakle zna ime viewa ali mu nezna tocnu adresu) zato mu treba
pomoć ViewDesolver (koji daje tocnu adresu).
DispatcherServleta uz pomoć ViewResolvera mapira logički naziv stranice koju treba prikazati (5). Sada
DispatcherServleta ima java objekt (data) i lokaciju/adresu Viewa koji ce to prikazati.
Kada DispatcherServlet sazna koji View mora konzultirati dovršava izgled stranice uz pomoć View komponente (6).
I zatim slijedi slanje podataka (dana + html) prema kornisku (7).
Koriste se anotacije:

- @Controller – oznacava da je neka classa controller


- @RequestMapping – to je zapravo preusmjerivać tj. pointer na koji controller da se otvori ovisno o URL-u
- Dakle ako korisnik upiše ..stranica../welcome pokrenut će se odgovarajuća metoda. A ako upiše
..stranica../hi pokrenut će se druga odgovorajuća metoda.
- @GetMapping je zapravo skraćenica od @RequestMapping(method = RequestMethod.GET)
- @PostMapping

Parametri u requestu i sessionu se također definiraju pomoću anotacija @SessionAttributes i @ModelAttributes

@Controller
@RequestMapping(“/predavanja“)
public class PredavanjaController {
@GetMapping(“/novo“) --- dakle ovo se zapravo odnosi na /predavanje/novo
public String prikažiFormu(Model model) {
model.addAttribute(“predavanje“, new Predavanje());
model.addAttribute(“vrste“, Predavanje.Vrsta.values());
return “predloziPredavanje“;
}
}
5. Spring Boot

Osnovna iz koje se vidi da je riječ o SpringBootApplication je anotacija @SpringBootApplication a metoda za


pokretanje je SpringApplication.run(..)

@SpringBootApplication
public class Applikacija {
public static void main (String[] args) {
SpringApplication.run(Applikacija.class, args);
}
}

Konfiguracija se temelji na Java anotacijama:

@Configuration – oznaka da je neka klasa kreirana u svrhu konfiguriranja aplikacije

@EnableAutoConfiguration

@ComponentScan

@EnableWebSecurity – omogućava osnove sigurnosne postavke u Spring MVC aplikaciji

@SpringBootApplication (uključuje anotacije @ComponentScan i @EnableAutoConfiguration)

Lombook

- Kako bi se izbjeglo suvišno generiranje settera i gettera moguće je koristiti Lombok bibliiteku
- Ona pomoću anotacije @Data generira sve osnovne metode i konstruktor
- Primjer:
6. Thymeleaf

Prvo da bi koristili thymeleaf, nakon što napravimo recimo index.html u resources/temlates (gdje će Spring defaultno
pogledat za View), moramo u taj index.html u <head> element dodati tj izmjeniti ga u

<html xmlns = „“http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">

Pošto nam je po defaultu bio uključen @EnableWebSecurity mozilla firefox nije dao pristup localhostu:8080 pa smo
to morali izjeniti.

To smo napravili na način da smo dodali security dependency u maven (pom.xml) a dodali smo i thymeleaf security

E sad kako bi nadjacali trenutno secuirity moramo napravit novu klasu za to. Njoj stavimo anotaciju @Controller i
kažemo joj da extenda WebSecurityConfigurerAdapter i onda @Override configure metodu:

Pošto želimo i malo css-a da uredimo naš web i njega trebamo uključiti u naš html. To učinimo na način da u head
elementu dodamo za to linkove:

<link rel=“stylesheet“ type=“text/css“ th:href=“@{resoureces/style.css}“> - ovo podrazumiejva da smo napravili css


file i stavili ga u folder/podfolder resources

<link rel=“stylesheet“ type=“text/css“ th:href=“@{resources/bootsrtap.css}“> - ovo ako smo skinuli bootsrap s weba
(to je onaj veliki css file koji je svima dobar)

U slučaju korištenja URL-a koji bi se zvao pritiskom na gumb atribut th:href bi se koristio:

<a th:href=“@{/predavanja/novo}“>Povratak</a>
Povezivanje unosnih polja na ekranu s objektima:

Prvo e definira objekt na razini forme a nakon toga polja u koja se spremaju podaci

th:object=“${predavanje}“ – služi za označavanje objekta čiji sadržaj se ispisuje na ekran

th:field=“*{predavac.ime}“ – za referenciranje objekata (varijabli)

Razlika između oznaka „${}” i j „*{}” je u tome što „*” označava referenciranje označenog objekta, a „${}” cijeli
kontekst

th:each=“pozicija : ${pozicije}“

th:value=“${pozicija}“

th:text=“${predavanje.predavac.ime}“

- Unutar atributa „th:text” moguće je kombinirati identifikatore varijabli i statički tekst

<span th:text=“${predavac.predavanje.ime}“ >PREDAVAC.IME</span>


7. Spring Security

Sigurnost se svodi na dva spekta:

- Autentifikaciju = odnosi se na prijavu korisnika (samo registrirani korisnici mogu pristupit)


- Autorizaciju = samo korisnici s posebnim ovlastima/rolama

SpringBoot starter Maven depandancy vec ukljucuje sve potrebne bibloteke za SPring security a za Thymeleaf
komponente potrebno je dodati:

Vlastiti security postignemo tako da nadjacamo configure metodu koja dolazi iz klase
WebSecurityConfigurerAdapter. Tako je moguće detaljno odrediti dio oko autentifikacije i autorizacije. Dodatno tj
pri tome potrebno je koristiti anotacije @Confugiration i @EnableWebSecurity.

Anotacija @Configuration naznačava da je neka klasa kreirana u svrhu konfiguriranja aplikacije, a anotacija
@EnableWebSecurity omogućava osnovne sigurnosne postavke u SpringMVC aplikaciji

@Configuration
@EnableWebSecurity
public class SecSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/anonymous*").anonymous()
.antMatchers("/login*").permitAll()
.anyRequest().authenticated()

.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.failureUrl("/login.html?error=true")
Ponekad controller klase imaju jednostavnu namjenu preusmjeravanje stranica. To je moguće zamijeniti korištenjem
WebMvcConfigurer sučelja i nadjačavanje metode addViewControllers. Za svaki URL moguće je definirati logički
View korištenjem metode setViewName

Thymeleaf stranice također podržavaju mogućnost prikazivanja ili sakrivanje djelova stranice s obzirom na ovlasti
korisnika. Za podršku korištenja „securitya“ potrebno je dodati namespace „sec“:

<html xmlns:th=“http//www.thymeleaf.org“ xmlns:sec=“http://www.thymeleaf.org/extras/spring-security“>

Nakon toga moguće je korisitit authorize metodu koja provjerava je li koriisnik autenticiran:
<div sec:authorize=“isAuthenticated()“>
<form method=“POST“ th:action=“@{/logout}“>
Ulogirali sete se kao <span sec:authentication=“name“></span>

Ili
Kojom rolom je autenticiran:
<div sec:authorize=“hasRole ('Role_Ad,in')“>
<div th:unless="${predavanje.objavljeno}" >
<h5>Predavanje nije objavljeno u programu konferencije.</h5>
</div>
<div th:if="${predavanje.objavljeno}" >
<h5>Predavanje je objavljeno i vidljivo u programu konferencije.</h5>
</div>
</div>
CSRF (cross site request forgery) se odnosi na ugrožavanje sigurnosti aplikacije na nain da se izvršavaju
neautorizirane naredbe od strane korisnika (čestko korisnik nije svijestan da je napadnut)

Thymeleaf automatski dodatje CSRF token na stranicu za prijavu a moguće ga je dodati i kao hidden parametar na
formu koja se submita:

<div class=“form-row>
<input type=“hidden“ name=“_csrf“ th:valeu=“${_csrf.token}“ />
<input type="submit" value="Predaj prijedlog" class="btnbtn-primary" />
</div>

Spring security ima posebnu vrstu filterena nazvana FilterChainProxy te je moguće odrediti domenu djelovanja:
/foo/** , /fab/** ili cak i /**

Primjer definiranja security filtera:

@Configuration
@Order(SecurityProperties.BASIC_AUTH_ORDER – 10)
public class ApplicationCofigurerAdapter extends WebSecuritConfigurerAdapter {
@Override
protected void configure (HttpSecurity http) ehrows exception {
http.antMatcher(„/foo/**); -- ovo sprječava da ode na sve ULT iza foo tipa foo/deveti
}
}
Aktivaciju springSecurity anotacija moguće je postići na sljedeći način:

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled=true)
public class ..{
}
Svakoj metodi moguće je dodati anotaciji @Secured kojoj je ograničeno korištenje samo onima koji imaju potrebe
role:

@Secured({“USER“, “ADMIN“})
public void spremiBilješku (Bilješka biljeska) {
} – ukoliku navedenu metodu pozove netko tko nema ovlasti baca se iznimka AuthenticationException ili
AcessDeniedException
8. GIT
Za razliku od drugih sustava za verzioniziranje GIT se temelji na verzijama datoteke koje zajedno čine verziju
(snapshot) cijelog sustava datoteke.

Radni direktorij predstavlja jedan checkout jedne verzije projekta

Staging Area je jednostavna datoteka koja se obično nalazi u Git repozitoriju koja sadrži info o tome što će se
sljedeće commitati u Git direktorij.

Git podrazumijeva tri glavna stanja u kojima se datoteka mogu nalaziti:

- Commited – podaci su spremljeni u lokalnu bazu podataka tj na računalo tj lokani Git fodler
- Modified – datoteke su promijenjene ali jo nisu spremljenu u lokalnu bazu tj lokalni Git folder
- Staged – promjenjene datoteke su označene za kreiranje novog snapshota

Pa se na osnovi toga Git uključuje tri glavna projekta:

- Git direktorij
- Radni direktorij
- Staging area

Svaka datoteka u Git repozitoriju može biti u dva stanja:

- Tracked – datoteka se nalazi unutar posljednjeg snapshota i može biti nepromijenjena, promijenjena ili
staged
- Untracked – sve ostale datoteke

Kod prvog kloniranja sve datoteke su u nepromijenjenom tracked stanju

Za spajanje na Git repozitorij u Eclipsu prvo je potrebno otvoriti Git perspektivu (kroz View) i odabrati opciju Clone a
Git repository.

Glavni branch zove se master (bez dodataka) a ima jos i nešto origin
Pa onda on pita gdje da lokalno spremi taj git C:\Users\Komp\git\SilvioTest

I onda mi se u Springu otvroti lokalni repoziotrij mog projekta

Za dodavanja Spring projekta na Git odaberemoe Team->Share Project i tamo onda odlucimo zelimo li spremiti to u
postojeci lokaclni repozitorij ili napraviti novi lokalni git repozitorij

Sada kada smo to shareli tj napravili lokalni git repozitopriij za taj projekt mozemo opet ici na Team-> i odabrati
commit i jos stp ostaloih stvari.

Onda se otvara prozor za staged i unstaged datoteke

Onda sve stageamo i napisemo commit message – to ce ond aupdejtat moj lokalni git repozitoprij tj datoteku u
C:\Users\Komp\git\SilvioTest . No tek kada pushamo sami projekt ce se uploudat i na gitLab.

Neke od sofwera/starnica za git:

- SourceTree
- bit bucket
- gitLab
9. i18n

Web aplikacije sve čeće treba prevoditi na visše jezika.

Cilj na HTML stranicama korisiti ključeve koji će služiti koa identifikator za dohvat teksta i vrjednosti koji se moraju
prikazati na ekranu s obzirom na odabrani locale.

Datoteka s parovima ključ-vrijednost nalazi se u .properties datotekama a dio naziva datoteke je i locale npr
messages_hr.properties.

Za termin višejezičnosti često se zove internationalization ili i18nt

Locale je termin (i naziv klase) koji je vezan uz jezičnu podršku nekog područja. Može se pisati dvoslnovnim
kraticoama (language code) po ISO-639 standardu (hr, en..) a moguće je dodatno i country code npr en_US ili en_GB.

U javi postoji klasa java.util.Locale koja označava određeni Locale i omogućava manipulaciju nad istim.

Sio – to funkcionira tako da ja u messages_hr.properies definiram rijeci po metodi kljuc-vrijednost

A zatim na HTML stranici koristeci thymeleaf povezem svoje rijeci s onima iz properties:

<th th:text=“#{msg.predavanje.tema}“>Teema</th>

ResourceBundleEditor plugin za Eclispe:


Kako bi i18n ispravno funkcionirao potrebno je konfigurirati interceptor i localResolver:

@Bean
public LocaleResolver localeResolver () {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
Locale locale = new Locale (“hr“);
localeResolver.setDefaultResolver(locale);
return localeResolver;
} -- kako bi aplikacija mozga odrediti koji locale se trenutno koristi koristi se LocaleResolver bean. te smo odredili i
defaultni jezik na 'hr'

@Bean
public LocaleChangeInterceptor localeChangeInterceptor () {
LocaleChangeIntercepotr lci = new LocaleChangeIntercepotr ();
lci.setParamName('language');
return lci;
} – zatim smo dodali bean koji ce reci promjeni na novi Locale s obzirom na paramaetar 'language'

Da bi on to mogao ovaj bean potrebno je dodati u aplikacijski interceptory registar. Dakle nasa klasa ce imate
anotaciju @Configuration i morat ce overrirad addInterceptors metodu:

@Override
public void addInterceptors (InterceptorRegistry registry) {
registery.addInterceptors (localeChangeInterceptor());
}

Po defaultu će spring aplikacija tražiti messages files koji sadrže internacionalizacisjke ključ – vrijednost elemente u
src/main/resources. Ime defaultnog locala će biti messages.properties a svi ostali ce imati prefiks message.
(message_hr.properties)

Ovo dvoje valjda govori gdje da traži source za messages:

@Bean
public MessageSource messageSource () {
ReloudableResourceBundleMessageSource messageSource = new ReloudableMessageBundleSource();
messageSource.setBasename(„classpath:i18n/messages“);
messageSource.setDefaultEncodint(„UTF-8“);
return messageSource;
}

@Bean
public LocalValidatorFactoryBean validator () {
LocalValidatorFactoryBean beanL = new LocalValidatorFactoryBean ();
beanL.setValidationMessageSource(messageSoucre());
return beanL;
}
10. Springbooti QuartzScheduler

Kao prvo za korištenje je potrebno dodati spring-boot-starter-quartz

Zadaci se definiraju pomoću klasa koje nasljeđuju klasu QuartzJobBean i implementiraju metodu executeInternal.

Ako je Quartz instaliran obavlja se automatska konfiguracija Scheduler objekata korištenjem SchedulerFactoryBean
instance.

Uz Scheduler kreiraju se jos i sljedeći objekti:

- JobDetail – definira konkretan zadatak što se izvršava


- Calendar – definira vremenske komponente
- Trigger – definira uvjet po kojima se zadatak pokreće

Zadaci se kreiraju korištenjem JobBuildera

Metoda storedDurably omogućava zadržavanje joba i nakon što njegov roditelj više ne postoji

Pomoću klase SimpleScheduleBuilder i metode withIntervalInSeconds definira se ciklus izvođenja zadatka.

Primjer Quartz zadatka:

public class ObjavaJob extends QuartzJobBean {


@Autowired
private MyServices myservice;
private String name;

@Override
Protected void executeInternal (JobExecutionContex contex) throws JobExecutionException{
…metoda koju želim da mi se ponavlja tipa svakih 10 sec posalji imal
}
}

Konfiguriranje:

@Configuration
public class SchedulerConfig {
@Bean
public JobDetail objavaJobDetail () {
return jobBuilder.newJob(ObjavaJob.class).withIdentity(„objvaJob“).storedDurably().build();
}

- S ovime definiramo Job i povezujemo ga našoj kalsi ObjavJob. Zatim kažemo triggeru da pokrene taj Job i
ponavlja svakih 10 sekundi. A Trigger, as the name suggests, defines the schedule at which a given Job will be
executed. A Job can have many Triggers, but a Trigger can only be associated with one Job.

@Bean
public Trigger objavaJobTrigger () {
SimpleSchedulerBuilder schBuilder =
SimpleSchedulerBuilder.simleSchedule().withIntervalsInSeconds(10).repeatForever();
return
TriggerBuilder.newTrigger().forJob(objavaJobDetail()).withIdentitiy(„objavaTrigger“).withSchedule(scheduleBuilder).
build();
}
}
Pomoću klase SimpleScheduleBuilder i metode withIntervalInSeconds definira se ciklus izvođenja zadatka.
// define the job and tie it to our HelloJob class

JobDetail job = newJob(HelloJob.class)

.withIdentity("job1", "group1")

.build();

// Trigger the job to run now, and then repeat every 40 seconds

Trigger trigger = newTrigger()

.withIdentity("trigger1", "group1")

.startNow()

.withSchedule(simpleSchedule()

.withIntervalInSeconds(40)

.repeatForever())

.build();

// Tell quartz to schedule the job using our trigger

scheduler.scheduleJob(job, trigger);
11. Jenkins i sonar
Jenkins

Kada puno ljudi radi na istom projektu i svako malo netko nešto commita (to se zove Continuous Integration)
potrebno je razviti testove koji će provjeriti je li commitani fajl i dalje ok.

Provjera ispravnosti novih promjena provodi se pomoću unit i integration testova koje programeri trebaju pisati
paralelno s samim kodom.

Jedan od alata za CI je Jenkins.

Jenkins je moguće preuzeti kao Java web aplikaciju (WAR) a pokreće se iz komande linije naredbom

„java-Dhttp.proxyHost=1231.213.102 - Dhttp.proxyPort=8080 – jar jenkins.war – httpPort=8088“ kojom se definira


proxy server iza kojeg se Jenkins izvodi i port na kojem će mu se pristupiat

- Aplikaciji je moguće pristupiti na ULR http://localhost:8088/

Osnovne funckije Jenksinsa: new item, people, build history, manage jenkis, my views, open blue ocean, credentials,
new view
SonarQube

Platforma za upravljanje kvalitetom programskog koda. Lako se integrira s Jenksinom.

Blocker critical major minor info


12. jUnit testiranje

Trenutna verzija je 5

Testne metode označavaju se anotacijom @Test a metode koje se izvode prije ili poslije testova (inicijalizacija i
oslobađanje resursa) mogu se označiti natocaijama @Before i @After.

import static org.junit.Assert.assertEquals;

Vrlo cesto kod testiranja se ne koristi prava baza pdoataka kako testovi nebi nesto poremetili. U takvim slucajevima
kosristi se inMemory baza podatka. Ona se kreira kod pokretanja testova a briše nakon završetka istih. Kod
korištenja Hibernatea in memory bazu podataka moguće je configurirati na razini SessionFactory objekta.

class sqareTest {

@Test //znaci ocito ima anotaciju


void test() {
JunitTesting test = new JunitTesting(); //ovje smo kreirali objekt tioa
JunitTesgin st mi je naziv classe tamo
int output = test.square(5); //naša metoda koju zovemo je square
assertEquals(25, output); //Spting metoda u koju upises sta ocekujes od ovog gore
testa. mi smo iovjde napisali 25 (5*5) i da ga uspiredi s outputom tj s rezultalom metode
square(5)
}

U praksi se često konfiguracija za testove odvaja u zasebne XML fajlove i ona se koristi na sljedeći način:

@ContexConfiguration (locations={„classpath:com/guitar/db/applicationTest-context.xml“}
@RunWith(SpringJUnit4ClassRuneer.class)
public class LocationTest {
@Autowired
Private LocationJpaRepository locationJpaRepository;

Primjer:

@Test
public void testJpaFind() {
List <Location> lokacije = locationJpaRepository.findAll();
assertNotNull(lokacije);
} //dakle ovaj test provjerava je li ova lista prazna pa ako je onda ce vratiti error tj test ce failat

Primjer uz JPA :

@Test
public void testJpaFindLike () {
List <Location> lokacije locationJpaRepository.findByStateLike(„iva“); ime metode koja se testira
assertNotNull(lokacije); -- ovaj test ocekuje da lista nece biti prazna
}
@Test
public void testJpaFindLikeCount () {
int count = locationJpaRepository.countByStateLike(„mar“);
assertSame(count, 2); -- ovaj test ocekuje dva ista broja tj da ce count biti 2
}

assertNotEquals(assertNotEquals("Utah", locations.get(0).getState());
assertEquals("Alabama", locations.get(0).getState());

@SuppressWarnings("deprecation") – ovo kaze da disable compilation warnings for a certain part of a program
(type, field, method)
@Test
publicvoidtestJpaFindOne() {
Locationlocation= locationJpaRepository.findOne(1L);
assertEquals(location.getCountry(), "United States");
assertEquals(location.getState(), "Alabama");
}

Nakon provedenih testova dobijemo rezuiltate u jUnit View. Podatak Runs je broj testova koji su se izvršili, Error
označava broj testova koji su završili Exceptionom a Failures označava broj testova koji su završili a nisu dali
tražene rezultate.

Postoje biblioteke za testiranje koda (kod koji ne koristi podatke iz baze vec su mu dovoljni neki fiksi podaci):
EasyMock, Mockitio i jMock.

Postoji i bibliteka za unapređenje jUnit testiranja baze podataka putem DbUnit. Ona putem XMLa ubaci podatke.
U slučaju pisanja testova za SpringBoot applikaciju konfiguracija je znatno jednostavnija:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigurationMockMvc
public class BiljeskeControllerTest {

@AutoWired
Private MockMvc mockMvc; -- osnovni objekt s kojim se obaljva testiranje je MockMvc
}

Primjer testa:

@Test
public void testShowFormAsAdmin () throws Exception {
this.mockMvc.perform(get(„/biljeske“).with(user(„admin“).password(„pass“).roles(„USER“, „ADMIN“))).
andExpect(status().isOk()).
andExpect(view().name(„biljeske“));
} -- znaci ovo radi provjeru hoce li ovaj otvrotii sranicu s ovim autentifikatorom usera

Za provjeru statusa zahtjeva koji je poslan Contorller metodama moguće je korisiti sljedeće:
- isOk(): provjerava je li statuz zahtjeva OK 200
- is3xxRediretion(): provjerava je lu u pitanje preusmjeravanje zahtjeva

U slučaju provjere rezultata u Model objektu moguće je koristiti sljedeće metode:


- attributeExists(): provjerava postojanje zadanog atributa
- attribute(): provjerava vrijednost atributa
U klasi SecurityMockMvcRequestPostProcessort nalazi se user koji služi za provjeru kako applikacija funkcionira u
slučaju da se prijav korisnika sa zadanim korisničkim imenom.
- Metoda autenthicadet() provjerava je li korisnik sa zadanim korisničkim imenom zapravi i prijavljen u
aplikaciju

EclEmma plugin je za Ecliple sto pofarba testove


13. HIBERNATE

Hibernate je ORM (Object Relation Mapping). Omogućava mapiranja POJO objekata na retket u bazi podataka čime
se izbjegava ručno popunjavanje objekata prilikom dohvaćanje iz baze

Princip rada:

POJO pojo = new POJO();


ORMSuloution orm = ORMsolution.getInstance();
orm.save(pojo);
Npr. ako su zadane tablice u bazi podatak:
CREATE TABLE STUDOMAT.VRSTA_KOLEGIJA (
VRSTA_KOLEGIJA_ID INT GENERATED ALWAYS AS IDENTITY,
NAZIV VARCHAR(30) NOT NULL,
PRIMARY KEY (VRSTA_KOLEGIJA_ID)
);
CREATE TABLE STUDOMAT.KOLEGIJ (
KOLEGIJ_ID INT GENERATED ALWAYS AS IDENTITY,
NAZIV VARCHAR(30) NOT NULL,
ECTS INT NOT NULL,
VRSTA_KOLEGIJA INT NOT NULL,
PRIMARY KEY (KOLEGIJ_ID),
FOREIGN KEY (VRSTA_KOLEGIJA) REFERENCES STUDOMAT.VRSTA_KOLEGIJA(VRSTA_KOLEGIJA_ID)
);

Njihove domenske klase izgledale bi:

@Entity
@Table(name=“STUDOMAT.KOLEGIJ“)
public class Kolegij implements Serilizable {

@Id
@Column(name=“KOLEGIJ_ID“)
@GeneratedValeu
private int id;

private String naziv;

@Column(name=“ECTS“)
private int brojECTSbodova

@Column(name=“VRSTA_KOLEGIJA“)
@Enumerated(EnumType.STRING) – ovo su one enumeracije (ono kaj nije interface)
@JoinTable(name=“STUDOMAT.VRTA_KOLEGIJA“, joinCoulmns = @JoinColumn(name=“NAZIV“)
Private VrsteKolegija vrstekolegija;
public Kolegij () {} – obavezan defaultni konstuktor

}
Svaka klasa čiji objekti s espremaju u bazu pododatak moraju imati konstruktor bez parametara (Lombokova
@NoArgsConstructor anotacija) -> takve klase nazivaju se perzistentne klase.

- Kontsuktor mora biti public ili private


- Hibernetu to omogućava „lazy loading“ tehnike
- Potrebno je napraviti o override hashCode i equals metedote kako bi se elementi mogli jednonačno
uspoređivati
Na primejr, ako je potrebno definirati vezu između klasa Questions i Answers:
@Entity
@Table(name=“QUIZ:ANSWERS“)
public class Answer implements Serializable {

@Id
@Columne (name=“ID“)
@GeneratedValue
private int id;

@Column(name=“ANSWERTEXT“)
private String answerText;

@Columnt(name=“CORRECT_ANSWER“)
private bollean correct;

@ManyToOne // -- jer je Answers dijete od Questions


@JoinColumn(name=“QUESTIONSID“) // Uz pomoć anotacije @JoinColumn potrebno je definirati naziv kolone unutar tablice Answers koja označava vezu s
tablicom Question.
private Question question;
}

@Entity
@Table(name=“QUIZ.QUESTIONS)
public class Questions implements Serializable {

@Id
@Columne (name=“ID“)
@GeneratedValue
private int id;

@Column(name=“QUESTIONTEXT“)
private String questionText;

unutar @OneToMany potrebno je pomoću atributa „mappedBy” definirati naziv kolone u klasi „Answer” koja sadrži
objekt „Question“
@OneToMany (mappedBy=“question“, fetch=FetchType.EAGER //
private List <Answer> answerList;
}

Ukoliko je izravno potrebno povezati dvije klase na način da se lista objekata klase „Answer” popuni unutar klase „Question”, potrebno je
koristiti anotacije „@OneToMany” (kod klase „Question”, jer ima funkciju „roditelja”) i „@ManyToOne” (kod klase „Answer” jer ima funkciju
„djeteta”).
Uz pomoć anotacije @JoinColumn potrebno je definirati naziv kolone unutar tablice Answers koja označava vezu s tablicom Question.
Također, unutar anotacije „@OneToMany” potrebno je pomoću atributa „mappedBy” definirati naziv kolone u klasi „Answer” koja sadrži
objekt „Question”
Hibernate anotacije:

@Entity – na razini klase


@Table – za određivanja tablice na koju se odnosi (parametar name @Table(name=“QUIZ.QUESTIONS“))
@Column – za definiranje naziva kolone u bazi koja se povezuje s dotičnim propertyem (ako je naziv varijable
idencitacn nazivu kolone u bazi moze se izostavit)
@Id – sluzi za definiranje propertya kao identifikatora klase
@GeneratedValue
@JoinCoulmn
Veze između tablica
@OneToMany - Objekt klase A može biti pocezan s više objektom klase B
@ManyToOne – Objekt klase A može biti pocezan s jednim objektom klase B
@ManyToMany – Vbiše objekata klase A s više objekata klase B
@OneToOne – objekt klase A povezan samo s jendnim objkekom klase B
Lazy loading - Postavlja se pomoću atributa anotacija „FetchType.LAZY” (ako se ne navede „EAGER”, podrazumijeva
se vrijednost „LAZY”)

Konfiguriranje Hiberneta:
podrška za deklerativno kreiranje transakcija na razini svake metode postiže se anotacijom
@EnableTransatcnionManagment

@Configuration
@EnableTransactionManager
public clas HibernateConfig {

@Bean
public PlatformTransactionManager hibTransManager () {
HibernetTransactionManager transMana = new HibernetTransactionManager ();
transMana.setSessionFactory(sessionFactory().getObject());
return transMana;

A postavljanje detalja vezuanih uz korištenje baze podatka moze se definirati pomoću dataSource beana:

@Bean
public DataSource datasource () {
DriverManagmentDataSource dtSource = new DriverManagmentDataSource();
dtSource.setDriverClassName(„org.h2.Driver“);
dtSource.setUsername("sa");
dtSource.setPassword("sa");
return dtSource;
}
Za ispravan rad Hiberneta potrebno je konfigurirati:

@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBeansessionFactory= newLocalSessionFactoryBean();
sessionFactory.setDataSource(dataSource());
sessionFactory.setPackagesToScan("hr.java.web.model");
sessionFactory.setHibernateProperties(hibernateProperties());
returnsessionFactory;

Kako bi Hibernate mogao pronaći entity klase s kojima se mapiraju tablice u bazi podatkaa portbeno je kreirati
entitiyManagerFactory bean:

@Bean
public LocalContainerEntityManagerFactoryBEan entittyManagerFactory() {
LocalContainerEntityManagerFactoryBean aj = new …
aj.setDataSource(dataSource());
aj.setPaclagesToScan("hr.java.web.model");
JpaVendorAdapter vendorAdapter= newHibernateJpaVendorAdapter();
aj.setJpaVendorAdapter(vendorAdapter);
return aj;
}

Baze podataka kojima se pristupa preko Hibernate imaju razlićite specifičnosti, naderbe i sl. ako zatreba tujekom
implemetacije promjeniti bazu podataka potrebno je promjenii smao dijalekt npr „H2Dialect“ u „OracleDialect“

private Properties hibernateProperties () {


Properties hibernateProperties = new Properties;
hibernateProperties.setProperty(“hibernet.dialect“, “ org.hibernate.dialect.H2Dialect“);
return hibernateProperties;
}

Klasa Session koja se kreira pomoćiu sessionFactory beana sadrži par općenitih metoda za korištenje nad pbjektima:
.save .saveOrUpdate .find .delete .createQuery

Korištenjem Hibernateai anotacija @Transactional (koja se može staviti na razini klase) sve metode izvode se u
zasebnim transakcijama, a anotacijom „@Primary” se u slučaju više istovjetnih repozitorija koji implementiraju isto
sučelje odabire „primarni”:

@Primary
@Repository
@Transactional
public class HibernatePredavacRepositoryimplements PredavacRepository{
privateSessionFactorysessionFactory;
@Autowired
publicHibernatePredavacRepository(SessionFactorysessionFactory) {
this.sessionFactory= sessionFactory;
}
14. Korištenje baza podataka u Java web aplikacijama

U slučaju korištenja fizičke baze podataka podaci za pristupanje nalaze se na aplikacijskom poslužitelju (konfiguraciji
Tomcat poslužitelja, unutar „server.xml” i „context.xml” datoteka).

U tom slučaju se u Java kodu nalazi samo JNDI identifikator za data source.

Resurs predstavlja objekt koji omogućava spajanje na sustave poput baze podataka

JNDI – Java Naming And Directory Intface: servis koji omogućuje komponentama lociranje drugig komponenata i
resursa

JDBC resurs se često naziva i data source.

JNDI resursi definiraju se unutar JNDI namespacea (kod Tomcata unutar „<Resource>” tagova u „context.xml”
datoteci i „<GlobalNamingResources>” unutar „server.xml” datoteke)

Konfiguriranje Tomcata:

unutar server.xml konfiguracije Tomcata moguće je definirati globalni resurs koji definia detalje vezane uz bazu
podataka i JNDI:

<Resource auth="Container"
driverClassName="org.h2.Driver"
maxActive="8"
name="biljeznicaDatabase"
username="student"
password="student"
type="javax.sql.DataSource"
url="jdbc:h2:tcp://localhost/~/BiljeznicaDB" />

A unutar context.xml konfiguracije Tomcata moguće ej definirati vezu na globalni resurs definiran unutar server.xml
konfiguracije:
<ResourceLink name=“jdbc/BiljeznicaDatabase“ global =“biljeznicaDatabase“ type=“javax.sql.DataSource“/>

Tomcat koristi DBCP (database conetction pool). omogućava definiranje nekih prametara unutar connectio poola
tipa broj konekcija, maksimalnoi vrijeme čekanje za konekciju, ali i postavljanje opcije koja oslobađa konekcije koje
nisu zatvorene (removeAbandoned=„true”) itd.

H2 baza podataka je idealna za korištenje u in-memor ynačinu rada


•Konfigurira se na način da se definira „jdbc:embedded-database” konfiguracija na način da se definiraju datoteke
koje sadrže SQL skriptu za kreiranje i popunjavanje baze podataka:

<jdbc:embedded-database id="dataSource" type="H2">


<jdbc:scriptlocation="classpath:biljeznica/db/jdbc/schema.sql" />
<jdbc:scriptlocation="classpath:biljeznica/db/jdbc/test-data.sql" />
</jdbc:embedded-database>

Repository
kao zamjenu za Mock implementaciju klase koja uvijek vraća zahardkodirane podatke implemetacija Repository sloja
zapoćinje na način da je prvo potrebno definirati sučelje s popisom metoda:

public interface BiljeskaRepository {


List<Biljeska> findAll();
Biljeska save(Biljeska biljeska);

}

public interface PredavacRepository {


Iterable <Predavac> findAll();
Predavac findOne(String id);
}

Impelementacija navedenog sucelja temelji se na SQL upitima i korištenju objekta klase JdbcTemlate i
SimpleJdbcInsert

@Repository
public class JdbcPredavacrepository implements PredavacRepository {

private JdbcTemplate jdbc;


private SimpleJdbcInsert predavInserter;

@Autowired
public JdbcPredavacRepositor (JdbcTemplate jdbc) {
this.jdbc = jdbc;
this.predavacInserter= newSimpleJdbcInsert(jdbc)
.withTableName("Predavac")
.usingGeneratedKeyColumns("id");
}

Kako bi se umjesto „zahardkodiranih” podataka o korisnicima koristili podaci iz baze podataka, securitykonfiguraciju
je potrebno proširiti na sljedeći način:
@Autowired
DataSourcedataSource;

@Override
protected void configure(AuthenticationManagerBuilderauth) throws Exception {
auth
.jdbcAuthentication()
.usersByUsernameQuery("selectusername, password, enabledfromKorisnik whereusername=?")
.authoritiesByUsernameQuery("select username, authority from KorisnikPravawhere username=?")
.passwordEncoder(newBCryptPasswordEncoder(4));
15. Spring JPA

Unutar klasa koje predstavljaju repozitorije je moguće dodavati svoje metode koje obavljaju upite prema zadanim
parametrima unutar naziva metode.

public interface LocationJpaRepository extends JpaRepository <Location,Long> {

List<Location> findByStateLike (String stateName);

Kako unutar Location klase postioji varijabla State zadani upit je validan:

@Entity
public class Location {
@Id
@GeneratedValue (strategy = GenerationType.AUTO)
public Long id;
private String state;
}

Sintaksa Query metoda pomoću kojih se kroz naziv metode definira upit je sljedeća:

- find…By
- Koriste se nazivi atributa JPA entiteta
- Višestruki kriteriji mogu se slagati korištenjem ključnih riječi „And” i „Or”
- Ključne riječi poput „Like” označavaju način pretraživanja podataka

U ovisnosti što metoda vraća treba postaviti povratne tipoce metoda

public interface LocationJpaRepository extends JpaRepository<Location, Long> {

Location findFirstByState(StringstateName);

List<Location> findByStateLike(StringstateName);

Long countByStateLike(StringstateName);
Ključnim rijećima And i Or moguće je povezivat kriterij SQL upita:

List <Location> findByStateLikeOrCountry (String value, String value2);

Ključne riječi Equals, Is, Or (is i equals su isto)

List<Location> findByStateIsOrCountryEquals(String value, String value2);

List<Location> findByStateNot(Stringstate);

Ključna riječ Like (uz dodavanje znaka %)

List <Location> locs = locationJpaRepository.findByStateLike(„Zapadni%“);

Ključne riječi StartingWith, EndingWith, Containing

List <Location> findByStateEndingWith (String rijećč);

Ključne riječi GraterThanEqual, LessThanEqual

List <Model> findByPriceGreaterThanEqualAndPriceLessThanEqual (int low, int high)– opet moram napisati
price

Kod rada s datumima mogu se koristiti ključne riječi Before, After ili Between

public interface ManufacturerJpaRepository extends JpaRepository<Manufacturer, Long> {

List<Manufacturer> findByFoundedDateBefore(Date date);

Ključne riječi True i False

List<Manufacturer> findByActiveTrue();

Ključne riječi isNull i isNotNull -- one ne zahtjevaju parametas s kojim bi se usporedile

List <Model> findByNameIsNull();

Pomoću In i NotIn je moguće kreirati upit koji dohvala ili filttira entitete čija se vrijednost nalazi unutar zbirke:

List <Model> findByModelTypeNameIn(List<String> tipovi);

Moguće je i ignorirati case s ključnim riječima IgnoreCase

List <Location> findByStateLikeIgnoreCaseStartingWith (String pocetak);

Ključna riječ za sortiranje je OrderBy

List <Location> findByStateNotLikeOrderByStateAsc (String imedrzave);

ključne riječi First – samo prvi elemnt, Top – definiramo broj elementa koji želimo dohvatiti (fist i top su aliasi),
Distinct – služi za brisanje duplikata – oni dolaze dosta rano u nazivu,odmah iza find

List <Location> findTop5ByStateIgnoreCaseStartingWith (Strin nekaj);

U slučaju kad je u upitu potrebno npr. unutar objekta klase „Biljeska” koristiti varijablu klase „Korisnik” koja se zove
„korisnickoIme”, to je potrebno napraviti korištenjem znaka „_” na sljedeći način:

public interface BiljeskaRepository extends JpaRepository<Biljeska, Integer> {

List <Biljeska> findByKorisnik_KorisnickoIme (string korisnikoIme);

Za razliku od JpaRepositorya koje uključuje i funkcionalnost straničenja postoji i CrudRepository koji uključuje samo
CRUD fnkcionalnosti. – JpaRepository ukljucuje stranicenje
public interface PredavanjeRepository extendsCrudRepository<Predavanje, Long>{
List<Predavanje> findByTema(String tema);
}

Pomoću anotacije @Query moguće je definirati i vlastiti upit koji ne koristi ključne riječi u nazivu metode

@Query(“SELECT p FROM Person p WHERE LOWER(p.lastName)“=LOWER(:lastName)


public List <Person> find (@Param(„lastName) String imezadnje);

SpringData REST

Omogućava izravno generiranje REST API sučelja na temelju naziva repozitorija. podržava napredne funkcije
straničenja i sortiranja krooz paremetre URLa npr. „http://localhost:8080/people/?page=5”

Koristi se dodavanjem anotacije @RestRespurce na razini klase:

@Data
@NoArgsConsturctor
@Entity
@RestResource (path=“predavanje“, rel =“predavanja“)
public class Predavanje {

}
16. Spring MVC REST servisi

Arhitekturalni stil za dizajniranje web servisa koji mogu koristiti različiti klijenti. temelji se na HTTP protokolu. Moze
se temeljiti na JSON ili XML formatu.
Moguća manipulacija nad HTTP metodama:

- POST - kreiranje
- GET - dohvacanje
- DELETE - brisanje
- PUT – ažuriranje

Označava se s @RestController anotacijom

Anotacija @RestController eliminira potrebu da se svakoj metodu unutar Controllera postavlja anotacija
@ResponseBody.
Anotacijom @ResponseBody Spring mapira povratnu vrijednost controllera u tijelo HTTP odgovora.
Anotacijom @RequestBody omogućava mapiranje odlazećeg zahtjeva na zadani parametar temeljenog na ACCEPT ili
COntentType zaglavlju.
Anotacija @CrossOrigin omogućava postavljanje ograničenja na iozvršavanje AJAX poziva (izvršavanje poziva iz
jednog taba u drugom). To je W3C specifikacija.
Moguće je koristiti i @GetMapping, @PostMapping, @PutMapping i @DeleteMapping. A za prenošenje parametra
iz URL-a moguće je koristiti @Pathvariable varijablu.

Anotacijom @ResponseStatus moguće je postaviti status koji će se vratutu kao odgovor:

Objekt klase ResponseEntitiy predstavlja cijeli HTTP odgovor iz gore navedenog:

@GetMapping(“/{id}“)
public ResponsEntitiy<Predavanje> findOne(@PathVariable String id) {
Predavanje predavanje = predavanje.findOne(id);

if(predavanje != null) {
return new ResponseEntity<>(predavanje,HttpStatus.OK)
} else {
return new ResponseEntity<>(null, HttpStatus.NOT_FOUND)
}
Alat za testiranje zove se POSTMAN

You might also like