From d8e578e773de26a5ad5918da06afd57e8eacb5b0 Mon Sep 17 00:00:00 2001 From: Tamer Metin Date: Tue, 25 Mar 2025 17:44:41 +0100 Subject: [PATCH 1/4] team 2 uebung --- .../app/task/dataaccess/TaskItemEntity.java | 67 +++++++++++++++++++ .../task/dataaccess/TaskItemRepository.java | 7 ++ .../app/task/dataaccess/TaskListEntity.java | 33 +++++++++ .../task/dataaccess/TaskListRepository.java | 13 ++++ .../dataaccess/TaskItemRepositoryTest.java | 45 +++++++++++++ .../dataaccess/TaskListRepositoryTest.java | 39 +++++++++++ 6 files changed, 204 insertions(+) create mode 100644 backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java create mode 100644 backend/src/main/java/org/example/app/task/dataaccess/TaskItemRepository.java create mode 100644 backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java create mode 100644 backend/src/main/java/org/example/app/task/dataaccess/TaskListRepository.java create mode 100644 backend/src/test/java/org/example/app/task/dataaccess/TaskItemRepositoryTest.java create mode 100644 backend/src/test/java/org/example/app/task/dataaccess/TaskListRepositoryTest.java diff --git a/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java b/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java new file mode 100644 index 0000000..7a3402b --- /dev/null +++ b/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java @@ -0,0 +1,67 @@ +package org.example.app.task.dataaccess; + +import jakarta.persistence.*; +import org.example.app.general.dataaccess.ApplicationPersistenceEntity; + +import java.time.LocalDateTime; + +@Entity +@Table(name = "task_item") +public class TaskItemEntity extends ApplicationPersistenceEntity { + + @Column + private String title; + + @Column + private boolean completed; + + @Column + private boolean starred; + + @JoinColumn(name = "LIST_ID") + @ManyToOne(fetch = FetchType.LAZY) + private TaskListEntity taskListEntity; + + @Column + private LocalDateTime deadline; + + 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; + } + + public boolean isStarred() { + return starred; + } + + public void setStarred(boolean starred) { + this.starred = starred; + } + + public LocalDateTime getDeadline() { + return deadline; + } + + public void setDeadline(LocalDateTime deadline) { + this.deadline = deadline; + } + + public TaskListEntity getTaskListEntity() { + return taskListEntity; + } + + public void setTaskListEntity(TaskListEntity taskListEntity) { + this.taskListEntity = taskListEntity; + } +} diff --git a/backend/src/main/java/org/example/app/task/dataaccess/TaskItemRepository.java b/backend/src/main/java/org/example/app/task/dataaccess/TaskItemRepository.java new file mode 100644 index 0000000..7774112 --- /dev/null +++ b/backend/src/main/java/org/example/app/task/dataaccess/TaskItemRepository.java @@ -0,0 +1,7 @@ +package org.example.app.task.dataaccess; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TaskItemRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java b/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java new file mode 100644 index 0000000..805992c --- /dev/null +++ b/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java @@ -0,0 +1,33 @@ +package org.example.app.task.dataaccess; + +import jakarta.persistence.*; +import org.example.app.general.dataaccess.ApplicationPersistenceEntity; + +import java.util.List; + +@Entity +@Table(name = "task_list") +public class TaskListEntity extends ApplicationPersistenceEntity { + + @Column + private String title; + + @OneToMany(fetch = FetchType.LAZY, mappedBy = "taskListEntity") + List taskItemEntities; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getTaskItemEntities() { + return taskItemEntities; + } + + public void setTaskItemEntities(List taskItemEntities) { + this.taskItemEntities = taskItemEntities; + } +} diff --git a/backend/src/main/java/org/example/app/task/dataaccess/TaskListRepository.java b/backend/src/main/java/org/example/app/task/dataaccess/TaskListRepository.java new file mode 100644 index 0000000..777d0c7 --- /dev/null +++ b/backend/src/main/java/org/example/app/task/dataaccess/TaskListRepository.java @@ -0,0 +1,13 @@ +package org.example.app.task.dataaccess; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; + +public interface TaskListRepository extends JpaRepository { + + @Query("SELECT list FROM TaskListEntity list JOIN list.taskItemEntities items WHERE items.completed = true") + List findByCompleted(); + +} \ No newline at end of file diff --git a/backend/src/test/java/org/example/app/task/dataaccess/TaskItemRepositoryTest.java b/backend/src/test/java/org/example/app/task/dataaccess/TaskItemRepositoryTest.java new file mode 100644 index 0000000..8af3b86 --- /dev/null +++ b/backend/src/test/java/org/example/app/task/dataaccess/TaskItemRepositoryTest.java @@ -0,0 +1,45 @@ +package org.example.app.task.dataaccess; + +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@QuarkusTest +public class TaskItemRepositoryTest extends Assertions { + + @Inject + private TaskItemRepository taskItemRepository; + + @Test + public void testFindById() { + + // given + Long itemId = 111L; + + // when + TaskItemEntity item = this.taskItemRepository.findById(itemId).get(); + + // then + assertThat(item.getTitle()).isEqualTo("Milk"); + } + + @Test + public void testSave() { + + // given + TaskItemEntity entity = new TaskItemEntity(); + entity.setTitle("title"); + entity.setVersion(0); + + // when + TaskItemEntity savedItem = this.taskItemRepository.save(entity); + + // then + assertThat(savedItem.getId()).isEqualTo(1000000L); + assertThat(savedItem.getVersion()).isNotNull(); + } + +} \ No newline at end of file diff --git a/backend/src/test/java/org/example/app/task/dataaccess/TaskListRepositoryTest.java b/backend/src/test/java/org/example/app/task/dataaccess/TaskListRepositoryTest.java new file mode 100644 index 0000000..ec9f8e8 --- /dev/null +++ b/backend/src/test/java/org/example/app/task/dataaccess/TaskListRepositoryTest.java @@ -0,0 +1,39 @@ +package org.example.app.task.dataaccess; + +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@QuarkusTest +public class TaskListRepositoryTest extends Assertions { + + @Inject + private TaskListRepository taskListRepository; + + @Test + public void testLoadAllTasklists() { + // when + List items = this.taskListRepository.findAll(); + + // then + assertThat(items).isNotEmpty().hasSize(4); + } + + @Test + public void testFindCompletedLists() { + // when + List items = this.taskListRepository.findByCompleted(); + + // then + assertThat(items).isNotEmpty(); + } + + + + +} \ No newline at end of file From 334ad56bf535c1acfa9000fb3a01e51830ac487c Mon Sep 17 00:00:00 2001 From: Tamer Metin Date: Wed, 26 Mar 2025 10:47:45 +0100 Subject: [PATCH 2/4] Logic layer --- .../org/example/app/task/common/TaskItem.java | 6 ++ .../org/example/app/task/common/TaskList.java | 6 ++ .../app/task/dataaccess/TaskItemEntity.java | 3 +- .../app/task/dataaccess/TaskListEntity.java | 3 +- .../example/app/task/logic/TaskItemEto.java | 60 +++++++++++++++++++ .../app/task/logic/TaskItemMapper.java | 24 ++++++++ .../example/app/task/logic/TaskListEto.java | 30 ++++++++++ .../app/task/logic/TaskListMapper.java | 12 ++++ .../app/task/logic/UcDeleteTaskItem.java | 21 +++++++ .../app/task/logic/UcDeleteTaskList.java | 21 +++++++ .../app/task/logic/UcFindTaskItem.java | 27 +++++++++ .../app/task/logic/UcFindTaskList.java | 27 +++++++++ .../app/task/logic/UcSaveTaskItem.java | 25 ++++++++ .../app/task/logic/UcSaveTaskList.java | 25 ++++++++ 14 files changed, 288 insertions(+), 2 deletions(-) create mode 100644 backend/src/main/java/org/example/app/task/common/TaskItem.java create mode 100644 backend/src/main/java/org/example/app/task/common/TaskList.java create mode 100644 backend/src/main/java/org/example/app/task/logic/TaskItemEto.java create mode 100644 backend/src/main/java/org/example/app/task/logic/TaskItemMapper.java create mode 100644 backend/src/main/java/org/example/app/task/logic/TaskListEto.java create mode 100644 backend/src/main/java/org/example/app/task/logic/TaskListMapper.java create mode 100644 backend/src/main/java/org/example/app/task/logic/UcDeleteTaskItem.java create mode 100644 backend/src/main/java/org/example/app/task/logic/UcDeleteTaskList.java create mode 100644 backend/src/main/java/org/example/app/task/logic/UcFindTaskItem.java create mode 100644 backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java create mode 100644 backend/src/main/java/org/example/app/task/logic/UcSaveTaskItem.java create mode 100644 backend/src/main/java/org/example/app/task/logic/UcSaveTaskList.java diff --git a/backend/src/main/java/org/example/app/task/common/TaskItem.java b/backend/src/main/java/org/example/app/task/common/TaskItem.java new file mode 100644 index 0000000..7f24ff5 --- /dev/null +++ b/backend/src/main/java/org/example/app/task/common/TaskItem.java @@ -0,0 +1,6 @@ +package org.example.app.task.common; + +import org.example.app.general.common.ApplicationEntity; + +public interface TaskItem extends ApplicationEntity { +} diff --git a/backend/src/main/java/org/example/app/task/common/TaskList.java b/backend/src/main/java/org/example/app/task/common/TaskList.java new file mode 100644 index 0000000..de1e24e --- /dev/null +++ b/backend/src/main/java/org/example/app/task/common/TaskList.java @@ -0,0 +1,6 @@ +package org.example.app.task.common; + +import org.example.app.general.common.ApplicationEntity; + +public interface TaskList extends ApplicationEntity { +} diff --git a/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java b/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java index 7a3402b..3f8a089 100644 --- a/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java +++ b/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java @@ -2,12 +2,13 @@ import jakarta.persistence.*; import org.example.app.general.dataaccess.ApplicationPersistenceEntity; +import org.example.app.task.common.TaskItem; import java.time.LocalDateTime; @Entity @Table(name = "task_item") -public class TaskItemEntity extends ApplicationPersistenceEntity { +public class TaskItemEntity extends ApplicationPersistenceEntity implements TaskItem { @Column private String title; diff --git a/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java b/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java index 805992c..043c8b3 100644 --- a/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java +++ b/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java @@ -2,12 +2,13 @@ import jakarta.persistence.*; import org.example.app.general.dataaccess.ApplicationPersistenceEntity; +import org.example.app.task.common.TaskList; import java.util.List; @Entity @Table(name = "task_list") -public class TaskListEntity extends ApplicationPersistenceEntity { +public class TaskListEntity extends ApplicationPersistenceEntity implements TaskList { @Column private String title; diff --git a/backend/src/main/java/org/example/app/task/logic/TaskItemEto.java b/backend/src/main/java/org/example/app/task/logic/TaskItemEto.java new file mode 100644 index 0000000..0a21343 --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/TaskItemEto.java @@ -0,0 +1,60 @@ +package org.example.app.task.logic; + +import org.example.app.general.common.AbstractEto; +import org.example.app.task.common.TaskItem; +import org.example.app.task.dataaccess.TaskListEntity; + +import java.time.LocalDateTime; + +public class TaskItemEto extends AbstractEto implements TaskItem { + + private String title; + + private boolean completed; + + private boolean starred; + + private TaskListEntity taskListEntity; + + private LocalDateTime deadline; + + 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; + } + + public boolean isStarred() { + return starred; + } + + public void setStarred(boolean starred) { + this.starred = starred; + } + + public LocalDateTime getDeadline() { + return deadline; + } + + public void setDeadline(LocalDateTime deadline) { + this.deadline = deadline; + } + + public TaskListEntity getTaskListEntity() { + return taskListEntity; + } + + public void setTaskListEntity(TaskListEntity taskListEntity) { + this.taskListEntity = taskListEntity; + } +} diff --git a/backend/src/main/java/org/example/app/task/logic/TaskItemMapper.java b/backend/src/main/java/org/example/app/task/logic/TaskItemMapper.java new file mode 100644 index 0000000..eedb2ed --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/TaskItemMapper.java @@ -0,0 +1,24 @@ +package org.example.app.task.logic; + +import org.example.app.task.dataaccess.TaskItemEntity; +import org.mapstruct.Mapper; + +import java.util.ArrayList; +import java.util.List; + +@Mapper(componentModel = "cdi") +public interface TaskItemMapper { + + default List toEtos(List items) { + List result = new ArrayList<>(); + for (TaskItemEntity item : items) { + result.add(toEto(item)); + } + + return result; + } + + TaskItemEto toEto(TaskItemEntity item); + + TaskItemEntity toEntity(TaskItemEto item); +} diff --git a/backend/src/main/java/org/example/app/task/logic/TaskListEto.java b/backend/src/main/java/org/example/app/task/logic/TaskListEto.java new file mode 100644 index 0000000..dcfe1ed --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/TaskListEto.java @@ -0,0 +1,30 @@ +package org.example.app.task.logic; + +import org.example.app.general.common.AbstractEto; +import org.example.app.task.common.TaskList; +import org.example.app.task.dataaccess.TaskItemEntity; + +import java.util.List; + +public class TaskListEto extends AbstractEto implements TaskList { + + private String title; + + List taskItemEntities; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getTaskItemEntities() { + return taskItemEntities; + } + + public void setTaskItemEntities(List taskItemEntities) { + this.taskItemEntities = taskItemEntities; + } +} diff --git a/backend/src/main/java/org/example/app/task/logic/TaskListMapper.java b/backend/src/main/java/org/example/app/task/logic/TaskListMapper.java new file mode 100644 index 0000000..d786752 --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/TaskListMapper.java @@ -0,0 +1,12 @@ +package org.example.app.task.logic; + +import org.example.app.task.dataaccess.TaskListEntity; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "cdi") +public interface TaskListMapper { + + TaskListEto toEto(TaskListEntity item); + + TaskListEntity toEntity(TaskListEto item); +} diff --git a/backend/src/main/java/org/example/app/task/logic/UcDeleteTaskItem.java b/backend/src/main/java/org/example/app/task/logic/UcDeleteTaskItem.java new file mode 100644 index 0000000..b5b909f --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/UcDeleteTaskItem.java @@ -0,0 +1,21 @@ +package org.example.app.task.logic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.transaction.Transactional; +import org.example.app.task.dataaccess.TaskItemRepository; + +@ApplicationScoped +@Named +@Transactional +public class UcDeleteTaskItem { + + @Inject + TaskItemRepository taskItemRepository; + + + public void deleteById(Long itemId) { + this.taskItemRepository.deleteById(itemId); + } +} diff --git a/backend/src/main/java/org/example/app/task/logic/UcDeleteTaskList.java b/backend/src/main/java/org/example/app/task/logic/UcDeleteTaskList.java new file mode 100644 index 0000000..5ede7f6 --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/UcDeleteTaskList.java @@ -0,0 +1,21 @@ +package org.example.app.task.logic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.transaction.Transactional; +import org.example.app.task.dataaccess.TaskListRepository; + +@ApplicationScoped +@Named +@Transactional +public class UcDeleteTaskList { + + @Inject + TaskListRepository taskListRepository; + + + public void deleteById(Long itemId) { + this.taskListRepository.deleteById(itemId); + } +} diff --git a/backend/src/main/java/org/example/app/task/logic/UcFindTaskItem.java b/backend/src/main/java/org/example/app/task/logic/UcFindTaskItem.java new file mode 100644 index 0000000..12c0b55 --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/UcFindTaskItem.java @@ -0,0 +1,27 @@ +package org.example.app.task.logic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.transaction.Transactional; +import org.example.app.task.dataaccess.TaskItemEntity; +import org.example.app.task.dataaccess.TaskItemRepository; + +import java.util.Optional; + +@ApplicationScoped +@Named +@Transactional +public class UcFindTaskItem { + + @Inject + TaskItemRepository taskItemRepository; + + @Inject + TaskItemMapper taskItemMapper; + + public TaskItemEto findById(Long itemId) { + Optional item = this.taskItemRepository.findById(itemId); + return item.map(ety -> this.taskItemMapper.toEto(ety)).orElse(null); + } +} diff --git a/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java b/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java new file mode 100644 index 0000000..7b7b69d --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java @@ -0,0 +1,27 @@ +package org.example.app.task.logic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.transaction.Transactional; +import org.example.app.task.dataaccess.TaskListEntity; +import org.example.app.task.dataaccess.TaskListRepository; + +import java.util.Optional; + +@ApplicationScoped +@Named +@Transactional +public class UcFindTaskList { + + @Inject + TaskListRepository taskListRepository; + + @Inject + TaskListMapper taskListMapper; + + public TaskListEto findById(Long itemId) { + Optional item = this.taskListRepository.findById(itemId); + return item.map(ety -> this.taskListMapper.toEto(ety)).orElse(null); + } +} diff --git a/backend/src/main/java/org/example/app/task/logic/UcSaveTaskItem.java b/backend/src/main/java/org/example/app/task/logic/UcSaveTaskItem.java new file mode 100644 index 0000000..ca489df --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/UcSaveTaskItem.java @@ -0,0 +1,25 @@ +package org.example.app.task.logic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.transaction.Transactional; +import org.example.app.task.dataaccess.TaskItemEntity; +import org.example.app.task.dataaccess.TaskItemRepository; + +@ApplicationScoped +@Named +@Transactional +public class UcSaveTaskItem { + + @Inject + TaskItemRepository taskItemRepository; + + @Inject + TaskItemMapper taskItemMapper; + + public void save(TaskItemEto taskItemEto) { + TaskItemEntity taskItemEntity = this.taskItemMapper.toEntity(taskItemEto); + this.taskItemRepository.save(taskItemEntity); + } +} diff --git a/backend/src/main/java/org/example/app/task/logic/UcSaveTaskList.java b/backend/src/main/java/org/example/app/task/logic/UcSaveTaskList.java new file mode 100644 index 0000000..766628c --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/UcSaveTaskList.java @@ -0,0 +1,25 @@ +package org.example.app.task.logic; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; +import jakarta.transaction.Transactional; +import org.example.app.task.dataaccess.TaskListEntity; +import org.example.app.task.dataaccess.TaskListRepository; + +@ApplicationScoped +@Named +@Transactional +public class UcSaveTaskList { + + @Inject + TaskListRepository taskListRepository; + + @Inject + TaskListMapper taskListMapper; + + public void save(TaskListEto taskListEto) { + TaskListEntity taskListEntity = this.taskListMapper.toEntity(taskListEto); + this.taskListRepository.save(taskListEntity); + } +} From 478169d731ca3e995f89acd16f879eecff04fa79 Mon Sep 17 00:00:00 2001 From: Ostrovskiy Date: Wed, 26 Mar 2025 12:55:53 +0100 Subject: [PATCH 3/4] Working on service assignement --- .../org/example/app/task/common/TaskItem.java | 52 ++++ .../org/example/app/task/common/TaskList.java | 12 + .../app/task/dataaccess/TaskItemEntity.java | 38 ++- .../app/task/dataaccess/TaskListEntity.java | 20 +- .../example/app/task/logic/TaskItemEto.java | 48 ++-- .../example/app/task/logic/TaskListCto.java | 50 ++++ .../example/app/task/logic/TaskListEto.java | 12 +- .../app/task/logic/UcFindTaskList.java | 16 ++ .../example/app/task/service/TaskService.java | 111 ++++++++ .../src/main/resources/META-INF/openapi.yaml | 248 ------------------ .../src/main/resources/application.properties | 14 + .../dataaccess/TaskItemRepositoryTest.java | 2 +- 12 files changed, 334 insertions(+), 289 deletions(-) create mode 100644 backend/src/main/java/org/example/app/task/logic/TaskListCto.java create mode 100644 backend/src/main/java/org/example/app/task/service/TaskService.java delete mode 100644 backend/src/main/resources/META-INF/openapi.yaml diff --git a/backend/src/main/java/org/example/app/task/common/TaskItem.java b/backend/src/main/java/org/example/app/task/common/TaskItem.java index 7f24ff5..5533528 100644 --- a/backend/src/main/java/org/example/app/task/common/TaskItem.java +++ b/backend/src/main/java/org/example/app/task/common/TaskItem.java @@ -2,5 +2,57 @@ import org.example.app.general.common.ApplicationEntity; +import java.time.LocalDateTime; + public interface TaskItem extends ApplicationEntity { + + /** + * @return the title of this task item. Gives a brief summary to describe what to do or buy. + */ + String getTitle(); + + /** + * @param title new value of {@link #getTitle()}. + */ + void setTitle(String title); + + /** + * @return {@code true} if this task is completed (done), {@code false} otherwise. + */ + boolean isCompleted(); + + /** + * @param completed new value of {@link #isCompleted()}. + */ + void setCompleted(boolean completed); + + /** + * @return {@code true} if this task is starred (marked as favorite), {@code false} otherwise. + */ + boolean isStarred(); + + /** + * @param starred new value of {@link #isStarred()}. + */ + void setStarred(boolean starred); + + /** + * @return the deadline as until this task shall be {@link #isCompleted() completed}. + */ + LocalDateTime getDeadline(); + + /** + * @param deadline the new value of {@link #getDeadline()}. + */ + void setDeadline(LocalDateTime deadline); + + /** + * @return the {@link TaskList#getId() primary key} of the owning {@link TaskList}. + */ + Long getTaskListId(); + + /** + * @param taskListId the new value of {@link #getTaskListId()}. + */ + void setTaskListId(Long taskListId); } diff --git a/backend/src/main/java/org/example/app/task/common/TaskList.java b/backend/src/main/java/org/example/app/task/common/TaskList.java index de1e24e..74cb341 100644 --- a/backend/src/main/java/org/example/app/task/common/TaskList.java +++ b/backend/src/main/java/org/example/app/task/common/TaskList.java @@ -3,4 +3,16 @@ import org.example.app.general.common.ApplicationEntity; public interface TaskList extends ApplicationEntity { + + /** + * @return the title of this {@link TaskList}. Gives a brief summary to describe this list of tasks (e.g. "Shopping + * list", "Packing list" or "Things to buy at construction market"). + */ + String getTitle(); + + /** + * @param title new value of {@link #getTitle()}. + */ + void setTitle(String title); } + diff --git a/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java b/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java index 3f8a089..5a9dd69 100644 --- a/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java +++ b/backend/src/main/java/org/example/app/task/dataaccess/TaskItemEntity.java @@ -25,39 +25,61 @@ public class TaskItemEntity extends ApplicationPersistenceEntity implements Task @Column private LocalDateTime deadline; - + @Override public String getTitle() { return title; } - + @Override public void setTitle(String title) { this.title = title; } - + @Override public boolean isCompleted() { return completed; } - + @Override public void setCompleted(boolean completed) { this.completed = completed; } - + @Override public boolean isStarred() { return starred; } - + @Override public void setStarred(boolean starred) { this.starred = starred; } - + @Override public LocalDateTime getDeadline() { return deadline; } - + @Override public void setDeadline(LocalDateTime deadline) { this.deadline = deadline; } + @Override + public Long getTaskListId() { + + if (this.taskListEntity == null) { + return null; + } + return this.taskListEntity.getId(); + } + + @Override + public void setTaskListId(Long taskListId) { + + if (taskListId == null) { + this.taskListEntity = null; + } else { + TaskListEntity taskListEntity = new TaskListEntity(); + taskListEntity.setId(taskListId); + taskListEntity.setVersion(Integer.valueOf(0)); + this.taskListEntity = taskListEntity; + } + } + public TaskListEntity getTaskListEntity() { return taskListEntity; } diff --git a/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java b/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java index 043c8b3..7af1446 100644 --- a/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java +++ b/backend/src/main/java/org/example/app/task/dataaccess/TaskListEntity.java @@ -15,15 +15,31 @@ public class TaskListEntity extends ApplicationPersistenceEntity implements Task @OneToMany(fetch = FetchType.LAZY, mappedBy = "taskListEntity") List taskItemEntities; - + @Override public String getTitle() { return title; } - + @Override public void setTitle(String title) { this.title = title; } + /** + * @return the {@link List} of {@link TaskItemEntity task-items} in this task-list. + */ + public List getItems() { + + return this.taskItemEntities; + } + + /** + * @param taskItems the new value of {@link #getItems()}. + */ + public void setItems(List taskItems) { + + this.taskItemEntities = taskItems; + } + public List getTaskItemEntities() { return taskItemEntities; } diff --git a/backend/src/main/java/org/example/app/task/logic/TaskItemEto.java b/backend/src/main/java/org/example/app/task/logic/TaskItemEto.java index 0a21343..1ef2dbc 100644 --- a/backend/src/main/java/org/example/app/task/logic/TaskItemEto.java +++ b/backend/src/main/java/org/example/app/task/logic/TaskItemEto.java @@ -1,60 +1,68 @@ package org.example.app.task.logic; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import org.eclipse.microprofile.openapi.annotations.media.Schema; import org.example.app.general.common.AbstractEto; import org.example.app.task.common.TaskItem; import org.example.app.task.dataaccess.TaskListEntity; import java.time.LocalDateTime; - +@Schema(name = "TaskItem", description = "Object that represents a task item") public class TaskItemEto extends AbstractEto implements TaskItem { - + @NotBlank(message = "A task item must always have a title") + @Schema(required = true, example = "Buy eggs", description = "The task title or description") private String title; - + @Schema(required = false, description = "Until when the task must be completed") private boolean completed; - + @Schema(required = false, description = "Until when the task must be completed") private boolean starred; - private TaskListEntity taskListEntity; - + @Min(value = 1, message = "A task item must always be associated with a task list") + @NotNull(message = "A task item must always be associated with a task list") + @Schema(required = true, example = "1", description = "The id of the task list to which this item belongs") + private Long taskListId; + @Schema(required = false, description = "Until when the task must be completed") private LocalDateTime deadline; - + @Override public String getTitle() { return title; } - + @Override public void setTitle(String title) { this.title = title; } - + @Override public boolean isCompleted() { return completed; } - + @Override public void setCompleted(boolean completed) { this.completed = completed; } - + @Override public boolean isStarred() { return starred; } - + @Override public void setStarred(boolean starred) { this.starred = starred; } - + @Override public LocalDateTime getDeadline() { return deadline; } - + @Override public void setDeadline(LocalDateTime deadline) { this.deadline = deadline; } - - public TaskListEntity getTaskListEntity() { - return taskListEntity; + @Override + public Long getTaskListId() { + return taskListId; } - - public void setTaskListEntity(TaskListEntity taskListEntity) { - this.taskListEntity = taskListEntity; + @Override + public void setTaskListId(Long id) { + this.taskListId = id; } } diff --git a/backend/src/main/java/org/example/app/task/logic/TaskListCto.java b/backend/src/main/java/org/example/app/task/logic/TaskListCto.java new file mode 100644 index 0000000..ae617a9 --- /dev/null +++ b/backend/src/main/java/org/example/app/task/logic/TaskListCto.java @@ -0,0 +1,50 @@ +package org.example.app.task.logic; + +import java.util.List; + +public class TaskListCto { + private TaskListEto list; + + private List items; + + /** + * The constructor. + */ + public TaskListCto() { + + super(); + } + + /** + * @return the {@link TaskListEto}. + */ + public TaskListEto getList() { + + return this.list; + } + + /** + * @param taskListEto new value of {@link #getList()}. + */ + public void setList(TaskListEto taskListEto) { + + this.list = taskListEto; + } + + /** + * @return the {@link List} of {@link TaskItemEto items} contained in the #get. + */ + public List getItems() { + + return this.items; + } + + /** + * @param items new value of {@link #getItems()}. + */ + public void setItems(List items) { + + this.items = items; + } + +} diff --git a/backend/src/main/java/org/example/app/task/logic/TaskListEto.java b/backend/src/main/java/org/example/app/task/logic/TaskListEto.java index dcfe1ed..7ccf2cf 100644 --- a/backend/src/main/java/org/example/app/task/logic/TaskListEto.java +++ b/backend/src/main/java/org/example/app/task/logic/TaskListEto.java @@ -10,21 +10,13 @@ public class TaskListEto extends AbstractEto implements TaskList { private String title; - List taskItemEntities; - + @Override public String getTitle() { return title; } - + @Override public void setTitle(String title) { this.title = title; } - public List getTaskItemEntities() { - return taskItemEntities; - } - - public void setTaskItemEntities(List taskItemEntities) { - this.taskItemEntities = taskItemEntities; - } } diff --git a/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java b/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java index 7b7b69d..1e356cf 100644 --- a/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java +++ b/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java @@ -19,9 +19,25 @@ public class UcFindTaskList { @Inject TaskListMapper taskListMapper; + @Inject + TaskItemMapper taskItemMapper; + public TaskListEto findById(Long itemId) { Optional item = this.taskListRepository.findById(itemId); return item.map(ety -> this.taskListMapper.toEto(ety)).orElse(null); } + + + public TaskListCto findTaskListWithItems(Long listId) { + Optional taskList = this.taskListRepository.findById(listId); + if (taskList.isEmpty()) { + return null; + } + TaskListCto cto = new TaskListCto(); + TaskListEntity taskListEntity = taskList.get(); + cto.setList(this.taskListMapper.toEto(taskListEntity)); + cto.setItems(this.taskItemMapper.toEtos(taskListEntity.getItems())); + return cto; + } } diff --git a/backend/src/main/java/org/example/app/task/service/TaskService.java b/backend/src/main/java/org/example/app/task/service/TaskService.java new file mode 100644 index 0000000..956607d --- /dev/null +++ b/backend/src/main/java/org/example/app/task/service/TaskService.java @@ -0,0 +1,111 @@ +package org.example.app.task.service; + +import io.quarkus.runtime.Application; +import jakarta.inject.Inject; +import jakarta.ws.rs.*; +import jakarta.ws.rs.core.MediaType; +import org.eclipse.microprofile.openapi.annotations.Operation; +import org.eclipse.microprofile.openapi.annotations.enums.SchemaType; +import org.eclipse.microprofile.openapi.annotations.media.Content; +import org.eclipse.microprofile.openapi.annotations.media.Schema; +import org.eclipse.microprofile.openapi.annotations.parameters.Parameter; +import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; +import org.example.app.task.logic.*; + + +import java.util.NoSuchElementException; + +@Path("/task") +public class TaskService { + + @Inject + private UcFindTaskItem ucFindTaskItem; + + @Inject + private UcFindTaskList ucFindTaskList; + + @Inject + private UcDeleteTaskItem ucDeleteTaskItem; + + @Inject + private UcDeleteTaskList ucDeleteTaskList; + + @Inject + private UcSaveTaskItem ucSaveTaskItem; + + @Inject + private UcSaveTaskList ucSaveTaskList; + + @GET + @Path("/item/{id}") + @Produces(MediaType.APPLICATION_JSON) + @Operation(summary = "Retrieve task item", description = "JSUT SOME DESCRIPTION") + @APIResponse(responseCode = "200", description = "Task Item!", content = @Content(mediaType + = MediaType.APPLICATION_JSON, schema = @Schema(implementation = TaskItemEto.class))) + @APIResponse(responseCode = "404", description = "NOT FOUND!") + @APIResponse(responseCode = "500", description = "SERVER ERROR!!!!!!!") + public TaskItemEto fetchTaskItem(@Parameter(description = "Task item id as paramSeter!", required = true, example = "2", schema + = @Schema(type = SchemaType.INTEGER)) @PathParam("id") Long id) { + TaskItemEto eto = this.ucFindTaskItem.findById(id); + if(eto==null) { + throw new NoSuchElementException(); + } + return eto; + } + + @GET + @Path("/list/{id}") + public TaskListEto fetchTaskList(@PathParam("id") Long id) { + TaskListEto eto = this.ucFindTaskList.findById(id); + if(eto==null) { + throw new NoSuchElementException(); + } + return eto; + } + + + @DELETE + @Path("/item/{id}") + @Produces(MediaType.APPLICATION_JSON) + public void deleteTaskItem(@PathParam("id") Long id) { + this.ucDeleteTaskItem.deleteById(id); + } + + @DELETE + @Path("/list/{id}") + @Produces(MediaType.APPLICATION_JSON) + public void deleteTaskList(@PathParam("id") Long id) { + this.ucDeleteTaskList.deleteById(id); + } + + + @POST + @Path("/item") + @Produces(MediaType.APPLICATION_JSON) + public void addOrUpdateTaskItem(TaskItemEto taskItemEto) { + this.ucSaveTaskItem.save(taskItemEto); + } + + @POST + @Path("/list") + @Produces(MediaType.APPLICATION_JSON) + public void addOrUpdateTaskList(TaskListEto taskListEto) { + this.ucSaveTaskList.save(taskListEto); + } +/** + @GET + @Path("/list-with-items/{id}") + public TaskListCto fetchTaskListWithItems(@PathParam("id") Long id) { + TaskListCto cto = this.ucFindTaskList.findTaskListWithItems(id); + if(cto==null) { + throw new NoSuchElementException(); + } + return cto; + } + + */ + + + + +} diff --git a/backend/src/main/resources/META-INF/openapi.yaml b/backend/src/main/resources/META-INF/openapi.yaml deleted file mode 100644 index d193f24..0000000 --- a/backend/src/main/resources/META-INF/openapi.yaml +++ /dev/null @@ -1,248 +0,0 @@ ---- -openapi: 3.0.3 -info: - title: Task API - description: A service to manage tasks - contact: - name: Task API Support - url: http://exampleurl.com/contact - email: techsupport@example.com - version: 1.0.0 -servers: -- url: http://localhost:8080 - description: Auto generated value -- url: http://0.0.0.0:8080 - description: Auto generated value -paths: - /task/item: - post: - tags: - - Task Service - summary: Add or update task item - description: Update a task item or add it as a new item if the id is empty - operationId: saveTaskItem - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TaskItem' - responses: - "200": - description: Task successfully updated - "201": - description: Task successfully created - "400": - description: Validation error - "500": - description: Server unavailable or a server-side error occurred - /task/item/{id}: - get: - tags: - - Task Service - summary: Fetch task item - description: Fetch a task item - operationId: findTaskItem - parameters: - - name: id - in: path - description: The id of the task item to retrieve - required: true - schema: - type: integer - example: 1 - responses: - "200": - description: Task item - content: - application/json: - schema: - $ref: '#/components/schemas/TaskItem' - "404": - description: Task item not found - "500": - description: Server unavailable or a server-side error occurred - delete: - tags: - - Task Service - summary: Delete task item - description: Delete a task item - operationId: deleteTaskItem - parameters: - - name: id - in: path - description: The id of the task item to delete - required: true - schema: - type: integer - example: 1 - responses: - "204": - description: Task list deleted - "500": - description: Server unavailable or a server-side error occurred - /task/list: - post: - tags: - - Task Service - summary: Create or update task list - description: Update a task list or creates a new one if the id is empty. - operationId: saveTask - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/TaskList' - responses: - "200": - description: Task list successfully updated - "201": - description: Task list successfully created - "400": - description: Validation error - "500": - description: Server unavailable or a server-side error occurred - /task/list-with-items/{id}: - get: - tags: - - Task Service - summary: Fetch task list with tasks - description: Fetch a task list including all of its task items - operationId: findTaskListWithItems - parameters: - - name: id - in: path - description: The id of the task list to retrieve - required: true - schema: - type: integer - example: 1 - responses: - "200": - description: Task list with task items - content: - application/json: - schema: - $ref: '#/components/schemas/TaskListWithItems' - "404": - description: Task list not found - "500": - description: Server unavailable or a server-side error occurred - /task/list/{id}: - get: - tags: - - Task Service - summary: Fetch task list - description: Fetch a task list - operationId: findTaskList - parameters: - - name: id - in: path - description: The id of the task list to retrieve - required: true - schema: - type: integer - example: 1 - responses: - "200": - description: Task list - content: - application/json: - schema: - $ref: '#/components/schemas/TaskList' - "404": - description: Task list not found - "500": - description: Server unavailable or a server-side error occurred - delete: - tags: - - Task Service - summary: Delete task list - description: Deletes an entire task list - operationId: deleteTaskList - parameters: - - name: id - in: path - description: The id of the task list to delete - required: true - schema: - type: integer - example: 1 - responses: - "204": - description: Task list deleted - "201": - description: Task list successfully created - "500": - description: Server unavailable or a server-side error occurred -components: - schemas: - LocalDateTime: - format: date-time - type: string - example: 2022-03-10T12:15:50 - TaskItem: - description: Object that represents a task item - required: - - title - - taskListId - type: object - properties: - id: - format: int64 - type: integer - version: - format: int32 - type: integer - title: - description: The task title or description - pattern: \S - type: string - example: Buy eggs - completed: - description: Whether or not the task is completed - type: boolean - example: false - starred: - description: Whether or not the task has been starred - type: boolean - example: false - taskListId: - format: int64 - description: The id of the task list to which this item belongs - minimum: 1 - type: integer - example: 1 - deadline: - allOf: - - $ref: '#/components/schemas/LocalDateTime' - - description: Until when the task must be completed - TaskList: - description: Object that represents a task list - required: - - title - type: object - properties: - id: - format: int64 - type: integer - version: - format: int32 - type: integer - title: - description: Title of the task list - pattern: \S - type: string - example: Shopping list - TaskListWithItems: - description: Object that represents a task list and its task items - required: - - list - - items - type: object - properties: - list: - $ref: '#/components/schemas/TaskList' - items: - type: array - items: - $ref: '#/components/schemas/TaskItem' diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index ac74aad..f2f4ee4 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -21,5 +21,19 @@ quarkus.http.cors.methods=GET, POST, OPTIONS, DELETE quarkus.rest-client.bored-api.url=https://www.boredapi.com/api/ +# OpenAPI +quarkus.smallrye-openapi.info-title=Task API +%dev.quarkus.smallrye-openapi.info-title=Task API (development) +%test.quarkus.smallrye-openapi.info-title=Task API (test) +quarkus.smallrye-openapi.info-version=1.0.0 +quarkus.smallrye-openapi.info-description=A service to manage tasks +quarkus.smallrye-openapi.info-contact-email=techsupport@example.com +quarkus.smallrye-openapi.info-contact-name=Task API Support +quarkus.smallrye-openapi.info-contact-url=http://exampleurl.com/contact +quarkus.smallrye-openapi.operation-id-strategy=method + +# Generate OpenAPI spec at build-time (can be grabbed and published in schema repository by CI process) +quarkus.smallrye-openapi.store-schema-directory=target/openapi + diff --git a/backend/src/test/java/org/example/app/task/dataaccess/TaskItemRepositoryTest.java b/backend/src/test/java/org/example/app/task/dataaccess/TaskItemRepositoryTest.java index 8af3b86..215b47d 100644 --- a/backend/src/test/java/org/example/app/task/dataaccess/TaskItemRepositoryTest.java +++ b/backend/src/test/java/org/example/app/task/dataaccess/TaskItemRepositoryTest.java @@ -17,7 +17,7 @@ public class TaskItemRepositoryTest extends Assertions { public void testFindById() { // given - Long itemId = 111L; + Long itemId = 11L; // when TaskItemEntity item = this.taskItemRepository.findById(itemId).get(); From fe1015fb754465610f2d393ff716d3a640ade3b3 Mon Sep 17 00:00:00 2001 From: Tamer Metin Date: Thu, 27 Mar 2025 12:00:55 +0100 Subject: [PATCH 4/4] Logic layer --- backend/pom.xml | 12 ++--- .../app/task/logic/TaskItemMapper.java | 48 +++++++++---------- .../app/task/logic/TaskListMapper.java | 4 ++ .../app/task/logic/UcFindTaskList.java | 7 +++ .../example/app/task/service/TaskService.java | 11 +++++ 5 files changed, 49 insertions(+), 33 deletions(-) diff --git a/backend/pom.xml b/backend/pom.xml index ed1fd00..a75708c 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -1,5 +1,6 @@ - + 4.0.0 org.example @@ -8,9 +9,6 @@ app quarkus-demo-app-backend - @@ -95,12 +93,10 @@ com.querydsl querydsl-apt - provided ${querydsl.version} jakarta + provided - - io.quarkus quarkus-junit5 @@ -207,7 +203,6 @@ org.jboss.logmanager.LogManager - ${maven.home} @@ -225,7 +220,6 @@ ${project.build.directory}/${project.build.finalName}-runner org.jboss.logmanager.LogManager - ${maven.home} diff --git a/backend/src/main/java/org/example/app/task/logic/TaskItemMapper.java b/backend/src/main/java/org/example/app/task/logic/TaskItemMapper.java index eedb2ed..734273c 100644 --- a/backend/src/main/java/org/example/app/task/logic/TaskItemMapper.java +++ b/backend/src/main/java/org/example/app/task/logic/TaskItemMapper.java @@ -1,24 +1,24 @@ -package org.example.app.task.logic; - -import org.example.app.task.dataaccess.TaskItemEntity; -import org.mapstruct.Mapper; - -import java.util.ArrayList; -import java.util.List; - -@Mapper(componentModel = "cdi") -public interface TaskItemMapper { - - default List toEtos(List items) { - List result = new ArrayList<>(); - for (TaskItemEntity item : items) { - result.add(toEto(item)); - } - - return result; - } - - TaskItemEto toEto(TaskItemEntity item); - - TaskItemEntity toEntity(TaskItemEto item); -} +package org.example.app.task.logic; + +import org.example.app.task.dataaccess.TaskItemEntity; +import org.mapstruct.Mapper; + +import java.util.ArrayList; +import java.util.List; + +@Mapper(componentModel = "cdi") +public interface TaskItemMapper { + + default List toEtos(List items) { + List result = new ArrayList<>(); + for (TaskItemEntity item : items) { + result.add(toEto(item)); + } + + return result; + } + + TaskItemEto toEto(TaskItemEntity item); + + TaskItemEntity toEntity(TaskItemEto item); +} diff --git a/backend/src/main/java/org/example/app/task/logic/TaskListMapper.java b/backend/src/main/java/org/example/app/task/logic/TaskListMapper.java index d786752..1745014 100644 --- a/backend/src/main/java/org/example/app/task/logic/TaskListMapper.java +++ b/backend/src/main/java/org/example/app/task/logic/TaskListMapper.java @@ -3,9 +3,13 @@ import org.example.app.task.dataaccess.TaskListEntity; import org.mapstruct.Mapper; +import java.util.List; + @Mapper(componentModel = "cdi") public interface TaskListMapper { + List toEtos(List item); + TaskListEto toEto(TaskListEntity item); TaskListEntity toEntity(TaskListEto item); diff --git a/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java b/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java index 1e356cf..19b34f7 100644 --- a/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java +++ b/backend/src/main/java/org/example/app/task/logic/UcFindTaskList.java @@ -7,6 +7,7 @@ import org.example.app.task.dataaccess.TaskListEntity; import org.example.app.task.dataaccess.TaskListRepository; +import java.util.List; import java.util.Optional; @ApplicationScoped @@ -28,6 +29,12 @@ public TaskListEto findById(Long itemId) { return item.map(ety -> this.taskListMapper.toEto(ety)).orElse(null); } + public List findAll() { + List item = this.taskListRepository.findAll(); + return this.taskListMapper.toEtos(item); + } + + public TaskListCto findTaskListWithItems(Long listId) { Optional taskList = this.taskListRepository.findById(listId); diff --git a/backend/src/main/java/org/example/app/task/service/TaskService.java b/backend/src/main/java/org/example/app/task/service/TaskService.java index 956607d..5eca9f0 100644 --- a/backend/src/main/java/org/example/app/task/service/TaskService.java +++ b/backend/src/main/java/org/example/app/task/service/TaskService.java @@ -13,6 +13,7 @@ import org.example.app.task.logic.*; +import java.util.List; import java.util.NoSuchElementException; @Path("/task") @@ -63,6 +64,16 @@ public TaskListEto fetchTaskList(@PathParam("id") Long id) { return eto; } + @GET + @Path("/lists") + public List allLists() { + List eto = this.ucFindTaskList.findAll(); + if(eto==null) { + throw new NoSuchElementException(); + } + return eto; + } + @DELETE @Path("/item/{id}")