ПИА/К1 2020
Prvi kolokvijum 2020. godine održan je 28. novembra i trajao je dva sata. Koristila se tehnologija Java Server Faces sa MySQL bazom podataka, dostupnim materijalima sa predavanja, dodatnim klasama za rad sa bazom (DB.java
) i sesijama (SessionUtils.java
) kao i skriptama za pravljenje baze za prvu i drugu grupu.
Iako se kolokvijum radio na JDK verziji 8, ispod je dato rešenje korišćenjem JDK verzije 11.
Grupa 1
- Овај задатак није решен. Помозите SI Wiki тако што ћете га решити.
Postavka
- Postavka je dostupna sa stranice predmeta.
Rešenje
Grupa 2
Postavka
- Postavka je dostupna sa stranice predmeta.
Napraviti sledeću mini internet aplikaciju za zoološki vrt. Veb aplikaciju realizovati koristeći tehnologiju Java Server Faces.
Na početnoj strani aplikacije, napraviti HTML formu, preko koje mogu da se prijavljuju korisnici sistema, a to su radnici i posetioci. Korisnici treba da imaju mogućnost unošenja korisničkog imena i lozinke i da pomoću radio dugmeta odaberu jednu opciju: da li se prijavljuju u sistem kao radnici ili posetioci. U slučaju ispravno unetih podataka, korisniku treba omogućiti rad sa ostatkom sistema (za svaki tip treba prikazati posebnu početnu stranicu nakon uspešnog prijavljivanja). Ukoliko korisnik ne unese neki od podataka ili unese pogrešne podatke, potrebno je ispisati poruku greške crvenim slovima sa mogućnošću ispravljanja greške. Po uspešnoj prijavi u sistem, korisniku dati i opciju da se odjavi. [7 poena]
Posetilac nakon uspešnog prijavljivanja, vidi spisak svih životinja koje se nalaze u vrtu. Omogućiti sortiranje životinja po težini. [5 poena] Posetilac vidi i predloge drugih korisnika za dolazak novih životinja u vrt. Pored svakog predloga omogućiti da ga posetilac podrži klikom na dugme ZA. Dugme se vidi samo u slučaju da posetilac već nije glasao. Klikom na ovo dugme, ažurirati broj glasova za predlog u bazi. [4 poena] Posetilac može i da unese svoj predlog, pri čemu unosi naziv životinje, i komentar. [4 poena]
Radnik nakon uspešnog prijavljivanja, vidi spisak svih predloga za nove životinje. Predlozi koji imaju preko 2 glasa treba da budu obojeni zelenom bojom. [4 poena] Radnik može da odobri neki predlog, pri čemu se prebacuje na sledeću stranicu na kojoj se nalazi forma za dodavanje životinje, sa već unapred popunjenim poljem za naziv životinje. Pri dodavanju životinje, unosi se i težina životinje. Odobrene predloge ne treba brisati iz baze, već onemogućiti ponovno odobravanje takvih predloga. [7 poena] Radnik ima mogućnost i da odbije neki neodobren predlog, pri čemu se on tada briše iz baze. [4 poena]
Rešenje
Ime paketa koje se koristi u rešenju je rs.ac.bg.etf.pia.zoo2020
.
Stranice
index.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Dobrodošli</title>
<h:outputStylesheet name="css/main.css"></h:outputStylesheet>
</h:head>
<h:body>
<h:form>
<p>
<label for="username">Username:</label>
<h:inputText id="username" value="#{loginManagedBean.username}"></h:inputText>
</p>
<p>
<label for="password">Password:</label>
<h:inputSecret id="password" value="#{loginManagedBean.password}"></h:inputSecret>
</p>
<p>
<h:selectOneRadio value="#{loginManagedBean.group}">
<f:selectItem itemValue="radnik" itemLabel="Radnik"></f:selectItem>
<f:selectItem itemValue="posetilac" itemLabel="Posetilac"></f:selectItem>
</h:selectOneRadio>
</p>
<p><h:commandButton action="#{loginManagedBean.login()}" value="Login"></h:commandButton></p>
<p><h:outputText value="#{loginManagedBean.error}" class="error"></h:outputText></p>
</h:form>
</h:body>
</html>
posetilac.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Posetilac</title>
</h:head>
<h:body>
<h:form>
<h:commandButton action="#{loginManagedBean.logout()}" value="Odjavi se"></h:commandButton>
<h2>Životinje</h2>
<h:dataTable value="#{posetilacManagedBean.zivotinje}" var="z">
<h:column>
<f:facet name="header">Životinja</f:facet>
#{z.naziv}
</h:column>
<h:column>
<f:facet name="header">Težina</f:facet>
#{z.tezina}
</h:column>
</h:dataTable>
<h2>Predlozi</h2>
<h:dataTable value="#{posetilacManagedBean.predlozi}" var="p">
<h:column>
<f:facet name="header">Životinja</f:facet>
#{p.zivotinja}
</h:column>
<h:column>
<f:facet name="header">Posetilac</f:facet>
#{p.posetilac}
</h:column>
<h:column>
<f:facet name="header">Komentar</f:facet>
#{p.komentar}
</h:column>
<h:column>
<f:facet name="header">Glasovi</f:facet>
#{p.glasovi}
</h:column>
<h:column>
<f:facet name="header">Glasaj</f:facet>
<h:commandButton rendered="#{not p.glasao}" action="#{posetilacManagedBean.vote(p)}" value="ZA"></h:commandButton>
</h:column>
</h:dataTable>
<h2>Novi predlog</h2>
<p>
<label for="zivotinja">Životinja:</label>
<h:inputText value="#{posetilacManagedBean.zivotinja}" id="zivotinja"></h:inputText>
</p>
<p>
<label for="komentar">Komentar:</label>
<h:inputText value="#{posetilacManagedBean.komentar}" id="komentar"></h:inputText>
</p>
<p><h:commandButton action="#{posetilacManagedBean.suggest()}" value="Predloži"></h:commandButton></p>
</h:form>
</h:body>
</html>
narudzbina.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Radnik</title>
<h:outputStylesheet name="css/main.css"></h:outputStylesheet>
</h:head>
<body>
<h:form>
<h:commandButton action="#{loginManagedBean.logout()}" value="Odjavi se"></h:commandButton>
<h2>Predlozi</h2>
<h:dataTable value="#{posetilacManagedBean.predlozi}" var="p">
<h:column class="#{(p.glasovi gt 2) ? 'green' : ''}">
<f:facet name="header">Životinja</f:facet>
#{p.zivotinja}
</h:column>
<h:column class="#{(p.glasovi gt 2) ? 'green' : ''}">
<f:facet name="header">Posetilac</f:facet>
#{p.posetilac}
</h:column>
<h:column class="#{(p.glasovi gt 2) ? 'green' : ''}">
<f:facet name="header">Komentar</f:facet>
#{p.komentar}
</h:column>
<h:column class="#{(p.glasovi gt 2) ? 'green' : ''}">
<f:facet name="header">Glasovi</f:facet>
#{p.glasovi}
</h:column>
<h:column class="#{(p.glasovi gt 2) ? 'green' : ''}">
<f:facet name="header">Odobri</f:facet>
<h:commandButton action="#{radnikManagedBean.approve(p)}" rendered="#{not p.odobren}" value="Odobri"></h:commandButton>
</h:column>
<h:column class="#{(p.glasovi gt 2) ? 'green' : ''}">
<f:facet name="header">Odbaci</f:facet>
<h:commandButton action="#{radnikManagedBean.reject(p)}" rendered="#{not p.odobren}" value="Odbaci"></h:commandButton>
</h:column>
</h:dataTable>
</h:form>
</body>
</html>
dodaj.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<h:head>
<title>Dodaj životinju</title>
</h:head>
<h:body>
<h2>Dodaj</h2>
<h:form>
<p>
<label for="naziv">Naziv:</label>
<h:inputText value="#{radnikManagedBean.naziv}" id="naziv"></h:inputText>
</p>
<p>
<label for="tezina">Težina:</label>
<h:inputText value="#{radnikManagedBean.tezina}" id="tezina"></h:inputText></p>
<p><h:commandButton action="#{radnikManagedBean.add()}" value="Dodaj"></h:commandButton></p>
</h:form>
</h:body>
</html>
Zrna
LoginManagedBean
package rs.ac.bg.etf.pia.zoo2020.beans;
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Named;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.logging.Level;
import java.util.logging.Logger;
import rs.ac.bg.etf.pia.zoo2020.util.DB;
import rs.ac.bg.etf.pia.zoo2020.util.SessionUtils;
@Named(value = "loginManagedBean")
@RequestScoped
public class LoginManagedBean {
private String username;
private String password;
private String group;
private String error;
public String login() {
if (username.isEmpty() || password.isEmpty() || group.isEmpty()) {
error = "Niste uneli sve podatke.";
return null;
}
DB inst = DB.getInstance();
Connection db = inst.getConnection();
try (PreparedStatement stmt = db.prepareStatement("SELECT ime, prezime FROM korisnici WHERE kor_ime = ? AND lozinka = ? AND tip = ?")) {
stmt.setString(1, username);
stmt.setString(2, password);
stmt.setString(3, group);
try (ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
SessionUtils.getSession().setAttribute("kor_ime", username);
return group + ".xhtml?faces-redirect=true";
} else {
error = "Pogrešno korisničko ime, lozinka ili grupa.";
return null;
}
}
} catch (SQLException ex) {
Logger.getLogger(LoginManagedBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
inst.putConnection(db);
}
return null;
}
public String logout() {
SessionUtils.getSession().removeAttribute("kor_ime");
return "index.xhtml?faces-redirect=true";
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
}
PosetilacManagedBean
package rs.ac.bg.etf.pia.zoo2020.beans;
import rs.ac.bg.etf.pia.zoo2020.entities.Predlog;
import rs.ac.bg.etf.pia.zoo2020.entities.Zivotinja;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Named;
import jakarta.enterprise.context.RequestScoped;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import rs.ac.bg.etf.pia.zoo2020.util.DB;
import rs.ac.bg.etf.pia.zoo2020.util.SessionUtils;
@Named(value = "posetilacManagedBean")
@RequestScoped
public class PosetilacManagedBean {
private final List<Zivotinja> zivotinje = new ArrayList<>();
private final List<Predlog> predlozi = new ArrayList<>();
private String zivotinja;
private String komentar;
@PostConstruct
public void getData() {
DB inst = DB.getInstance();
Connection db = inst.getConnection();
try (
Statement stmt = db.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM zivotinje");
Statement stmt2 = db.createStatement();
ResultSet rs2 = stmt2.executeQuery("SELECT * FROM predlozi WHERE odobren = 0");
PreparedStatement stmt3 = db.prepareStatement("SELECT * FROM glasovi WHERE posetilac = ? and idP = ?");
) {
while (rs.next()) {
Zivotinja z = new Zivotinja();
z.setNaziv(rs.getString("naziv"));
z.setTezina(rs.getInt("tezina"));
z.setIdZ(rs.getInt("idZ"));
zivotinje.add(z);
}
while (rs2.next()) {
Predlog p = new Predlog();
p.setGlasovi(rs2.getInt("glasovi"));
p.setKomentar(rs2.getString("komentar"));
p.setPosetilac(rs2.getString("posetilac"));
p.setZivotinja(rs2.getString("zivotinja"));
int idP = rs2.getInt("idP");
p.setIdP(idP);
stmt3.setString(1, SessionUtils.getSession().getAttribute("kor_ime").toString());
stmt3.setInt(2, idP);
try (ResultSet rs3 = stmt3.executeQuery()) {
p.setGlasao(rs3.next());
}
predlozi.add(p);
}
} catch (SQLException ex) {
Logger.getLogger(PosetilacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
inst.putConnection(db);
}
zivotinje.sort((a, b) -> a.getTezina() - b.getTezina());
}
public String vote(Predlog p) {
DB inst = DB.getInstance();
Connection db = inst.getConnection();
try (
PreparedStatement stmt = db.prepareStatement("INSERT INTO glasovi (idP, posetilac) VALUES (?, ?)");
PreparedStatement stmt2 = db.prepareStatement("UPDATE predlozi SET glasovi = glasovi + 1 WHERE idP = ?");
) {
stmt.setInt(1, p.getIdP());
stmt.setString(2, SessionUtils.getSession().getAttribute("kor_ime").toString());
stmt.execute();
stmt2.setInt(1, p.getIdP());
stmt2.execute();
} catch (SQLException ex) {
Logger.getLogger(PosetilacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
inst.putConnection(db);
}
return "posetilac.xhtml?faces-redirect=true";
}
public String suggest() {
DB inst = DB.getInstance();
Connection db = inst.getConnection();
try (
PreparedStatement stmt = db.prepareStatement("INSERT INTO predlozi (posetilac, zivotinja, komentar, glasovi, odobren) VALUES (?, ?, ?, 0, 0)");
) {
stmt.setString(1, SessionUtils.getSession().getAttribute("kor_ime").toString());
stmt.setString(2, zivotinja);
stmt.setString(3, komentar);
stmt.execute();
} catch (SQLException ex) {
Logger.getLogger(PosetilacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
inst.putConnection(db);
}
return "posetilac.xhtml?faces-redirect=true";
}
public List<Zivotinja> getZivotinje() {
return zivotinje;
}
public List<Predlog> getPredlozi() {
return predlozi;
}
public String getZivotinja() {
return zivotinja;
}
public void setZivotinja(String zivotinja) {
this.zivotinja = zivotinja;
}
public String getKomentar() {
return komentar;
}
public void setKomentar(String komentar) {
this.komentar = komentar;
}
}
RadnikManagedBean
package rs.ac.bg.etf.pia.zoo2020.beans;
import rs.ac.bg.etf.pia.zoo2020.entities.Predlog;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Named;
import jakarta.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import rs.ac.bg.etf.pia.zoo2020.util.DB;
import rs.ac.bg.etf.pia.zoo2020.util.SessionUtils;
@Named(value = "radnikManagedBean")
@SessionScoped
public class RadnikManagedBean implements Serializable {
private List<Predlog> predlozi = new ArrayList<>();
private String naziv;
private String tezina;
private int idP;
@PostConstruct
public void getData() {
DB inst = DB.getInstance();
Connection db = inst.getConnection();
try (
Statement stmt2 = db.createStatement();
ResultSet rs2 = stmt2.executeQuery("SELECT * FROM predlozi");
PreparedStatement stmt3 = db.prepareStatement("SELECT * FROM glasovi WHERE posetilac = ? and idP = ?");
) {
while (rs2.next()) {
Predlog p = new Predlog();
p.setGlasovi(rs2.getInt("glasovi"));
p.setKomentar(rs2.getString("komentar"));
p.setPosetilac(rs2.getString("posetilac"));
p.setZivotinja(rs2.getString("zivotinja"));
p.setIdP(rs2.getInt("idP"));
stmt3.setString(1, SessionUtils.getSession().getAttribute("kor_ime").toString());
stmt3.setInt(2, rs2.getInt("idP"));
predlozi.add(p);
}
} catch (SQLException ex) {
Logger.getLogger(PosetilacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
inst.putConnection(db);
}
}
public String approve(Predlog p) {
naziv = p.getZivotinja();
idP = p.getIdP();
return "dodaj.xhtml?faces-redirect=true";
}
public String reject(Predlog p) {
DB inst = DB.getInstance();
Connection db = inst.getConnection();
try (
PreparedStatement stmt = db.prepareStatement("DELETE FROM predlozi WHERE idP = ?");
) {
stmt.setInt(1, p.getIdP());
stmt.execute();
} catch (SQLException ex) {
Logger.getLogger(PosetilacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
inst.putConnection(db);
}
return "radnik.xhtml?faces-redirect=true";
}
public String add() {
DB inst = DB.getInstance();
Connection db = inst.getConnection();
try (
PreparedStatement stmt = db.prepareStatement("INSERT INTO zivotinje (naziv, tezina) VALUES (?, ?)");
PreparedStatement stmt2 = db.prepareStatement("UPDATE predlozi SET odobren = 1 WHERE idP = ?");
) {
stmt.setString(1, naziv);
stmt.setInt(2, Integer.parseInt(tezina));
stmt.execute();
stmt2.setInt(1, idP);
stmt2.execute();
} catch (SQLException ex) {
Logger.getLogger(PosetilacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
} finally {
inst.putConnection(db);
}
return "radnik.xhtml?faces-redirect=true";
}
public String getTezina() {
return tezina;
}
public void setTezina(String tezina) {
this.tezina = tezina;
}
public String getNaziv() {
return naziv;
}
public void setNaziv(String naziv) {
this.naziv = naziv;
}
public List<Predlog> getPredlozi() {
return predlozi;
}
public void setPredlozi(List<Predlog> predlozi) {
this.predlozi = predlozi;
}
}
Entiteti
Zivotinja.java
package rs.ac.bg.etf.pia.zoo2020.entities;
public class Zivotinja {
private int idZ;
private String naziv;
private int tezina;
public int getIdZ() {
return idZ;
}
public void setIdZ(int idZ) {
this.idZ = idZ;
}
public String getNaziv() {
return naziv;
}
public void setNaziv(String naziv) {
this.naziv = naziv;
}
public int getTezina() {
return tezina;
}
public void setTezina(int tezina) {
this.tezina = tezina;
}
}
Predlog.java
package rs.ac.bg.etf.pia.zoo2020.entities;
public class Predlog {
private String posetilac;
private String zivotinja;
private String komentar;
private int glasovi;
private boolean glasao;
private boolean odobren;
private int idP;
public int getIdP() {
return idP;
}
public void setIdP(int idP) {
this.idP = idP;
}
public boolean isOdobren() {
return odobren;
}
public void setOdobren(boolean odobren) {
this.odobren = odobren;
}
public String getPosetilac() {
return posetilac;
}
public void setPosetilac(String posetilac) {
this.posetilac = posetilac;
}
public String getZivotinja() {
return zivotinja;
}
public void setZivotinja(String zivotinja) {
this.zivotinja = zivotinja;
}
public String getKomentar() {
return komentar;
}
public void setKomentar(String komentar) {
this.komentar = komentar;
}
public int getGlasovi() {
return glasovi;
}
public void setGlasovi(int glasovi) {
this.glasovi = glasovi;
}
public boolean isGlasao() {
return glasao;
}
public void setGlasao(boolean glasao) {
this.glasao = glasao;
}
}
Ostali fajlovi
main.css
.error {
color: red;
}
.green {
color: green;
}