diff --git a/.metadata/.lock b/.metadata/.lock
new file mode 100644
index 0000000..e69de29
diff --git a/.metadata/.log b/.metadata/.log
new file mode 100644
index 0000000..0b5c4b1
--- /dev/null
+++ b/.metadata/.log
@@ -0,0 +1,20 @@
+!SESSION 2024-12-21 02:05:54.514 -----------------------------------------------
+eclipse.buildId=4.33.0.20240905-0613
+java.version=23
+java.vendor=Eclipse Adoptium
+BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_US
+Framework arguments: -product org.eclipse.epp.package.jee.product
+Command-line arguments: -os win32 -ws win32 -arch x86_64 -product org.eclipse.epp.package.jee.product
+
+!ENTRY ch.qos.logback.classic 1 0 2024-12-21 02:05:57.305
+!MESSAGE Activated before the state location was initialized. Retry after the state location is initialized.
+
+!ENTRY ch.qos.logback.classic 1 0 2024-12-21 02:06:07.249
+!MESSAGE Logback config file: C:\Users\musta\OneDrive\Desktop\forage-midas\.metadata\.plugins\org.eclipse.m2e.logback\logback.2.6.1.20240411-1122.xml
+
+!ENTRY org.eclipse.egit.ui 2 0 2024-12-21 02:06:11.222
+!MESSAGE Warning: The environment variable HOME is not set. The following directory will be used to store the Git
+user global configuration and to define the default location to store repositories: 'C:\Users\musta'. If this is
+not correct please set the HOME environment variable and restart Eclipse. Otherwise Git for Windows and
+EGit might behave differently since they see different configuration options.
+This warning can be switched off on the Team > Git > Confirmations and Warnings preference page.
diff --git a/.metadata/.mylyn/repositories.xml.zip b/.metadata/.mylyn/repositories.xml.zip
new file mode 100644
index 0000000..2b29a04
Binary files /dev/null and b/.metadata/.mylyn/repositories.xml.zip differ
diff --git a/.metadata/.plugins/org.eclipse.core.resources/.projects/.org.eclipse.egit.core.cmp/.location b/.metadata/.plugins/org.eclipse.core.resources/.projects/.org.eclipse.egit.core.cmp/.location
new file mode 100644
index 0000000..4b183bd
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.core.resources/.projects/.org.eclipse.egit.core.cmp/.location differ
diff --git a/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version
new file mode 100644
index 0000000..25cb955
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index
new file mode 100644
index 0000000..d237251
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index differ
diff --git a/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version
new file mode 100644
index 0000000..6b2aaa7
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/.metadata/.plugins/org.eclipse.core.resources/.root/1.tree b/.metadata/.plugins/org.eclipse.core.resources/.root/1.tree
new file mode 100644
index 0000000..3ede64c
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.core.resources/.root/1.tree differ
diff --git a/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources
new file mode 100644
index 0000000..2f7a257
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources differ
diff --git a/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi b/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi
new file mode 100644
index 0000000..1bf3e56
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi
@@ -0,0 +1,3145 @@
+
+
+
+ activeSchemeId:org.eclipse.ui.defaultAcceleratorConfiguration
+
+
+
+
+
+
+
+ topLevel
+ shellMaximized
+
+
+
+
+ persp.actionSet:org.eclipse.mylyn.tasks.ui.navigation
+ persp.actionSet:org.eclipse.ui.cheatsheets.actionSet
+ persp.actionSet:org.eclipse.search.searchActionSet
+ persp.actionSet:org.eclipse.text.quicksearch.actionSet
+ persp.actionSet:org.eclipse.ui.edit.text.actionSet.annotationNavigation
+ persp.actionSet:org.eclipse.ui.edit.text.actionSet.navigation
+ persp.actionSet:org.eclipse.ui.edit.text.actionSet.convertLineDelimitersTo
+ persp.actionSet:org.eclipse.ui.externaltools.ExternalToolsSet
+ persp.actionSet:org.eclipse.ui.actionSet.keyBindings
+ persp.actionSet:org.eclipse.ui.actionSet.openFiles
+ persp.actionSet:org.eclipse.jst.j2ee.J2eeMainActionSet
+ persp.actionSet:org.eclipse.jdt.ui.JavaActionSet
+ persp.actionSet:org.eclipse.debug.ui.launchActionSet
+ persp.actionSet:org.eclipse.ui.NavigateActionSet
+ persp.actionSet:org.eclipse.debug.ui.debugActionSet
+ persp.viewSC:org.eclipse.ui.navigator.ProjectExplorer
+ persp.viewSC:org.eclipse.wst.server.ui.ServersView
+ persp.viewSC:org.eclipse.datatools.connectivity.DataSourceExplorerNavigator
+ persp.viewSC:org.eclipse.ui.views.BookmarkView
+ persp.viewSC:org.eclipse.ui.views.ContentOutline
+ persp.viewSC:org.eclipse.ui.views.PropertySheet
+ persp.viewSC:org.eclipse.wst.common.snippets.internal.ui.SnippetsView
+ persp.viewSC:org.eclipse.ui.views.AllMarkersView
+ persp.viewSC:org.eclipse.ui.views.ProblemView
+ persp.viewSC:org.eclipse.mylyn.tasks.ui.views.tasks
+ persp.viewSC:org.eclipse.tm.terminal.view.ui.TerminalsView
+ persp.viewSC:org.eclipse.jdt.ui.PackagesView
+ persp.viewSC:org.eclipse.search.ui.views.SearchView
+ persp.viewSC:org.eclipse.ui.console.ConsoleView
+ persp.showIn:org.eclipse.ui.navigator.ProjectExplorer
+ persp.showIn:org.eclipse.jdt.ui.PackagesView
+ persp.actionSet:org.eclipse.wst.ws.explorer.explorer
+ persp.newWizSC:org.eclipse.m2e.core.wizards.Maven2ProjectWizard
+ persp.newWizSC:org.eclipse.wst.css.ui.internal.wizard.NewCSSWizard
+ persp.newWizSC:org.eclipse.wst.jsdt.ui.NewJSWizard
+ persp.editorOnboardingText:Open a file or drop files here to open them.
+ persp.editorOnboardingCommand:Find Actions$$$Ctrl+3
+ persp.editorOnboardingCommand:Show Key Assist$$$Ctrl+Shift+L
+ persp.editorOnboardingCommand:New$$$Ctrl+N
+ persp.perspSC:org.eclipse.debug.ui.DebugPerspective
+ persp.perspSC:org.eclipse.jdt.ui.JavaPerspective
+ persp.perspSC:org.eclipse.ui.resourcePerspective
+ persp.perspSC:org.eclipse.wst.web.ui.webDevPerspective
+ persp.newWizSC:org.eclipse.jst.j2ee.ui.project.facet.EarProjectWizard
+ persp.newWizSC:org.eclipse.jst.servlet.ui.project.facet.WebProjectWizard
+ persp.newWizSC:org.eclipse.jst.ejb.ui.project.facet.EjbProjectWizard
+ persp.newWizSC:org.eclipse.jst.j2ee.jca.ui.internal.wizard.ConnectorProjectWizard
+ persp.newWizSC:org.eclipse.jst.j2ee.ui.project.facet.appclient.AppClientProjectWizard
+ persp.newWizSC:org.eclipse.wst.web.ui.internal.wizards.SimpleWebProjectWizard
+ persp.newWizSC:org.eclipse.jpt.ui.wizard.newJpaProject
+ persp.newWizSC:org.eclipse.jst.servlet.ui.internal.wizard.AddServletWizard
+ persp.newWizSC:org.eclipse.jst.ejb.ui.internal.wizard.AddSessionBeanWizard
+ persp.newWizSC:org.eclipse.jst.ejb.ui.internal.wizard.AddMessageDrivenBeanWizard
+ persp.newWizSC:org.eclipse.jpt.ui.wizard.newEntity
+ persp.newWizSC:org.eclipse.jst.ws.creation.ui.wizard.serverwizard
+ persp.newWizSC:org.eclipse.wst.html.ui.internal.wizard.NewHTMLWizard
+ persp.newWizSC:org.eclipse.wst.xml.ui.internal.wizards.NewXMLWizard
+ persp.newWizSC:org.eclipse.ui.wizards.new.folder
+ persp.newWizSC:org.eclipse.ui.wizards.new.file
+ persp.actionSet:org.eclipse.wst.server.ui.internal.webbrowser.actionSet
+ persp.actionSet:org.eclipse.debug.ui.breakpointActionSet
+ persp.actionSet:org.eclipse.eclemma.ui.CoverageActionSet
+ persp.showIn:org.eclipse.eclemma.ui.CoverageView
+ persp.showIn:org.eclipse.tm.terminal.view.ui.TerminalsView
+ persp.newWizSC:org.eclipse.jst.jsp.ui.internal.wizard.NewJSPWizard
+ persp.newWizSC:org.eclipse.jpt.jpa.ui.wizard.newJpaProject
+ persp.perspSC:org.eclipse.jpt.ui.jpaPerspective
+
+
+ active
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:Java Browsing
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:Java
+
+
+ View
+ categoryTag:Debug
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:Git
+
+
+ View
+ categoryTag:Debug
+
+
+ View
+ categoryTag:Debug
+
+
+ View
+ categoryTag:Debug
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:General
+
+
+
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:Server
+
+
+ View
+ categoryTag:Terminal
+
+
+ View
+ categoryTag:Data Management
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:Java
+
+
+ View
+ categoryTag:Java Browsing
+
+
+ View
+ categoryTag:Java
+
+
+
+
+
+
+
+
+ View
+ categoryTag:Help
+
+
+ View
+ categoryTag:General
+
+
+ View
+ categoryTag:Help
+
+
+
+
+
+
+ View
+ categoryTag:Help
+
+
+
+
+
+ View
+ categoryTag:General
+
+ ViewMenu
+ menuContribution:menu
+
+
+
+
+
+
+ View
+ categoryTag:Help
+
+
+
+ EditorStack
+ org.eclipse.e4.primaryDataStack
+
+
+
+
+
+
+ View
+ categoryTag:General
+ active
+ activeOnClose
+
+ ViewMenu
+ menuContribution:menu
+
+
+
+
+
+
+ View
+ categoryTag:Java Browsing
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:Git
+
+
+
+
+
+ View
+ categoryTag:General
+
+ ViewMenu
+ menuContribution:menu
+
+
+
+
+
+
+ View
+ categoryTag:Server
+
+
+
+
+ View
+ categoryTag:Terminal
+
+
+
+
+ View
+ categoryTag:Data Management
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Java Browsing
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+
+ View
+ categoryTag:General
+
+ ViewMenu
+ menuContribution:menu
+
+
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+ toolbarSeparator
+
+
+
+ Draggable
+
+
+
+ toolbarSeparator
+
+
+
+ Draggable
+
+
+
+
+ toolbarSeparator
+
+
+
+ Draggable
+
+
+ Draggable
+
+
+ Draggable
+
+
+ Draggable
+
+
+ Draggable
+
+
+ toolbarSeparator
+
+
+
+ Draggable
+
+
+
+ toolbarSeparator
+
+
+
+ toolbarSeparator
+
+
+
+ Draggable
+
+
+ stretch
+ SHOW_RESTORE_MENU
+
+
+ Draggable
+ HIDEABLE
+ SHOW_RESTORE_MENU
+
+
+
+
+ stretch
+
+
+ Draggable
+
+
+ Draggable
+
+
+
+
+ Draggable
+
+
+
+
+ TrimStack
+ Draggable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ platform:win32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ platform:win32
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Editor
+ removeOnHide
+
+
+
+
+ View
+ categoryTag:Ant
+
+
+
+
+ View
+ categoryTag:Gradle
+
+
+
+
+ View
+ categoryTag:Gradle
+
+
+
+
+ View
+ categoryTag:Data Management
+
+
+
+
+ View
+ categoryTag:Data Management
+
+
+
+
+ View
+ categoryTag:Data Management
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Git
+
+
+
+
+ View
+ categoryTag:Git
+
+
+
+
+ View
+ categoryTag:Git
+
+
+
+
+ View
+ categoryTag:Git
+ NoRestore
+
+
+
+
+ View
+ categoryTag:Git
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:Help
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Java Browsing
+
+
+
+
+ View
+ categoryTag:Java Browsing
+
+
+
+
+ View
+ categoryTag:Java Browsing
+
+
+
+
+ View
+ categoryTag:Java Browsing
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:Java
+
+
+
+
+ View
+ categoryTag:JPA
+
+
+
+
+ View
+ categoryTag:JPA
+
+
+
+
+ View
+ categoryTag:JavaServer Faces
+
+
+
+
+ View
+ categoryTag:JavaServer Faces
+
+
+
+
+ View
+ categoryTag:Web Services
+
+
+
+
+ View
+ categoryTag:Language Servers
+
+
+
+
+ View
+ categoryTag:Language Servers
+
+
+
+
+ View
+ categoryTag:Language Servers
+
+
+
+
+ View
+ categoryTag:Maven
+
+
+
+
+ View
+ categoryTag:Maven
+
+
+
+
+ View
+ categoryTag:Maven
+
+
+
+
+ View
+ categoryTag:Mylyn
+
+
+
+
+ View
+ categoryTag:Mylyn
+
+
+
+
+ View
+ categoryTag:Mylyn
+
+
+
+
+ View
+ categoryTag:Mylyn
+
+
+
+
+ View
+ categoryTag:Mylyn
+
+
+
+
+ View
+ categoryTag:Mylyn
+
+
+
+
+ View
+ categoryTag:API Tools
+
+
+
+
+ View
+ categoryTag:OSGi
+
+
+
+
+ View
+ categoryTag:Plug-in Development
+
+
+
+
+ View
+ categoryTag:Plug-in Development
+
+
+
+
+ View
+ categoryTag:Plug-in Development
+
+
+
+
+ View
+ categoryTag:Plug-in Development
+
+
+
+
+ View
+ categoryTag:Plug-in Development
+
+
+
+
+ View
+ categoryTag:Plug-in Development
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:Version Control (Team)
+
+
+
+
+ View
+ categoryTag:Version Control (Team)
+
+
+ View
+ categoryTag:Help
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:Help
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:General
+
+
+
+
+ View
+ categoryTag:Debug
+
+
+
+
+ View
+ categoryTag:Other
+
+
+
+
+ View
+ categoryTag:Other
+
+
+
+
+ View
+ categoryTag:Other
+
+
+
+
+ View
+ categoryTag:Server
+
+
+
+
+ View
+ categoryTag:XML
+
+
+
+
+ View
+ categoryTag:XML
+
+
+
+
+ View
+ categoryTag:XML
+
+
+
+
+ View
+ categoryTag:XML
+
+
+
+
+ View
+ categoryTag:XML
+
+
+
+
+ View
+ categoryTag:Oomph
+
+
+
+
+ View
+ categoryTag:Connections
+
+
+
+
+ View
+ categoryTag:Terminal
+
+
+
+
+ View
+ categoryTag:Other
+
+
+
+ glue
+ move_after:PerspectiveSpacer
+ SHOW_RESTORE_MENU
+
+
+ move_after:Spacer Glue
+ HIDEABLE
+ SHOW_RESTORE_MENU
+
+
+ glue
+ move_after:SearchField
+ SHOW_RESTORE_MENU
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache b/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache
new file mode 100644
index 0000000..593f470
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache differ
diff --git a/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache b/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache
new file mode 100644
index 0000000..593f470
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache differ
diff --git a/.metadata/.plugins/org.eclipse.jdt.core/javaLikeNames.txt b/.metadata/.plugins/org.eclipse.jdt.core/javaLikeNames.txt
new file mode 100644
index 0000000..8586397
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.jdt.core/javaLikeNames.txt
@@ -0,0 +1 @@
+java
\ No newline at end of file
diff --git a/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache b/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache
new file mode 100644
index 0000000..593f470
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache differ
diff --git a/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat b/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat
new file mode 100644
index 0000000..3de398e
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat differ
diff --git a/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml b/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml
new file mode 100644
index 0000000..a4ee3cb
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml b/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml
new file mode 100644
index 0000000..9e390f5
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/.metadata/.plugins/org.eclipse.m2e.core/workspaceState.ser b/.metadata/.plugins/org.eclipse.m2e.core/workspaceState.ser
new file mode 100644
index 0000000..abbf8e5
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.m2e.core/workspaceState.ser differ
diff --git a/.metadata/.plugins/org.eclipse.m2e.logback/0.log b/.metadata/.plugins/org.eclipse.m2e.logback/0.log
new file mode 100644
index 0000000..e6bd79d
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.m2e.logback/0.log
@@ -0,0 +1 @@
+2024-12-21 02:06:11,089 [Worker-4: Loading available Gradle versions] INFO o.e.b.c.i.u.g.PublishedGradleVersions - Gradle version information cache is up-to-date. Trying to read.
diff --git a/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.6.1.20240411-1122.xml b/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.6.1.20240411-1122.xml
new file mode 100644
index 0000000..9effde7
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.m2e.logback/logback.2.6.1.20240411-1122.xml
@@ -0,0 +1,41 @@
+
+
+
+ %date [%thread] %-5level %logger{35} - %msg%n
+
+
+ ${org.eclipse.m2e.log.console.threshold:-OFF}
+
+
+
+
+ ${org.eclipse.m2e.log.dir}/0.log
+
+ ${org.eclipse.m2e.log.dir}/%i.log
+ 1
+ 10
+
+
+ 10MB
+
+
+ %date [%thread] %-5level %logger{35} - %msg%n
+
+
+
+
+
+ WARN
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.metadata/.plugins/org.eclipse.mylyn.github.ui/avatars.ser b/.metadata/.plugins/org.eclipse.mylyn.github.ui/avatars.ser
new file mode 100644
index 0000000..1e9a069
Binary files /dev/null and b/.metadata/.plugins/org.eclipse.mylyn.github.ui/avatars.ser differ
diff --git a/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup b/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup
new file mode 100644
index 0000000..1f73e14
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup
@@ -0,0 +1,6 @@
+
+
diff --git a/.metadata/.plugins/org.eclipse.tips.ide/dialog_settings.xml b/.metadata/.plugins/org.eclipse.tips.ide/dialog_settings.xml
new file mode 100644
index 0000000..5ca0b77
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.tips.ide/dialog_settings.xml
@@ -0,0 +1,3 @@
+
+
diff --git a/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml b/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
new file mode 100644
index 0000000..14afaec
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
@@ -0,0 +1,16 @@
+
+
diff --git a/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml b/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml
new file mode 100644
index 0000000..4868369
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml
@@ -0,0 +1,4 @@
+
+
diff --git a/.metadata/.plugins/org.eclipse.ui.intro/introstate b/.metadata/.plugins/org.eclipse.ui.intro/introstate
new file mode 100644
index 0000000..02f134f
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.ui.intro/introstate
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml b/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
new file mode 100644
index 0000000..5ca0b77
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
@@ -0,0 +1,3 @@
+
+
diff --git a/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml b/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
new file mode 100644
index 0000000..54fbf58
--- /dev/null
+++ b/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.metadata/version.ini b/.metadata/version.ini
new file mode 100644
index 0000000..47679b5
--- /dev/null
+++ b/.metadata/version.ini
@@ -0,0 +1,3 @@
+#Sat Dec 21 02:06:06 EST 2024
+org.eclipse.core.runtime=2
+org.eclipse.platform=4.33.0.v20240903-0240
diff --git a/README.md b/README.md
index 637f474..2749ebd 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,19 @@
# Midas
Project repo for the JPMC Advanced Software Engineering Forage program
+
+
+**Task One:**
+
+![Screenshot 2024-12-21 122439](https://github.com/user-attachments/assets/0c663a0a-f959-431c-9bbe-2f4ddfbe3c5d)
+
+**Task Three:**
+
+![Task 3](https://github.com/user-attachments/assets/d508d384-db04-4389-ac32-138295439f7c)
+
+**Task Four:**
+
+![Task 4](https://github.com/user-attachments/assets/94047c5e-e309-4766-b8d3-b7f1182a3150)
+
+**Task Five:**
+
+![Task 5](https://github.com/user-attachments/assets/79205cf0-ffef-4f98-b0a4-cc605ea8ad55)
diff --git a/application.yml b/application.yml
index e69de29..455d778 100644
--- a/application.yml
+++ b/application.yml
@@ -0,0 +1,18 @@
+general:
+ kafka-topic: transactions-topic
+ kafka-bootstrap-servers: localhost:9092
+
+spring:
+ datasource:
+ url: jdbc:h2:file:./mydb;AUTO_SERVER=TRUE;DB_CLOSE_DELAY=-1
+ username: sa
+ password:
+ jpa:
+ hibernate:
+ ddl-auto: update # Use 'update' to keep the schema in sync with the entities
+ show-sql: true
+ h2:
+ console:
+ enabled: true
+server:
+ port: 33400
\ No newline at end of file
diff --git a/data/mydb.mv.db b/data/mydb.mv.db
new file mode 100644
index 0000000..3ce54a2
Binary files /dev/null and b/data/mydb.mv.db differ
diff --git a/data/mydb.trace.db b/data/mydb.trace.db
new file mode 100644
index 0000000..1961bc8
--- /dev/null
+++ b/data/mydb.trace.db
@@ -0,0 +1,3 @@
+2024-12-28 14:15:24.802026-05:00 jdbc[3]: exception
+org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "USER_RECORD" not found (this database is empty); SQL statement:
+INSERT INTO user_record (name, balance) VALUES ('Waldorf', 1000) [42104-224]
diff --git a/pom.xml b/pom.xml
index d1dedfe..351285f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,8 +17,47 @@
17
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+ 3.2.5
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ 3.2.5
+
+
+ org.springframework.kafka
+ spring-kafka
+ 3.1.4
+
+
+ com.h2database
+ h2
+ 2.2.224
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ 3.2.5
+
+
+ org.springframework.kafka
+ spring-kafka-test
+ 3.1.4
+
+
+ org.testcontainers
+ kafka
+ 1.19.1
+
+
+ com.h2database
+ h2
+ runtime
+
-
diff --git a/src/main/java/com/jpmc/midascore/MidasCoreApplication.java b/src/main/java/com/jpmc/midascore/MidasCoreApplication.java
index 9222581..31556ec 100644
--- a/src/main/java/com/jpmc/midascore/MidasCoreApplication.java
+++ b/src/main/java/com/jpmc/midascore/MidasCoreApplication.java
@@ -10,4 +10,4 @@ public static void main(String[] args) {
SpringApplication.run(MidasCoreApplication.class, args);
}
-}
+}
\ No newline at end of file
diff --git a/src/test/java/com/jpmc/midascore/FileLoader.java b/src/main/java/com/jpmc/midascore/component/FileLoader.java
similarity index 93%
rename from src/test/java/com/jpmc/midascore/FileLoader.java
rename to src/main/java/com/jpmc/midascore/component/FileLoader.java
index 69992eb..8d99e0d 100644
--- a/src/test/java/com/jpmc/midascore/FileLoader.java
+++ b/src/main/java/com/jpmc/midascore/component/FileLoader.java
@@ -1,4 +1,4 @@
-package com.jpmc.midascore;
+package com.jpmc.midascore.component;
import org.springframework.stereotype.Component;
import org.testcontainers.shaded.org.apache.commons.io.IOUtils;
diff --git a/src/test/java/com/jpmc/midascore/UserPopulator.java b/src/main/java/com/jpmc/midascore/component/UserPopulator.java
similarity index 84%
rename from src/test/java/com/jpmc/midascore/UserPopulator.java
rename to src/main/java/com/jpmc/midascore/component/UserPopulator.java
index 63f6047..62837bb 100644
--- a/src/test/java/com/jpmc/midascore/UserPopulator.java
+++ b/src/main/java/com/jpmc/midascore/component/UserPopulator.java
@@ -1,9 +1,9 @@
-package com.jpmc.midascore;
+package com.jpmc.midascore.component;
-import com.jpmc.midascore.component.DatabaseConduit;
import com.jpmc.midascore.entity.UserRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
@Component
public class UserPopulator {
@@ -13,6 +13,7 @@ public class UserPopulator {
@Autowired
private DatabaseConduit databaseConduit;
+ @Transactional
public void populate() {
String[] userLines = fileLoader.loadStrings("/test_data/lkjhgfdsa.hjkl");
for (String userLine : userLines) {
diff --git a/src/main/java/com/jpmc/midascore/config/AppConfig.java b/src/main/java/com/jpmc/midascore/config/AppConfig.java
new file mode 100644
index 0000000..1080fb8
--- /dev/null
+++ b/src/main/java/com/jpmc/midascore/config/AppConfig.java
@@ -0,0 +1,14 @@
+package com.jpmc.midascore.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+@Configuration
+public class AppConfig {
+
+ @Bean
+ public RestTemplate restTemplate(){
+ return new RestTemplate();
+ }
+}
diff --git a/src/main/java/com/jpmc/midascore/config/KafkaConsumerConfig.java b/src/main/java/com/jpmc/midascore/config/KafkaConsumerConfig.java
new file mode 100644
index 0000000..c2e2d68
--- /dev/null
+++ b/src/main/java/com/jpmc/midascore/config/KafkaConsumerConfig.java
@@ -0,0 +1,44 @@
+package com.jpmc.midascore.config;
+
+import com.jpmc.midascore.foundation.Transaction;
+import org.apache.kafka.clients.consumer.ConsumerConfig;
+import org.apache.kafka.common.serialization.StringDeserializer;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.annotation.EnableKafka;
+import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
+import org.springframework.kafka.core.ConsumerFactory;
+import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
+import org.springframework.kafka.support.serializer.JsonDeserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@EnableKafka
+@Configuration
+public class KafkaConsumerConfig {
+
+ @Value("${general.kafka-bootstrap-servers}")
+ private String bootstrapServers;
+
+ @Bean
+ public ConsumerFactory consumerFactory() {
+ JsonDeserializer deserializer = new JsonDeserializer<>(Transaction.class);
+ deserializer.addTrustedPackages("*"); // Adjust package trust if needed
+ Map config = new HashMap<>();
+ config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
+ config.put(ConsumerConfig.GROUP_ID_CONFIG, "transaction-group");
+ config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
+ config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, deserializer);
+ return new DefaultKafkaConsumerFactory<>(config, new StringDeserializer(), deserializer);
+ }
+
+ @Bean
+ public ConcurrentKafkaListenerContainerFactory kafkaListenerContainerFactory() {
+ ConcurrentKafkaListenerContainerFactory factory =
+ new ConcurrentKafkaListenerContainerFactory<>();
+ factory.setConsumerFactory(consumerFactory());
+ return factory;
+ }
+}
diff --git a/src/main/java/com/jpmc/midascore/config/KafkaProducerConfig.java b/src/main/java/com/jpmc/midascore/config/KafkaProducerConfig.java
new file mode 100644
index 0000000..3ae4e7b
--- /dev/null
+++ b/src/main/java/com/jpmc/midascore/config/KafkaProducerConfig.java
@@ -0,0 +1,36 @@
+package com.jpmc.midascore.config;
+
+import com.jpmc.midascore.foundation.Transaction;
+import org.apache.kafka.clients.producer.ProducerConfig;
+import org.apache.kafka.common.serialization.StringSerializer;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.kafka.core.DefaultKafkaProducerFactory;
+import org.springframework.kafka.core.KafkaTemplate;
+import org.springframework.kafka.core.ProducerFactory;
+import org.springframework.kafka.support.serializer.JsonSerializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Configuration
+public class KafkaProducerConfig {
+
+ @Value("${general.kafka-bootstrap-servers}")
+ private String bootstrapServers;
+
+ @Bean
+ public KafkaTemplate kafkaTemplate() {
+ return new KafkaTemplate<>(producerFactory());
+ }
+
+ @Bean
+ public ProducerFactory producerFactory() {
+ Map configProps = new HashMap<>();
+ configProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
+ configProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
+ configProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
+ return new DefaultKafkaProducerFactory<>(configProps);
+ }
+}
diff --git a/src/main/java/com/jpmc/midascore/controller/TransactionController.java b/src/main/java/com/jpmc/midascore/controller/TransactionController.java
new file mode 100644
index 0000000..de2e33d
--- /dev/null
+++ b/src/main/java/com/jpmc/midascore/controller/TransactionController.java
@@ -0,0 +1,21 @@
+package com.jpmc.midascore.controller;
+
+import com.jpmc.midascore.foundation.Balance;
+import com.jpmc.midascore.service.TransactionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class TransactionController {
+
+ @Autowired
+ private TransactionService transactionService;
+
+ @GetMapping("/balance")
+ public Balance getBalance(@RequestParam Long userId){
+ return transactionService.getBalance(userId);
+ }
+
+}
diff --git a/src/main/java/com/jpmc/midascore/entity/TransactionRecord.java b/src/main/java/com/jpmc/midascore/entity/TransactionRecord.java
new file mode 100644
index 0000000..f0d0536
--- /dev/null
+++ b/src/main/java/com/jpmc/midascore/entity/TransactionRecord.java
@@ -0,0 +1,61 @@
+package com.jpmc.midascore.entity;
+
+import jakarta.persistence.*;
+
+@Entity
+public class TransactionRecord {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private long id;
+
+ @ManyToOne
+ @JoinColumn(name = "sender_id", nullable = false)
+ private UserRecord sender;
+
+ @ManyToOne
+ @JoinColumn(name = "recipient_id", nullable = false)
+ private UserRecord recipient;
+
+ private float amount;
+
+ public TransactionRecord() {
+ }
+
+ public TransactionRecord(UserRecord sender, UserRecord recipient, float amount) {
+ this.sender = sender;
+ this.recipient = recipient;
+ this.amount = amount;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public void setSender(UserRecord sender) {
+ this.sender = sender;
+ }
+
+ public void setRecipient(UserRecord recipient) {
+ this.recipient = recipient;
+ }
+
+ public void setAmount(float amount) {
+ this.amount = amount;
+ }
+
+ public float getAmount() {
+ return amount;
+ }
+
+ @Override
+ public String toString() {
+ return "TransactionRecord{" +
+ "id=" + id +
+ ", sender=" + sender.getId() + // Assuming UserRecord has getId() method
+ ", recipient=" + recipient.getId() + // Assuming UserRecord has getId() method
+ ", amount=" + amount +
+ '}';
+ }
+
+}
diff --git a/src/main/java/com/jpmc/midascore/foundation/Incentive.java b/src/main/java/com/jpmc/midascore/foundation/Incentive.java
new file mode 100644
index 0000000..9a35fab
--- /dev/null
+++ b/src/main/java/com/jpmc/midascore/foundation/Incentive.java
@@ -0,0 +1,16 @@
+package com.jpmc.midascore.foundation;
+
+public class Incentive {
+
+ private float amount;
+
+ public float getAmount() {
+ return amount;
+ }
+
+ public void setAmount(float amount) {
+ this.amount = amount;
+ }
+
+
+}
diff --git a/src/main/java/com/jpmc/midascore/repository/TransactionRecordRepository.java b/src/main/java/com/jpmc/midascore/repository/TransactionRecordRepository.java
new file mode 100644
index 0000000..42c1127
--- /dev/null
+++ b/src/main/java/com/jpmc/midascore/repository/TransactionRecordRepository.java
@@ -0,0 +1,7 @@
+package com.jpmc.midascore.repository;
+
+import com.jpmc.midascore.entity.TransactionRecord;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface TransactionRecordRepository extends JpaRepository {
+}
\ No newline at end of file
diff --git a/src/main/java/com/jpmc/midascore/repository/UserRepository.java b/src/main/java/com/jpmc/midascore/repository/UserRepository.java
index 937275b..33ba0c1 100644
--- a/src/main/java/com/jpmc/midascore/repository/UserRepository.java
+++ b/src/main/java/com/jpmc/midascore/repository/UserRepository.java
@@ -4,5 +4,6 @@
import org.springframework.data.repository.CrudRepository;
public interface UserRepository extends CrudRepository {
- UserRecord findById(long id);
+ //UserRecord findById(long id);
+ UserRecord findByName(String name);
}
diff --git a/src/main/java/com/jpmc/midascore/service/TransactionService.java b/src/main/java/com/jpmc/midascore/service/TransactionService.java
new file mode 100644
index 0000000..1ec4d75
--- /dev/null
+++ b/src/main/java/com/jpmc/midascore/service/TransactionService.java
@@ -0,0 +1,87 @@
+package com.jpmc.midascore.service;
+
+import com.jpmc.midascore.entity.TransactionRecord;
+import com.jpmc.midascore.entity.UserRecord;
+import com.jpmc.midascore.foundation.Balance;
+import com.jpmc.midascore.foundation.Incentive;
+import com.jpmc.midascore.foundation.Transaction;
+import com.jpmc.midascore.repository.TransactionRecordRepository;
+import com.jpmc.midascore.repository.UserRepository;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Optional;
+
+@Service
+public class TransactionService {
+
+ private final UserRepository userRepository;
+ private final TransactionRecordRepository transactionRecordRepository;
+ private final RestTemplate restTemplate;
+
+ // Constructor injection
+ public TransactionService(UserRepository userRepository, TransactionRecordRepository transactionRecordRepository, RestTemplate restTemplate) {
+ this.userRepository = userRepository;
+ this.transactionRecordRepository = transactionRecordRepository;
+ this.restTemplate = restTemplate;
+ }
+
+ @KafkaListener(topics = "${general.kafka-topic}", groupId = "transaction-group")
+ public void processTransaction(Transaction transaction) {
+
+ // Fetch sender and recipient from the repository by ID
+ UserRecord sender = userRepository.findById(transaction.getSenderId()).orElse(null);
+ UserRecord recipient = userRepository.findById(transaction.getRecipientId()).orElse(null);
+
+ //System.out.println("Users from service file: " + userRepository.findAll());
+ //System.out.println("Transaction sender id Works: " + transaction.getSenderId());
+ //System.out.println("Sender object: " + sender);
+
+ if (sender != null && recipient != null && sender.getBalance() >= transaction.getAmount()) {
+
+ // If transaction is valid, record it
+ TransactionRecord transactionRecord = new TransactionRecord(sender, recipient, transaction.getAmount());
+ transactionRecordRepository.save(transactionRecord);
+
+ // Update balance of sender
+ sender.setBalance(sender.getBalance() - transaction.getAmount());
+
+ // Try and catch when calling the api
+ float incentiveAmount = 0;
+ try {
+ incentiveAmount = getIncentiveApi(transaction).getAmount();
+ } catch
+ (Exception e) {
+ System.out.println("Error occurred while calling Incentive Api " + e);
+ }
+ // Update balance of recipient
+ recipient.setBalance(recipient.getBalance() + transaction.getAmount() + Math.max(0, incentiveAmount));
+
+ // Persist updated users with their new balances
+ userRepository.save(sender);
+ userRepository.save(recipient);
+ } else {
+ // If not valid, discard the transaction (no changes to database)
+ System.out.println("Transaction discarded: " + transaction);
+ }
+ }
+
+ public Incentive getIncentiveApi(Transaction transaction) {
+ String url = "http://localhost:8080/incentive";
+ return restTemplate.postForObject(url, transaction, Incentive.class);
+ }
+
+ public Balance getBalance(Long userId) {
+
+ Optional user = userRepository.findById(userId);
+ float finalBalance = 0;
+
+ if (user.isPresent()) {
+ finalBalance = user.get().getBalance();
+ return new Balance(finalBalance);
+ } else {
+ return new Balance(finalBalance);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/jpmc/midascore/Listeners.java b/src/test/java/com/jpmc/midascore/Listeners.java
new file mode 100644
index 0000000..3c8518e
--- /dev/null
+++ b/src/test/java/com/jpmc/midascore/Listeners.java
@@ -0,0 +1,14 @@
+package com.jpmc.midascore;
+
+import com.jpmc.midascore.foundation.Transaction;
+import org.springframework.kafka.annotation.KafkaListener;
+import org.springframework.stereotype.Component;
+
+@Component
+public class Listeners {
+
+ @KafkaListener(topics = "${general.kafka-topic}", groupId = "transaction-group")
+ public void listen(Transaction transaction) {
+ System.out.println("Received Transaction: " + transaction);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/com/jpmc/midascore/TaskFiveTests.java b/src/test/java/com/jpmc/midascore/TaskFiveTests.java
index f1b6e65..4f9a5f0 100644
--- a/src/test/java/com/jpmc/midascore/TaskFiveTests.java
+++ b/src/test/java/com/jpmc/midascore/TaskFiveTests.java
@@ -1,5 +1,7 @@
package com.jpmc.midascore;
+import com.jpmc.midascore.component.FileLoader;
+import com.jpmc.midascore.component.UserPopulator;
import com.jpmc.midascore.foundation.Balance;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
@@ -9,7 +11,7 @@
import org.springframework.kafka.test.context.EmbeddedKafka;
import org.springframework.test.annotation.DirtiesContext;
-@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = "server.port=0")
@DirtiesContext
@EmbeddedKafka(partitions = 1, brokerProperties = {"listeners=PLAINTEXT://localhost:9092", "port=9092"})
public class TaskFiveTests {
diff --git a/src/test/java/com/jpmc/midascore/TaskFourTests.java b/src/test/java/com/jpmc/midascore/TaskFourTests.java
index 75b941b..ad874ac 100644
--- a/src/test/java/com/jpmc/midascore/TaskFourTests.java
+++ b/src/test/java/com/jpmc/midascore/TaskFourTests.java
@@ -1,5 +1,9 @@
package com.jpmc.midascore;
+import com.jpmc.midascore.component.FileLoader;
+import com.jpmc.midascore.component.UserPopulator;
+import com.jpmc.midascore.entity.UserRecord;
+import com.jpmc.midascore.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -23,6 +27,9 @@ public class TaskFourTests {
@Autowired
private FileLoader fileLoader;
+ @Autowired
+ private UserRepository userRepository;
+
@Test
void task_four_verifier() throws InterruptedException {
userPopulator.populate();
@@ -38,6 +45,16 @@ void task_four_verifier() throws InterruptedException {
logger.info("----------------------------------------------------------");
logger.info("use your debugger to find out what wilbur's balance is after all transactions are processed");
logger.info("kill this test once you find the answer");
+ logger.info("----------------------------------------------------------");
+
+ // Print Wilbur's final balance after all transactions are processed
+ UserRecord wilbur = userRepository.findByName("wilbur");
+ if (wilbur != null) {
+ System.out.println("Final balance for Wilbur: " + Math.floor(wilbur.getBalance()));
+ } else {
+ System.out.println("Wilbur not found in the database.");
+ }
+
while (true) {
Thread.sleep(20000);
logger.info("...");
diff --git a/src/test/java/com/jpmc/midascore/TaskThreeTests.java b/src/test/java/com/jpmc/midascore/TaskThreeTests.java
index 6ef57b6..1309790 100644
--- a/src/test/java/com/jpmc/midascore/TaskThreeTests.java
+++ b/src/test/java/com/jpmc/midascore/TaskThreeTests.java
@@ -1,5 +1,10 @@
package com.jpmc.midascore;
+import com.jpmc.midascore.component.FileLoader;
+import com.jpmc.midascore.component.UserPopulator;
+import com.jpmc.midascore.entity.UserRecord;
+import com.jpmc.midascore.repository.TransactionRecordRepository;
+import com.jpmc.midascore.repository.UserRepository;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -14,6 +19,12 @@
public class TaskThreeTests {
static final Logger logger = LoggerFactory.getLogger(TaskThreeTests.class);
+ @Autowired
+ private UserRepository userRepository;
+
+ @Autowired
+ private TransactionRecordRepository transactionRecordRepository; // Assuming this repository is set up
+
@Autowired
private KafkaProducer kafkaProducer;
@@ -26,6 +37,9 @@ public class TaskThreeTests {
@Test
void task_three_verifier() throws InterruptedException {
userPopulator.populate();
+
+ //userRepository.findAll().forEach(user -> System.out.println("Users from test file: " + user));
+
String[] transactionLines = fileLoader.loadStrings("/test_data/mnbvcxz.vbnm");
for (String transactionLine : transactionLines) {
kafkaProducer.send(transactionLine);
@@ -38,6 +52,16 @@ void task_three_verifier() throws InterruptedException {
logger.info("----------------------------------------------------------");
logger.info("use your debugger to find out what waldorf's balance is after all transactions are processed");
logger.info("kill this test once you find the answer");
+ logger.info("----------------------------------------------------------");
+
+ // Print Waldorf's final balance after all transactions are processed
+ UserRecord waldorf = userRepository.findByName("waldorf");
+ if (waldorf != null) {
+ System.out.println("Final balance for Waldorf: " + Math.floor(waldorf.getBalance()));
+ } else {
+ System.out.println("Waldorf not found in the database.");
+ }
+
while (true) {
Thread.sleep(20000);
logger.info("...");
diff --git a/src/test/java/com/jpmc/midascore/TaskTwoTests.java b/src/test/java/com/jpmc/midascore/TaskTwoTests.java
index 30a7a92..b795c47 100644
--- a/src/test/java/com/jpmc/midascore/TaskTwoTests.java
+++ b/src/test/java/com/jpmc/midascore/TaskTwoTests.java
@@ -1,5 +1,6 @@
package com.jpmc.midascore;
+import com.jpmc.midascore.component.FileLoader;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;