ПИА/К1 2021

Извор: SI Wiki
Пређи на навигацију Пређи на претрагу

Prvi kolokvijum 2021. godine održan je 26. 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 skriptom za pravljenje baze. Bile su dve grupe.

Iako se kolokvijum radio na JDK verziji 8, ispod je dato rešenje korišćenjem JDK verzije 11.

Grupa 1

Postavka

Postavka je dostupna sa stranice predmeta.

Napraviti sledeću mini internet aplikaciju za prodavnicu za kućne ljubimce "Maza". Internet 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 kupci i prodavci. Korisnici treba da imaju mogućnost unošenja korisničkog imena i lozinke i da pomoću padajuće liste odaberu da li se prijavljuju kao kupci ili prodavci. U slučaju ispravno unetih podataka, korisniku treba omogućiti rad sa ostatkom sistema (za svaki tip korisnika treba prikazati posebnu početnu veb stranicu nakon prijavljivanja). Ukoliko korisnik ne unese neki od podataka ili unese pogrešne podatke, potrebno je ispisati poruku greške slovima crvene boje, sa mogućnošću ispravljanja greške u formi. Po uspešnoj prijavi u sistem, korisniku dati i opciju da se odjavi. [7 poena]

Kupac nakon uspešnog prijavljivanja, vidi tabelarni prikaz svih proizvoda. Proizvode koji su na promociji obojiti zelenom bojom. [5 poena] Pored svakog proizvoda postoji polje za potvrdu – „štikliranje“ (checkbox) i polje za unos željene količine proizvoda. Ispod tabele sa proizvodima stoji dugme Naruči. Pritiskom na dugme Naruči kupac prelazi na drugu stranicu na kojoj je prikazan sadržaj narudžbine, sa svim štikliranim proizvodima i njihovim količinama. Smatrati da svih proizvoda ima dovoljno na stanju za svaku narudžbinu. [5 poena] Pored svakog naručenog proizvoda stoji dugme Ukloni. Pritiskom na dugme Ukloni taj proizvod se briše iz narudžbine. [3 poena] Ispod spiska naručenih proizvoda stoji dugme Potvrdi, čime se narudžbina upisuje u bazu podataka. Datum narudžbine je trenutni datum. [5 poena]

Prodavac nakon uspešnog prijavljivanja, vidi svoje lične podatke (ime, prezime, datum rođenja), kao i tabelarni prikaz svih narudžbina. U tabeli prikazati korisničko ime kupca, datum narudžbine i nazive naručenih proizvoda u okviru te narudžbine. [7 poena] Ispod tabele narudžbina, u svakom trenutku ispisivati najvernijeg kupca, tj. kupca koji ima najviše narudžbina. [3 poena]

Rešenje

Ime paketa koje se koristi u rešenju je rs.ac.bg.etf.pia.petshop2021.

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">Korisničko ime:</label>
                <h:inputText id="username" value="#{loginManagedBean.username}"></h:inputText>
            </p>
            <p>
                <label for="password">Lozinka:</label>
                <h:inputText id="password" value="#{loginManagedBean.password}"></h:inputText>
            </p>
            <p>
                <label for="tip">Tip:</label>
                <h:selectOneMenu value="#{loginManagedBean.tip}">
                    <f:selectItem itemLabel="Kupac" itemValue="kupac"></f:selectItem>
                    <f:selectItem itemLabel="Prodavac" itemValue="prodavac"></f:selectItem>
                </h:selectOneMenu>
            </p>
            <p><h:commandButton value="Prijavi se" action="#{loginManagedBean.login()}"></h:commandButton></p>
            <p><h:outputText class="error" value="#{loginManagedBean.error}"></h:outputText></p>
        </h:form>
    </h:body>
</html>
kupac.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>Kupac</title>
        <h:outputStylesheet name="css/main.css"></h:outputStylesheet>
    </h:head>
    <h:body>
        <h:form>
            <h:commandLink value="Izloguj se" action="#{loginManagedBean.logout()}"></h:commandLink>
            <h:dataTable value="#{kupacManagedBean.allProducts}" var="product">
                <h:column class="#{product.promocija ? 'promocija' : ''}">
                    <f:facet name="header">Naziv</f:facet>
                    <h:outputText value="#{product.naziv}"></h:outputText>
                </h:column>
                <h:column class="#{product.promocija ? 'promocija' : ''}">
                    <f:facet name="header">Opis</f:facet>
                    <h:outputText value="#{product.opis}"></h:outputText>
                </h:column>
                <h:column class="#{product.promocija ? 'promocija' : ''}">
                    <f:facet name="header">Cena</f:facet>
                    <h:outputText value="#{product.cena}"></h:outputText>
                </h:column>
                <h:column class="#{product.promocija ? 'promocija' : ''}">
                    <f:facet name="header">Kupiti?</f:facet>
                    <h:selectBooleanCheckbox value="#{product.kupiti}"></h:selectBooleanCheckbox>
                </h:column>
                <h:column class="#{product.promocija ? 'promocija' : ''}">
                    <f:facet name="header">Koliko?</f:facet>
                    <h:inputText value="#{product.koliko}"></h:inputText>
                </h:column>
            </h:dataTable>
            <h:commandButton value="Naruči" action="narudzbina"></h:commandButton>
        </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>Narudžbina</title>
    </h:head>
    <h:body>
        <h:form>
            <h:dataTable value="#{kupacManagedBean.allProducts}" var="product">
                <h:column>
                    <f:facet name="header">Naziv</f:facet>
                    <h:outputText value="#{product.naziv}" rendered="#{product.kupiti and product.koliko gt 0}"></h:outputText>
                </h:column>
                <h:column>
                    <f:facet name="header">Količina</f:facet>
                    <h:outputText value="#{product.koliko}" rendered="#{product.kupiti and product.koliko gt 0}"></h:outputText>
                </h:column>
                <h:column>
                    <f:facet name="header">Ukloniti?</f:facet>
                    <h:commandButton value="Ukloni" action="#{kupacManagedBean.remove(product)}" rendered="#{product.kupiti and product.koliko gt 0}"></h:commandButton>
                </h:column>
            </h:dataTable>
            <h:commandButton value="Potvrdi" action="#{kupacManagedBean.order()}"></h:commandButton>
        </h:form>
    </h:body>
</html>
prodavac.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>Prodavac</title>
        <h:outputStylesheet name="css/main.css"></h:outputStylesheet>
    </h:head>
    <h:body>
        <h:form>
            <h:commandLink value="Izloguj se" action="#{loginManagedBean.logout()}"></h:commandLink>
        </h:form>
        <p>
            Dobrodošli
            <h:outputText value="#{prodavacManagedBean.name}"></h:outputText>&nbsp;<h:outputText value="#{prodavacManagedBean.surname}"></h:outputText>
            koji ste rođeni
            <h:outputText value="#{prodavacManagedBean.birthdate}"></h:outputText>.
        </p>
        <h:dataTable value="#{prodavacManagedBean.orders}" var="order">
            <h:column>
                <f:facet name="header">Kupac</f:facet>
                <h:outputText value="#{order.kupac}"></h:outputText>
            </h:column>
            <h:column>
                <f:facet name="header">Datum</f:facet>
                <h:outputText value="#{order.datumNarudzbine}"></h:outputText>
            </h:column>
            <h:column>
                <f:facet name="header">Proizvodi</f:facet>
                <h:outputText value="#{order.proizvodi}"></h:outputText>
            </h:column>
        </h:dataTable>
        <p>Najverniji kupac: <h:outputText value="#{prodavacManagedBean.najvernijiKupac}"></h:outputText></p>
    </h:body>
</html>

Zrna

LoginManagedBean
package rs.ac.bg.etf.pia.petshop2021.beans;

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 jakarta.inject.Named;
import jakarta.enterprise.context.RequestScoped;
import jakarta.servlet.http.HttpSession;
import rs.ac.bg.etf.pia.petshop2021.util.DB;
import rs.ac.bg.etf.pia.petshop2021.util.SessionUtils;

@Named(value = "loginManagedBean")
@RequestScoped
public class LoginManagedBean {
    private String username;
    private String password;
    private String tip;
    private String error;

    public LoginManagedBean() {}

    public String login() {
        if (username.isEmpty() || password.isEmpty() || tip.isEmpty()) {
            error = "Niste uneli sve podatke.";
            return null;
        }
        Connection conn = DB.getInstance().getConnection();
        try (PreparedStatement stmt = conn.prepareStatement("SELECT * FROM korisnici WHERE kor_ime = ? AND lozinka = ? AND tip = ?")) {
            stmt.setString(1, username);
            stmt.setString(2, password);
            stmt.setString(3, tip);
            try (ResultSet rs = stmt.executeQuery()) {
                if (rs.next()) {
                    HttpSession session = SessionUtils.getSession();
                    session.setAttribute("kor_ime", username);
                    session.setAttribute("ime", rs.getString("ime"));
                    session.setAttribute("prezime", rs.getString("prezime"));
                    session.setAttribute("datum_rodjenja", rs.getDate("datum_rodjenja").toLocalDate());
                    return tip + ".xhtml?faces-redirect=true";
                } else {
                    error = "Nije ispravno korisničko ime, lozinka ili tip.";
                    return null;
                }
            }
        } catch (SQLException ex) {
            Logger.getLogger(LoginManagedBean.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DB.getInstance().putConnection(conn);
        }
        error = "Nepoznata greška.";
        return null;
    }
    
    public String logout() {
        HttpSession session = SessionUtils.getSession();
        session.removeAttribute("kor_ime");
        session.removeAttribute("ime");
        session.removeAttribute("prezime");
        session.removeAttribute("datum_rodjenja");
        return "index.xhtml?faces-redirect=true";
    }
    
    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 getTip() {
        return tip;
    }

    public void setTip(String tip) {
        this.tip = tip;
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }
}
KupacManagedBean
package rs.ac.bg.etf.pia.petshop2021.beans;

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 jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.SessionScoped;
import jakarta.inject.Named;
import rs.ac.bg.etf.pia.petshop2021.entities.Product;
import rs.ac.bg.etf.pia.petshop2021.util.DB;
import rs.ac.bg.etf.pia.petshop2021.util.SessionUtils;

@Named(value = "kupacManagedBean")
@SessionScoped
public class KupacManagedBean implements Serializable {
    private List<Product> allProducts;

    public KupacManagedBean() {}

    @PostConstruct
    public void initData() {
        allProducts = new ArrayList<>();
        Connection conn = DB.getInstance().getConnection();
        try (
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM proizvodi");
        ) {
            while (rs.next()) {
                Product p = new Product();
                p.setNaziv(rs.getString("naziv"));
                p.setOpis(rs.getString("opis"));
                p.setCena(rs.getInt("cena"));
                p.setPromocija(rs.getBoolean("promocija"));
                allProducts.add(p);
            }
        } catch (SQLException ex) {
            Logger.getLogger(LoginManagedBean.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DB.getInstance().putConnection(conn);
        }
    }

    public void remove(Product p) {
        p.setKoliko(0);
        p.setKupiti(false);
    }
    
    public String order() {
        Connection conn = DB.getInstance().getConnection();
        try (
            PreparedStatement stmt = conn.prepareStatement("INSERT INTO narudzbine (kupac, datum) VALUES (?, NOW())", Statement.RETURN_GENERATED_KEYS);
            PreparedStatement stmt2 = conn.prepareStatement("INSERT INTO narudzbinasadrzi (narudzbina, proizvod, kolicina) VALUES (?, ?, ?)");
        ) {
            stmt.setString(1, (String) SessionUtils.getSession().getAttribute("kor_ime"));
            stmt.executeUpdate();
            try (ResultSet rs = stmt.getGeneratedKeys()) {
                if (rs.next()) {
                    stmt2.setInt(1, rs.getInt(1));
                } else {
                    return null;
                }
            }
            for (Product p : allProducts) {
                if (p.getKoliko() <= 0 || !p.isKupiti()) {
                    continue;
                }
                stmt2.setString(2, p.getNaziv());
                stmt2.setInt(3, p.getKoliko());
                stmt2.executeUpdate();
                p.setKupiti(false);
                p.setKoliko(0);
            }
        } catch (SQLException ex) {
            Logger.getLogger(KupacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DB.getInstance().putConnection(conn);
        }
        return "kupac?faces-redirect=true";
    }

    public List<Product> getAllProducts() {
        return allProducts;
    }

    public void setAllProducts(List<Product> allProducts) {
        this.allProducts = allProducts;
    }
}
ProdavacManagedBean
package rs.ac.bg.etf.pia.petshop2021.beans;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import jakarta.annotation.PostConstruct;
import jakarta.inject.Named;
import jakarta.enterprise.context.RequestScoped;
import jakarta.servlet.http.HttpSession;
import rs.ac.bg.etf.pia.petshop2021.entities.Order;
import rs.ac.bg.etf.pia.petshop2021.util.DB;
import rs.ac.bg.etf.pia.petshop2021.util.SessionUtils;

@Named(value = "prodavacManagedBean")
@RequestScoped
public class ProdavacManagedBean {
    private String name;
    private String surname;
    private LocalDate birthdate;
    private List<Order> orders;
    
    public ProdavacManagedBean() {}

    @PostConstruct
    public void initData() {
        HttpSession session = SessionUtils.getSession();
        name = (String) session.getAttribute("ime");
        surname = (String) session.getAttribute("prezime");
        birthdate = (LocalDate) session.getAttribute("datum_rodjenja");
        orders = new ArrayList<>();
        Connection conn = DB.getInstance().getConnection();
        try (
            Statement stmt = conn.createStatement();
            PreparedStatement stmt2 = conn.prepareStatement("SELECT * FROM narudzbinasadrzi WHERE narudzbina = ?");
            ResultSet rs = stmt.executeQuery("SELECT * FROM narudzbine");
        ) {
            while (rs.next()) {
                Order order = new Order();
                stmt2.setInt(1, rs.getInt(1));
                order.setKupac(rs.getString(2));
                order.setDatumNarudzbine(rs.getDate(3).toLocalDate());
                StringBuilder proizvodi = new StringBuilder();
                boolean first = true;
                try (ResultSet rs2 = stmt2.executeQuery()) {
                    while (rs2.next()) {
                        if (first) {
                            first = false;
                        } else {
                            proizvodi.append(", ");
                        }
                        proizvodi.append(rs2.getString(2));
                    }
                }
                order.setProizvodi(proizvodi.toString());
                orders.add(order);
            }
        } catch (SQLException ex) {
            Logger.getLogger(ProdavacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DB.getInstance().putConnection(conn);
        }
    }
    
    public String getNajvernijiKupac() {
        Connection conn = DB.getInstance().getConnection();
        try (
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT kupac, COUNT(*) AS br_naruzbina FROM narudzbine GROUP BY kupac ORDER BY br_naruzbina DESC LIMIT 1");
        ) {
            if (rs.next()) {
                return rs.getString(1);
            }
        } catch (SQLException ex) {
            Logger.getLogger(ProdavacManagedBean.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            DB.getInstance().putConnection(conn);
        }
        return "Nema narudžbina?";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSurname() {
        return surname;
    }

    public void setSurname(String surname) {
        this.surname = surname;
    }

    public LocalDate getBirthdate() {
        return birthdate;
    }

    public void setBirthdate(LocalDate birthdate) {
        this.birthdate = birthdate;
    }

    public List<Order> getOrders() {
        return orders;
    }

    public void setOrders(List<Order> orders) {
        this.orders = orders;
    }
}

Entiteti

Order.java
package rs.ac.bg.etf.pia.petshop2021.entities;

import java.time.LocalDate;
import java.util.List;

public class Order {
    private String kupac;
    private LocalDate datumNarudzbine;
    private String proizvodi;

    public String getKupac() {
        return kupac;
    }

    public void setKupac(String kupac) {
        this.kupac = kupac;
    }

    public LocalDate getDatumNarudzbine() {
        return datumNarudzbine;
    }

    public void setDatumNarudzbine(LocalDate datumNarudzbine) {
        this.datumNarudzbine = datumNarudzbine;
    }

    public String getProizvodi() {
        return proizvodi;
    }

    public void setProizvodi(String proizvodi) {
        this.proizvodi = proizvodi;
    }
}
Product.java
package rs.ac.bg.etf.pia.petshop2021.entities;

public class Product {
    private String naziv;
    private String opis;
    private int cena;
    private boolean promocija;
    private boolean kupiti;
    private int koliko;

    public boolean isKupiti() {
        return kupiti;
    }

    public void setKupiti(boolean kupiti) {
        this.kupiti = kupiti;
    }

    public int getKoliko() {
        return koliko;
    }

    public void setKoliko(int koliko) {
        this.koliko = koliko;
    }

    public String getNaziv() {
        return naziv;
    }

    public void setNaziv(String naziv) {
        this.naziv = naziv;
    }

    public String getOpis() {
        return opis;
    }

    public void setOpis(String opis) {
        this.opis = opis;
    }

    public int getCena() {
        return cena;
    }

    public void setCena(int cena) {
        this.cena = cena;
    }

    public boolean isPromocija() {
        return promocija;
    }

    public void setPromocija(boolean promocija) {
        this.promocija = promocija;
    }
}

Ostali fajlovi

main.css
.error {
    color: red;
}

.promocija {
    background-color: green;
}

Grupa 2

Овај задатак није решен. Помозите SI Wiki тако што ћете га решити.

Postavka

Postavka je dostupna sa stranice predmeta.

Rešenje