GithubHelp home page GithubHelp logo

longbox's Introduction

LongBox ITR03 Build

Your digital solution for archiving and preserving comic books. Developed by passionate fans, this open-source desktop app offers concise documentation for out-of-print, independent, and mainstream comics. Addressing the decline in sales, LongBox provides a user-friendly platform for organizing and archiving collections. With web application plans, it aims to be a central hub for enthusiasts. Users can create profiles, submit comics, and enjoy a recommendation system. Built from scratch, LongBox prioritizes simplicity without relying on existing projects.

System

This project uses a 3-layer software architecture. The system is built around the Java Swing framework and behaves as a model view controller application in conformance to the oracle documentation for Swing applications. A sketch of it is:

SystemDiagram

Documentation

There are three major documentation types for this project.

  1. Several design & planning documents. These have several iterations/revisions and can be found in the planning directory
    • A Post-Mortem analysis of the project can be found at the end of the ITR3_Updated_Plan document.
  2. A code review document that provides peer review done by the team on each other's user stories/features. It provides problem reports, code smells and end-2-end tests for the project.
  3. A refactoring document that highlights major design changes in response to code review and problem reports above.
  4. All system diagrams.

Getting Started

Prerequisites

  • The project is built on Java 19.
  • The project uses Gradle as the build system.
  • The project uses PostgreSQL 16 as the database.

Installing

  1. Clone the GitHub Repository delivery-2 branch or download the source for Delivery 2 release.
  2. If using eclipse, once the project has been cloned, gradle nature needs to be added to the project. How to configure gradle in eclipse.
  3. To use the database, we need PostgreSQL. Run PostgreSQL via command line and create a new database called longbox_db.

createdb longbox_db;

  1. After creating the database, open the database using

psql -p 5432 -d longbox_db;

  1. Once the database view open (you should see longbox_db=# on the left side). Run the following command to load the database (Database script: create_longbox_db):

\i < path of create_longbox_db.sql >;

  1. To ensure the database server communicates with the project, go to the file hibernate.cfg.xml configuration file and ensure the connection.url property matches the one for your personal machine's PostgreSQL installation and the database made above.

Build

To build the project run the command:

gradle clean build

To run the application run the command:

gradle run

Testing

The project uses JUnit and gradle integration for unit testing and integration testing of system code. Unit and integration tests are in test. E2E testing is described in the Code Review Document and organized by feature within the document.

To execute the full JUnit test suite run the command:

gradle test

To view the coverage of the tests navigate to the JaCoCo coverage report. This must be done after running the test suite.

If using Eclipse, they can all be run as follows:

right click on src/test/java > RunAs > JUnit Test.

Customer Tests

The video for customer tests can be found here Customer Meeting 2.

Launching in Eclipse IDE

To launch the project:

Run Main.java in src/main/java.

Build System

Gradle - Dependency Management

Features

Login

This is the first page that the user of the app sees.

Login

Registration

New users can sign up and use our app. Upon sign up users can select preferred genres, using which user will be recommended comics.

Signup

Home

This is the first page that the user lands on after logging in the system. The current user's username is displayed near the logout button. using the top bar, user can navigate and access all the features of the system.

Recommendations

Upon login users land on a page of recommendations that are tailored to for them. The entries in this list can be opened to explore more about them.

Recommendations

Comic Repository and Advanced Search

Users can view all the comic books in the app's collection. Users can use the advanced search and search the comics based on Title, Artist, Author, Genre, Publisher and Year Published. The search results are viewed in a different window.

ComicRepo

Search Results

View Detailed Information

After selecting a comic book, users can view detailed information about the comic book.

Add and View Comments

In this window user also has an option to add a new comment, view existing comments in order of newest to oldest.

Reading & Finished Lists

Users can add and remove books from their personal reading and finished lists of comic books. Add and remove is accomplished when viewing a comic book in its individual page. The lists can be viewed in the profile view and from here the comic books can be selected again to edit their list membership.

Comic Ratings

Users can also add ratings to comic books and view them.

ComicInfo

Add Comic

Using this page, a user can add a comic book to the system. A user can favourite a comic while adding to the system.

AddComic

Favourite a comic

All the comics added to favourites are visible in this page, a user can remove a comic from favourites.

Favourites

Confirmation to remove from favourites:

Unfavourite

View Profile

Users can view their details on the profile page. Users have the option to edit their about me. Users can view the reading and finished comics as a list here.

Profile

Trending

User can view the trending comics of the app, they can also filter it by the Continent.

Trending

Leaderboards

The Social page allows the user to see all the users that use the system. There is also a filter option to filter the results by number of comics read and finished, more or less than a number.

Social

User Lookup

Using the app, a user can view information about another user such including the comments done by them on comics, their reading and finished list and preferred genres. Users can either double click on a user in the social panel or double click on the comment by a user in the Comic Information page, to navigate to this page.

OtherUser

Logout

After using the system, the user can log out and will be redirected to the login page.

Logout

Authors

Hashir Jamil
Ahan Bhargava
Mher Eric Gyuluman
Ali Sina
Oscar Ye

longbox's People

Contributors

ahan10 avatar hashir-jamil avatar supahacka02 avatar hippothicco avatar alisina97 avatar dextersargent avatar

Stargazers

 avatar

Watchers

Hadi Hemmati avatar  avatar

Forkers

ahan10

longbox's Issues

[BR7] Adding a comic book and leaving all fields empty

Description:
If all the fields of the book are left empty a NumberFormatException is thrown

Steps to reproduce:

  1. Login into the app using valid credentials.
  2. Navigate to the ‘Add Comic Page’
  3. Not filling any of the fields.
  4. Not selecting the is favorite checkbox.
  5. Clicking the ‘Enter Comic Book’ button.
  6. Error thrown in the console of compiler.
  7. Database not updated.

Suggested fix:
Having the series title as a required field, and the integer fields are set to 0 as a default value.

[BR4] The text is cut off in the about me text box if a big paragraph is added.

Description:
If the about me is bigger than the size of the textbox, the text cannot be viewed completely and is cut off, but is updated correctly in the database.

Steps to reproduce:

  1. This test case ensures that a big text can be added and read.
  2. Login into the app using valid credentials.
  3. Navigate to the profile page where the about me text box should be there.
  4. The ‘Edit’ button is clicked.
  5. A big text is added to the text box.
  6. Text is cut off after a certain length.
  7. The database is updated correctly with the big paragraph.

Suggested Fix:
Placing the JTextArea inside a JScrollPane

[BR3] Logout + Comic Book Page Left Open Allows Add or Remove from Collection With Exception

After logging out with the comic book page left open on a comic book, the add to favorites/reading/finished list features can still be accessed but throws a null pointer exception. Even if you log back in this persists.

Steps to reproduce:

Log in
Open a comic book by double clicking a comic in the comic repository table.
Log out but do not close the sign in/sign up window.
Try to add/remove the still open comic book page to any of the lists.
You will get a NullPointerException for a null user/userId
Log back in and try to do the same again.
The same original unclosed comic book window still throws this error.
Only opening a new window of the same comic book resynchronizes user actions to be correct.

Suggested fix:
Close comic book page upon logout or handle all null pointer exceptions. If the page is to be left open then nullify all buttons once logged out so no one can add or remove from lists.

[BR2] Logout + Comic Book Page Left Open Allows Comments With Exception

After logging out with the comic book page left open on a comic book, the comments feature can still be accessed but throws a null pointer exception. Even if you log back in this persists.

Steps to reproduce:

Log in
Open a comic book by double clicking a comic in the comic repository table.
Log out but do not close the sign in/sign up window.
Try to add a comment on the still open comic book page.
You will get a NullPointerException for a null user/userId
Log back in and try to comment again.
The same original unclosed comic book window still throws this error.
Only opening a new window of the same comic book resynchronizes user actions to be correct.

Suggested Fix:
Close comic book page upon logout or handle all null pointer exceptions. If the page is to be left open then nullify all buttons once logged out so no one can comment.

[BR1] Registration with wrong email address/username leads to NullPointerException & Exception is Not Displayed

When a user is trying to register with an email or username that is already associated with an account the error is not displayed to the user but instead the program does not respond and the error logs show the following trace:

The associated bug report has been produced and is called [BR1]

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "java.lang.Long.longValue()" because the return value of "org.longbox.domainobjects.dto.UserDto.getId()" is null
at org.longbox.domainobjects.mapper.UserMapper.toEntity(UserMapper.java:36)
at org.longbox.businesslogic.service.UserService.saveUser(UserService.java:56)
at org.longbox.businesslogic.controller.AuthenticationController.registerUser(AuthenticationController.java:86)
at org.longbox.businesslogic.controller.AuthenticationController.actionPerformed(AuthenticationController.java:45)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6620)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
at java.desktop/java.awt.Component.processEvent(Component.java:6385)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

reloadTable() method in ProfilePanel contains multiple smells

  • It is responsible for loading and reloading the data into the tables, and it is a large method.
  • UserDao, ComicBookReadingListDao and ComicBookFinishedListDao objects are being created multiple times, it should be a global object and that instance should be used for one session, currently multiple objects are being created.
  • Abstraction of client code and database not done as Dao’s are being used directly instead of through a service layer.
  • Similar names for readingList and readList, it was confusing to read the code, readingList can be renamed to finishedList.
  • Currently there is controller code inside the GUI code (mouseListener), this should be moved to the controller class.
  • Improper handling for UserIDDoesNotExistException.
  • Code duplication, the lists are being converted from entity type to Dto type in two steps, this can be done using the ComicBookMapper class, and code duplication can be removed.
  • Values for setBounds are hard coded, similar values can be clubbed together and converted to constants.
  • Long parameter list, variable of the same type can be clubbed together and be denoted by commas.

Too big method saveAddComicBookFromInput()

  • This feature uses a method called saveAddComicBookFromInput().
  • This method is big and there are multiple operations being performed in a single method.
  • The ComicBookDto object to be added is being constructed in the controller class itself, it can be moved to the GUI class and a method can be made to return the ComicBookDto object that must be returned. This would ensure that there is no long method changing done to extract text.
  • The way edge cases are handled is verbose and complex, also it is being handled when the object is being created, it should be done before creating the object.
  • The text resetting is done via a chain of method calls and can be confusing to read, this again can be converted to a method called clearFields() in the GUI class and a call can be made.
  • Multiple operations are being done at the same time, the favoriting of a comic book can have its separate method.
  • There is a method chaining done to get the state of Is Favorite checkbox, a getter can be used in its place.
  • Improper exception handling is done, the UserIDDoesNotExistException is being thrown instead it should be handled and appropriate error message should be shown to the user.
  • JOptionPane, a UI component is initialized inside the controller and business logic, it should be moved to the GUI class.

[BR10] Inadequate Error Logging in User Registration & Login Features

In the data access implementation and stub classes for user entities, the database access methods associated with the user service are only returning generic traces.

The suggested fix is to create more detailed stack traces in the error states and to perhaps use formal logging.

[BR6] Adding a comic book with number of issues or year published as text

Description:
If the number of issues or year published is left empty a NumberFormatException is thrown

Steps to reproduce:

  1. Login into the app using valid credentials.
  2. Navigate to the ‘Add Comic Page’
  3. In the year published/ number of issues enter text.
  4. Not selecting the is favorite checkbox.
  5. Clicking the ‘Enter Comic Book’ button.
  6. Error thrown in the console of compiler.
  7. Database not updated.

Suggested fix:
Setting the year published and number of issues to 0 (default value) if a value is not supplied

Error logs:

Text in Number of Issues:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "text"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:665)
at java.base/java.lang.Integer.parseInt(Integer.java:781)
at org.longbox.businesslogic.controller.HomeController.saveAddComicBookFormInput(HomeController.java:102)
at org.longbox.businesslogic.controller.HomeController.actionPerformed(HomeController.java:54)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6620)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
at java.desktop/java.awt.Component.processEvent(Component.java:6385)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Text in Year Published:
Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: "text"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:665)
at java.base/java.lang.Integer.parseInt(Integer.java:781)
at org.longbox.businesslogic.controller.HomeController.saveAddComicBookFormInput(HomeController.java:104)
at org.longbox.businesslogic.controller.HomeController.actionPerformed(HomeController.java:54)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6620)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
at java.desktop/java.awt.Component.processEvent(Component.java:6385)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

[BR5] Adding a comic book with number of issues or year published empty

Description:
If the number of issues or year published is left empty a NumberFormatException is thrown

Steps to reproduce:

  1. Login into the app using valid credentials.
  2. Navigate to the ‘Add Comic Page’
  3. Fill some fields (skipped number of issues and/or year published field).
  4. Not selecting the is favorite checkbox.
  5. Clicking the ‘Enter Comic Book’ button.
  6. Error thrown in the console of compiler
  7. Database not updated.

Suggested fix:
Setting the year published and number of issues to 0 (default value) if a value is not supplied

Error logs:

Empty Number of Issues:

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:675)
at java.base/java.lang.Integer.parseInt(Integer.java:781)
at org.longbox.businesslogic.controller.HomeController.saveAddComicBookFormInput(HomeController.java:102)
at org.longbox.businesslogic.controller.HomeController.actionPerformed(HomeController.java:54)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6620)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
at java.desktop/java.awt.Component.processEvent(Component.java:6385)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

Empty Year Published:

Exception in thread "AWT-EventQueue-0" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:675)
at java.base/java.lang.Integer.parseInt(Integer.java:781)
at org.longbox.businesslogic.controller.HomeController.saveAddComicBookFormInput(HomeController.java:104)
at org.longbox.businesslogic.controller.HomeController.actionPerformed(HomeController.java:54)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6620)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
at java.desktop/java.awt.Component.processEvent(Component.java:6385)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

[BR20] Use Dependency Injection to access Dao in ComicRepositoryPanel

The ComicRepositoryPanel class directly instantiates dependencies like ComicBookDaoImpl and ComicBookFavouritesListDaoImpl internally. This design choice can lead to tight coupling, making the code harder to maintain and test. Please try using dependency injection via the service layer promoting loose coupling and facilitating easier unit testing.

Improper abstraction of database form client code

Multiple instance of the code does not follow the abstraction, they are directly accessing the Dao directly instead of via the service layer. This can be found in:

  • ComicBookInfoController: Implementation of favourites button, reading button and finished button still directly communicate with Dao instead of via a service layer.

  • reloadTables() method of ProfilePanel.

  • actionPerformed() of ProfileController

[BR11] UserDto & User Entity Mapping Too Complex

In the org.longbox.domainobjects.dto.UserDto org.longbox.domainobjects.entity.User classes the mapping between dto and entity should not be done using constructors. It should be done using the mapping classes. Dto and entity are Java Beans and should only have NoArgsConstructors.

The suggested fix is to remove all overloaded constructors for both the UserDto and User entity classes. Only use setter methods and mapping classes to map between these two objects.

[BR19] Too big method initComicCollectionPage()

The initComicCollectionPage() method in the ComicRepositoryPanel class is too long and complex, which violates the Single Responsibility Principle (SRP) and makes the code harder to understand and maintain.
Impact:
Decreased readability: Large methods are harder to understand and navigate, especially for new developers or during code reviews.
Maintenance issues: Changes or updates to the functionality of this method can be challenging and error-prone due to its size and complexity.
Recommendation: Refactor the initComicCollectionPage() method into smaller, more focused methods that handle specific responsibilities. This will improve code organization, readability, and maintainability.

Code smells in actionPerformed() for ProfileController

  • The actionPerformed() method is big, all the business logic is inside the if cases, they should be handled by methods.
  • Strings are being compared for equality using ‘==’, while it should use the .equals() method since String is an object (non-primitive type).
  • We are abstracting the database layer from the client code by using a service layer, but code is communicating directly with the database, dependency injection should be used.
  • The UserDaoImpl object is being created multiple times, it should be a global object and that instance should be used for one session, currently multiple objects are being created.
  • There are repeated method (code duplication) calls, this can be converted into a method in the GUI class and that method can be called. As well as method chaining is being done.
    = The actionPerformed() is using nested if cases, which can be confusing to read and debug at times.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.