feat: Add complete example for Jakarta Faces and a devcontainer setup
This commit is contained in:
parent
d851c1b628
commit
a03f180e43
45 changed files with 1791 additions and 294 deletions
BIN
Icon.png
BIN
Icon.png
Binary file not shown.
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 259 KiB |
|
|
@ -100,9 +100,9 @@ func createMainWindow(a fyne.App, config *config.Config) {
|
||||||
|
|
||||||
standartProjects := []project.Project{
|
standartProjects := []project.Project{
|
||||||
{
|
{
|
||||||
Name: "JakartaEE Todo-App mit Servlet",
|
Name: "JakartaEE Todo-App mit Server Faces",
|
||||||
Description: "Eine Todo-Anwendung mit Jakarta Servlet und\nPostgreSQL-Datenbank.",
|
Description: "Eine Todo-Anwendung mit Jakarta Faces und\nPostgreSQL-Datenbank.",
|
||||||
FolderName: "jakarta-servlet-todo",
|
FolderName: "jakarta-faces-todo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "JakartaEE Todo-App mit JSP",
|
Name: "JakartaEE Todo-App mit JSP",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
.git
|
||||||
|
.github
|
||||||
|
.settings
|
||||||
|
target
|
||||||
|
*.iml
|
||||||
|
.idea
|
||||||
|
.vscode
|
||||||
|
node_modules
|
||||||
27
cmd/jws/projects/jakarta-faces-todo/.devcontainer/.gitignore
vendored
Normal file
27
cmd/jws/projects/jakarta-faces-todo/.devcontainer/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Maven
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
# IDE-spezifische Dateien
|
||||||
|
.idea/
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
.vscode/
|
||||||
|
.settings/
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.factorypath
|
||||||
|
|
||||||
|
# Temporäre Dateien
|
||||||
|
*.log
|
||||||
|
*.tmp
|
||||||
|
*.temp
|
||||||
|
|
||||||
|
# Lokale Konfigurationsdateien
|
||||||
|
src/main/resources/application-local.properties
|
||||||
|
|
||||||
|
# Devcontainer Volumen
|
||||||
|
.devcontainer/postgres-data/
|
||||||
12
cmd/jws/projects/jakarta-faces-todo/.devcontainer/Dockerfile
Normal file
12
cmd/jws/projects/jakarta-faces-todo/.devcontainer/Dockerfile
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
FROM icr.io/appcafe/open-liberty:23.0.0.4-kernel-slim-java17-openj9-ubi
|
||||||
|
|
||||||
|
COPY --chown=1001:0 src/main/liberty/config /config
|
||||||
|
# # Verzeichnis erstellen und PostgreSQL JDBC-Treiber herunterladen
|
||||||
|
RUN mkdir -p /config/lib && \
|
||||||
|
curl -o /config/lib/postgresql.jar https://jdbc.postgresql.org/download/postgresql-42.6.0.jar
|
||||||
|
|
||||||
|
RUN features.sh
|
||||||
|
|
||||||
|
#COPY --chown=1001:0 target/*.war /config/apps
|
||||||
|
|
||||||
|
RUN configure.sh
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
FROM mcr.microsoft.com/devcontainers/java:1-21-bullseye
|
||||||
|
|
||||||
|
#ARG INSTALL_MAVEN="true"
|
||||||
|
#ARG MAVEN_VERSION=""
|
||||||
|
|
||||||
|
#ARG INSTALL_GRADLE="false"
|
||||||
|
#ARG GRADLE_VERSION=""
|
||||||
|
|
||||||
|
#RUN if [ "${INSTALL_MAVEN}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install maven \"${MAVEN_VERSION}\""; fi \
|
||||||
|
# && if [ "${INSTALL_GRADLE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install gradle \"${GRADLE_VERSION}\""; fi
|
||||||
|
|
||||||
|
# Hier kannst du zusätzliche Tools oder Bibliotheken installieren, die du für die Entwicklung benötigst.
|
||||||
|
# Zum Beispiel den PostgreSQL JDBC-Treiber, wenn du ihn für die Entwicklung benötigst:
|
||||||
|
RUN apt-get update && apt-get install -y curl && curl -o /tmp/postgresql.jar https://jdbc.postgresql.org/download/postgresql-42.6.0.jar && mkdir -p /usr/local/lib/ && mv /tmp/postgresql.jar /usr/local/lib/postgresql.jar
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"name": "Java & PostgreSQL",
|
||||||
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
|
"service": "app",
|
||||||
|
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||||
|
"forwardPorts": [9080, 5432, 9433],
|
||||||
|
"postCreateCommand": "mvn clean install -DskipTests",
|
||||||
|
"remoteUser": "vscode",
|
||||||
|
"features": {
|
||||||
|
"ghcr.io/devcontainers/features/docker-in-docker:2": {"version": "latest"},
|
||||||
|
"ghcr.io/devcontainers-extra/features/maven-sdkman:2": {"version": "latest"},
|
||||||
|
"ghcr.io/devcontainers/features/git:1": {"version": "latest"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
container_name: javadev
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: .devcontainer/Dockerfile.dev
|
||||||
|
volumes:
|
||||||
|
- ../..:/workspaces:cached
|
||||||
|
- ./app:/app
|
||||||
|
environment:
|
||||||
|
POSTGRES_HOST: postgresdb
|
||||||
|
POSTGRES_PORT: 5432
|
||||||
|
POSTGRES_DB: postgres
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
networks:
|
||||||
|
- my_network
|
||||||
|
command: sleep infinity
|
||||||
|
|
||||||
|
openliberty:
|
||||||
|
container_name: openliberty_app
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
dockerfile: .devcontainer/Dockerfile
|
||||||
|
ports:
|
||||||
|
- "9080:9080"
|
||||||
|
- "9443:9443"
|
||||||
|
environment:
|
||||||
|
POSTGRES_HOST: postgresdb
|
||||||
|
POSTGRES_PORT: 5432
|
||||||
|
POSTGRES_DB: todo_db
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
volumes:
|
||||||
|
- ./app:/config/dropins
|
||||||
|
depends_on:
|
||||||
|
- db
|
||||||
|
networks:
|
||||||
|
- my_network
|
||||||
|
|
||||||
|
db:
|
||||||
|
container_name: postgresdb
|
||||||
|
image: postgres:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
|
environment:
|
||||||
|
POSTGRES_PASSWORD: postgres
|
||||||
|
POSTGRES_USER: postgres
|
||||||
|
POSTGRES_DB: todo_db
|
||||||
|
networks:
|
||||||
|
- my_network
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
my_network:
|
||||||
|
driver: bridge
|
||||||
17
cmd/jws/projects/jakarta-faces-todo/.devcontainer/init.sql
Normal file
17
cmd/jws/projects/jakarta-faces-todo/.devcontainer/init.sql
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
CREATE TABLE users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
username VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
password VARCHAR(255) NOT NULL,
|
||||||
|
email VARCHAR(255) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE todos (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
description VARCHAR(1000),
|
||||||
|
target_date DATE,
|
||||||
|
completed BOOLEAN,
|
||||||
|
user_id BIGINT NOT NULL,
|
||||||
|
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||||
|
);
|
||||||
|
|
||||||
87
cmd/jws/projects/jakarta-faces-todo/pom.xml
Normal file
87
cmd/jws/projects/jakarta-faces-todo/pom.xml
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.todoapp</groupId>
|
||||||
|
<artifactId>todo-app</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>war</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
<jakartaee.version>10.0.0</jakartaee.version>
|
||||||
|
<hibernate.version>6.2.5.Final</hibernate.version>
|
||||||
|
<postgresql.version>42.6.0</postgresql.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<!-- Jakarta EE 10 API -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.platform</groupId>
|
||||||
|
<artifactId>jakarta.jakartaee-api</artifactId>
|
||||||
|
<version>${jakartaee.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Hibernate Core -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate.orm</groupId>
|
||||||
|
<artifactId>hibernate-core</artifactId>
|
||||||
|
<version>${hibernate.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- PostgreSQL JDBC Driver -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.postgresql</groupId>
|
||||||
|
<artifactId>postgresql</artifactId>
|
||||||
|
<version>${postgresql.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.websocket</groupId>
|
||||||
|
<artifactId>jakarta.websocket-api</artifactId>
|
||||||
|
<version>2.1.0</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.hibernate</groupId>
|
||||||
|
<artifactId>hibernate-core</artifactId>
|
||||||
|
<version>6.3.1.Final</version> <!-- Stelle sicher, dass du eine aktuelle Version benutzt -->
|
||||||
|
</dependency>
|
||||||
|
<!-- Mindestens zum Passwort-Hashing -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>at.favre.lib</groupId>
|
||||||
|
<artifactId>bcrypt</artifactId>
|
||||||
|
<version>0.10.2</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<finalName>todo-app</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.10.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-war-plugin</artifactId>
|
||||||
|
<version>3.3.2</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>io.openliberty.tools</groupId>
|
||||||
|
<artifactId>liberty-maven-plugin</artifactId>
|
||||||
|
<version>3.7.1</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
34
cmd/jws/projects/jakarta-faces-todo/server.xml
Normal file
34
cmd/jws/projects/jakarta-faces-todo/server.xml
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<server description="OpenLiberty Todo App Server">
|
||||||
|
|
||||||
|
<featureManager>
|
||||||
|
<feature>servlet-6.0</feature>
|
||||||
|
<feature>pages-3.1</feature>
|
||||||
|
<feature>jdbc-4.2</feature>
|
||||||
|
<feature>jndi-1.0</feature>
|
||||||
|
<feature>monitor-1.0</feature>
|
||||||
|
<feature>faces-4.0</feature>
|
||||||
|
</featureManager>
|
||||||
|
|
||||||
|
<httpEndpoint id="defaultHttpEndpoint"
|
||||||
|
httpPort="9080"
|
||||||
|
httpsPort="9443" />
|
||||||
|
|
||||||
|
<applicationManager autoExpand="true" />
|
||||||
|
|
||||||
|
<dataSource id="PostgresDataSource">
|
||||||
|
<jdbcDriver libraryRef="PostgresLib" />
|
||||||
|
<properties.postgresql serverName="postgres"
|
||||||
|
portNumber="5432"
|
||||||
|
databaseName="todo_db"
|
||||||
|
user="postgres"
|
||||||
|
password="postgres" />
|
||||||
|
</dataSource>
|
||||||
|
|
||||||
|
<library id="PostgresLib">
|
||||||
|
<fileset dir="${server.config.dir}/lib" includes="postgresql-*.jar" />
|
||||||
|
</library>
|
||||||
|
|
||||||
|
<webApplication location="todo-app.war" contextRoot="/todo-app" />
|
||||||
|
|
||||||
|
</server>
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
package com.todoapp.bean;
|
||||||
|
|
||||||
|
import at.favre.lib.crypto.bcrypt.BCrypt;
|
||||||
|
import com.todoapp.dao.UserDAO;
|
||||||
|
import com.todoapp.model.User;
|
||||||
|
import jakarta.enterprise.context.SessionScoped;
|
||||||
|
import jakarta.faces.application.FacesMessage;
|
||||||
|
import jakarta.faces.context.FacesContext;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.inject.Named;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@Named
|
||||||
|
@SessionScoped
|
||||||
|
public class AuthBean implements Serializable {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private UserDAO userDAO;
|
||||||
|
|
||||||
|
private User user = new User();
|
||||||
|
private String confirmPassword;
|
||||||
|
|
||||||
|
public String login() {
|
||||||
|
User foundUser = userDAO
|
||||||
|
.getUserByUsername(user.getUsername())
|
||||||
|
.orElse(null);
|
||||||
|
if (
|
||||||
|
foundUser != null &&
|
||||||
|
BCrypt.verifyer()
|
||||||
|
.verify(
|
||||||
|
user.getPassword().toCharArray(),
|
||||||
|
foundUser.getPassword()
|
||||||
|
)
|
||||||
|
.verified
|
||||||
|
) {
|
||||||
|
FacesContext.getCurrentInstance()
|
||||||
|
.getExternalContext()
|
||||||
|
.getSessionMap()
|
||||||
|
.put("user", foundUser);
|
||||||
|
return "todo-list?faces-redirect=true";
|
||||||
|
} else {
|
||||||
|
FacesContext.getCurrentInstance()
|
||||||
|
.addMessage(
|
||||||
|
null,
|
||||||
|
new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_ERROR,
|
||||||
|
"Invalid username or password",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String register() {
|
||||||
|
if (!user.getPassword().equals(confirmPassword)) {
|
||||||
|
FacesContext.getCurrentInstance()
|
||||||
|
.addMessage(
|
||||||
|
null,
|
||||||
|
new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_ERROR,
|
||||||
|
"Passwords do not match",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (userDAO.usernameExists(user.getUsername())) {
|
||||||
|
FacesContext.getCurrentInstance()
|
||||||
|
.addMessage(
|
||||||
|
null,
|
||||||
|
new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_ERROR,
|
||||||
|
"Username already exists",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (userDAO.emailExists(user.getEmail())) {
|
||||||
|
FacesContext.getCurrentInstance()
|
||||||
|
.addMessage(
|
||||||
|
null,
|
||||||
|
new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_ERROR,
|
||||||
|
"Email already registered",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String hashedPassword = BCrypt.withDefaults()
|
||||||
|
.hashToString(12, user.getPassword().toCharArray());
|
||||||
|
user.setPassword(hashedPassword);
|
||||||
|
userDAO.saveUser(user);
|
||||||
|
|
||||||
|
FacesContext.getCurrentInstance()
|
||||||
|
.addMessage(
|
||||||
|
null,
|
||||||
|
new FacesMessage(
|
||||||
|
FacesMessage.SEVERITY_INFO,
|
||||||
|
"Registration successful. Please log in.",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return "login?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String logout() {
|
||||||
|
FacesContext.getCurrentInstance()
|
||||||
|
.getExternalContext()
|
||||||
|
.invalidateSession();
|
||||||
|
return "login?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter und Setter
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfirmPassword() {
|
||||||
|
return confirmPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfirmPassword(String confirmPassword) {
|
||||||
|
this.confirmPassword = confirmPassword;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
package com.todoapp.bean;
|
||||||
|
|
||||||
|
import com.todoapp.dao.TodoDAO;
|
||||||
|
import com.todoapp.model.Todo;
|
||||||
|
import com.todoapp.model.User;
|
||||||
|
import jakarta.enterprise.context.SessionScoped;
|
||||||
|
import jakarta.faces.context.FacesContext;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.inject.Named;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Named
|
||||||
|
@SessionScoped
|
||||||
|
public class TodoBean implements Serializable {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private TodoDAO todoDAO;
|
||||||
|
|
||||||
|
private Todo todo = new Todo();
|
||||||
|
private List<Todo> todos;
|
||||||
|
|
||||||
|
public String saveOrUpdateTodo() {
|
||||||
|
if (todo.getId() == null) {
|
||||||
|
return saveTodo();
|
||||||
|
} else {
|
||||||
|
return updateTodo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Todo> getTodosByUser(Long userId) {
|
||||||
|
if (todos == null) {
|
||||||
|
todos = todoDAO.getTodosByUser(userId);
|
||||||
|
}
|
||||||
|
return todos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Todo> getTodosByUser() {
|
||||||
|
User user = (User) FacesContext.getCurrentInstance()
|
||||||
|
.getExternalContext()
|
||||||
|
.getSessionMap()
|
||||||
|
.get("user");
|
||||||
|
System.out.println("Fetching todos for user ID: " + user.getId());
|
||||||
|
List<Todo> todos = todoDAO.getTodosByUser(user.getId());
|
||||||
|
System.out.println("Fetched todos: " + todos);
|
||||||
|
return todos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void loadTodo() {
|
||||||
|
String idParam = FacesContext.getCurrentInstance()
|
||||||
|
.getExternalContext()
|
||||||
|
.getRequestParameterMap()
|
||||||
|
.get("id");
|
||||||
|
if (idParam != null && !idParam.isEmpty()) {
|
||||||
|
Long id = Long.parseLong(idParam);
|
||||||
|
todo = todoDAO.getTodoById(id);
|
||||||
|
} else {
|
||||||
|
todo = new Todo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String saveTodo(User user) {
|
||||||
|
todo.setUser(user);
|
||||||
|
todoDAO.saveTodo(todo);
|
||||||
|
todo = new Todo();
|
||||||
|
todos = null;
|
||||||
|
return "todo-list?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String saveTodo() {
|
||||||
|
User user = (User) FacesContext.getCurrentInstance()
|
||||||
|
.getExternalContext()
|
||||||
|
.getSessionMap()
|
||||||
|
.get("user");
|
||||||
|
System.out.println(user);
|
||||||
|
todo.setUser(user);
|
||||||
|
todoDAO.saveTodo(todo);
|
||||||
|
todo = new Todo();
|
||||||
|
todos = null;
|
||||||
|
return "todo-list?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String updateTodo() {
|
||||||
|
todoDAO.updateTodo(todo);
|
||||||
|
todo = new Todo();
|
||||||
|
todos = null;
|
||||||
|
return "todo-list?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String deleteTodo(Long id) {
|
||||||
|
todoDAO.deleteTodo(id);
|
||||||
|
todos = null;
|
||||||
|
return "todo-list?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String completeTodo(Long id) {
|
||||||
|
Todo todoToComplete = todoDAO.getTodoById(id);
|
||||||
|
todoToComplete.setCompleted(!todoToComplete.isCompleted());
|
||||||
|
todoDAO.updateTodo(todoToComplete);
|
||||||
|
todos = null;
|
||||||
|
return "todo-list?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter und Setter für 'todo'
|
||||||
|
public Todo getTodo() {
|
||||||
|
return todo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTodo(Todo todo) {
|
||||||
|
this.todo = todo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package com.todoapp.bean;
|
||||||
|
|
||||||
|
import com.todoapp.dao.UserDAO;
|
||||||
|
import com.todoapp.model.User;
|
||||||
|
import jakarta.enterprise.context.SessionScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.inject.Named;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Named
|
||||||
|
@SessionScoped
|
||||||
|
public class UserBean implements Serializable {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private UserDAO userDAO;
|
||||||
|
|
||||||
|
private User user = new User();
|
||||||
|
private List<User> users;
|
||||||
|
|
||||||
|
public List<User> getAllUsers() {
|
||||||
|
if (users == null) {
|
||||||
|
users = userDAO.getAllUsers();
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String saveUser() {
|
||||||
|
userDAO.saveUser(user);
|
||||||
|
user = new User();
|
||||||
|
users = null; // Reset the list to force a refresh
|
||||||
|
return "user-list?faces-redirect=true";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter und Setter für 'user'
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
package com.todoapp.dao;
|
||||||
|
|
||||||
|
import com.todoapp.model.Todo;
|
||||||
|
import com.todoapp.util.HibernateUtil;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import java.util.List;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.query.Query;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class TodoDAO {
|
||||||
|
|
||||||
|
public void saveTodo(Todo todo) {
|
||||||
|
Transaction transaction = null;
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
session.persist(todo);
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (transaction != null) {
|
||||||
|
transaction.rollback();
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateTodo(Todo todo) {
|
||||||
|
Transaction transaction = null;
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
session.merge(todo);
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (transaction != null) {
|
||||||
|
transaction.rollback();
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteTodo(Long id) {
|
||||||
|
Transaction transaction = null;
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
Todo todo = session.get(Todo.class, id);
|
||||||
|
if (todo != null) {
|
||||||
|
session.remove(todo);
|
||||||
|
}
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (transaction != null) {
|
||||||
|
transaction.rollback();
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Todo getTodoById(Long id) {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
return session.get(Todo.class, id);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Todo> getAllTodos() {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
return session.createQuery("FROM Todo", Todo.class).list();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Todo> getTodosByUser(Long userId) {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
Query<Todo> query = session.createQuery(
|
||||||
|
"FROM Todo t WHERE t.user.id = :userId ORDER BY t.completed, t.targetDate",
|
||||||
|
Todo.class
|
||||||
|
);
|
||||||
|
query.setParameter("userId", userId);
|
||||||
|
return query.list();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Todo> getCompletedTodosByUser(Long userId) {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
Query<Todo> query = session.createQuery(
|
||||||
|
"FROM Todo t WHERE t.user.id = :userId AND t.completed = true",
|
||||||
|
Todo.class
|
||||||
|
);
|
||||||
|
query.setParameter("userId", userId);
|
||||||
|
return query.list();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Todo> getIncompleteTodosByUser(Long userId) {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
Query<Todo> query = session.createQuery(
|
||||||
|
"FROM Todo t WHERE t.user.id = :userId AND t.completed = false ORDER BY t.targetDate",
|
||||||
|
Todo.class
|
||||||
|
);
|
||||||
|
query.setParameter("userId", userId);
|
||||||
|
return query.list();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
package com.todoapp.dao;
|
||||||
|
|
||||||
|
import com.todoapp.model.User;
|
||||||
|
import com.todoapp.util.HibernateUtil;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.Transaction;
|
||||||
|
import org.hibernate.query.Query;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class UserDAO {
|
||||||
|
|
||||||
|
public void saveUser(User user) {
|
||||||
|
Transaction transaction = null;
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
session.persist(user);
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (transaction != null) {
|
||||||
|
transaction.rollback();
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateUser(User user) {
|
||||||
|
Transaction transaction = null;
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
session.merge(user);
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (transaction != null) {
|
||||||
|
transaction.rollback();
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deleteUser(Long id) {
|
||||||
|
Transaction transaction = null;
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
transaction = session.beginTransaction();
|
||||||
|
User user = session.get(User.class, id);
|
||||||
|
if (user != null) {
|
||||||
|
session.remove(user);
|
||||||
|
}
|
||||||
|
transaction.commit();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (transaction != null) {
|
||||||
|
transaction.rollback();
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUserById(Long id) {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
return session.get(User.class, id);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<User> getUserByUsername(String username) {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
Query<User> query = session.createQuery(
|
||||||
|
"FROM User WHERE username = :username",
|
||||||
|
User.class
|
||||||
|
);
|
||||||
|
query.setParameter("username", username);
|
||||||
|
User user = query.uniqueResult();
|
||||||
|
return Optional.ofNullable(user);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<User> getAllUsers() {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
return session.createQuery("FROM User", User.class).list();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean usernameExists(String username) {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
Query<Long> query = session.createQuery(
|
||||||
|
"SELECT COUNT(u) FROM User u WHERE u.username = :username",
|
||||||
|
Long.class
|
||||||
|
);
|
||||||
|
query.setParameter("username", username);
|
||||||
|
return query.uniqueResult() > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean emailExists(String email) {
|
||||||
|
try (
|
||||||
|
Session session = HibernateUtil.getSessionFactory().openSession()
|
||||||
|
) {
|
||||||
|
Query<Long> query = session.createQuery(
|
||||||
|
"SELECT COUNT(u) FROM User u WHERE u.email = :email",
|
||||||
|
Long.class
|
||||||
|
);
|
||||||
|
query.setParameter("email", email);
|
||||||
|
return query.uniqueResult() > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
package com.todoapp.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "todos")
|
||||||
|
public class Todo implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Column(length = 1000)
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Column(name = "target_date")
|
||||||
|
private LocalDate targetDate;
|
||||||
|
|
||||||
|
private boolean completed;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "user_id", nullable = false)
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
// Konstruktoren
|
||||||
|
public Todo() {}
|
||||||
|
|
||||||
|
public Todo(
|
||||||
|
String title,
|
||||||
|
String description,
|
||||||
|
LocalDate targetDate,
|
||||||
|
boolean completed
|
||||||
|
) {
|
||||||
|
this.title = title;
|
||||||
|
this.description = description;
|
||||||
|
this.targetDate = targetDate;
|
||||||
|
this.completed = completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter und Setter
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalDate getTargetDate() {
|
||||||
|
return targetDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTargetDate(LocalDate targetDate) {
|
||||||
|
this.targetDate = targetDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompleted() {
|
||||||
|
return completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCompleted(boolean completed) {
|
||||||
|
this.completed = completed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(User user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return (
|
||||||
|
"Todo{" +
|
||||||
|
"id=" +
|
||||||
|
id +
|
||||||
|
", title='" +
|
||||||
|
title +
|
||||||
|
'\'' +
|
||||||
|
", targetDate=" +
|
||||||
|
targetDate +
|
||||||
|
", completed=" +
|
||||||
|
completed +
|
||||||
|
'}'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
package com.todoapp.model;
|
||||||
|
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "users")
|
||||||
|
public class User implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(nullable = false, unique = true)
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
|
||||||
|
private List<Todo> todos = new ArrayList<>();
|
||||||
|
|
||||||
|
// Konstruktoren
|
||||||
|
public User() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public User(String username, String password, String email) {
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getter und Setter
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Todo> getTodos() {
|
||||||
|
return todos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTodos(List<Todo> todos) {
|
||||||
|
this.todos = todos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hilfsmethoden
|
||||||
|
public void addTodo(Todo todo) {
|
||||||
|
todos.add(todo);
|
||||||
|
todo.setUser(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeTodo(Todo todo) {
|
||||||
|
todos.remove(todo);
|
||||||
|
todo.setUser(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "User{" +
|
||||||
|
"id=" + id +
|
||||||
|
", username='" + username + '\'' +
|
||||||
|
", email='" + email + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.todoapp.util;
|
||||||
|
|
||||||
|
import jakarta.servlet.*;
|
||||||
|
import jakarta.servlet.annotation.WebFilter;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@WebFilter(urlPatterns = { "/todos/*", "/users/*" })
|
||||||
|
public class AuthFilter implements Filter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
// Initialisierung
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||||
|
HttpServletResponse httpResponse = (HttpServletResponse) response;
|
||||||
|
|
||||||
|
HttpSession session = httpRequest.getSession(false);
|
||||||
|
|
||||||
|
boolean isLoggedIn = (session != null && session.getAttribute("userId") != null);
|
||||||
|
boolean isLoginRequest = httpRequest.getRequestURI().contains("/auth/login");
|
||||||
|
boolean isRegisterRequest = httpRequest.getRequestURI().contains("/auth/register");
|
||||||
|
boolean isResourceRequest = httpRequest.getRequestURI().contains("/css/") ||
|
||||||
|
httpRequest.getRequestURI().contains("/js/");
|
||||||
|
|
||||||
|
if (isLoggedIn || isLoginRequest || isRegisterRequest || isResourceRequest) {
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
} else {
|
||||||
|
httpResponse.sendRedirect(httpRequest.getContextPath() + "/auth/login");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
// Aufräumen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
//package com.todoapp.util;
|
||||||
|
//
|
||||||
|
//import org.hibernate.SessionFactory;
|
||||||
|
//import org.hibernate.boot.Metadata;
|
||||||
|
//import org.hibernate.boot.MetadataSources;
|
||||||
|
//import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
|
//import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
|
//import org.hibernate.cfg.Configuration;
|
||||||
|
//
|
||||||
|
//public class HibernateUtil {
|
||||||
|
// private static StandardServiceRegistry registry;
|
||||||
|
// private static SessionFactory sessionFactory;
|
||||||
|
//
|
||||||
|
// public static SessionFactory getSessionFactory() {
|
||||||
|
// if (sessionFactory == null) {
|
||||||
|
// try {
|
||||||
|
// // Create registry
|
||||||
|
// registry = new StandardServiceRegistryBuilder()
|
||||||
|
// .configure()
|
||||||
|
// .build();
|
||||||
|
//
|
||||||
|
// // Create MetadataSources
|
||||||
|
// MetadataSources sources = new MetadataSources(registry);
|
||||||
|
//
|
||||||
|
// // Create Metadata
|
||||||
|
// Metadata metadata = sources.getMetadataBuilder().build();
|
||||||
|
//
|
||||||
|
// // Create SessionFactory
|
||||||
|
// sessionFactory = metadata.getSessionFactoryBuilder().build();
|
||||||
|
//
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// if (registry != null) {
|
||||||
|
// StandardServiceRegistryBuilder.destroy(registry);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return sessionFactory;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// public static void shutdown() {
|
||||||
|
// if (registry != null) {
|
||||||
|
// StandardServiceRegistryBuilder.destroy(registry);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
package com.todoapp.util;
|
||||||
|
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import javax.naming.Context;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
public class HibernateUtil {
|
||||||
|
private static SessionFactory sessionFactory;
|
||||||
|
|
||||||
|
public static SessionFactory getSessionFactory() {
|
||||||
|
if (sessionFactory == null) {
|
||||||
|
try {
|
||||||
|
Configuration configuration = new Configuration();
|
||||||
|
configuration.setProperty("hibernate.connection.driver_class", "org.postgresql.Driver");
|
||||||
|
configuration.setProperty("hibernate.connection.url", "jdbc:postgresql://postgresdb:5432/todo_db");
|
||||||
|
configuration.setProperty("hibernate.connection.username", "postgres");
|
||||||
|
configuration.setProperty("hibernate.connection.password", "postgres");
|
||||||
|
|
||||||
|
// Entity-Klassen registrieren
|
||||||
|
configuration.addAnnotatedClass(com.todoapp.model.User.class);
|
||||||
|
configuration.addAnnotatedClass(com.todoapp.model.Todo.class);
|
||||||
|
sessionFactory = configuration.buildSessionFactory();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static SessionFactory getSessionFactory() {
|
||||||
|
// if (sessionFactory == null) {
|
||||||
|
// try {
|
||||||
|
// // Create Configuration
|
||||||
|
// Configuration configuration = new Configuration();
|
||||||
|
//
|
||||||
|
// // Set JNDI DataSource
|
||||||
|
// Context ctx = new InitialContext();
|
||||||
|
// DataSource ds = (DataSource) ctx.lookup("jdbc/PostgresDataSource");
|
||||||
|
// configuration.setProperty("hibernate.connection.datasource",
|
||||||
|
// "jdbc/PostgresDataSource");
|
||||||
|
//
|
||||||
|
// //// Load hibernate.cfg.xml
|
||||||
|
// // configuration.configure("hibernate.cfg.xml");
|
||||||
|
//
|
||||||
|
// // Build SessionFactory
|
||||||
|
// sessionFactory = configuration.buildSessionFactory();
|
||||||
|
//
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// e.printStackTrace();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return sessionFactory;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static void shutdown() {
|
||||||
|
if (sessionFactory != null) {
|
||||||
|
sessionFactory.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<server description="OpenLiberty Todo App Server">
|
||||||
|
|
||||||
|
<featureManager>
|
||||||
|
<feature>servlet-6.0</feature>
|
||||||
|
<feature>pages-3.1</feature>
|
||||||
|
<feature>jdbc-4.2</feature>
|
||||||
|
<feature>jndi-1.0</feature>
|
||||||
|
<feature>monitor-1.0</feature>
|
||||||
|
<feature>faces-4.0</feature>
|
||||||
|
<feature>websocket-2.1</feature>
|
||||||
|
</featureManager>
|
||||||
|
|
||||||
|
<httpEndpoint id="defaultHttpEndpoint"
|
||||||
|
httpPort="9080"
|
||||||
|
httpsPort="9443" />
|
||||||
|
|
||||||
|
<applicationManager autoExpand="true" />
|
||||||
|
|
||||||
|
<dataSource id="PostgresDataSource" jndiName="jdbc/PostgresDataSource">
|
||||||
|
<jdbcDriver libraryRef="PostgresLib" />
|
||||||
|
<properties.postgresql serverName="${POSTGRES_HOST}"
|
||||||
|
portNumber="${POSTGRES_PORT}"
|
||||||
|
databaseName="${POSTGRES_DB}"
|
||||||
|
user="${POSTGRES_USER}"
|
||||||
|
password="${POSTGRES_PASSWORD}" />
|
||||||
|
</dataSource>
|
||||||
|
|
||||||
|
|
||||||
|
<library id="PostgresLib">
|
||||||
|
<fileset dir="${server.config.dir}/lib" includes="postgresql-*.jar" />
|
||||||
|
</library>
|
||||||
|
|
||||||
|
</server>
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
|
||||||
|
version="3.0">
|
||||||
|
<persistence-unit name="todoPU" transaction-type="RESOURCE_LOCAL">
|
||||||
|
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
|
||||||
|
<class>com.todoapp.model.User</class>
|
||||||
|
<class>com.todoapp.model.Todo</class>
|
||||||
|
<properties>
|
||||||
|
<property name="jakarta.persistence.jdbc.driver" value="org.postgresql.Driver"/>
|
||||||
|
<property name="jakarta.persistence.jdbc.url" value="jdbc:postgresql://postgresdb:5432/todo_db"/>
|
||||||
|
<property name="jakarta.persistence.jdbc.user" value="postgres"/>
|
||||||
|
<property name="jakarta.persistence.jdbc.password" value="postgres"/>
|
||||||
|
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
|
||||||
|
<property name="hibernate.hbm2ddl.auto" value="update"/>
|
||||||
|
<property name="hibernate.show_sql" value="true"/>
|
||||||
|
</properties>
|
||||||
|
</persistence-unit>
|
||||||
|
</persistence>
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE hibernate-configuration PUBLIC
|
||||||
|
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
|
||||||
|
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
|
||||||
|
<hibernate-configuration>
|
||||||
|
<session-factory>
|
||||||
|
<!-- JNDI connection settings -->
|
||||||
|
<property name="hibernate.connection.datasource">jdbc/PostgresDataSource</property>
|
||||||
|
|
||||||
|
<!-- Select our SQL dialect -->
|
||||||
|
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
|
||||||
|
|
||||||
|
<!-- Echo the SQL to stdout -->
|
||||||
|
<property name="hibernate.show_sql">true</property>
|
||||||
|
|
||||||
|
<!-- Set the current session context -->
|
||||||
|
<property name="hibernate.current_session_context_class">thread</property>
|
||||||
|
|
||||||
|
<!-- Drop and re-create the database schema on startup -->
|
||||||
|
<property name="hibernate.hbm2ddl.auto">update</property>
|
||||||
|
|
||||||
|
<!-- Entity mapping -->
|
||||||
|
<mapping class="com.todoapp.model.User"/>
|
||||||
|
<mapping class="com.todoapp.model.Todo"/>
|
||||||
|
</session-factory>
|
||||||
|
</hibernate-configuration>
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<faces-config
|
||||||
|
xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-facesconfig_4_0.xsd"
|
||||||
|
version="4.0">
|
||||||
|
</faces-config>
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
|
||||||
|
version="6.0">
|
||||||
|
|
||||||
|
<display-name>Todo Application</display-name>
|
||||||
|
|
||||||
|
<welcome-file-list>
|
||||||
|
<welcome-file>login.xhtml</welcome-file>
|
||||||
|
</welcome-file-list>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>Faces Servlet</servlet-name>
|
||||||
|
<servlet-class>jakarta.faces.webapp.FacesServlet</servlet-class>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>Faces Servlet</servlet-name>
|
||||||
|
<url-pattern>*.xhtml</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
<context-param>
|
||||||
|
<param-name>jakarta.faces.PROJECT_STAGE</param-name>
|
||||||
|
<param-value>Development</param-value>
|
||||||
|
</context-param>
|
||||||
|
|
||||||
|
<error-page>
|
||||||
|
<error-code>404</error-code>
|
||||||
|
<location>/error.xhtml</location>
|
||||||
|
</error-page>
|
||||||
|
|
||||||
|
<error-page>
|
||||||
|
<error-code>500</error-code>
|
||||||
|
<location>/error.xhtml</location>
|
||||||
|
</error-page>
|
||||||
|
|
||||||
|
<session-config>
|
||||||
|
<session-timeout>30</session-timeout>
|
||||||
|
</session-config>
|
||||||
|
|
||||||
|
</web-app>
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="jakarta.faces.html"
|
||||||
|
xmlns:f="jakarta.faces.core">
|
||||||
|
<h:head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<title>Fehler</title>
|
||||||
|
<h:outputStylesheet name="./css/style.css"/>
|
||||||
|
</h:head>
|
||||||
|
<h:body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Oops! Es ist ein Fehler aufgetreten</h1>
|
||||||
|
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<p>Etwas ist schiefgelaufen. Bitte versuchen Sie es später erneut.</p>
|
||||||
|
<p>Fehlercode: #{facesContext.externalContext.responseStatusCode}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:link outcome="/todos" value="Zurück zur Startseite" styleClass="btn"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="jakarta.faces.html"
|
||||||
|
xmlns:f="jakarta.faces.core">
|
||||||
|
<h:head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<title>Login</title>
|
||||||
|
<h:outputStylesheet name="./css/style.css"/>
|
||||||
|
</h:head>
|
||||||
|
<h:body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Login</h1>
|
||||||
|
|
||||||
|
<h:messages globalOnly="true" styleClass="alert alert-danger"/>
|
||||||
|
|
||||||
|
<h:form>
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="username" value="Benutzername:"/>
|
||||||
|
<h:inputText id="username" value="#{authBean.user.username}" required="true"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="password" value="Passwort:"/>
|
||||||
|
<h:inputSecret id="password" value="#{authBean.user.password}" required="true"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:commandButton value="Anmelden" action="#{authBean.login}" styleClass="btn"/>
|
||||||
|
</div>
|
||||||
|
</h:form>
|
||||||
|
|
||||||
|
<p>Noch keinen Account? <h:link outcome="register" value="Registrieren"/></p>
|
||||||
|
</div>
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="jakarta.faces.html"
|
||||||
|
xmlns:f="jakarta.faces.core">
|
||||||
|
<h:head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<title>Registrierung</title>
|
||||||
|
<h:outputStylesheet name="./css/style.css"/>
|
||||||
|
</h:head>
|
||||||
|
<h:body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Registrierung</h1>
|
||||||
|
|
||||||
|
<h:messages globalOnly="true" styleClass="alert alert-danger"/>
|
||||||
|
|
||||||
|
<h:form>
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="username" value="Benutzername:"/>
|
||||||
|
<h:inputText id="username" value="#{authBean.user.username}" required="true"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="email" value="E-Mail:"/>
|
||||||
|
<h:inputText id="email" value="#{authBean.user.email}" required="true"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="password" value="Passwort:"/>
|
||||||
|
<h:inputSecret id="password" value="#{authBean.user.password}" required="true"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="confirmPassword" value="Passwort bestätigen:"/>
|
||||||
|
<h:inputSecret id="confirmPassword" value="#{authBean.confirmPassword}" required="true"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:commandButton value="Registrieren" action="#{authBean.register}" styleClass="btn"/>
|
||||||
|
</div>
|
||||||
|
</h:form>
|
||||||
|
|
||||||
|
<p>Bereits registriert? <h:link outcome="login" value="Anmelden"/></p>
|
||||||
|
</div>
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
/* Allgemeine Stile */
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header und Navigation */
|
||||||
|
header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-btn {
|
||||||
|
background-color: #f44336;
|
||||||
|
color: white;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logout-btn:hover {
|
||||||
|
background-color: #d32f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Formulare */
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group input,
|
||||||
|
.form-group textarea {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group button {
|
||||||
|
background-color: #4caf50;
|
||||||
|
color: white;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group button:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alerts */
|
||||||
|
.alert {
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-danger {
|
||||||
|
background-color: #f8d7da;
|
||||||
|
color: #721c24;
|
||||||
|
border: 1px solid #f5c6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-success {
|
||||||
|
background-color: #d4edda;
|
||||||
|
color: #155724;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Links */
|
||||||
|
a {
|
||||||
|
color: #007bff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Buttons */
|
||||||
|
.btn {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px 12px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 1.42857143;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn {
|
||||||
|
background-color: #4caf50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-btn:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-btn {
|
||||||
|
background-color: #2196f3;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-btn:hover {
|
||||||
|
background-color: #0b7dda;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn {
|
||||||
|
background-color: #f44336;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.delete-btn:hover {
|
||||||
|
background-color: #d32f2f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.complete-btn {
|
||||||
|
background-color: #ff9800;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.complete-btn:hover {
|
||||||
|
background-color: #e68a00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn {
|
||||||
|
background-color: #9e9e9e;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cancel-btn:hover {
|
||||||
|
background-color: #7e7e7e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-btn {
|
||||||
|
background-color: #4caf50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.save-btn:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Todo-Liste */
|
||||||
|
.todo-actions {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-table th,
|
||||||
|
.todo-table td {
|
||||||
|
padding: 10px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-table th {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-table tr:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo-table tr.completed {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
padding: 3px 8px;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.completed {
|
||||||
|
background-color: #4caf50;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status.pending {
|
||||||
|
background-color: #ff9800;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-todos {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="jakarta.faces.html"
|
||||||
|
xmlns:f="jakarta.faces.core">
|
||||||
|
<f:metadata>
|
||||||
|
<f:viewAction action="#{todoBean.loadTodo}" />
|
||||||
|
</f:metadata>
|
||||||
|
<h:head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<title>#{todoBean.todo.id == null ? 'Neue Aufgabe' : 'Aufgabe bearbeiten'}</title>
|
||||||
|
<h:outputStylesheet name="./css/style.css"/>
|
||||||
|
</h:head>
|
||||||
|
<h:body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>#{todoBean.todo.id == null ? 'Neue Aufgabe' : 'Aufgabe bearbeiten'}</h1>
|
||||||
|
|
||||||
|
<h:form>
|
||||||
|
<h:inputHidden value="#{todoBean.todo.id}"/>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="title" value="Titel:"/>
|
||||||
|
<h:inputText id="title" value="#{todoBean.todo.title}" required="true"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="description" value="Beschreibung:"/>
|
||||||
|
<h:inputTextarea id="description" value="#{todoBean.todo.description}" rows="5"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:outputLabel for="targetDate" value="Fälligkeitsdatum:"/>
|
||||||
|
<h:inputText id="targetDate" value="#{todoBean.todo.targetDate}" required="false">
|
||||||
|
<f:convertDateTime type="localDate" pattern="yyyy-MM-dd"/>
|
||||||
|
</h:inputText>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h:commandButton value="Speichern"
|
||||||
|
action="#{todoBean.saveOrUpdateTodo}"
|
||||||
|
styleClass="btn save-btn"/>
|
||||||
|
<h:link outcome="todo-list" value="Abbrechen" styleClass="btn cancel-btn"/>
|
||||||
|
</div>
|
||||||
|
</h:form>
|
||||||
|
</div>
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="jakarta.faces.html"
|
||||||
|
xmlns:f="jakarta.faces.core"
|
||||||
|
xmlns:ui="jakarta.faces.facelets">
|
||||||
|
<h:head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<title>Meine Aufgaben</title>
|
||||||
|
<h:outputStylesheet name="./css/style.css"/>
|
||||||
|
</h:head>
|
||||||
|
<h:body>
|
||||||
|
<div class="container">
|
||||||
|
<header>
|
||||||
|
<h1>Meine Aufgaben</h1>
|
||||||
|
<div class="user-info">
|
||||||
|
<span>Hallo, #{sessionScope.username}!</span>
|
||||||
|
<h:form>
|
||||||
|
<h:commandLink action="#{authBean.logout}" value="Abmelden" styleClass="logout-btn"/>
|
||||||
|
</h:form>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div class="todo-actions">
|
||||||
|
<h:link outcome="todo-form" value="Neue Aufgabe" styleClass="btn add-btn"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h:panelGroup rendered="#{empty todoBean.todosByUser}">
|
||||||
|
<div class="no-todos">
|
||||||
|
<p>Keine Aufgaben vorhanden. Erstellen Sie eine neue Aufgabe!</p>
|
||||||
|
</div>
|
||||||
|
</h:panelGroup>
|
||||||
|
|
||||||
|
<h:dataTable value="#{todoBean.todosByUser}" var="todo" styleClass="todo-table"
|
||||||
|
rendered="#{not empty todoBean.todosByUser}">
|
||||||
|
<h:column>
|
||||||
|
<f:facet name="header">Titel</f:facet>
|
||||||
|
#{todo.title}
|
||||||
|
</h:column>
|
||||||
|
<h:column>
|
||||||
|
<f:facet name="header">Beschreibung</f:facet>
|
||||||
|
#{todo.description}
|
||||||
|
</h:column>
|
||||||
|
<h:column>
|
||||||
|
<f:facet name="header">Fälligkeitsdatum</f:facet>
|
||||||
|
<h:outputText value="#{todo.targetDate}">
|
||||||
|
<f:convertDateTime type="localDate" pattern="yyyy-MM-dd"/>
|
||||||
|
</h:outputText>
|
||||||
|
</h:column>
|
||||||
|
<h:column>
|
||||||
|
<f:facet name="header">Status</f:facet>
|
||||||
|
<h:outputText value="Erledigt" rendered="#{todo.completed}" styleClass="status completed"/>
|
||||||
|
<h:outputText value="Offen" rendered="#{not todo.completed}" styleClass="status pending"/>
|
||||||
|
</h:column>
|
||||||
|
<h:column>
|
||||||
|
<f:facet name="header">Aktionen</f:facet>
|
||||||
|
<h:link outcome="todo-form" value="Bearbeiten" styleClass="btn edit-btn">
|
||||||
|
<f:param name="id" value="#{todo.id}"/>
|
||||||
|
</h:link>
|
||||||
|
<h:form>
|
||||||
|
<h:commandLink action="#{todoBean.deleteTodo(todo.id)}" value="Löschen"
|
||||||
|
styleClass="btn delete-btn"
|
||||||
|
onclick="return confirm('Möchten Sie diese Aufgabe wirklich löschen?')"/>
|
||||||
|
<h:commandLink action="#{todoBean.completeTodo(todo.id)}" value="#{todo.completed ? 'Als offen markieren' : 'Als erledigt markieren'}"
|
||||||
|
styleClass="btn complete-btn"/>
|
||||||
|
</h:form>
|
||||||
|
</h:column>
|
||||||
|
</h:dataTable>
|
||||||
|
</div>
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
FROM mcr.microsoft.com/devcontainers/java:1-21-bullseye
|
|
||||||
|
|
||||||
ARG INSTALL_MAVEN="false"
|
|
||||||
ARG MAVEN_VERSION=""
|
|
||||||
|
|
||||||
ARG INSTALL_GRADLE="false"
|
|
||||||
ARG GRADLE_VERSION=""
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get upgrade -y && \
|
|
||||||
apt-get install -y \
|
|
||||||
git
|
|
||||||
|
|
||||||
RUN if [ "${INSTALL_MAVEN}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install maven \"${MAVEN_VERSION}\""; fi \
|
|
||||||
&& if [ "${INSTALL_GRADLE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install gradle \"${GRADLE_VERSION}\""; fi
|
|
||||||
|
|
||||||
RUN mkdir -p /workspaces/${localWorkspaceFolderBasename} && chown -R vscode:vscode /workspaces/${localWorkspaceFolderBasename}
|
|
||||||
|
|
||||||
ENTRYPOINT ["/bin/bash"]
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"name": "Jakarta EE Todo App & PostgreSQL",
|
|
||||||
"dockerComposeFile": "docker-compose.yml",
|
|
||||||
"service": "app",
|
|
||||||
"workspaceFolder": "/workspaces",
|
|
||||||
"extensions": ["vscjava.vscode-java-pack", "redhat.vscode-xml"],
|
|
||||||
"forwardPorts": [9080],
|
|
||||||
"remoteUser": "vscode"
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
version: "3.8"
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres-data:
|
|
||||||
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
container_name: javadev
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
environment:
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_DB: postgres
|
|
||||||
POSTGRES_HOSTNAME: postgresdb
|
|
||||||
volumes:
|
|
||||||
- ..:/workspace
|
|
||||||
command: sleep infinity
|
|
||||||
network_mode: service:db
|
|
||||||
stdin_open: true
|
|
||||||
|
|
||||||
db:
|
|
||||||
container_name: postgresdb
|
|
||||||
image: postgres:latest
|
|
||||||
restart: unless-stopped
|
|
||||||
volumes:
|
|
||||||
- postgres-data:/var/lib/postgresql/data
|
|
||||||
environment:
|
|
||||||
POSTGRES_PASSWORD: postgres
|
|
||||||
POSTGRES_USER: postgres
|
|
||||||
POSTGRES_DB: postgres
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<groupId>com.example</groupId>
|
|
||||||
<artifactId>jakarta-servlet-todo</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
<packaging>war</packaging>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<maven.compiler.source>11</maven.compiler.source>
|
|
||||||
<maven.compiler.target>11</maven.compiler.target>
|
|
||||||
<jakartaee.version>10.0.0</jakartaee.version>
|
|
||||||
<hibernate.version>6.0.0.Final</hibernate.version>
|
|
||||||
<postgresql.version>42.3.1</postgresql.version>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>jakarta.platform</groupId>
|
|
||||||
<artifactId>jakarta.jakartaee-api</artifactId>
|
|
||||||
<version>${jakartaee.version}</version>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate.orm</groupId>
|
|
||||||
<artifactId>hibernate-core</artifactId>
|
|
||||||
<version>${hibernate.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.postgresql</groupId>
|
|
||||||
<artifactId>postgresql</artifactId>
|
|
||||||
<version>${postgresql.version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<finalName>${project.artifactId}</finalName>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-war-plugin</artifactId>
|
|
||||||
<version>3.3.2</version>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
|
||||||
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
package com.example.dao;
|
|
||||||
|
|
||||||
import com.example.model.Todo;
|
|
||||||
import jakarta.persistence.EntityManager;
|
|
||||||
import jakarta.persistence.PersistenceContext;
|
|
||||||
import jakarta.transaction.Transactional;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class TodoDAO {
|
|
||||||
|
|
||||||
@PersistenceContext
|
|
||||||
private EntityManager em;
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void create(Todo todo) {
|
|
||||||
em.persist(todo);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Todo> findAll() {
|
|
||||||
return em.createQuery("SELECT t FROM Todo t", Todo.class).getResultList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void update(Todo todo) {
|
|
||||||
em.merge(todo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public void delete(Long id) {
|
|
||||||
Todo todo = em.find(Todo.class, id);
|
|
||||||
if (todo != null) {
|
|
||||||
em.remove(todo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
package com.example.model;
|
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "todos")
|
|
||||||
public class Todo {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
private String title;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
private boolean completed;
|
|
||||||
|
|
||||||
// Getter und Setter
|
|
||||||
public Long getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(Long id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTitle() {
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
this.title = title;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCompleted() {
|
|
||||||
return completed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCompleted(boolean completed) {
|
|
||||||
this.completed = completed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
package com.example.servlet;
|
|
||||||
|
|
||||||
import com.example.dao.TodoDAO;
|
|
||||||
import com.example.model.Todo;
|
|
||||||
import jakarta.inject.Inject;
|
|
||||||
import jakarta.servlet.ServletException;
|
|
||||||
import jakarta.servlet.annotation.WebServlet;
|
|
||||||
import jakarta.servlet.http.HttpServlet;
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@WebServlet("/todos")
|
|
||||||
public class TodoServlet extends HttpServlet {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private TodoDAO todoDAO;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
List<Todo> todos = todoDAO.findAll();
|
|
||||||
req.setAttribute("todos", todos);
|
|
||||||
req.getRequestDispatcher("/index.jsp").forward(req, resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
|
||||||
String title = req.getParameter("title");
|
|
||||||
boolean completed = "on".equals(req.getParameter("completed"));
|
|
||||||
|
|
||||||
Todo todo = new Todo();
|
|
||||||
todo.setTitle(title);
|
|
||||||
todo.setCompleted(completed);
|
|
||||||
|
|
||||||
todoDAO.create(todo);
|
|
||||||
resp.sendRedirect(req.getContextPath() + "/todos");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
<persistence xmlns="https://jakarta.ee/xml/ns/persistence"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd"
|
|
||||||
version="3.0">
|
|
||||||
|
|
||||||
<persistence-unit name="todoPU">
|
|
||||||
<class>com.example.model.Todo</class>
|
|
||||||
<properties>
|
|
||||||
<property name="jakarta.persistence.jdbc.driver" value="org.postgresql.Driver"/>
|
|
||||||
<property name="jakarta.persistence.jdbc.url" value="jdbc:postgresql://db:5432/tododb"/>
|
|
||||||
<property name="jakarta.persistence.jdbc.user" value="todouser"/>
|
|
||||||
<property name="jakarta.persistence.jdbc.password" value="todopass"/>
|
|
||||||
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
|
|
||||||
<property name="hibernate.hbm2ddl.auto" value="update"/>
|
|
||||||
</properties>
|
|
||||||
</persistence-unit>
|
|
||||||
|
|
||||||
</persistence>
|
|
||||||
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
|
|
||||||
version="4.0">
|
|
||||||
|
|
||||||
<display-name>JakartaEE Todo App</display-name>
|
|
||||||
|
|
||||||
</web-app>
|
|
||||||
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Todo App</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Todo App</h1>
|
|
||||||
|
|
||||||
<form method="post" action="todos">
|
|
||||||
<label for="title">Title:</label>
|
|
||||||
<input type="text" id="title" name="title" required />
|
|
||||||
|
|
||||||
<label for="completed">Completed:</label>
|
|
||||||
<input type="checkbox" id="completed" name="completed" />
|
|
||||||
|
|
||||||
<button type="submit">Add Todo</button>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<h2>Todos</h2>
|
|
||||||
<ul>
|
|
||||||
<%
|
|
||||||
List<com.example.model.Todo> todos = (List<com.example.model.Todo>) request.getAttribute("todos");
|
|
||||||
if (todos != null) {
|
|
||||||
for (com.example.model.Todo todo : todos) {
|
|
||||||
%>
|
|
||||||
<li><%= todo.getTitle() %> - <%= todo.isCompleted() ? "Completed" : "Pending" %></li>
|
|
||||||
<%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
%>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue