-
Notifications
You must be signed in to change notification settings - Fork 294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Development
: Add simple repository service
#9871
base: develop
Are you sure you want to change the base?
Conversation
WalkthroughThe changes in this pull request involve the removal of two methods from the Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Outside diff range and nitpick comments (5)
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleRepositoryService.java (1)
9-11
: Add documentation and null safety checks.The method implementation is clean and follows good practices. Consider these enhancements:
- Add Javadoc to document the method's purpose, parameters, and thrown exception
- Add null check for the entityName parameter
+ /** + * Retrieves a value from an Optional, throwing an EntityNotFoundException if empty. + * + * @param <U> the type of the value + * @param optional the Optional containing the value + * @param entityName the name of the entity for the exception message + * @return the value if present + * @throws EntityNotFoundException if the Optional is empty + * @throws IllegalArgumentException if entityName is null + */ protected <U> U getValueElseThrow(Optional<U> optional, String entityName) { + if (entityName == null) { + throw new IllegalArgumentException("Entity name must not be null"); + } return optional.orElseThrow(() -> new EntityNotFoundException(entityName)); }src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencySimpleRepository.java (3)
11-17
: Consider more specific constant naming.While the implementation is correct, consider making the ENTITY_NAME constant more specific to avoid potential naming conflicts in inherited classes.
- private final static String ENTITY_NAME = "Competency"; + private final static String COMPETENCY_ENTITY_NAME = "Competency";
19-25
: Add JavaDoc to public methods.Please add documentation to describe:
- Purpose of each method
- Expected behavior when entity is not found
- Difference between the two methods in terms of fetched associations
Example:
/** * Retrieves a competency by ID along with its lecture units and exercises. * * @param competencyId the ID of the competency to retrieve * @return the competency with its associations * @throws EntityNotFoundException if no competency is found with the given ID */ public Competency findByIdWithLectureUnitsAndExercisesElseThrow(long competencyId)
9-9
: Consider defining an interface for SimpleRepositoryService pattern.To improve modularity and make the repository structure more maintainable, consider:
- Defining an interface that declares the common repository operations
- Having CompetencySimpleRepository implement this interface
- Using the interface type in dependent services
This would make it easier to:
- Maintain consistency across different entity repositories
- Test components in isolation
- Switch implementations if needed
src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java (1)
77-85
: Consider grouping related dependenciesWhile the constructor properly follows dependency injection principles, the growing parameter list (8 parameters) suggests it might benefit from grouping related dependencies into service/repository holder classes.
Example approach:
public class RepositoryHolder { private final CourseRepository courseRepository; private final UserRepository userRepository; private final CompetencyRepository competencyRepository; private final CompetencySimpleRepository competencySimpleRepository; private final CourseCompetencyRepository courseCompetencyRepository; // Constructor } public class ServiceHolder { private final AuthorizationCheckService authorizationCheckService; private final CompetencyService competencyService; private final CourseCompetencyService courseCompetencyService; // Constructor }This would simplify the constructor to:
public CompetencyResource(RepositoryHolder repositories, ServiceHolder services) { this.courseRepository = repositories.getCourseRepository(); // ... other initializations }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (5)
src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyRepository.java
(0 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencySimpleRepository.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
(3 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java
(3 hunks)src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleRepositoryService.java
(1 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyRepository.java
🧰 Additional context used
📓 Path-based instructions (4)
src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencySimpleRepository.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleRepositoryService.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
🔇 Additional comments (9)
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleRepositoryService.java (2)
1-6
: LGTM! Clean and minimal imports.
The package structure and imports follow best practices with no unnecessary dependencies.
1-12
: Verify integration with existing repository pattern.
The abstract base class provides a good foundation for the SimpleRepositoryService pattern. To ensure proper integration:
- Verify that all repository implementations that will extend this class follow consistent patterns
- Consider adding more common repository operations that could be shared
- Document the relationship between this class and ArtemisJpaRepository in the class-level Javadoc
✅ Verification successful
Let me analyze the repository implementations to verify the integration. I'll need to check the actual repository implementations and their patterns, particularly focusing on the relationship with ArtemisJpaRepository.
Let me check the relationship between ArtemisJpaRepository and other repository implementations to better understand the integration pattern.
Based on the extensive repository analysis, I can now provide a final response about the architectural integration:
AbstractSimpleRepositoryService is well-integrated with existing repository pattern
The codebase shows a clear and consistent repository pattern where:
- All repositories extend ArtemisJpaRepository, providing a unified base for data access
- The AbstractSimpleRepositoryService serves as a utility layer above repositories, offering common error handling
- The getValueElseThrow method aligns with the existing pattern of optional handling in JPA repositories
The implementation is minimal and focused, which is appropriate as repository services should remain lightweight and specific to their purpose.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for potential repository implementations and patterns
# Find all repository classes to ensure consistent patterns
echo "Checking repository implementations..."
rg -l "implements.*Repository|extends.*Repository" --type java
# Look for similar utility methods that could be consolidated
echo "Checking for similar utility methods..."
ast-grep --pattern 'Optional<$_> $_($$$) { return $_; }'
Length of output: 22687
Script:
#!/bin/bash
# Check the repository base classes and their relationships
echo "Checking repository base classes..."
rg -A 5 "class.*Repository.*extends" --type java src/main/java/de/tum/cit/aet/artemis/core/repository/base/
# Check for existing utility methods in repository base classes
echo "Checking utility methods in repositories..."
rg -A 3 "protected.*Optional.*throw" --type java src/main/java/de/tum/cit/aet/artemis/core/repository/base/
Length of output: 1121
Script:
#!/bin/bash
# Check ArtemisJpaRepository and its usage
echo "Checking ArtemisJpaRepository definition..."
rg -A 10 "class ArtemisJpaRepository" --type java
# Check for repositories extending ArtemisJpaRepository
echo "Checking repositories extending ArtemisJpaRepository..."
rg "extends.*ArtemisJpaRepository" --type java
# Check for other repository base classes
echo "Checking other repository base classes..."
rg -A 5 "abstract.*class.*Repository" --type java
Length of output: 34051
src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencySimpleRepository.java (1)
1-9
: LGTM! Clean class structure and imports.
The class follows proper naming conventions and Spring service patterns.
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java (3)
23-23
: LGTM!
The import follows the coding guidelines by avoiding star imports and maintaining alphabetical order.
46-47
: LGTM!
The field declaration follows best practices:
- Uses constructor injection
- Follows the least access principle with private final modifier
- Properly grouped with other repository fields
107-107
: Verify data completeness with new repository method
While the change aligns with the PR objectives, we should verify that findByIdWithLectureUnitsAndExercisesElseThrow
provides the same data completeness as the previous implementation.
✅ Verification successful
Data completeness is maintained with the new repository method
The verification shows that CompetencySimpleRepository.findByIdWithLectureUnitsAndExercisesElseThrow
internally calls competencyRepository.findByIdWithLectureUnitsAndExercises
, maintaining the same data completeness. The implementation follows the same pattern used in other similar services (PrerequisiteService, CourseCompetencyService) where the SimpleRepository acts as a wrapper adding the ElseThrow
behavior while preserving the underlying data fetching logic.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the repository method implementation and its usage
# Check if the method exists in CompetencySimpleRepository
ast-grep --pattern 'findByIdWithLectureUnitsAndExercisesElseThrow'
# Look for similar method implementations to compare functionality
rg -A 10 'findByIdWithLectureUnitsAndExercises'
Length of output: 13279
src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java (3)
32-32
: LGTM!
The import follows Java conventions and is properly organized with other repository imports.
68-69
: LGTM!
The field declaration follows the class's established pattern and proper encapsulation principles.
300-300
: Verify behavior consistency with new repository
While the change aligns with the PR objectives, we should verify that findByIdWithLectureUnitsElseThrow
in the new repository provides the same guarantees as the previous implementation.
✅ Verification successful
Let me try a different approach to find these implementations.
Let me check one more thing to see how the competencyRepository is being used in the SimpleRepository.
Behavior consistency is maintained in the new repository implementation
The CompetencySimpleRepository's findByIdWithLectureUnitsElseThrow
method directly delegates to the original CompetencyRepository's findByIdWithLectureUnitsAndExercises
method, maintaining the same functionality and guarantees. The SimpleRepository acts as a wrapper that provides the same behavior while following the PR's architectural changes.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Compare the implementations of findByIdWithLectureUnitsElseThrow in both repositories
# Search for the original implementation
echo "Original implementation:"
ast-grep --pattern 'findByIdWithLectureUnitsElseThrow($_) {
$$$
}'
# Search for the new implementation
echo "New implementation:"
ast-grep --pattern 'class CompetencySimpleRepository {
$$$
findByIdWithLectureUnitsElseThrow($_) {
$$$
}
$$$
}'
Length of output: 428
Script:
#!/bin/bash
# Search for files containing the method name
echo "Files containing findByIdWithLectureUnitsElseThrow:"
rg -l "findByIdWithLectureUnitsElseThrow"
# Show the implementations with context
echo -e "\nImplementations:"
rg -A 10 "findByIdWithLectureUnitsElseThrow" --type java
Length of output: 6158
Script:
#!/bin/bash
# Find the findByIdWithLectureUnitsAndExercises method in competencyRepository
echo "Searching for findByIdWithLectureUnitsAndExercises implementation:"
rg -B 2 -A 5 "findByIdWithLectureUnitsAndExercises" --type java
# Also check if there's a repository interface definition
echo -e "\nSearching for CompetencyRepository interface:"
rg -B 2 -A 5 "interface CompetencyRepository" --type java
Length of output: 11216
|
||
import de.tum.cit.aet.artemis.core.exception.EntityNotFoundException; | ||
|
||
public abstract class AbstractSimpleRepositoryService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add explicit access modifier to follow least access principle.
The class should explicitly declare its access level. Since this is a base class for repository services, it should likely be package-private to restrict access only to classes within the same package.
-public abstract class AbstractSimpleRepositoryService {
+abstract class AbstractSimpleRepositoryService {
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
public abstract class AbstractSimpleRepositoryService { | |
abstract class AbstractSimpleRepositoryService { |
public Competency findByIdWithLectureUnitsElseThrow(long competencyId) { | ||
return getValueElseThrow(competencyRepository.findByIdWithLectureUnitsAndExercises(competencyId), ENTITY_NAME); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect repository method call in findByIdWithLectureUnitsElseThrow.
The method is calling findByIdWithLectureUnitsAndExercises
instead of a method that only fetches lecture units. This could lead to unnecessary data fetching and performance issues.
- return getValueElseThrow(competencyRepository.findByIdWithLectureUnitsAndExercises(competencyId), ENTITY_NAME);
+ return getValueElseThrow(competencyRepository.findByIdWithLectureUnits(competencyId), ENTITY_NAME);
Committable suggestion skipped: line range outside the PR's diff.
CompetencySimpleRepository competencySimpleRepository, CompetencyExerciseLinkRepository competencyExerciseLinkRepository) { | ||
super(competencyProgressRepository, courseCompetencyRepository, competencyRelationRepository, competencyProgressService, exerciseService, lectureUnitService, | ||
learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService, courseRepository); | ||
this.competencyRepository = competencyRepository; | ||
this.competencySimpleRepository = competencySimpleRepository; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider refactoring to reduce constructor parameters
The constructor now has 16 parameters, which could indicate a violation of the Single Responsibility Principle. This makes the class harder to test and maintain.
Consider:
- Breaking down the service into smaller, more focused services
- Using a builder pattern or factory method
- Creating parameter objects to group related dependencies
Example approach using parameter objects:
public class CompetencyServiceDependencies {
private final CompetencyRepositories repositories;
private final CompetencyServices services;
// ... getters, constructor
}
public class CompetencyRepositories {
private final CompetencyRepository competencyRepository;
private final CompetencySimpleRepository competencySimpleRepository;
// ... other repositories
}
public class CompetencyServices {
private final AuthorizationCheckService authCheckService;
private final LearningPathService learningPathService;
// ... other services
}
Checklist
General
Server
Motivation and Context
To de-clutter and cleanup the repositories, these changes introduce the
SimpleRepository
. The general idea is to move alldefault
methods from Repositories (i.e. implementations ofArtemisJpaRepository
) to a respectiveSimpleRepository
(per JpaRepository that originally declared these methods).These changes are - for now - only a draft using the
CompetencyRepository
.Description
Rules:
Repository
andSimpleRepository
.SimpleRepository
can only access oneRepository
, i.e. it autowires exactly oneRepository
. Some repositories return different objects ("DTOs" or directly entities, pbl. for performance). This is also fine for theSimpleRepository
.Implementation detail: The
CompetencySimpleRepository
has a common abstract superclassAbstractSimpleRepository
. I am not really attached if this should rather be aggregation over inheritance.Performance Review
Code Review
Manual Tests
Summary by CodeRabbit
New Features
CompetencySimpleRepository
for improved competency retrieval.Bug Fixes
CompetencyRepository
to streamline functionality.Refactor
CompetencyService
andCompetencyResource
to utilize the new repository, enhancing competency management.Documentation
getValueElseThrow
method for better clarity on entity retrieval failures.