├── src └── main │ ├── resources │ ├── META-INF │ │ ├── resources │ │ │ ├── js │ │ │ │ └── starter.js │ │ │ ├── favicon │ │ │ │ ├── favicon.ico │ │ │ │ ├── favicon-144x144.png │ │ │ │ ├── favicon-16x16.png │ │ │ │ ├── favicon-196x196.png │ │ │ │ ├── favicon-32x32.png │ │ │ │ └── favicon-96x96.png │ │ │ ├── images │ │ │ │ └── login-bg.jpeg │ │ │ ├── css │ │ │ │ └── starter.css │ │ │ ├── includes │ │ │ │ ├── menu.xhtml │ │ │ │ ├── menubar.xhtml │ │ │ │ ├── top-bar.xhtml │ │ │ │ └── controlsidebar-tabs-content.xhtml │ │ │ ├── index.xhtml │ │ │ ├── templates │ │ │ │ ├── template.xhtml │ │ │ │ └── template-top.xhtml │ │ │ ├── login.xhtml │ │ │ ├── car-form.xhtml │ │ │ └── car-list.xhtml │ │ ├── faces-config.xml │ │ └── web.xml │ ├── starter.properties │ ├── starter-en.properties │ ├── admin-config.properties │ └── application.properties │ └── java │ └── com │ └── github │ └── adminfaces │ └── starter │ ├── infra │ ├── model │ │ ├── SortOrder.java │ │ └── Filter.java │ ├── converter │ │ └── EntityConverter.java │ └── security │ │ └── LogonMB.java │ ├── util │ └── Utils.java │ ├── model │ └── Car.java │ ├── bean │ ├── CarFormMB.java │ └── CarListMB.java │ └── service │ └── CarService.java ├── docker ├── build_and_run.sh └── Dockerfile.jvm ├── README.adoc └── pom.xml /src/main/resources/META-INF/resources/js/starter.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/main/resources/starter.properties: -------------------------------------------------------------------------------- 1 | starter.version=${project.version} -------------------------------------------------------------------------------- /src/main/resources/starter-en.properties: -------------------------------------------------------------------------------- 1 | starter.version=${project.version} -------------------------------------------------------------------------------- /src/main/resources/admin-config.properties: -------------------------------------------------------------------------------- 1 | admin.renderControlSidebar=true 2 | admin.controlSidebar.showOnMobile=true 3 | -------------------------------------------------------------------------------- /docker/build_and_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mvn clean package && docker build -f docker/Dockerfile.jvm -t quarkus/admin-starter . && docker run -i --rm -p 8080:8080 quarkus/admin-starter -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adminfaces/quarkus-admin-starter/HEAD/src/main/resources/META-INF/resources/favicon/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/images/login-bg.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adminfaces/quarkus-admin-starter/HEAD/src/main/resources/META-INF/resources/images/login-bg.jpeg -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/favicon/favicon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adminfaces/quarkus-admin-starter/HEAD/src/main/resources/META-INF/resources/favicon/favicon-144x144.png -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/favicon/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adminfaces/quarkus-admin-starter/HEAD/src/main/resources/META-INF/resources/favicon/favicon-16x16.png -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/favicon/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adminfaces/quarkus-admin-starter/HEAD/src/main/resources/META-INF/resources/favicon/favicon-196x196.png -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/favicon/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adminfaces/quarkus-admin-starter/HEAD/src/main/resources/META-INF/resources/favicon/favicon-32x32.png -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/favicon/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adminfaces/quarkus-admin-starter/HEAD/src/main/resources/META-INF/resources/favicon/favicon-96x96.png -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/infra/model/SortOrder.java: -------------------------------------------------------------------------------- 1 | package com.github.adminfaces.starter.infra.model; 2 | 3 | /** 4 | * Created by rmpestano on 10/31/14. 5 | */ 6 | public enum SortOrder { 7 | 8 | ASCENDING, DESCENDING, UNSORTED; 9 | 10 | public boolean isAscending() { 11 | return ASCENDING.equals(this); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | # must include web.xml and faces-config.xml to be parsed. 2 | quarkus.native.resources.includes=META-INF/*.xml,*.properties 3 | # default bean validation locale 4 | quarkus.default-locale=en 5 | # The list of all the supported MyFaces locales 6 | quarkus.locales=ar,ca,cs,de,en,en_US,es,fr,it,ja,mt,nl,pl,pt,pt_BR,ru,sk,uk,zh_CN,zh_HK,zh_TW 7 | quarkus.http.port=8080 8 | quarkus.http.access-log.enabled=false 9 | quarkus.http.enable-compression=true 10 | quarkus.http.filter.others.header.Cache-Control=no-cache 11 | quarkus.http.filter.others.matches=/.* 12 | quarkus.http.filter.others.methods=GET,POST,PUT,DELETE 13 | quarkus.http.filter.others.order=0 14 | quarkus.servlet.direct-buffers=true 15 | quarkus.live-reload.instrumentation=true -------------------------------------------------------------------------------- /src/main/resources/META-INF/faces-config.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | en 12 | 13 | 14 | starter 15 | 16 | 17 | starter 18 | msg 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/css/starter.css: -------------------------------------------------------------------------------- 1 | .sidebar-form { 2 | border-radius: 3px; 3 | border: 1px solid #374850; 4 | margin: 10px 10px; 5 | } 6 | .sidebar-form, .sidebar-menu>li.header { 7 | overflow: hidden; 8 | text-overflow: clip; 9 | } 10 | 11 | #userImage { 12 | float: left; 13 | width: 25px; 14 | height: 25px; 15 | border-radius: 50%; 16 | margin-right: 10px; 17 | margin-top: -2px; 18 | } 19 | 20 | ul.dropdown-menu > li.user-header { 21 | height: auto!important; 22 | } 23 | 24 | a.dropdown-toggle { 25 | background-color: #3c8dbc!important; 26 | } 27 | 28 | a#logout { 29 | color: #3c8dbc!important; 30 | background: transparent; 31 | } 32 | 33 | @media (max-width: 768px) { 34 | body .control-sidebar { 35 | padding-top:100px; 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/includes/menu.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | Home 11 | 12 | 13 | 14 | General 15 | 16 | 17 | 18 | 19 | Cars 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/index.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | Welcome to the AdminFaces Starter Project! 14 | 15 | Integrating , and 17 | into your 18 | application. 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/includes/menubar.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | Home 11 | 12 | 13 | 14 | Cars 16 | 17 | 18 | 19 | 20 | 21 | 22 | List cars 23 | 24 | 25 | 26 | 27 | 28 | New car 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | = Quarkus AdminFaces Starter 2 | :page-layout: base 3 | :source-language: java 4 | :icons: font 5 | :linkattrs: 6 | :sectanchors: 7 | :sectlink: 8 | :numbered: 9 | :doctype: book 10 | :toc: preamble 11 | :tip-caption: :bulb: 12 | :note-caption: :information_source: 13 | :important-caption: :heavy_exclamation_mark: 14 | :caution-caption: :fire: 15 | :warning-caption: :warning: 16 | 17 | This project shows a `responsive *JSF*` application using https://adminfaces.github.io/site/[AdminFaces^] and running on https://quarkus.io/[Quarkus^]. 18 | 19 | NOTE: Only hotspot is supported. 20 | 21 | == Running Admin starter 22 | 23 | == Requirements 24 | 25 | * maven `3.6.3` or greater 26 | * Java 17+ 27 | 28 | === Via Maven 29 | 30 | * `git clone https://github.com/adminfaces/quarkus-admin-starter && cd quarkus-admin-starter && mvn compile quarkus:dev` 31 | * access http://localhost:8080/ 32 | 33 | === Via Java 34 | 35 | `mvn clean package && java -jar target/quarkus-app/quarkus-run.jar` 36 | 37 | === Via Docker 38 | 39 | to run via docker execute the following commands: 40 | 41 | * `mvn clean package && docker build -f docker/Dockerfile.jvm -t quarkus/admin-starter . && docker run -i --rm -p 8080:8080 quarkus/admin-starter` 42 | 43 | OR run already pushed image: 44 | 45 | * `docker run -i --rm --name admin-starter -m 85M -e JAVA_OPTIONS='-Xmx32m -Xms32m' -p 8080:8080 rmpestano/quarkus-admin-starter` 46 | -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/util/Utils.java: -------------------------------------------------------------------------------- 1 | package com.github.adminfaces.starter.util; 2 | 3 | import com.github.adminfaces.starter.model.Car; 4 | import org.omnifaces.util.Messages; 5 | 6 | import jakarta.annotation.PostConstruct; 7 | import jakarta.enterprise.context.ApplicationScoped; 8 | import jakarta.enterprise.context.Dependent; 9 | import jakarta.enterprise.inject.Produces; 10 | import jakarta.faces.application.FacesMessage; 11 | import java.io.Serializable; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.stream.IntStream; 15 | 16 | /** 17 | * Created by rmpestano on 07/02/17. 18 | */ 19 | @ApplicationScoped 20 | public class Utils implements Serializable { 21 | 22 | private List cars; 23 | 24 | 25 | @PostConstruct 26 | public void init() { 27 | cars = new ArrayList<>(); 28 | IntStream.rangeClosed(1, 50) 29 | .forEach(i -> cars.add(create(i))); 30 | } 31 | 32 | private static Car create(int i) { 33 | return new Car(i).model("model " + i).name("name" + i).price(Double.valueOf(i)); 34 | } 35 | 36 | public static void addDetailMessage(String message) { 37 | addDetailMessage(message, null); 38 | } 39 | 40 | public static void addDetailMessage(String message, FacesMessage.Severity severity) { 41 | 42 | FacesMessage facesMessage = Messages.create("").detail(message).get(); 43 | if (severity != null && severity != FacesMessage.SEVERITY_INFO) { 44 | facesMessage.setSeverity(severity); 45 | } 46 | Messages.add(null, facesMessage); 47 | } 48 | 49 | @Produces 50 | @Dependent 51 | public List getCars() { 52 | return cars; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/infra/converter/EntityConverter.java: -------------------------------------------------------------------------------- 1 | package com.github.adminfaces.starter.infra.converter; 2 | 3 | 4 | import jakarta.faces.component.UIComponent; 5 | import jakarta.faces.context.FacesContext; 6 | import jakarta.faces.convert.Converter; 7 | import jakarta.faces.convert.FacesConverter; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Map.Entry; 11 | import java.util.Set; 12 | import java.util.UUID; 13 | 14 | @FacesConverter(value = "entityConverter") 15 | public class EntityConverter implements Converter { 16 | 17 | @Override 18 | public String getAsString(FacesContext context, UIComponent component, Object entity) { 19 | if (entity == null || "".equals(entity)) { 20 | return null; 21 | } 22 | 23 | if (!getEntityMap(context).containsKey(entity)) { 24 | String uuid = UUID.randomUUID().toString(); 25 | getEntityMap(context).put(entity, uuid); 26 | return uuid; 27 | } else { 28 | return getEntityMap(context).get(entity); 29 | } 30 | } 31 | 32 | @Override 33 | public Object getAsObject(FacesContext context, UIComponent component, String uuid) { 34 | Set> entries = getEntityMap(context).entrySet(); 35 | for (Entry entry : entries) { 36 | if (entry.getValue().equals(uuid)) { 37 | return entry.getKey(); 38 | } 39 | } 40 | return null; 41 | } 42 | 43 | @SuppressWarnings("unchecked") 44 | private Map getEntityMap(FacesContext context) { 45 | Map viewMap = context.getViewRoot().getViewMap(); 46 | Map entities = (Map) viewMap.get("entities"); 47 | if (entities == null) { 48 | entities = new HashMap<>(); 49 | viewMap.put("entities", entities); 50 | } 51 | return entities; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/infra/security/LogonMB.java: -------------------------------------------------------------------------------- 1 | package com.github.adminfaces.starter.infra.security; 2 | 3 | import com.github.adminfaces.starter.util.Utils; 4 | import com.github.adminfaces.template.config.AdminConfig; 5 | import com.github.adminfaces.template.session.AdminSession; 6 | import org.omnifaces.util.Faces; 7 | 8 | import jakarta.annotation.Priority; 9 | import jakarta.enterprise.context.SessionScoped; 10 | import jakarta.enterprise.inject.Alternative; 11 | import jakarta.inject.Inject; 12 | import jakarta.inject.Named; 13 | import java.io.Serializable; 14 | 15 | 16 | @Named 17 | @SessionScoped 18 | @Alternative 19 | @Priority(1) 20 | public class LogonMB extends AdminSession implements Serializable { 21 | 22 | private String currentUser; 23 | private String email; 24 | private String password; 25 | private boolean remember; 26 | 27 | @Inject 28 | AdminConfig adminConfig; 29 | 30 | 31 | public void login() { 32 | currentUser = email; 33 | Utils.addDetailMessage("Logged in successfully as " + email + ""); 34 | Faces.getExternalContext().getFlash().setKeepMessages(true); 35 | Faces.redirect(adminConfig.getIndexPage()); 36 | } 37 | 38 | @Override 39 | public boolean isLoggedIn() { 40 | return currentUser != null; 41 | } 42 | 43 | public String getEmail() { 44 | return email; 45 | } 46 | 47 | public void setEmail(String email) { 48 | this.email = email; 49 | } 50 | 51 | public String getPassword() { 52 | return password; 53 | } 54 | 55 | public void setPassword(String password) { 56 | this.password = password; 57 | } 58 | 59 | public boolean isRemember() { 60 | return remember; 61 | } 62 | 63 | public void setRemember(boolean remember) { 64 | this.remember = remember; 65 | } 66 | 67 | public String getCurrentUser() { 68 | return currentUser; 69 | } 70 | 71 | public void setCurrentUser(String currentUser) { 72 | this.currentUser = currentUser; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/infra/model/Filter.java: -------------------------------------------------------------------------------- 1 | package com.github.adminfaces.starter.infra.model; 2 | 3 | 4 | import java.io.Serializable; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * Created by rmpestano on 9/7/14. 10 | * class which holds database pagination metadata 11 | */ 12 | public class Filter { 13 | private T entity; 14 | private int first; 15 | private int pageSize; 16 | private String sortField; 17 | private SortOrder sortOrder; 18 | private Map params = new HashMap(); 19 | 20 | 21 | public Filter() { 22 | } 23 | 24 | public Filter(T entity) { 25 | this.entity = entity; 26 | } 27 | 28 | public Filter setFirst(int first) { 29 | this.first = first; 30 | return this; 31 | } 32 | 33 | public int getFirst() { 34 | return first; 35 | } 36 | 37 | public Filter setPageSize(int pageSize) { 38 | this.pageSize = pageSize; 39 | return this; 40 | } 41 | 42 | public int getPageSize() { 43 | return pageSize; 44 | } 45 | 46 | public Filter setSortField(String sortField) { 47 | this.sortField = sortField; 48 | return this; 49 | } 50 | 51 | public String getSortField() { 52 | return sortField; 53 | } 54 | 55 | public Filter setSortOrder(SortOrder sortOrder) { 56 | this.sortOrder = sortOrder; 57 | return this; 58 | } 59 | 60 | public SortOrder getSortOrder() { 61 | return sortOrder; 62 | } 63 | 64 | public Filter setParams(Map params) { 65 | this.params = params; 66 | return this; 67 | } 68 | 69 | public Map getParams() { 70 | return params; 71 | } 72 | 73 | public T getEntity() { 74 | return entity; 75 | } 76 | 77 | public Filter setEntity(T entity) { 78 | this.entity = entity; 79 | return this; 80 | } 81 | 82 | public Filter addParam(String key, Object value) { 83 | getParams().put(key, value); 84 | return this; 85 | } 86 | 87 | public boolean hasParam(String key) { 88 | return getParams().containsKey(key) && getParam(key) != null; 89 | } 90 | 91 | public Object getParam(String key) { 92 | return getParams().get(key); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/templates/template.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Admin Starter 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Admin Starter 22 | 23 | 24 | 25 | Admin 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 50 | Copyright (C) 2017 - AdminFaces 51 | 52 | 53 | 54 | #{msg['starter.version']} 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/templates/template-top.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | Admin Starter 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Admin Starter 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 47 | Copyright (C) 2017 - AdminFaces 48 | 49 | 50 | 51 | #{msg['starter.version']} 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/model/Car.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package com.github.adminfaces.starter.model; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author rmpestano 11 | */ 12 | public class Car implements Serializable, Comparable { 13 | 14 | private Integer id; 15 | private String model; 16 | private String name; 17 | private Double price; 18 | 19 | public Car() { 20 | } 21 | 22 | public Car(Integer id) { 23 | this.id = id; 24 | } 25 | 26 | public String getModel() { 27 | return model; 28 | } 29 | 30 | public Double getPrice() { 31 | return price; 32 | } 33 | 34 | public Integer getId() { 35 | return id; 36 | } 37 | 38 | public String getName() { 39 | return name; 40 | } 41 | 42 | public void setModel(String model) { 43 | this.model = model; 44 | } 45 | 46 | public void setName(String name) { 47 | this.name = name; 48 | } 49 | 50 | public void setPrice(Double price) { 51 | this.price = price; 52 | } 53 | 54 | public void setId(Integer id) { 55 | this.id = id; 56 | } 57 | 58 | public Car model(String model) { 59 | this.model = model; 60 | return this; 61 | } 62 | 63 | public Car price(Double price) { 64 | this.price = price; 65 | return this; 66 | } 67 | 68 | public Car name(String name) { 69 | this.name = name; 70 | return this; 71 | } 72 | 73 | @Override 74 | public int hashCode() { 75 | final int prime = 31; 76 | int result = 1; 77 | result = prime * result + ((id == null) ? 0 : id.hashCode()); 78 | return result; 79 | } 80 | 81 | @Override 82 | public boolean equals(Object obj) { 83 | if (this == obj) 84 | return true; 85 | if (obj == null) 86 | return false; 87 | if (getClass() != obj.getClass()) 88 | return false; 89 | Car other = (Car) obj; 90 | if (id == null) { 91 | if (other.id != null) 92 | return false; 93 | } else if (!id.equals(other.id)) 94 | return false; 95 | return true; 96 | } 97 | 98 | public boolean hasModel() { 99 | return model != null && !"".equals(model.trim()); 100 | } 101 | 102 | public boolean hasName() { 103 | return name != null && !"".equals(name.trim()); 104 | } 105 | 106 | @Override 107 | public int compareTo(Car o) { 108 | return this.id.compareTo(o.getId()); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/includes/top-bar.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 29 | #{logonMB.currentUser} 30 | 31 | 32 | 33 | 34 | 36 | 37 | 38 | #{logonMB.currentUser} 39 | Subtitle 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/bean/CarFormMB.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package com.github.adminfaces.starter.bean; 6 | 7 | import com.github.adminfaces.starter.model.Car; 8 | import com.github.adminfaces.starter.service.CarService; 9 | import com.github.adminfaces.starter.util.Utils; 10 | import jakarta.faces.view.ViewScoped; 11 | import org.omnifaces.util.Faces; 12 | 13 | import jakarta.annotation.PostConstruct; 14 | import jakarta.annotation.PreDestroy; 15 | import jakarta.inject.Inject; 16 | import jakarta.inject.Named; 17 | import java.io.Serializable; 18 | import java.util.logging.Logger; 19 | 20 | import static com.github.adminfaces.template.util.Assert.has; 21 | 22 | /** 23 | * @author rmpestano 24 | */ 25 | @Named 26 | @ViewScoped 27 | public class CarFormMB implements Serializable { 28 | private Integer id; 29 | private Car car; 30 | 31 | @Inject 32 | CarService carService; 33 | 34 | public void init() { 35 | if (Faces.isAjaxRequest()) { 36 | return; 37 | } 38 | if (has(id)) { 39 | car = carService.findById(id); 40 | } else { 41 | car = new Car(); 42 | } 43 | } 44 | 45 | @PostConstruct 46 | public void postConstruct() { 47 | Logger.getLogger(getClass().getName()).info(getClass() + ": postConstruct"); 48 | } 49 | 50 | @PreDestroy 51 | public void preDestroy() { 52 | Logger.getLogger(getClass().getName()).info(getClass() + ": preDestroy"); 53 | } 54 | 55 | public Integer getId() { 56 | return id; 57 | } 58 | 59 | public void setId(Integer id) { 60 | this.id = id; 61 | } 62 | 63 | public Car getCar() { 64 | return car; 65 | } 66 | 67 | public void setCar(Car car) { 68 | this.car = car; 69 | } 70 | 71 | 72 | public void remove() { 73 | if (has(car) && has(car.getId())) { 74 | carService.remove(car); 75 | Utils.addDetailMessage("Car " + car.getModel() 76 | + " removed successfully"); 77 | Faces.getFlash().setKeepMessages(true); 78 | Faces.redirect("car-list.xhtml"); 79 | } 80 | } 81 | 82 | public void save() { 83 | String msg; 84 | if (car.getId() == null) { 85 | carService.insert(car); 86 | msg = "Car " + car.getModel() + " created successfully"; 87 | } else { 88 | carService.update(car); 89 | msg = "Car " + car.getModel() + " updated successfully"; 90 | } 91 | Utils.addDetailMessage(msg); 92 | } 93 | 94 | public void clear() { 95 | car = new Car(); 96 | id = null; 97 | } 98 | 99 | public boolean isNew() { 100 | return car == null || car.getId() == null; 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /docker/Dockerfile.jvm: -------------------------------------------------------------------------------- 1 | #### 2 | # This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode 3 | # 4 | # Before building the container image run: 5 | # 6 | # ./mvnw package 7 | # 8 | # Then, build the image with: 9 | # 10 | # docker build -f src/main/docker/Dockerfile.jvm -t melloware/quarkus-faces-jvm . 11 | # 12 | # Then run the container using: 13 | # 14 | # docker run -i --rm -p 8080:8080 melloware/quarkus-faces-jvm 15 | # 16 | # If you want to include the debug port into your docker image 17 | # you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5005 18 | # 19 | # Then run the container using : 20 | # 21 | # docker run -i --rm -p 8080:8080 melloware/quarkus-faces-jvm 22 | # 23 | # This image uses the `run-java.sh` script to run the application. 24 | # This scripts computes the command line to execute your Java application, and 25 | # includes memory/GC tuning. 26 | # You can configure the behavior using the following environment properties: 27 | # - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class") 28 | # - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options 29 | # in JAVA_OPTS (example: "-Dsome.property=foo") 30 | # - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is 31 | # used to calculate a default maximal heap memory based on a containers restriction. 32 | # If used in a container without any memory constraints for the container then this 33 | # option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio 34 | # of the container available memory as set here. The default is `50` which means 50% 35 | # of the available memory is used as an upper boundary. You can skip this mechanism by 36 | # setting this value to `0` in which case no `-Xmx` option is added. 37 | # - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This 38 | # is used to calculate a default initial heap memory based on the maximum heap memory. 39 | # If used in a container without any memory constraints for the container then this 40 | # option has no effect. If there is a memory constraint then `-Xms` is set to a ratio 41 | # of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx` 42 | # is used as the initial heap size. You can skip this mechanism by setting this value 43 | # to `0` in which case no `-Xms` option is added (example: "25") 44 | # - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS. 45 | # This is used to calculate the maximum value of the initial heap memory. If used in 46 | # a container without any memory constraints for the container then this option has 47 | # no effect. If there is a memory constraint then `-Xms` is limited to the value set 48 | # here. The default is 4096MB which means the calculated value of `-Xms` never will 49 | # be greater than 4096MB. The value of this variable is expressed in MB (example: "4096") 50 | # - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output 51 | # when things are happening. This option, if set to true, will set 52 | # `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true"). 53 | # - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example: 54 | # true"). 55 | # - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787"). 56 | # - CONTAINER_CORE_LIMIT: A calculated core limit as described in 57 | # https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2") 58 | # - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024"). 59 | # - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion. 60 | # (example: "20") 61 | # - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking. 62 | # (example: "40") 63 | # - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection. 64 | # (example: "4") 65 | # - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus 66 | # previous GC times. (example: "90") 67 | # - GC_METASPACE_SIZE: The initial metaspace size. (example: "20") 68 | # - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100") 69 | # - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should 70 | # contain the necessary JRE command-line options to specify the required GC, which 71 | # will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC). 72 | # - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080") 73 | # - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080") 74 | # - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be 75 | # accessed directly. (example: "foo.example.com,bar.example.com") 76 | # 77 | ### 78 | FROM registry.access.redhat.com/ubi8/openjdk-17:1.14 79 | 80 | ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en' 81 | 82 | 83 | # We make four distinct layers so if there are application changes the library layers can be re-used 84 | COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/ 85 | COPY --chown=185 target/quarkus-app/*.jar /deployments/ 86 | COPY --chown=185 target/quarkus-app/app/ /deployments/app/ 87 | COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/ 88 | 89 | EXPOSE 8080 90 | USER 185 91 | ENV AB_JOLOKIA_OFF="" 92 | ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager" 93 | ENV JAVA_APP_JAR="/deployments/quarkus-run.jar" -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/bean/CarListMB.java: -------------------------------------------------------------------------------- 1 | package com.github.adminfaces.starter.bean; 2 | 3 | import com.github.adminfaces.starter.infra.model.Filter; 4 | import com.github.adminfaces.starter.model.Car; 5 | import com.github.adminfaces.starter.service.CarService; 6 | import com.github.adminfaces.template.exception.BusinessException; 7 | import jakarta.faces.view.ViewScoped; 8 | import org.primefaces.model.FilterMeta; 9 | import org.primefaces.model.LazyDataModel; 10 | import org.primefaces.model.SortMeta; 11 | import org.primefaces.model.SortOrder; 12 | 13 | import jakarta.annotation.PostConstruct; 14 | import jakarta.annotation.PreDestroy; 15 | import jakarta.inject.Inject; 16 | import jakarta.inject.Named; 17 | import java.io.Serializable; 18 | import java.util.List; 19 | import java.util.Map; 20 | import java.util.logging.Logger; 21 | import java.util.stream.Collectors; 22 | 23 | import static com.github.adminfaces.starter.util.Utils.addDetailMessage; 24 | import static com.github.adminfaces.template.util.Assert.has; 25 | 26 | 27 | @Named 28 | @ViewScoped 29 | public class CarListMB implements Serializable { 30 | 31 | @Inject 32 | CarService carService; 33 | 34 | Integer id; 35 | 36 | LazyDataModel cars; 37 | 38 | Filter filter = new Filter<>(new Car()); 39 | 40 | List selectedCars; //cars selected in checkbox column 41 | 42 | List filteredValue;// datatable filteredValue attribute (column filters) 43 | 44 | @PostConstruct 45 | public void initDataModel() { 46 | Logger.getLogger(getClass().getName()).info(getClass() + ": postConstruct"); 47 | cars = new LazyDataModel() { 48 | 49 | @Override 50 | public int count(Map map) { 51 | return (int) carService.count(filter); 52 | } 53 | 54 | @Override 55 | public List load(int first, int pageSize, Map sortMap, Map filterMap) { 56 | if (has(sortMap)) { 57 | sortMap.entrySet().stream() 58 | .findAny() 59 | .ifPresent(sortField -> { 60 | filter.setSortField(sortField.getKey()); 61 | filter.setSortOrder(getSortOrder(SortOrder.ASCENDING == sortField.getValue().getOrder(), sortField.getValue().getOrder() == SortOrder.DESCENDING)); 62 | } 63 | ); 64 | } 65 | filter.setFirst(first).setPageSize(pageSize); 66 | if (has(filterMap)) { 67 | filter.setParams(filterMap.entrySet().stream() 68 | .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)) 69 | ); 70 | } 71 | return carService.paginate(filter); 72 | } 73 | 74 | private com.github.adminfaces.starter.infra.model.SortOrder getSortOrder(boolean asc, boolean desc) { 75 | return asc ? 76 | com.github.adminfaces.starter.infra.model.SortOrder.ASCENDING : desc ? 77 | com.github.adminfaces.starter.infra.model.SortOrder.DESCENDING : com.github.adminfaces.starter.infra.model.SortOrder.UNSORTED; 78 | } 79 | 80 | @Override 81 | public Car getRowData(String key) { 82 | return carService.findById(Integer.valueOf(key)); 83 | } 84 | 85 | @Override 86 | public String getRowKey(Car car) { 87 | return car.getId().toString(); 88 | } 89 | }; 90 | } 91 | 92 | @PreDestroy 93 | public void preDestroy() { 94 | Logger.getLogger(getClass().getName()).info(getClass() + ": preDestroy"); 95 | } 96 | 97 | public void clear() { 98 | filter = new Filter<>(new Car()); 99 | } 100 | 101 | public List completeModel(String query) { 102 | List result = carService.getModels(query); 103 | return result; 104 | } 105 | 106 | public void findCarById(Integer id) { 107 | if (id == null) { 108 | throw new BusinessException("Provide Car ID to load"); 109 | } 110 | selectedCars = List.of(carService.findById(id)); 111 | } 112 | 113 | public void delete() { 114 | int numCars = 0; 115 | for (Car selectedCar : selectedCars) { 116 | numCars++; 117 | carService.remove(selectedCar); 118 | } 119 | selectedCars.clear(); 120 | addDetailMessage(numCars + " cars deleted successfully!"); 121 | } 122 | 123 | public List getSelectedCars() { 124 | return selectedCars; 125 | } 126 | 127 | public List getFilteredValue() { 128 | return filteredValue; 129 | } 130 | 131 | public void setFilteredValue(List filteredValue) { 132 | this.filteredValue = filteredValue; 133 | } 134 | 135 | public void setSelectedCars(List selectedCars) { 136 | this.selectedCars = selectedCars; 137 | } 138 | 139 | public LazyDataModel getCars() { 140 | return cars; 141 | } 142 | 143 | public void setCars(LazyDataModel cars) { 144 | this.cars = cars; 145 | } 146 | 147 | public Filter getFilter() { 148 | return filter; 149 | } 150 | 151 | public void setFilter(Filter filter) { 152 | this.filter = filter; 153 | } 154 | 155 | public Integer getId() { 156 | return id; 157 | } 158 | 159 | public void setId(Integer id) { 160 | this.id = id; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/login.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | 9 | 10 | Admin Starter 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 76 | 77 | 78 | 79 | 80 | 81 | AdminStarter 82 | 83 | 84 | 85 | 86 | Sign in to start your session 87 | 88 | 89 | 90 | 93 | 94 | 95 | 96 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 109 | 110 | 111 | 112 | 113 | 114 | - OR - 115 | Sign in using 117 | Facebook 118 | Sign in using 120 | Google+ 121 | 122 | 123 | 124 | I forgot my password 125 | Register a new membership 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | com.github.adminfaces 8 | quarkus-admin-starter 9 | 1.0-SNAPSHOT 10 | Quarkus - AdminFaces - Starter 11 | 12 | 13 | 3.0.2.Final 14 | 4.1.3 15 | 3.12.4 16 | 4.0.0 17 | 3.0.2.Final 18 | 3.0.0 19 | 3.0.0 20 | UTF-8 21 | 17 22 | 17 23 | 24 | 25 | 26 | 27 | 28 | io.quarkus 29 | quarkus-bom 30 | ${quarkus.version} 31 | pom 32 | import 33 | 34 | 35 | 36 | 37 | 38 | 39 | org.apache.myfaces.core.extensions.quarkus 40 | myfaces-quarkus 41 | ${myfaces.version} 42 | 43 | 44 | io.quarkiverse.primefaces 45 | quarkus-primefaces 46 | ${primefaces-quarkus.version} 47 | 48 | 49 | io.quarkiverse.omnifaces 50 | quarkus-omnifaces 51 | ${omnifaces-quarkus.version} 52 | 53 | 54 | com.github.adminfaces 55 | admin-template 56 | 2.0 57 | 58 | 59 | org.omnifaces 60 | omnifaces 61 | 62 | 63 | org.primefaces 64 | primefaces 65 | 66 | 67 | 68 | 83 | 84 | 85 | 86 | ${project.artifactId} 87 | 88 | 89 | maven-surefire-plugin 90 | ${surefire.version} 91 | 92 | 93 | org.jboss.logmanager.LogManager 94 | 95 | 96 | 97 | 98 | io.quarkus 99 | quarkus-maven-plugin 100 | ${quarkus.version} 101 | 102 | 103 | 104 | build 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | native 114 | 115 | 116 | 117 | io.quarkus 118 | quarkus-maven-plugin 119 | ${quarkus.version} 120 | 121 | 122 | 123 | native-image 124 | 125 | 126 | true 127 | 128 | 129 | 130 | 131 | 132 | org.apache.maven.plugins 133 | maven-failsafe-plugin 134 | ${failsafe.version} 135 | 136 | 137 | 138 | integration-test 139 | verify 140 | 141 | 142 | 143 | 144 | ${project.build.directory}/${project.build.finalName}-runner 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/includes/controlsidebar-tabs-content.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | Recent Activity 11 | 12 | 13 | 14 | 15 | 16 | 17 | Langdon's Birthday 18 | 19 | Will be 23 on April 24th 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Frodo Updated His Profile 29 | 30 | New phone +1(800)555-1234 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | Nora Joined Mailing List 40 | 41 | nora@example.com 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Cron Job 254 Executed 51 | 52 | Execution time 5 seconds 53 | 54 | 55 | 56 | 57 | 58 | Tasks Progress 59 | 60 | 61 | 62 | 63 | Custom Template Design 64 | 70% 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Update Resume 76 | 95% 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | Laravel Integration 88 | 50% 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | Back End Framework 100 | 68% 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | General Settings 114 | 115 | 116 | 117 | Report panel usage 118 | 119 | 120 | 121 | 122 | Some information about this general settings option 123 | 124 | 125 | 126 | 127 | 128 | Allow mail redirect 129 | 130 | 131 | 132 | 133 | Other sets of options are available 134 | 135 | 136 | 137 | 138 | 139 | Expose author name in posts 140 | 141 | 142 | 143 | 144 | Allow the user to show his name in blog posts 145 | 146 | 147 | 148 | Chat Settings 149 | 150 | 151 | 152 | Show me as online 153 | 154 | 155 | 156 | 157 | 158 | 159 | Turn off notifications 160 | 161 | 162 | 163 | 164 | 165 | 166 | Delete chat history 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | -------------------------------------------------------------------------------- /src/main/java/com/github/adminfaces/starter/service/CarService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * To change this template, choose Tools | Templates 3 | * and open the template in the editor. 4 | */ 5 | package com.github.adminfaces.starter.service; 6 | 7 | import com.github.adminfaces.template.exception.BusinessException; 8 | import com.github.adminfaces.starter.infra.model.Filter; 9 | import com.github.adminfaces.starter.infra.model.SortOrder; 10 | import com.github.adminfaces.starter.model.Car; 11 | 12 | import jakarta.enterprise.context.Dependent; 13 | import jakarta.inject.Inject; 14 | import java.io.Serializable; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Objects; 18 | import java.util.function.Predicate; 19 | import java.util.stream.Collectors; 20 | 21 | import static com.github.adminfaces.template.util.Assert.has; 22 | 23 | /** 24 | * @author rmpestano 25 | * Car Business logic 26 | */ 27 | @Dependent 28 | public class CarService implements Serializable { 29 | 30 | @Inject 31 | List allCars; 32 | 33 | public List listByModel(String model) { 34 | return allCars.stream() 35 | .filter(c -> c.getModel().equalsIgnoreCase(model)) 36 | .collect(Collectors.toList()); 37 | 38 | } 39 | 40 | public List paginate(Filter filter) { 41 | List pagedCars = new ArrayList<>(); 42 | if(has(filter.getSortOrder()) && !SortOrder.UNSORTED.equals(filter.getSortOrder())) { 43 | pagedCars = allCars.stream(). 44 | sorted((c1, c2) -> { 45 | if (filter.getSortOrder().isAscending()) { 46 | return c1.getId().compareTo(c2.getId()); 47 | } else { 48 | return c2.getId().compareTo(c1.getId()); 49 | } 50 | }) 51 | .collect(Collectors.toList()); 52 | } 53 | int page = filter.getFirst() + filter.getPageSize(); 54 | if (!pagedCars.isEmpty() && filter.getParams().isEmpty()) { 55 | pagedCars = allCars.subList(filter.getFirst(), Math.min(page, allCars.size())); 56 | return pagedCars; 57 | } 58 | 59 | List> predicates = configFilter(filter); 60 | 61 | List pagedList = allCars.stream().filter(predicates 62 | .stream().reduce(Predicate::or).orElse(t -> true)) 63 | .collect(Collectors.toList()); 64 | 65 | if (page < pagedList.size()) { 66 | pagedList = pagedList.subList(filter.getFirst(), page); 67 | } 68 | 69 | if (has(filter.getSortField()) && !SortOrder.UNSORTED.equals(filter.getSortOrder())) { 70 | pagedList = pagedList.stream(). 71 | sorted((c1, c2) -> { 72 | boolean asc = SortOrder.ASCENDING.equals(filter.getSortOrder()); 73 | if (asc) { 74 | return c1.getId().compareTo(c2.getId()); 75 | } else { 76 | return c2.getId().compareTo(c1.getId()); 77 | } 78 | }) 79 | .collect(Collectors.toList()); 80 | } 81 | return pagedList; 82 | } 83 | 84 | private List> configFilter(Filter filter) { 85 | List> predicates = new ArrayList<>(); 86 | if (filter.hasParam("id")) { 87 | Predicate idPredicate = (Car c) -> c.getId().equals(filter.getParam("id")); 88 | predicates.add(idPredicate); 89 | } 90 | 91 | if (filter.hasParam("minPrice") && filter.hasParam("maxPrice")) { 92 | Predicate minMaxPricePredicate = (Car c) -> c.getPrice() 93 | >= Double.parseDouble((String) filter.getParam("minPrice")) && c.getPrice() 94 | <= Double.parseDouble((String) filter.getParam("maxPrice")); 95 | predicates.add(minMaxPricePredicate); 96 | } else if (filter.hasParam("minPrice")) { 97 | Predicate minPricePredicate = (Car c) -> c.getPrice() 98 | >= Double.parseDouble((String) filter.getParam("minPrice")); 99 | predicates.add(minPricePredicate); 100 | } else if (filter.hasParam("maxPrice")) { 101 | Predicate maxPricePredicate = (Car c) -> c.getPrice() 102 | <= Double.parseDouble((String) filter.getParam("maxPrice")); 103 | predicates.add(maxPricePredicate); 104 | } 105 | 106 | if (has(filter.getEntity())) { 107 | Car filterEntity = filter.getEntity(); 108 | if (has(filterEntity.getModel())) { 109 | Predicate modelPredicate = (Car c) -> c.getModel().toLowerCase().contains(filterEntity.getModel().toLowerCase()); 110 | predicates.add(modelPredicate); 111 | } 112 | 113 | if (has(filterEntity.getPrice())) { 114 | Predicate pricePredicate = (Car c) -> c.getPrice().equals(filterEntity.getPrice()); 115 | predicates.add(pricePredicate); 116 | } 117 | 118 | if (has(filterEntity.getName())) { 119 | Predicate namePredicate = (Car c) -> c.getName().toLowerCase().contains(filterEntity.getName().toLowerCase()); 120 | predicates.add(namePredicate); 121 | } 122 | } 123 | return predicates; 124 | } 125 | 126 | public List getModels(String query) { 127 | return allCars.stream().map(Car::getModel) 128 | .filter(model -> model 129 | .toLowerCase().contains(query.toLowerCase())) 130 | .collect(Collectors.toList()); 131 | } 132 | 133 | public void insert(Car car) { 134 | validate(car); 135 | car.setId(allCars.stream() 136 | .mapToInt(Car::getId) 137 | .max() 138 | .getAsInt()+1); 139 | allCars.add(car); 140 | } 141 | 142 | public void validate(Car car) { 143 | BusinessException be = new BusinessException(); 144 | if (!car.hasModel()) { 145 | be.addException(new BusinessException("Car model cannot be empty")); 146 | } 147 | if (!car.hasName()) { 148 | be.addException(new BusinessException("Car name cannot be empty")); 149 | } 150 | 151 | if (!has(car.getPrice())) { 152 | be.addException(new BusinessException("Car price cannot be empty")); 153 | } 154 | 155 | if (allCars.stream().filter(c -> c.getName().equalsIgnoreCase(car.getName()) 156 | && !Objects.equals(c.getId(), c.getId())).count() > 0) { 157 | be.addException(new BusinessException("Car name must be unique")); 158 | } 159 | if(has(be.getExceptionList())) { 160 | throw be; 161 | } 162 | } 163 | 164 | public void remove(Car car) { 165 | allCars.remove(car); 166 | } 167 | 168 | public long count(Filter filter) { 169 | return allCars.stream() 170 | .filter(configFilter(filter).stream() 171 | .reduce(Predicate::or).orElse(t -> true)) 172 | .count(); 173 | } 174 | 175 | public Car findById(Integer id) { 176 | return allCars.stream() 177 | .filter(c -> c.getId().equals(id)) 178 | .findFirst() 179 | .orElseThrow(() -> new BusinessException("Car not found with id " + id)); 180 | } 181 | 182 | public void update(Car car) { 183 | validate(car); 184 | allCars.remove(car); 185 | allCars.add(car); 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/car-form.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | Car form 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 26 | 27 | 30 | 31 | 32 | 35 | 36 | 37 | 38 | 42 | 43 | 46 | 49 | 51 | 53 | 54 | 55 | 56 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 114 | 117 | 119 | 121 | 122 | 123 | 124 | 127 | 128 | 129 | 130 | 131 | 132 | 134 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/resources/car-list.xhtml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 14 | 15 | 16 | 17 | Car listing 18 | 19 | 20 | 21 | Find cars by name, price and model 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 39 | 40 | 41 | 42 | 45 | 46 | 47 | 50 | 54 | 55 | 56 | 61 | 62 | 63 | 64 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | Find Car by id: 81 | 82 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | #{c.name} 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | #{c.price} 123 | 124 | 125 | 126 | 127 | 128 | 130 | 132 | 133 | 134 | 135 | 136 | 137 | 139 | 141 | ID: #{car.id} - Name: #{car.name} - Model: #{car.model} 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | true 12 | 13 | COOKIE 14 | 15 | 16 | 17 | index.xhtml 18 | 19 | 20 | 21 | jakarta.faces.STATE_SAVING_METHOD 22 | server 23 | 24 | 25 | jakarta.faces.PROJECT_STAGE 26 | Development 27 | 28 | 29 | jakarta.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE 30 | true 31 | 32 | 33 | jakarta.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL 34 | true 35 | 36 | 37 | 38 | primefaces.CLIENT_SIDE_VALIDATION 39 | true 40 | 41 | 42 | primefaces.FONT_AWESOME 43 | true 44 | 45 | 46 | primefaces.THEME 47 | admin 48 | 49 | 50 | 51 | primefaces.MOVE_SCRIPTS_TO_BOTTOM 52 | true 53 | 54 | 55 | primefaces.CSP 56 | false 57 | 58 | 59 | primefaces.TRANSFORM_METADATA 60 | true 61 | 62 | 63 | primefaces.COOKIES_SAME_SITE 64 | Strict 65 | 66 | 67 | primefaces.CACHE_PROVIDER 68 | org.primefaces.showcase.util.CaffeineCacheProvider 69 | 70 | 71 | primefaces.MULTI_VIEW_STATE_STORE 72 | client-window 73 | 74 | 75 | primefaces.js.COMBINED_RESOURCE_HANDLER_DISABLED 76 | true 77 | 78 | 79 | 80 | 81 | org.apache.myfaces.CACHE_EL_EXPRESSIONS 82 | alwaysRecompile 83 | 84 | 85 | org.apache.myfaces.CHECK_ID_PRODUCTION_MODE 86 | false 87 | 88 | 89 | org.apache.myfaces.EARLY_FLUSH_ENABLED 90 | true 91 | 92 | 93 | org.apache.myfaces.NUMBER_OF_VIEWS_IN_SESSION 94 | 10 95 | 96 | 97 | org.apache.myfaces.NUMBER_OF_SEQUENTIAL_VIEWS_IN_SESSION 98 | 3 99 | 100 | 101 | org.apache.myfaces.SUPPORT_JSP_AND_FACES_EL 102 | false 103 | 104 | 105 | org.apache.myfaces.VIEW_UNIQUE_IDS_CACHE_ENABLED 106 | true 107 | 108 | 109 | org.apache.myfaces.COMPONENT_UNIQUE_IDS_CACHE_SIZE 110 | 500 111 | 112 | 113 | org.apache.myfaces.USE_LAMBDA_METAFACTORY 114 | false 115 | 116 | 117 | 118 | 119 | org.omnifaces.COMBINED_RESOURCE_HANDLER_DISABLED 120 | #{facesContext.application.projectStage eq 'Development'} 121 | 122 | 123 | 124 | org.apache.myfaces.webapp.StartupServletContextListener 125 | 126 | 127 | 128 | 129 | 130 | CharacterEncodingFilter 131 | org.omnifaces.filter.CharacterEncodingFilter 132 | 133 | 134 | CharacterEncodingFilter 135 | /* 136 | 137 | 138 | 139 | 140 | NoCacheFilter 141 | org.omnifaces.filter.CacheControlFilter 142 | 143 | 144 | NoCacheFilter 145 | FacesServlet 146 | 147 | 148 | 149 | gzipResponseFilter 150 | org.omnifaces.filter.GzipResponseFilter 151 | 152 | The threshold size in bytes. Must be a number between 0 and 9999. Defaults to 150. 153 | 154 | threshold 155 | 200 156 | 157 | 158 | 159 | gzipResponseFilter 160 | Faces Servlet 161 | REQUEST 162 | ERROR 163 | 164 | 165 | 166 | 167 | FacesServlet 168 | jakarta.faces.webapp.FacesServlet 169 | 170 | 171 | FacesServlet 172 | *.jsf 173 | 174 | 175 | FacesServlet 176 | *.xhtml 177 | 178 | 179 | 180 | FileUpload Resume Servlet 181 | org.primefaces.webapp.FileUploadChunksServlet 182 | 183 | 184 | FileUpload Resume Servlet 185 | /file/resume/ 186 | 187 | 188 | 189 | ttf 190 | application/font-sfnt 191 | 192 | 193 | woff 194 | application/font-woff 195 | 196 | 197 | woff2 198 | application/font-woff2 199 | 200 | 201 | eot 202 | application/vnd.ms-fontobject 203 | 204 | 205 | eot?#iefix 206 | application/vnd.ms-fontobject 207 | 208 | 209 | svg 210 | image/svg+xml 211 | 212 | 213 | svg#latobold 214 | image/svg+xml 215 | 216 | 217 | svg#latoblack 218 | image/svg+xml 219 | 220 | 221 | svg#latolight 222 | image/svg+xml 223 | 224 | 225 | svg#latoregular 226 | image/svg+xml 227 | 228 | 229 | svg#fontawesomeregular 230 | image/svg+xml 231 | 232 | 233 | --------------------------------------------------------------------------------
38 | #{logonMB.currentUser} 39 | Subtitle 40 |
Sign in to start your session
- OR -
Will be 23 on April 24th
New phone +1(800)555-1234
nora@example.com
Execution time 5 seconds
122 | Some information about this general settings option 123 |
133 | Other sets of options are available 134 |
144 | Allow the user to show his name in blog posts 145 |