Professional Documents
Culture Documents
Java I I II
Java I I II
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.
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
- 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
Taiga – kanban Balsamiq – web mock NjinjaMock – web mock inVision – web mock
Web sloj
Servisni sloj
Sloj Repozitorja
- 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
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
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
@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
@SpringBootApplication
public class Applikacija {
public static void main (String[] args) {
SpringApplication.run(Applikacija.class, args);
}
}
@EnableAutoConfiguration
@ComponentScan
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
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=“@{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
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}“
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“:
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 /**
@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.
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.
- 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
- Git direktorij
- Radni direktorij
- Staging area
- Tracked – datoteka se nalazi unutar posljednjeg snapshota i može biti nepromijenjena, promijenjena ili
staged
- Untracked – sve ostale datoteke
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
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 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.
- SourceTree
- bit bucket
- gitLab
9. i18n
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.
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.
A zatim na HTML stranici koristeci thymeleaf povezem svoje rijeci s onima iz properties:
<th th:text=“#{msg.predavanje.tema}“>Teema</th>
@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)
@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
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.
Metoda storedDurably omogućava zadržavanje joba i nakon što njegov roditelj više ne postoji
@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
.withIdentity("job1", "group1")
.build();
// Trigger the job to run now, and then repeat every 40 seconds
.withIdentity("trigger1", "group1")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(40)
.repeatForever())
.build();
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.
Jenkins je moguće preuzeti kao Java web aplikaciju (WAR) a pokreće se iz komande linije naredbom
Osnovne funckije Jenksinsa: new item, people, build history, manage jenkis, my views, open blue ocean, credentials,
new view
SonarQube
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.
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 {
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
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:
@Entity
@Table(name=“STUDOMAT.KOLEGIJ“)
public class Kolegij implements Serilizable {
@Id
@Column(name=“KOLEGIJ_ID“)
@GeneratedValeu
private int id;
@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.
@Id
@Columne (name=“ID“)
@GeneratedValue
private int id;
@Column(name=“ANSWERTEXT“)
private String answerText;
@Columnt(name=“CORRECT_ANSWER“)
private bollean correct;
@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:
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“
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
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.
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:
Impelementacija navedenog sucelja temelji se na SQL upitima i korištenju objekta klase JdbcTemlate i
SimpleJdbcInsert
@Repository
public class JdbcPredavacrepository implements PredavacRepository {
@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.
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
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> findByStateNot(Stringstate);
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
List<Manufacturer> findByActiveTrue();
Pomoću In i NotIn je moguće kreirati upit koji dohvala ili filttira entitete čija se vrijednost nalazi unutar zbirke:
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
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:
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
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”
@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
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.
@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