├── .classpath
├── .gitignore
├── .project
├── README.md
├── pom.xml
└── src
└── main
├── java
└── com
│ └── codetreatise
│ ├── Main.java
│ ├── bean
│ └── User.java
│ ├── config
│ ├── AppJavaConfig.java
│ ├── SpringFXMLLoader.java
│ └── StageManager.java
│ ├── controller
│ ├── LoginController.java
│ └── UserController.java
│ ├── generic
│ └── GenericService.java
│ ├── logging
│ └── ExceptionWriter.java
│ ├── repository
│ └── UserRepository.java
│ ├── service
│ ├── UserService.java
│ └── impl
│ │ └── UserServiceImpl.java
│ └── view
│ └── FxmlView.java
└── resources
├── Bundle.properties
├── application.properties
├── fxml
├── Login.fxml
└── User.fxml
├── images
└── edit.png
└── styles
└── Styles.css
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 |
3 | .settings/
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | JavaFXSpringBootApp
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.common.project.facet.core.builder
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.springframework.ide.eclipse.core.springbuilder
20 |
21 |
22 |
23 |
24 | org.eclipse.m2e.core.maven2Builder
25 |
26 |
27 |
28 |
29 |
30 | org.springframework.ide.eclipse.core.springnature
31 | org.eclipse.jdt.core.javanature
32 | org.eclipse.m2e.core.maven2Nature
33 | org.eclipse.wst.common.project.facet.core.nature
34 |
35 |
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaFX Spring Boot App
2 | The application frontend created using JavaFX and backend services are implemented using Spring Boot. The app demonstrate simple CRUD operation and switching between two scenes with Login and User Dashboard view.
3 |
4 | # Getting Started:
5 |
6 | 1. Clone the project in your workspace using command - git clone https://github.com/RamAlapure/JavaFXSpringBootApp.git
7 | 2. Then import as maven project into eclipse.
8 | 3. Check Java 8 configuration if there is any error.
9 | 4. Update project as maven if dependencies are not resolved.
10 | 5. Create a schema javafx in your mysql database or open configuration file application.properties from resources directory and change schema name to your schema name and also change username and password.
11 | 6. If all goes well just run Main.java
12 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | com.codetreatise
7 | JavaFXSpringBootApp
8 | jar
9 | 1.0
10 |
11 | JavaFXSpringBootApp
12 |
13 |
14 | org.springframework.boot
15 | spring-boot-starter-parent
16 | 1.5.2.RELEASE
17 |
18 |
19 |
20 |
21 |
22 | UTF-8
23 | UTF-8
24 | 1.8
25 |
26 |
27 |
28 |
29 | org.springframework.boot
30 | spring-boot-starter-aop
31 |
32 |
33 | org.springframework.boot
34 | spring-boot-starter-cache
35 |
36 |
37 | org.springframework.boot
38 | spring-boot-starter-data-jpa
39 |
40 |
41 | org.springframework.boot
42 | spring-boot-starter-security
43 |
44 |
45 |
46 | mysql
47 | mysql-connector-java
48 | runtime
49 |
50 |
51 | org.springframework.boot
52 | spring-boot-starter-test
53 | test
54 |
55 |
56 |
57 |
58 |
59 |
60 | org.springframework.boot
61 | spring-boot-maven-plugin
62 |
63 |
64 | org.apache.maven.plugins
65 | maven-compiler-plugin
66 |
67 | true
68 |
69 |
70 |
71 |
72 | The Application front-end designed using JavaFX and Spring Boot is used as backend to bootstrap the app. The scenes are created in FXML using Scene Builder. The app demonstrate simple CRUD using Spring Boot and JavaFX.
73 |
74 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/Main.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise;
2 |
3 | import javafx.application.Application;
4 | import javafx.stage.Stage;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 | import org.springframework.boot.builder.SpringApplicationBuilder;
7 | import org.springframework.context.ConfigurableApplicationContext;
8 |
9 | import com.codetreatise.config.StageManager;
10 | import com.codetreatise.view.FxmlView;
11 |
12 | @SpringBootApplication
13 | public class Main extends Application {
14 |
15 | protected ConfigurableApplicationContext springContext;
16 | protected StageManager stageManager;
17 |
18 | public static void main(final String[] args) {
19 | Application.launch(args);
20 | }
21 |
22 | @Override
23 | public void init() throws Exception {
24 | springContext = springBootApplicationContext();
25 | }
26 |
27 | @Override
28 | public void start(Stage stage) throws Exception {
29 | stageManager = springContext.getBean(StageManager.class, stage);
30 | displayInitialScene();
31 | }
32 |
33 | @Override
34 | public void stop() throws Exception {
35 | springContext.close();
36 | }
37 |
38 | /**
39 | * Useful to override this method by sub-classes wishing to change the first
40 | * Scene to be displayed on startup. Example: Functional tests on main
41 | * window.
42 | */
43 | protected void displayInitialScene() {
44 | stageManager.switchScene(FxmlView.LOGIN);
45 | }
46 |
47 |
48 | private ConfigurableApplicationContext springBootApplicationContext() {
49 | SpringApplicationBuilder builder = new SpringApplicationBuilder(Main.class);
50 | String[] args = getParameters().getRaw().stream().toArray(String[]::new);
51 | return builder.run(args);
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/bean/User.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.bean;
2 |
3 | import java.time.LocalDate;
4 |
5 | import javax.persistence.Column;
6 | import javax.persistence.Entity;
7 | import javax.persistence.GeneratedValue;
8 | import javax.persistence.GenerationType;
9 | import javax.persistence.Id;
10 | import javax.persistence.Table;
11 |
12 | /**
13 | * @author Ram Alapure
14 | * @since 05-04-2017
15 | */
16 |
17 | @Entity
18 | @Table(name="User")
19 | public class User {
20 |
21 | @Id
22 | @GeneratedValue(strategy=GenerationType.IDENTITY)
23 | @Column(name = "id", updatable = false, nullable = false)
24 | private long id;
25 |
26 | private String firstName;
27 |
28 | private String lastName;
29 |
30 | private LocalDate dob;
31 |
32 | private String gender;
33 |
34 | private String role;
35 |
36 | private String email;
37 |
38 | private String password;
39 |
40 |
41 | public long getId() {
42 | return id;
43 | }
44 |
45 | public void setId(long id) {
46 | this.id = id;
47 | }
48 |
49 | public String getFirstName() {
50 | return firstName;
51 | }
52 |
53 | public void setFirstName(String firstName) {
54 | this.firstName = firstName;
55 | }
56 |
57 | public String getLastName() {
58 | return lastName;
59 | }
60 |
61 | public void setLastName(String lastName) {
62 | this.lastName = lastName;
63 | }
64 |
65 | public LocalDate getDob() {
66 | return dob;
67 | }
68 |
69 | public void setDob(LocalDate dob) {
70 | this.dob = dob;
71 | }
72 |
73 | public String getGender() {
74 | return gender;
75 | }
76 |
77 | public void setGender(String gender) {
78 | this.gender = gender;
79 | }
80 |
81 | public String getRole() {
82 | return role;
83 | }
84 |
85 | public void setRole(String role) {
86 | this.role = role;
87 | }
88 |
89 | public String getEmail() {
90 | return email;
91 | }
92 |
93 | public void setEmail(String email) {
94 | this.email = email;
95 | }
96 |
97 | public String getPassword() {
98 | return password;
99 | }
100 |
101 | public void setPassword(String password) {
102 | this.password = password;
103 | }
104 |
105 | @Override
106 | public String toString() {
107 | return "User [id=" + id + ", firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ", email="
108 | + email + "]";
109 | }
110 |
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/config/AppJavaConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * To change this license header, choose License Headers in Project Properties.
3 | * To change this template file, choose Tools | Templates
4 | * and open the template in the editor.
5 | */
6 | package com.codetreatise.config;
7 |
8 | import java.io.IOException;
9 | import java.io.StringWriter;
10 | import java.util.ResourceBundle;
11 | import javafx.stage.Stage;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.context.annotation.Bean;
14 | import org.springframework.context.annotation.Configuration;
15 | import org.springframework.context.annotation.Lazy;
16 | import org.springframework.context.annotation.Scope;
17 |
18 | import com.codetreatise.logging.ExceptionWriter;
19 |
20 | @Configuration
21 | public class AppJavaConfig {
22 |
23 | @Autowired
24 | SpringFXMLLoader springFXMLLoader;
25 |
26 | /**
27 | * Useful when dumping stack trace to a string for logging.
28 | * @return ExceptionWriter contains logging utility methods
29 | */
30 | @Bean
31 | @Scope("prototype")
32 | public ExceptionWriter exceptionWriter() {
33 | return new ExceptionWriter(new StringWriter());
34 | }
35 |
36 | @Bean
37 | public ResourceBundle resourceBundle() {
38 | return ResourceBundle.getBundle("Bundle");
39 | }
40 |
41 | @Bean
42 | @Lazy(value = true) //Stage only created after Spring context bootstap
43 | public StageManager stageManager(Stage stage) throws IOException {
44 | return new StageManager(springFXMLLoader, stage);
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/config/SpringFXMLLoader.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.config;
2 |
3 | import java.io.IOException;
4 | import java.util.ResourceBundle;
5 | import javafx.fxml.FXMLLoader;
6 | import javafx.scene.Parent;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.context.ApplicationContext;
9 | import org.springframework.stereotype.Component;
10 |
11 | /**
12 | * Will load the FXML hierarchy as specified in the load method and register
13 | * Spring as the FXML Controller Factory. Allows Spring and Java FX to coexist
14 | * once the Spring Application context has been bootstrapped.
15 | */
16 | @Component
17 | public class SpringFXMLLoader {
18 | private final ResourceBundle resourceBundle;
19 | private final ApplicationContext context;
20 |
21 | @Autowired
22 | public SpringFXMLLoader(ApplicationContext context, ResourceBundle resourceBundle) {
23 | this.resourceBundle = resourceBundle;
24 | this.context = context;
25 | }
26 |
27 | public Parent load(String fxmlPath) throws IOException {
28 | FXMLLoader loader = new FXMLLoader();
29 | loader.setControllerFactory(context::getBean); //Spring now FXML Controller Factory
30 | loader.setResources(resourceBundle);
31 | loader.setLocation(getClass().getResource(fxmlPath));
32 | return loader.load();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/config/StageManager.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.config;
2 |
3 | import static org.slf4j.LoggerFactory.getLogger;
4 |
5 | import java.util.Objects;
6 |
7 | import org.slf4j.Logger;
8 |
9 | import com.codetreatise.view.FxmlView;
10 |
11 | import javafx.application.Platform;
12 | import javafx.scene.Parent;
13 | import javafx.scene.Scene;
14 | import javafx.stage.Stage;
15 |
16 | /**
17 | * Manages switching Scenes on the Primary Stage
18 | */
19 | public class StageManager {
20 |
21 | private static final Logger LOG = getLogger(StageManager.class);
22 | private final Stage primaryStage;
23 | private final SpringFXMLLoader springFXMLLoader;
24 |
25 | public StageManager(SpringFXMLLoader springFXMLLoader, Stage stage) {
26 | this.springFXMLLoader = springFXMLLoader;
27 | this.primaryStage = stage;
28 | }
29 |
30 | public void switchScene(final FxmlView view) {
31 | Parent viewRootNodeHierarchy = loadViewNodeHierarchy(view.getFxmlFile());
32 | show(viewRootNodeHierarchy, view.getTitle());
33 | }
34 |
35 | private void show(final Parent rootnode, String title) {
36 | Scene scene = prepareScene(rootnode);
37 | //scene.getStylesheets().add("/styles/Styles.css");
38 |
39 | //primaryStage.initStyle(StageStyle.TRANSPARENT);
40 | primaryStage.setTitle(title);
41 | primaryStage.setScene(scene);
42 | primaryStage.sizeToScene();
43 | primaryStage.centerOnScreen();
44 |
45 | try {
46 | primaryStage.show();
47 | } catch (Exception exception) {
48 | logAndExit ("Unable to show scene for title" + title, exception);
49 | }
50 | }
51 |
52 | private Scene prepareScene(Parent rootnode){
53 | Scene scene = primaryStage.getScene();
54 |
55 | if (scene == null) {
56 | scene = new Scene(rootnode);
57 | }
58 | scene.setRoot(rootnode);
59 | return scene;
60 | }
61 |
62 | /**
63 | * Loads the object hierarchy from a FXML document and returns to root node
64 | * of that hierarchy.
65 | *
66 | * @return Parent root node of the FXML document hierarchy
67 | */
68 | private Parent loadViewNodeHierarchy(String fxmlFilePath) {
69 | Parent rootNode = null;
70 | try {
71 | rootNode = springFXMLLoader.load(fxmlFilePath);
72 | Objects.requireNonNull(rootNode, "A Root FXML node must not be null");
73 | } catch (Exception exception) {
74 | logAndExit("Unable to load FXML view" + fxmlFilePath, exception);
75 | }
76 | return rootNode;
77 | }
78 |
79 |
80 | private void logAndExit(String errorMsg, Exception exception) {
81 | LOG.error(errorMsg, exception, exception.getCause());
82 | Platform.exit();
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/controller/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.controller;
2 |
3 |
4 | import java.io.IOException;
5 | import java.net.URL;
6 | import java.util.ResourceBundle;
7 |
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.context.annotation.Lazy;
10 | import org.springframework.stereotype.Controller;
11 |
12 | import com.codetreatise.config.StageManager;
13 | import com.codetreatise.service.UserService;
14 | import com.codetreatise.view.FxmlView;
15 |
16 | import javafx.event.ActionEvent;
17 | import javafx.fxml.FXML;
18 | import javafx.fxml.Initializable;
19 | import javafx.scene.control.Button;
20 | import javafx.scene.control.Label;
21 | import javafx.scene.control.PasswordField;
22 | import javafx.scene.control.TextField;
23 |
24 | /**
25 | * @author Ram Alapure
26 | * @since 05-04-2017
27 | */
28 |
29 | @Controller
30 | public class LoginController implements Initializable{
31 |
32 | @FXML
33 | private Button btnLogin;
34 |
35 | @FXML
36 | private PasswordField password;
37 |
38 | @FXML
39 | private TextField username;
40 |
41 | @FXML
42 | private Label lblLogin;
43 |
44 | @Autowired
45 | private UserService userService;
46 |
47 | @Lazy
48 | @Autowired
49 | private StageManager stageManager;
50 |
51 | @FXML
52 | private void login(ActionEvent event) throws IOException{
53 | if(userService.authenticate(getUsername(), getPassword())){
54 |
55 | stageManager.switchScene(FxmlView.USER);
56 |
57 | }else{
58 | lblLogin.setText("Login Failed.");
59 | }
60 | }
61 |
62 | public String getPassword() {
63 | return password.getText();
64 | }
65 |
66 | public String getUsername() {
67 | return username.getText();
68 | }
69 |
70 | @Override
71 | public void initialize(URL location, ResourceBundle resources) {
72 |
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.controller;
2 |
3 | import java.io.IOException;
4 | import java.net.URL;
5 | import java.time.LocalDate;
6 | import java.util.List;
7 | import java.util.Optional;
8 | import java.util.ResourceBundle;
9 | import java.util.regex.Matcher;
10 | import java.util.regex.Pattern;
11 |
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.context.annotation.Lazy;
14 | import org.springframework.stereotype.Controller;
15 |
16 | import com.codetreatise.bean.User;
17 | import com.codetreatise.config.StageManager;
18 | import com.codetreatise.service.UserService;
19 | import com.codetreatise.view.FxmlView;
20 |
21 | import javafx.application.Platform;
22 | import javafx.collections.FXCollections;
23 | import javafx.collections.ObservableList;
24 | import javafx.event.ActionEvent;
25 | import javafx.fxml.FXML;
26 | import javafx.fxml.Initializable;
27 | import javafx.geometry.Pos;
28 | import javafx.scene.control.Alert;
29 | import javafx.scene.control.Alert.AlertType;
30 | import javafx.scene.control.Button;
31 | import javafx.scene.control.ButtonType;
32 | import javafx.scene.control.ComboBox;
33 | import javafx.scene.control.DatePicker;
34 | import javafx.scene.control.Label;
35 | import javafx.scene.control.MenuItem;
36 | import javafx.scene.control.PasswordField;
37 | import javafx.scene.control.RadioButton;
38 | import javafx.scene.control.SelectionMode;
39 | import javafx.scene.control.TableCell;
40 | import javafx.scene.control.TableColumn;
41 | import javafx.scene.control.TableView;
42 | import javafx.scene.control.TextField;
43 | import javafx.scene.control.ToggleGroup;
44 | import javafx.scene.control.cell.PropertyValueFactory;
45 | import javafx.scene.image.Image;
46 | import javafx.scene.image.ImageView;
47 | import javafx.util.Callback;
48 | /**
49 | * @author Ram Alapure
50 | * @since 05-04-2017
51 | */
52 |
53 | @Controller
54 | public class UserController implements Initializable{
55 |
56 | @FXML
57 | private Button btnLogout;
58 |
59 | @FXML
60 | private Label userId;
61 |
62 | @FXML
63 | private TextField firstName;
64 |
65 | @FXML
66 | private TextField lastName;
67 |
68 | @FXML
69 | private DatePicker dob;
70 |
71 | @FXML
72 | private RadioButton rbMale;
73 |
74 | @FXML
75 | private ToggleGroup gender;
76 |
77 | @FXML
78 | private RadioButton rbFemale;
79 |
80 | @FXML
81 | private ComboBox cbRole;
82 |
83 | @FXML
84 | private TextField email;
85 |
86 | @FXML
87 | private PasswordField password;
88 |
89 | @FXML
90 | private Button reset;
91 |
92 | @FXML
93 | private Button saveUser;
94 |
95 | @FXML
96 | private TableView userTable;
97 |
98 | @FXML
99 | private TableColumn colUserId;
100 |
101 | @FXML
102 | private TableColumn colFirstName;
103 |
104 | @FXML
105 | private TableColumn colLastName;
106 |
107 | @FXML
108 | private TableColumn colDOB;
109 |
110 | @FXML
111 | private TableColumn colGender;
112 |
113 | @FXML
114 | private TableColumn colRole;
115 |
116 | @FXML
117 | private TableColumn colEmail;
118 |
119 | @FXML
120 | private TableColumn colEdit;
121 |
122 | @FXML
123 | private MenuItem deleteUsers;
124 |
125 | @Lazy
126 | @Autowired
127 | private StageManager stageManager;
128 |
129 | @Autowired
130 | private UserService userService;
131 |
132 | private ObservableList userList = FXCollections.observableArrayList();
133 | private ObservableList roles = FXCollections.observableArrayList("Admin", "User");
134 |
135 | @FXML
136 | private void exit(ActionEvent event) {
137 | Platform.exit();
138 | }
139 |
140 | /**
141 | * Logout and go to the login page
142 | */
143 | @FXML
144 | private void logout(ActionEvent event) throws IOException {
145 | stageManager.switchScene(FxmlView.LOGIN);
146 | }
147 |
148 | @FXML
149 | void reset(ActionEvent event) {
150 | clearFields();
151 | }
152 |
153 | @FXML
154 | private void saveUser(ActionEvent event){
155 |
156 | if(validate("First Name", getFirstName(), "[a-zA-Z]+") &&
157 | validate("Last Name", getLastName(), "[a-zA-Z]+") &&
158 | emptyValidation("DOB", dob.getEditor().getText().isEmpty()) &&
159 | emptyValidation("Role", getRole() == null) ){
160 |
161 | if(userId.getText() == null || userId.getText() == ""){
162 | if(validate("Email", getEmail(), "[a-zA-Z0-9][a-zA-Z0-9._]*@[a-zA-Z0-9]+([.][a-zA-Z]+)+") &&
163 | emptyValidation("Password", getPassword().isEmpty())){
164 |
165 | User user = new User();
166 | user.setFirstName(getFirstName());
167 | user.setLastName(getLastName());
168 | user.setDob(getDob());
169 | user.setGender(getGender());
170 | user.setRole(getRole());
171 | user.setEmail(getEmail());
172 | user.setPassword(getPassword());
173 |
174 | User newUser = userService.save(user);
175 |
176 | saveAlert(newUser);
177 | }
178 |
179 | }else{
180 | User user = userService.find(Long.parseLong(userId.getText()));
181 | user.setFirstName(getFirstName());
182 | user.setLastName(getLastName());
183 | user.setDob(getDob());
184 | user.setGender(getGender());
185 | user.setRole(getRole());
186 | User updatedUser = userService.update(user);
187 | updateAlert(updatedUser);
188 | }
189 |
190 | clearFields();
191 | loadUserDetails();
192 | }
193 |
194 |
195 | }
196 |
197 | @FXML
198 | private void deleteUsers(ActionEvent event){
199 | List users = userTable.getSelectionModel().getSelectedItems();
200 |
201 | Alert alert = new Alert(AlertType.CONFIRMATION);
202 | alert.setTitle("Confirmation Dialog");
203 | alert.setHeaderText(null);
204 | alert.setContentText("Are you sure you want to delete selected?");
205 | Optional action = alert.showAndWait();
206 |
207 | if(action.get() == ButtonType.OK) userService.deleteInBatch(users);
208 |
209 | loadUserDetails();
210 | }
211 |
212 | private void clearFields() {
213 | userId.setText(null);
214 | firstName.clear();
215 | lastName.clear();
216 | dob.getEditor().clear();
217 | rbMale.setSelected(true);
218 | rbFemale.setSelected(false);
219 | cbRole.getSelectionModel().clearSelection();
220 | email.clear();
221 | password.clear();
222 | }
223 |
224 | private void saveAlert(User user){
225 |
226 | Alert alert = new Alert(AlertType.INFORMATION);
227 | alert.setTitle("User saved successfully.");
228 | alert.setHeaderText(null);
229 | alert.setContentText("The user "+user.getFirstName()+" "+user.getLastName() +" has been created and \n"+getGenderTitle(user.getGender())+" id is "+ user.getId() +".");
230 | alert.showAndWait();
231 | }
232 |
233 | private void updateAlert(User user){
234 |
235 | Alert alert = new Alert(AlertType.INFORMATION);
236 | alert.setTitle("User updated successfully.");
237 | alert.setHeaderText(null);
238 | alert.setContentText("The user "+user.getFirstName()+" "+user.getLastName() +" has been updated.");
239 | alert.showAndWait();
240 | }
241 |
242 | private String getGenderTitle(String gender){
243 | return (gender.equals("Male")) ? "his" : "her";
244 | }
245 |
246 | public String getFirstName() {
247 | return firstName.getText();
248 | }
249 |
250 | public String getLastName() {
251 | return lastName.getText();
252 | }
253 |
254 | public LocalDate getDob() {
255 | return dob.getValue();
256 | }
257 |
258 | public String getGender(){
259 | return rbMale.isSelected() ? "Male" : "Female";
260 | }
261 |
262 | public String getRole() {
263 | return cbRole.getSelectionModel().getSelectedItem();
264 | }
265 |
266 | public String getEmail() {
267 | return email.getText();
268 | }
269 |
270 | public String getPassword() {
271 | return password.getText();
272 | }
273 |
274 |
275 | @Override
276 | public void initialize(URL location, ResourceBundle resources) {
277 |
278 | cbRole.setItems(roles);
279 |
280 | userTable.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
281 |
282 | setColumnProperties();
283 |
284 | // Add all users into table
285 | loadUserDetails();
286 | }
287 |
288 |
289 |
290 | /*
291 | * Set All userTable column properties
292 | */
293 | private void setColumnProperties(){
294 | /* Override date format in table
295 | * colDOB.setCellFactory(TextFieldTableCell.forTableColumn(new StringConverter() {
296 | String pattern = "dd/MM/yyyy";
297 | DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(pattern);
298 | @Override
299 | public String toString(LocalDate date) {
300 | if (date != null) {
301 | return dateFormatter.format(date);
302 | } else {
303 | return "";
304 | }
305 | }
306 |
307 | @Override
308 | public LocalDate fromString(String string) {
309 | if (string != null && !string.isEmpty()) {
310 | return LocalDate.parse(string, dateFormatter);
311 | } else {
312 | return null;
313 | }
314 | }
315 | }));*/
316 |
317 | colUserId.setCellValueFactory(new PropertyValueFactory<>("id"));
318 | colFirstName.setCellValueFactory(new PropertyValueFactory<>("firstName"));
319 | colLastName.setCellValueFactory(new PropertyValueFactory<>("lastName"));
320 | colDOB.setCellValueFactory(new PropertyValueFactory<>("dob"));
321 | colGender.setCellValueFactory(new PropertyValueFactory<>("gender"));
322 | colRole.setCellValueFactory(new PropertyValueFactory<>("role"));
323 | colEmail.setCellValueFactory(new PropertyValueFactory<>("email"));
324 | colEdit.setCellFactory(cellFactory);
325 | }
326 |
327 | Callback, TableCell> cellFactory =
328 | new Callback, TableCell>()
329 | {
330 | @Override
331 | public TableCell call( final TableColumn param)
332 | {
333 | final TableCell cell = new TableCell()
334 | {
335 | Image imgEdit = new Image(getClass().getResourceAsStream("/images/edit.png"));
336 | final Button btnEdit = new Button();
337 |
338 | @Override
339 | public void updateItem(Boolean check, boolean empty)
340 | {
341 | super.updateItem(check, empty);
342 | if(empty)
343 | {
344 | setGraphic(null);
345 | setText(null);
346 | }
347 | else{
348 | btnEdit.setOnAction(e ->{
349 | User user = getTableView().getItems().get(getIndex());
350 | updateUser(user);
351 | });
352 |
353 | btnEdit.setStyle("-fx-background-color: transparent;");
354 | ImageView iv = new ImageView();
355 | iv.setImage(imgEdit);
356 | iv.setPreserveRatio(true);
357 | iv.setSmooth(true);
358 | iv.setCache(true);
359 | btnEdit.setGraphic(iv);
360 |
361 | setGraphic(btnEdit);
362 | setAlignment(Pos.CENTER);
363 | setText(null);
364 | }
365 | }
366 |
367 | private void updateUser(User user) {
368 | userId.setText(Long.toString(user.getId()));
369 | firstName.setText(user.getFirstName());
370 | lastName.setText(user.getLastName());
371 | dob.setValue(user.getDob());
372 | if(user.getGender().equals("Male")) rbMale.setSelected(true);
373 | else rbFemale.setSelected(true);
374 | cbRole.getSelectionModel().select(user.getRole());
375 | }
376 | };
377 | return cell;
378 | }
379 | };
380 |
381 |
382 |
383 | /*
384 | * Add All users to observable list and update table
385 | */
386 | private void loadUserDetails(){
387 | userList.clear();
388 | userList.addAll(userService.findAll());
389 |
390 | userTable.setItems(userList);
391 | }
392 |
393 | /*
394 | * Validations
395 | */
396 | private boolean validate(String field, String value, String pattern){
397 | if(!value.isEmpty()){
398 | Pattern p = Pattern.compile(pattern);
399 | Matcher m = p.matcher(value);
400 | if(m.find() && m.group().equals(value)){
401 | return true;
402 | }else{
403 | validationAlert(field, false);
404 | return false;
405 | }
406 | }else{
407 | validationAlert(field, true);
408 | return false;
409 | }
410 | }
411 |
412 | private boolean emptyValidation(String field, boolean empty){
413 | if(!empty){
414 | return true;
415 | }else{
416 | validationAlert(field, true);
417 | return false;
418 | }
419 | }
420 |
421 | private void validationAlert(String field, boolean empty){
422 | Alert alert = new Alert(AlertType.WARNING);
423 | alert.setTitle("Validation Error");
424 | alert.setHeaderText(null);
425 | if(field.equals("Role")) alert.setContentText("Please Select "+ field);
426 | else{
427 | if(empty) alert.setContentText("Please Enter "+ field);
428 | else alert.setContentText("Please Enter Valid "+ field);
429 | }
430 | alert.showAndWait();
431 | }
432 | }
433 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/generic/GenericService.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.generic;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * @author Ram Alapure
7 | * @since 05-04-2017
8 | */
9 |
10 | public interface GenericService {
11 |
12 | T save(T entity);
13 |
14 | T update(T entity);
15 |
16 | void delete(T entity);
17 |
18 | void delete(Long id);
19 |
20 | void deleteInBatch(List entities);
21 |
22 | T find(Long id);
23 |
24 | List findAll();
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/logging/ExceptionWriter.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * To change this license header, choose License Headers in Project Properties.
4 | * To change this template file, choose Tools | Templates
5 | * and open the template in the editor.
6 | */
7 | package com.codetreatise.logging;
8 |
9 | import java.io.PrintWriter;
10 | import java.io.Writer;
11 |
12 | /**
13 | * Handles writing exceptions to the Logger Tab and and utility methods needed
14 | * to facilitate logging of exceptions
15 | */
16 | public class ExceptionWriter extends PrintWriter {
17 | public ExceptionWriter(Writer writer) {
18 | super(writer);
19 | }
20 |
21 | private String wrapAroundWithNewlines(String stringWithoutNewlines) {
22 | return ("\n" + stringWithoutNewlines + "\n");
23 | }
24 |
25 | /*
26 | * Convert a stacktrace into a string
27 | */
28 | public String getExceptionAsString(Throwable throwable) {
29 | throwable.printStackTrace(this);
30 |
31 | String exception = super.out.toString();
32 |
33 | return (wrapAroundWithNewlines(exception));
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.repository;
2 |
3 | import org.springframework.data.jpa.repository.JpaRepository;
4 | import org.springframework.stereotype.Repository;
5 |
6 | import com.codetreatise.bean.User;
7 |
8 | @Repository
9 | public interface UserRepository extends JpaRepository {
10 |
11 | User findByEmail(String email);
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/service/UserService.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.service;
2 |
3 | import com.codetreatise.bean.User;
4 | import com.codetreatise.generic.GenericService;
5 |
6 | public interface UserService extends GenericService {
7 |
8 | boolean authenticate(String email, String password);
9 |
10 | User findByEmail(String email);
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/service/impl/UserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.service.impl;
2 |
3 | import java.util.List;
4 |
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.stereotype.Service;
7 |
8 | import com.codetreatise.bean.User;
9 | import com.codetreatise.repository.UserRepository;
10 | import com.codetreatise.service.UserService;
11 |
12 | @Service
13 | public class UserServiceImpl implements UserService {
14 |
15 | @Autowired
16 | private UserRepository userRepository;
17 |
18 | @Override
19 | public User save(User entity) {
20 | return userRepository.save(entity);
21 | }
22 |
23 | @Override
24 | public User update(User entity) {
25 | return userRepository.save(entity);
26 | }
27 |
28 | @Override
29 | public void delete(User entity) {
30 | userRepository.delete(entity);
31 | }
32 |
33 | @Override
34 | public void delete(Long id) {
35 | userRepository.delete(id);
36 | }
37 |
38 | @Override
39 | public User find(Long id) {
40 | return userRepository.findOne(id);
41 | }
42 |
43 | @Override
44 | public List findAll() {
45 | return userRepository.findAll();
46 | }
47 |
48 | @Override
49 | public boolean authenticate(String username, String password){
50 | User user = this.findByEmail(username);
51 | if(user == null){
52 | return false;
53 | }else{
54 | if(password.equals(user.getPassword())) return true;
55 | else return false;
56 | }
57 | }
58 |
59 | @Override
60 | public User findByEmail(String email) {
61 | return userRepository.findByEmail(email);
62 | }
63 |
64 | @Override
65 | public void deleteInBatch(List users) {
66 | userRepository.deleteInBatch(users);
67 | }
68 |
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/com/codetreatise/view/FxmlView.java:
--------------------------------------------------------------------------------
1 | package com.codetreatise.view;
2 |
3 | import java.util.ResourceBundle;
4 |
5 | public enum FxmlView {
6 |
7 | USER {
8 | @Override
9 | public String getTitle() {
10 | return getStringFromResourceBundle("user.title");
11 | }
12 |
13 | @Override
14 | public String getFxmlFile() {
15 | return "/fxml/User.fxml";
16 | }
17 | },
18 | LOGIN {
19 | @Override
20 | public String getTitle() {
21 | return getStringFromResourceBundle("login.title");
22 | }
23 |
24 | @Override
25 | public String getFxmlFile() {
26 | return "/fxml/Login.fxml";
27 | }
28 | };
29 |
30 | public abstract String getTitle();
31 | public abstract String getFxmlFile();
32 |
33 | String getStringFromResourceBundle(String key){
34 | return ResourceBundle.getBundle("Bundle").getString(key);
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/resources/Bundle.properties:
--------------------------------------------------------------------------------
1 | login.title=Login
2 | user.title=User Dashboard
3 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | specs.dir=/specs/
2 |
3 | ################### Spring Boot Data Source Configuration ############
4 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver
5 | spring.datasource.url=jdbc:mysql://localhost:3306/javafx?useSSL=false
6 | spring.datasource.username=root
7 | spring.datasource.password=root@123
8 | spring.datasource.initialize=true
9 | spring.jpa.hibernate.ddl-auto=update
10 | spring.jpa.show-sql=true
--------------------------------------------------------------------------------
/src/main/resources/fxml/Login.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/main/resources/fxml/User.fxml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
33 |
38 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
57 |
58 |
59 |
64 |
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 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
125 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
--------------------------------------------------------------------------------
/src/main/resources/images/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RamAlapure/JavaFXSpringBootApp/7f5594aa7e7edd5f38de3323249a9b8aabe2496e/src/main/resources/images/edit.png
--------------------------------------------------------------------------------
/src/main/resources/styles/Styles.css:
--------------------------------------------------------------------------------
1 | /* CSS for app */
2 |
3 | .btnGreen{
4 | -fx-background-color: #3cbc53;
5 | }
6 |
7 | .background{
8 | -fx-background-color: DODGERBLUE;
9 | }
10 |
11 |
--------------------------------------------------------------------------------