-
Notifications
You must be signed in to change notification settings - Fork 301
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
Warning There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure. 🔧 pmd (7.8.0)src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.javaThe following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration. src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.javaThe following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration. src/main/java/de/tum/cit/aet/artemis/core/repository/base/ISimpleService.javaThe following rules are missing or misspelled in your ruleset file category/vm/bestpractices.xml: BooleanInstantiation, DontImportJavaLang, DuplicateImports, EmptyFinallyBlock, EmptyIfStmt, EmptyInitializer, EmptyStatementBlock, EmptyStatementNotInLoop, EmptySwitchStatements, EmptySynchronizedBlock, EmptyTryBlock, EmptyWhileStmt, ExcessiveClassLength, ExcessiveMethodLength, ImportFromSamePackage, MissingBreakInSwitch, SimplifyBooleanAssertion. Please check your ruleset configuration.
WalkthroughThis pull request introduces a significant refactoring of competency-related repositories and services in the Artemis platform. The primary changes involve removing default methods from repository interfaces like Changes
Sequence DiagramsequenceDiagram
participant Client
participant Resource
participant SimpleService
participant Repository
Client->>Resource: Request competency data
Resource->>SimpleService: Find competency
SimpleService->>Repository: Retrieve competency
Repository-->>SimpleService: Return optional competency
SimpleService->>SimpleService: Check and throw if not found
SimpleService-->>Resource: Return competency
Resource-->>Client: Return competency data
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
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleRepositoryService.java
Outdated
Show resolved
Hide resolved
src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencySimpleRepository.java
Outdated
Show resolved
Hide resolved
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
Outdated
Show resolved
Hide resolved
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: 5
🧹 Outside diff range and nitpick comments (27)
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleService.java (3)
8-11
: Consider enhancing the class documentation.While the current documentation is clear, it could be more comprehensive by including:
@param <T>
documentation explaining the generic type parameter- Usage examples
- More details about the intended use cases and benefits
/** * Abstract base for simple (repository) services. These are services on repository * layer which contain the default methods of the repository layer/data access. + * + * @param <T> the domain object type this service handles, must extend DomainObject + * @see DomainObject + * + * Example usage: + * <pre> + * public class UserSimpleService extends AbstractSimpleService<User> { + * // Implementation specific to User entity + * } + * </pre> */
12-12
: Well-designed class structure!The abstract class with bounded generic type provides a solid foundation for repository services. This design promotes:
- Type safety through bounded generics
- Code reuse through inheritance
- Clear separation of concerns
Consider adding interfaces for different repository capabilities (e.g.,
Searchable
,Sortable
) to allow for more flexible composition of repository features.
14-16
: Consider enhancing error handling and parameter validation.The method implementation is clean and follows good practices. However, consider these improvements:
- protected <U extends T> U getValueElseThrow(Optional<U> optional, String entityName) { - return optional.orElseThrow(() -> new EntityNotFoundException(entityName)); + protected <U extends T> U getValueElseThrow(Optional<U> optional, String entityName) { + if (entityName == null || entityName.isBlank()) { + throw new IllegalArgumentException("Entity name must not be null or blank"); + } + return optional.orElseThrow(() -> + new EntityNotFoundException(String.format("%s with given criteria not found", entityName))); }This change:
- Adds parameter validation
- Provides more descriptive error messages
- Maintains the clean implementation while improving robustness
src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.java (3)
16-22
: Consider field visibility and naming conventions.The implementation looks good, but consider these minor improvements:
- Add
private
modifier toENTITY_NAME
to follow the principle of least access- Follow Java naming convention by removing the underscore:
private static final String ENTITYNAME
- private final static String ENTITY_NAME = "Competency"; + private static final String ENTITYNAME = "Competency";
24-26
: Consider adding Javadoc for eager loading behavior.Add documentation to clarify that this method eagerly loads both lecture units and exercises, which could impact performance for large datasets.
+ /** + * Finds a competency by ID with eagerly loaded lecture units and exercises. + * Note: This method performs eager loading which might impact performance for large datasets. + * + * @param competencyId the ID of the competency to find + * @return the competency with its lecture units and exercises + * @throws RuntimeException if the competency is not found + */ public Competency findByIdWithLectureUnitsAndExercisesElseThrow(long competencyId) {
24-30
: Consider performance implications of eager loading.Both methods use eager loading which could lead to N+1 query problems. Consider:
- Adding query optimization hints or join fetch in the repository methods
- Implementing lazy loading alternatives for cases where the related entities aren't needed
- Adding pagination support for large datasets
src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleServiceArchitectureTest.java (1)
40-41
: Consider documenting the architectural decision.While the change to allow services in
repository.simple
package aligns with the PR's objective of introducingSimpleRepository
, it represents a significant architectural decision that deviates from traditional package structuring. Consider adding a comment explaining the rationale behind this exception.- ArchRule rule = classesOfThisModuleThat().areAnnotatedWith(Service.class).should().resideInAPackage("..service..").orShould().resideInAPackage("..repository.simple..") - .because("services should be in the package 'service'."); + // Allow services in repository.simple package to support the SimpleRepository pattern + // which provides default repository operations through service classes + ArchRule rule = classesOfThisModuleThat().areAnnotatedWith(Service.class) + .should().resideInAPackage("..service..") + .orShould().resideInAPackage("..repository.simple..") + .because("services should be in the service package, with an exception for SimpleRepository services");src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java (3)
42-45
: Fix parameter naming inconsistencyThe parameter name
courseCompetencySimpleRepository
doesn't match its typeCourseCompetencySimpleService
. This could lead to confusion about the actual type of the dependency.- CourseCompetencySimpleService courseCompetencySimpleRepository, + CourseCompetencySimpleService courseCompetencySimpleService,
41-48
: Consider breaking down the service responsibilitiesThe constructor has 15 dependencies, which suggests this service might be violating the Single Responsibility Principle. Consider:
- Breaking down the service into smaller, more focused services
- Creating a facade or composite service if these dependencies are truly needed
- Using a builder pattern for complex object construction
This would improve maintainability and testability of the code.
46-48
: Consider grouping related dependencies in the super callThe super constructor call could be more organized by grouping related services together. For example:
- Core services (competency, progress)
- Infrastructure services (repositories)
- Support services (authorization, import)
This would make the code more maintainable and easier to understand.
super(competencyProgressRepository, courseCompetencyRepository, courseCompetencySimpleRepository, competencyRelationRepository, competencyProgressService, exerciseService, lectureUnitService, learningPathService, authCheckService, standardizedCompetencyRepository, lectureUnitCompletionRepository, learningObjectImportService, courseRepository); + // Group related services in super call: + // Core competency services + super(competencyProgressService, + courseCompetencySimpleService, + competencyProgressRepository, + courseCompetencyRepository, + competencyRelationRepository, + // Learning services + learningPathService, + lectureUnitService, + exerciseService, + // Infrastructure + authCheckService, + standardizedCompetencyRepository, + lectureUnitCompletionRepository, + // Support services + learningObjectImportService, + courseRepository);src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java (1)
109-109
: Update variable reference after field renameThe implementation correctly delegates to the new service layer, but ensure to update the variable reference after renaming the field:
- Competency competency = competencySimpleRepository.findByIdWithLectureUnitsAndExercisesElseThrow(competencyId); + Competency competency = competencySimpleService.findByIdWithLectureUnitsAndExercisesElseThrow(competencyId);src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleRepositoryArchitectureTest.java (2)
311-329
: Add timeline and conditions for enabling the testWhile the test implementation is correct, it's currently disabled without clear criteria for when it should be enabled. Consider:
- Adding a TODO comment with conditions that need to be met before enabling
- Creating a tracking issue for enabling this test once all repositories are migrated
Enhance the test documentation
The test description could be more detailed to explain:
- Why default methods should be avoided in repositories
- The relationship with SimpleService pattern
- Migration strategy for existing default methods
- /** - * Disabled for now. - * Enforce that no default methods are declared in the JPARepository interfaces. - * Instead, one should use/create a SimpleService in the 'simple'-subpackage. - */ + /** + * Enforces that no default methods are declared in the JPARepository interfaces to maintain + * a clear separation of concerns. Instead of default methods in repositories, functionality + * should be moved to dedicated SimpleService classes in the 'simple'-subpackage. + * + * This promotes: + * - Better separation of concerns (repositories for data access, services for business logic) + * - Improved testability through proper dependency injection + * - Consistent architectural patterns across the codebase + * + * Currently disabled until all existing repositories are migrated to use SimpleService pattern. + * Track progress in issue: TODO-ADD-ISSUE-LINK + */
310-310
: Document the SimpleService patternConsider adding class-level documentation to explain the SimpleService architectural pattern being enforced. This would help developers understand:
- The motivation behind the pattern
- How it relates to the repository layer
- Best practices for implementation
+ /** + * Architectural tests for enforcing repository and service patterns. + * + * The SimpleService Pattern: + * - Purpose: Provides a clean separation between data access (repositories) and common data operations + * - Structure: Each SimpleService wraps exactly one repository and provides common operations + * - Benefits: + * - Removes default methods from repositories + * - Centralizes common data access patterns + * - Improves testability and maintainability + * - Usage: + * - Place SimpleServices in the repository.simple package + * - Inject exactly one repository via constructor + * - Keep the service focused on common data operations + */src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java (2)
80-81
: Consider splitting the resource class to reduce constructor parameters.The constructor now has 9 dependencies, which might indicate that the class has too many responsibilities. Consider splitting this into smaller, more focused resource classes (e.g.,
CompetencyManagementResource
,CompetencyImportResource
).Example split:
@RestController @RequestMapping("api/courses/{courseId}/competencies/import") public class CompetencyImportResource { private final CourseRepository courseRepository; private final AuthorizationCheckService authorizationCheckService; private final CourseCompetencySimpleService courseCompetencySimpleRepository; private final CompetencyService competencyService; // Import-related endpoints... }Also applies to: 87-87, 90-90
193-193
: Consider more generic method names in simple services.The method names in simple services are very specific to use cases (e.g.,
findByIdWithExercisesAndLectureUnitsAndLecturesElseThrow
). Consider using more generic names with optional parameters or separate methods for different fetch strategies.Example approach:
public interface CompetencySimpleService { Competency findById(Long id, FetchOptions... options); // Where FetchOptions is an enum: EXERCISES, LECTURE_UNITS, LECTURES, etc. }Also applies to: 305-305, 326-326
src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java (3)
33-33
: Rename variable to match service naming conventionThe variable name
courseCompetencySimpleRepository
doesn't match its typeCourseCompetencySimpleService
. Consider renaming it tocourseCompetencySimpleService
for consistency.- private final CourseCompetencySimpleService courseCompetencySimpleRepository; + private final CourseCompetencySimpleService courseCompetencySimpleService;Also applies to: 76-76
Line range hint
325-331
: Consider enhancing logging for deletion operationThe deletion logic looks good with proper authorization and validation. Consider adding more detailed logging to track what was deleted.
- log.info("REST request to delete a Prerequisite : {}", prerequisiteId); + log.info("REST request to delete Prerequisite [id: {}, title: {}] from Course [id: {}]", + prerequisiteId, prerequisite.getTitle(), courseId);
Line range hint
1-371
: Consider documenting the SimpleService abstraction patternThe transition to using
CourseCompetencySimpleService
is part of a larger architectural change to streamline repository access. Consider adding documentation (e.g., in README or wiki) explaining:
- The purpose and benefits of the SimpleService abstraction
- When to use SimpleService vs direct repository access
- Guidelines for implementing new SimpleService classes
src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java (2)
95-96
: Consider renaming the field to better reflect its service nature.The variable name
courseCompetencySimpleRepository
suggests it's a repository while it's actually a service. Consider renaming it tocourseCompetencySimpleService
to maintain consistency with the service-oriented architecture.- private final CourseCompetencySimpleService courseCompetencySimpleRepository; + private final CourseCompetencySimpleService courseCompetencySimpleService;
Line range hint
103-114
: Maintain consistent parameter naming with its type.The parameter name should reflect that it's a service, not a repository, to maintain consistency with its type and usage.
- CourseCompetencySimpleService courseCompetencySimpleRepository, + CourseCompetencySimpleService courseCompetencySimpleService,src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java (3)
68-69
: Consider making field final and improving naming conventionThe field follows proper encapsulation, but consider:
- Making it
final
to ensure immutability after injection- Renaming from
courseCompetencySimpleRepository
tocourseCompetencySimpleService
to match the actual type and maintain consistency with service naming conventions- private final CourseCompetencySimpleService courseCompetencySimpleRepository; + private final CourseCompetencySimpleService courseCompetencySimpleService;
120-121
: Consider adding Javadoc for the SimpleService usageThe method implementation has changed to use the new
SimpleService
. Consider adding documentation to explain:
- Why the implementation was changed to use
SimpleService
- What benefits this brings (e.g., standardized error handling, simplified repository access)
public CourseCompetency findCompetencyWithExercisesAndLectureUnitsAndProgressForUser(Long competencyId, Long userId) { + // Using SimpleService for standardized repository access and error handling CourseCompetency competency = courseCompetencySimpleRepository.findByIdWithLectureUnitsAndExercisesElseThrow(competencyId); return findProgressAndLectureUnitCompletionsForUser(competency, userId); }
Line range hint
1-450
: Consider architectural improvements for the service layerThe service class has grown quite large (450+ lines) and handles multiple responsibilities. Consider:
- Breaking it down into smaller, focused services
- Extracting common functionality into abstract base classes
- Using composition over inheritance for better maintainability
This aligns with the PR's objective of streamlining the repository structure and could be extended to the service layer.
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyProgressService.java (1)
Line range hint
1-600
: Consider extracting calculation components into separate classesThe class handles multiple complex calculations (progress, confidence, various heuristics) which could be extracted into separate strategy classes to improve maintainability and testability.
Additionally, consider extracting magic numbers into named constants, particularly in the confidence calculation methods.
Example structure:
public interface ConfidenceHeuristicCalculator { double calculate(Set<CompetencyExerciseMasteryCalculationDTO> participantScores); } public class RecencyConfidenceCalculator implements ConfidenceHeuristicCalculator { private static final int MIN_EXERCISES = 3; // ... other constants @Override public double calculate(Set<CompetencyExerciseMasteryCalculationDTO> participantScores) { // ... existing recency calculation logic } }src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java (1)
29-31
: Consider adding JavaDoc comments to public methodsThe method
findByIdWithExercisesAndLectureUnitsAndLecturesElseThrow
lacks a JavaDoc comment. Adding documentation will enhance code readability and maintainability.src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathRecommendationService.java (2)
36-36
: Verify the package structure for service classesThe
CourseCompetencySimpleService
is imported from therepository.simple
package. Since this is a service class, consider moving it to aservice
package to better reflect its role and maintain a clear separation between repositories and services.
699-699
: Separate repository and service responsibilitiesAt line 699, the method
findByIdWithExercisesAndLectureUnitsElseThrow
is called oncourseCompetencySimpleRepository
, which is of typeCourseCompetencySimpleService
. This method performs data access operations typical of a repository. To adhere to the single responsibility principle and clean architecture practices, consider moving data access methods to a repository class and using the service class for business logic.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (14)
src/main/java/de/tum/cit/aet/artemis/atlas/repository/CourseCompetencyRepository.java
(0 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyProgressService.java
(5 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/service/competency/CourseCompetencyService.java
(4 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
(2 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathRecommendationService.java
(4 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java
(5 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java
(4 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java
(4 hunks)src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleService.java
(1 hunks)src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleRepositoryArchitectureTest.java
(3 hunks)src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleServiceArchitectureTest.java
(1 hunks)
💤 Files with no reviewable changes (1)
- src/main/java/de/tum/cit/aet/artemis/atlas/repository/CourseCompetencyRepository.java
🧰 Additional context used
📓 Path-based instructions (13)
src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.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/repository/simple/CourseCompetencySimpleService.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/CompetencyProgressService.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/service/competency/CourseCompetencyService.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/PrerequisiteService.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/learningpath/LearningPathRecommendationService.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/atlas/web/CourseCompetencyResource.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/PrerequisiteResource.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/AbstractSimpleService.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/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleRepositoryArchitectureTest.java (1)
Pattern src/test/java/**/*.java
: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true
src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleServiceArchitectureTest.java (1)
Pattern src/test/java/**/*.java
: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true
📓 Learnings (2)
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyProgressService.java (1)
Learnt from: julian-christl
PR: ls1intum/Artemis#8052
File: src/test/java/de/tum/in/www1/artemis/lecture/CompetencyIntegrationTest.java:310-310
Timestamp: 2024-11-12T12:51:58.050Z
Learning: Modifications to parameters in `competencyProgressUtilService.createCompetencyProgress` for debugging purposes are considered irrelevant to the test outcomes but helpful for clarity during debugging.
src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java (1)
Learnt from: julian-christl
PR: ls1intum/Artemis#8052
File: src/test/java/de/tum/in/www1/artemis/lecture/CompetencyIntegrationTest.java:310-310
Timestamp: 2024-11-12T12:51:58.050Z
Learning: Modifications to parameters in `competencyProgressUtilService.createCompetencyProgress` for debugging purposes are considered irrelevant to the test outcomes but helpful for clarity during debugging.
🔇 Additional comments (26)
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleService.java (1)
1-7
: LGTM! Clean and minimal imports.
The package structure and imports follow Java best practices with specific imports and proper organization.
src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.java (3)
1-11
: LGTM: Package structure and imports are well-organized.
The imports are specific and follow the Java coding guidelines.
12-14
: LGTM: Class structure aligns with the PR objectives.
The class is properly annotated and extends the correct base class to implement the SimpleRepository pattern.
28-30
:
Fix incorrect repository method call.
The method findByIdWithLectureUnitsElseThrow
is incorrectly using findByIdWithLectureUnitsAndExercises
, which loads more data than necessary. This could lead to performance issues.
public Competency findByIdWithLectureUnitsElseThrow(long competencyId) {
- return getValueElseThrow(competencyRepository.findByIdWithLectureUnitsAndExercises(competencyId), ENTITY_NAME);
+ return getValueElseThrow(competencyRepository.findByIdWithLectureUnits(competencyId), ENTITY_NAME);
}
Let's verify if the correct repository method exists:
✅ Verification successful
The review comment is correct - method should use findByIdWithLectureUnits
The repository interface shows both methods exist:
findByIdWithLectureUnits
: Fetches competency with lecture units onlyfindByIdWithLectureUnitsAndExercises
: Fetches competency with both lecture units AND exercises
Since the service method is named findByIdWithLectureUnitsElseThrow
, it should only load lecture units data. The current implementation loads unnecessary exercise data which could impact performance. The suggested fix to use findByIdWithLectureUnits
is correct.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for the repository method definition
ast-grep --pattern 'interface CompetencyRepository {
$$$
Optional<Competency> findByIdWithLectureUnits($_) {
$$$
}
$$$
}'
Length of output: 259
Script:
#!/bin/bash
# Let's try a different approach to find the repository interface and its methods
rg -A 5 "interface CompetencyRepository"
Length of output: 765
Script:
#!/bin/bash
# Let's see the entire content of the repository file to check available methods
cat src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyRepository.java
Length of output: 2381
src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleServiceArchitectureTest.java (1)
40-41
: Verify the impact on existing architecture tests.
The change to allow services in the repository package might affect other architecture tests or rules. Let's verify there are no conflicting rules.
✅ Verification successful
Let me gather more information to verify if there are any conflicting rules in the architecture tests.
The architecture rules are consistent with the change
The change to allow services in the repository.simple
package is actually well-aligned with the existing architecture rules. The search results show:
- The service package rule explicitly includes an exception for
repository.simple
packages - There's a specific test in
AbstractModuleRepositoryArchitectureTest
that validates services inrepository.simple
packages, enforcing they should have a single repository autowired - No conflicting rules were found that would prevent services from residing in the
repository.simple
package
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other architecture tests that might have conflicting package rules
rg -l "resideInAPackage.*service" src/test/java/de/tum/cit/aet/artemis/shared/architecture/
# Search for existing services in the repository.simple package to validate the rule
ast-grep --pattern 'class $_ {
$$$
@Service
$$$
}' src/main/java/de/tum/cit/aet/artemis/**/repository/simple/
Length of output: 321
Script:
#!/bin/bash
# Let's examine the content of the architecture test file to check for any conflicting rules
rg -A 5 -B 5 "resideInAPackage.*service" src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleServiceArchitectureTest.java
# Let's also check if there are any other rules related to repository package
rg -A 5 -B 5 "resideInAPackage.*repository" src/test/java/de/tum/cit/aet/artemis/shared/architecture/
Length of output: 11005
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java (2)
22-22
: LGTM!
The import statement follows the coding guidelines by avoiding star imports and maintains proper organization within the repository-related imports section.
41-48
: Verify the integration with SimpleRepository pattern
The changes align with the PR objectives of introducing the SimpleRepository pattern. However, let's verify that all necessary methods from ArtemisJpaRepository are properly delegated to the SimpleRepository.
✅ Verification successful
Let me gather more information about the SimpleRepository pattern implementation.
Let me try a different approach to find the SimpleRepository pattern implementation.
Let me check the AbstractSimpleService implementation and the actual methods being used.
SimpleRepository pattern integration is correctly implemented
The implementation aligns with the SimpleRepository pattern and is properly integrated:
- CourseCompetencySimpleService extends AbstractSimpleService and provides specialized finder methods
- All necessary repository methods are delegated through the SimpleService
- The service is being used correctly across the codebase for fetching competencies with various relationships
- The pattern maintains clean separation of concerns while providing convenient access to domain objects
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if all necessary methods from ArtemisJpaRepository are available in SimpleRepository
# Find all method calls to courseCompetencyRepository in the service
rg -A 2 "courseCompetencyRepository\." src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/
# Find corresponding methods in SimpleRepository
ast-grep --pattern 'interface $REPO extends ArtemisJpaRepository {
$$$
}' src/main/java/de/tum/cit/aet/artemis/atlas/repository/
Length of output: 6481
Script:
#!/bin/bash
# Find the SimpleRepository interface and its methods
ast-grep --pattern 'interface CourseCompetencySimpleService {
$$$
}'
# Check the implementation class
ast-grep --pattern 'class $CLASS implements CourseCompetencySimpleService {
$$$
}'
# Find the base repository interface
ast-grep --pattern 'interface CourseCompetencyRepository extends $_ {
$$$
}'
Length of output: 612
Script:
#!/bin/bash
# Search for files containing CourseCompetencySimpleService
fd CourseCompetencySimpleService
# Search for repository pattern implementation
rg -l "CourseCompetencySimpleService" src/main/java/
# Look for method implementations
rg -A 5 "class.*CourseCompetencySimpleService" src/main/java/
Length of output: 1834
Script:
#!/bin/bash
# Check AbstractSimpleService implementation
rg -A 10 "class AbstractSimpleService" src/main/java/
# Check CourseCompetencySimpleService implementation details
cat src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
# Find usages of CourseCompetencySimpleService methods
rg -A 2 "courseCompetencySimpleRepository\." src/main/java/
Length of output: 8095
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java (2)
25-26
: LGTM: Imports follow guidelines
The new imports are specific and follow Java naming conventions, avoiding star imports as per coding guidelines.
52-61
: 🛠️ Refactor suggestion
Constructor has too many parameters
The constructor now has 16 parameters, making it harder to maintain and test. This issue was previously identified and the suggestion to use parameter objects is still valid.
Additionally, ensure the field name change is reflected in the constructor:
- CompetencySimpleService competencySimpleRepository
+ CompetencySimpleService competencySimpleService
src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleRepositoryArchitectureTest.java (1)
11-11
: LGTM: Imports are well-organized and necessary
The new imports are correctly organized and required for the new architectural test methods.
Also applies to: 18-18, 32-32, 35-36
src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java (2)
33-34
: LGTM! Clean dependency declarations following best practices.
The new service dependencies are properly declared as private final fields, following constructor injection pattern and immutability principles.
Also applies to: 69-70, 75-76
193-193
: Verify repository method replacements across the codebase.
The changes replace direct repository access with simple service methods. Let's verify that all callers are updated consistently.
Also applies to: 305-305, 326-326
✅ Verification successful
Repository method replacements are consistently updated across the codebase
The search results show that all repository method calls related to findByIdWithExercisesAndLectureUnits
and similar methods are properly using the simple service layer. The changes in CompetencyResource.java
align with the overall pattern where:
- Direct repository access is replaced with simple service methods
- All callers are consistently using the simple service layer (
courseCompetencySimpleRepository
,competencySimpleRepository
) - No instances of direct repository access for these methods were found outside of the repository classes themselves
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for direct repository method calls that should use simple services
echo "Searching for direct repository calls that should use simple services..."
rg "findByIdWithExercisesAndLectureUnits|findByIdWithLectureUnits" --type java
echo "Searching for simple service usage to verify consistent adoption..."
rg "competencySimpleRepository\.|courseCompetencySimpleRepository\." --type java
Length of output: 21622
src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java (2)
82-89
: LGTM: Constructor follows proper dependency injection pattern
The constructor properly initializes all dependencies and follows Spring's constructor injection pattern.
192-192
: Verify authorization checks across all import paths
The authorization check and error handling look good. However, let's verify that similar authorization checks exist in other import-related endpoints.
✅ Verification successful
Authorization checks are properly implemented across all import paths
After reviewing the file, I can confirm that all import-related endpoints have proper authorization checks:
importPrerequisite
: Has@EnforceAtLeastInstructorInCourse
and additional check for editor role in source courseimportPrerequisites
: Has@EnforceAtLeastEditorInCourse
and checks editor role in source coursesimportAllPrerequisitesFromCourse
: Has@EnforceAtLeastInstructorInCourse
and checks editor role in source courseimportStandardizedPrerequisites
: Has@EnforceAtLeastEditorInCourse
Each method also includes additional validation checks and proper error handling for invalid scenarios.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent authorization checks in import-related endpoints
# Look for @EnforceAtLeast annotations and authorizationCheckService usage in import methods
rg -A 2 "import.*Prerequisites?" src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java | grep -E "@Enforce|authorizationCheckService"
Length of output: 154
Script:
#!/bin/bash
# Let's first check the entire PrerequisiteResource file content to understand the authorization context
cat src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java
Length of output: 20891
src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java (2)
41-41
: LGTM!
The import statement follows Java conventions and is properly organized with other repository/service imports.
222-222
: LGTM!
The change to use courseCompetencySimpleRepository
aligns with the PR objective while maintaining existing security and validation checks.
Let's verify that this is the only occurrence of this method call:
✅ Verification successful
The method name is used consistently across different repositories
The search results show that findByIdWithExercisesElseThrow
is a common pattern used across different repository classes (StudentExamRepository
, ExerciseGroupRepository
, CourseCompetencySimpleService
), each implementing it for their respective domain entities. The change to use courseCompetencySimpleRepository
is isolated to the competency-related code and doesn't affect other repository implementations.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for any other occurrences of findByIdWithExercisesElseThrow
rg "findByIdWithExercisesElseThrow" -A 2
Length of output: 4879
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java (3)
37-37
: LGTM: Import follows Java conventions
The import statement for CourseCompetencySimpleService
is properly organized and follows Java conventions.
91-97
: Verify constructor parameter ordering
The constructor follows proper dependency injection patterns, but consider:
- Grouping related dependencies together (repositories, services)
- Maintaining a consistent order between parameter declaration and field assignment
120-120
: Verify error handling in the SimpleService call
The method findByIdWithLectureUnitsAndExercisesElseThrow
suggests it throws an exception, but we should verify:
- The exception type matches the service's error handling strategy
- The exception contains appropriate error details for API responses
✅ Verification successful
Based on the gathered information, I can now provide a final response regarding the error handling verification:
Error handling in findByIdWithLectureUnitsAndExercisesElseThrow
follows service standards
The error handling implementation is appropriate because:
- The method uses the standard
getValueElseThrow
pattern fromAbstractSimpleService
- It throws
EntityNotFoundException
which is properly annotated with@ResponseStatus(HttpStatus.NOT_FOUND)
- The exception includes descriptive messages with entity name and identifier
- The error details are suitable for API responses as the exception automatically maps to HTTP 404
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check the implementation of findByIdWithLectureUnitsAndExercisesElseThrow
ast-grep --pattern 'class CourseCompetencySimpleService {
$$$
findByIdWithLectureUnitsAndExercisesElseThrow($_) {
$$$
}
}'
Length of output: 258
Script:
#!/bin/bash
# Let's try a different approach to find the repository implementation
rg -A 10 "findByIdWithLectureUnitsAndExercisesElseThrow" --type java
Length of output: 7885
Script:
#!/bin/bash
# Let's check the base class to understand the error handling strategy
rg -A 5 "class SimpleService" --type java
# Also check the getValueElseThrow implementation
rg -A 5 "getValueElseThrow" --type java
Length of output: 112614
Script:
#!/bin/bash
# Let's check the implementation of EntityNotFoundException
rg -A 5 "class EntityNotFoundException" --type java
# Also check the base class AbstractSimpleService
rg -A 10 "class AbstractSimpleService" --type java
Length of output: 1526
Script:
#!/bin/bash
# Let's check the full implementation of EntityNotFoundException to understand error details
cat src/main/java/de/tum/cit/aet/artemis/core/exception/EntityNotFoundException.java
# Also check if there's a global exception handler that might format these exceptions
rg -A 10 "EntityNotFoundException" --type java --glob "*ExceptionHandler.java"
Length of output: 1147
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyProgressService.java (2)
34-34
: LGTM: Clean dependency injection implementation
The addition of CourseCompetencySimpleService
follows best practices with:
- Proper constructor injection
- Final field declaration
- Consistent naming convention
Also applies to: 66-66, 81-82, 88-88
111-111
: Verify consistent repository usage pattern
The migration to courseCompetencySimpleRepository
is implemented correctly in both sync and async methods. However, let's verify that this pattern is consistently applied across the codebase.
Also applies to: 190-190
✅ Verification successful
Based on the code analysis, I can now generate the final response:
Migration to CourseCompetencySimpleService is correctly implemented
The codebase shows that the migration to courseCompetencySimpleRepository
is consistent and properly implemented. The findAllIdsByLearningObject
method in CourseCompetencySimpleService
correctly delegates to the appropriate repository method based on the learning object type, maintaining the same behavior as the original implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify consistent usage of CourseCompetencySimpleService vs CourseCompetencyRepository
# Search for direct repository usage that might need migration
rg -A 2 "CourseCompetencyRepository.*findAllIdsByLearningObject|CourseCompetencyRepository.*findAllByLearningObject"
# Search for similar patterns that might need to be migrated
ast-grep --pattern 'courseCompetencyRepository.find$$$ByLearningObject($$$)'
Length of output: 321
Script:
#!/bin/bash
# Let's try a broader search to find any references to CourseCompetencyRepository
rg -l "CourseCompetencyRepository"
# Also search for the new SimpleRepository usage
rg -l "CourseCompetencySimpleRepository"
# And look for any findByLearningObject patterns more broadly
rg "findByLearningObject|findAllByLearningObject"
Length of output: 1306
Script:
#!/bin/bash
# Let's examine the content of the repository and service files to understand the pattern
cat src/main/java/de/tum/cit/aet/artemis/atlas/repository/CourseCompetencyRepository.java
cat src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
# Also check the CompetencyProgressService implementation
cat src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyProgressService.java
Length of output: 49448
src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java (5)
21-24
: Proper use of constructor injection and encapsulation
The courseCompetencyRepository
is correctly injected via constructor injection and declared as private final
, adhering to dependency injection best practices.
33-35
: Duplicate comment: Missing JavaDoc comments on public methods
This method also lacks a JavaDoc comment. Consistently documenting public methods is advisable.
37-39
: Duplicate comment: Missing JavaDoc comments on public methods
This method lacks a JavaDoc comment as well.
55-57
: Duplicate comment: Missing JavaDoc comments on public methods
Consider adding a JavaDoc comment to improve documentation.
59-61
: Duplicate comment: Missing JavaDoc comments on public methods
Adding JavaDoc comments to public methods enhances clarity.
src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
Outdated
Show resolved
Hide resolved
...tum/cit/aet/artemis/shared/architecture/module/AbstractModuleRepositoryArchitectureTest.java
Outdated
Show resolved
Hide resolved
src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
Show resolved
Hide resolved
...ava/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathRecommendationService.java
Outdated
Show resolved
Hide resolved
...ava/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathRecommendationService.java
Outdated
Show resolved
Hide resolved
There hasn't been any activity on this pull request recently. Therefore, this pull request has been automatically marked as stale and will be closed if no further activity occurs within seven days. Thank you for your contributions. |
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.
One suggestion to ensure a more uniform implementation of the abstract base class.
Overall design: What possible methods do you envision that would require the abstract class rather than an interface? With this example, as far as I can tell all the relevant methods could be declared and provided via a default implementation in the ArtemisJpaRepository
interface instead.
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleService.java
Outdated
Show resolved
Hide resolved
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: 1
🔭 Outside diff range comments (1)
src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java (1)
Line range hint
228-231
: Consider using SimpleService in importPrerequisites method.For consistency with other methods, consider updating this method to use
courseCompetencySimpleService
instead of directly accessing the repository.Apply this diff:
- Set<CourseCompetency> prerequisitesToImport = courseCompetencyRepository.findAllByIdWithExercisesAndLectureUnitsAndLecturesAndAttachments(importOptions.competencyIds()); + Set<CourseCompetency> prerequisitesToImport = courseCompetencySimpleService.findAllByIdWithExercisesAndLectureUnitsAndLecturesAndAttachmentsElseThrow(importOptions.competencyIds());
🧹 Nitpick comments (4)
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleService.java (4)
8-11
: Enhance class documentation with standard JavaDoc tagsWhile the current documentation explains the purpose, consider adding:
@param <T>
to document the generic type parameter@since
to indicate when this class was introduced/** * Abstract base for simple (repository) services. These are services on repository * layer which contain the default methods of the repository layer/data access. + * + * @param <T> the domain object type this service handles + * @since 0.1 */
14-14
: Add JavaDoc for abstract method contractThe abstract method should be documented to clearly specify the contract that implementing classes must follow.
+ /** + * Returns the name of the entity type handled by this service. + * This name is used in error messages when entities are not found. + * + * @return the entity type name as a string + */ protected abstract String getEntityName();
16-22
: Add JavaDoc for helper methodsThe helper methods should be documented to explain their purpose and behavior.
+ /** + * Retrieves a value from an Optional or throws an EntityNotFoundException. + * Uses the entity name from getEntityName(). + * + * @param <U> the specific type of the entity + * @param optional the Optional containing the entity + * @return the entity if present + * @throws EntityNotFoundException if the entity is not present + */ protected <U extends T> U getValueElseThrow(Optional<U> optional) { return getValueElseThrow(optional, getEntityName()); } + /** + * Retrieves a value from an Optional or throws an EntityNotFoundException. + * + * @param <U> the specific type of the entity + * @param optional the Optional containing the entity + * @param entityName the name of the entity for the error message + * @return the entity if present + * @throws EntityNotFoundException if the entity is not present + */ protected <U extends T> U getValueElseThrow(Optional<U> optional, String entityName) { return optional.orElseThrow(() -> new EntityNotFoundException(entityName)); }The implementation is clean, follows best practices, and provides good error handling.
1-23
: Consider future extensibility of the SimpleService patternAs this class serves as the foundation for the SimpleService pattern, consider:
- Adding lifecycle hooks (e.g.,
beforeSave
,afterLoad
) for cross-cutting concerns- Implementing audit logging for entity operations
- Adding support for batch operations to improve performance when dealing with collections
These considerations will help maintain consistency as more repository implementations adopt this pattern.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyProgressService.java
(5 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/service/competency/CourseCompetencyService.java
(4 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
(2 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathRecommendationService.java
(4 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java
(5 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java
(4 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java
(4 hunks)src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleService.java
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (8)
- src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.java
- src/main/java/de/tum/cit/aet/artemis/atlas/web/CourseCompetencyResource.java
- src/main/java/de/tum/cit/aet/artemis/atlas/web/CompetencyResource.java
- src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyProgressService.java
- src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/PrerequisiteService.java
- src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CompetencyService.java
- src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
- src/main/java/de/tum/cit/aet/artemis/atlas/service/competency/CourseCompetencyService.java
🧰 Additional context used
📓 Path-based instructions (3)
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleService.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/PrerequisiteResource.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/learningpath/LearningPathRecommendationService.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 (5)
src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java (1)
192-192
: LGTM! Service layer integration looks good.
The changes to use CourseCompetencySimpleService
in these methods are consistent with the architectural shift towards service layer abstraction. The error handling and authorization checks are properly maintained.
Also applies to: 325-325
src/main/java/de/tum/cit/aet/artemis/core/repository/base/AbstractSimpleService.java (2)
1-7
: LGTM: Package structure and imports are well-organized
The package naming and import statements follow best practices with specific imports.
12-12
: LGTM: Class declaration follows best practices
The abstract class with bounded generic type parameter is well-designed and follows the single responsibility principle.
src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathRecommendationService.java (2)
60-60
: LGTM: Service field follows best practices
The field declaration follows Spring best practices with:
- Final modifier for immutability
- Constructor injection (visible in constructor)
- Clear and descriptive naming
699-700
: Verify eager loading performance impact
The method findByIdWithExercisesAndLectureUnitsElseThrow
suggests eager loading of exercises and lecture units. While this matches the usage pattern in this service, we should verify that:
- The eager loading doesn't impact performance in other scenarios
- The relationships are actually needed in all cases where this method is called
✅ Verification successful
Let me analyze the results and generate additional verification scripts to understand the usage patterns better.
Let me analyze the implementation of getOrderOfLearningObjectsForCompetency
to understand if it actually uses both exercises and lecture units.
Based on the implementation details revealed in the code, I can now generate the final response:
Eager loading is justified and properly used
The getOrderOfLearningObjectsForCompetency
method actively uses both exercises and lecture units from the competency:
- It processes completed and pending lecture units via
competency.getLectureUnitLinks()
- It handles exercises through
competency.getExerciseLinks()
for difficulty-based scheduling - Both are used in progress calculations and final learning object ordering
The eager loading matches the usage pattern and improves performance by avoiding N+1 queries, as the method needs both relationships for:
- Computing progress and confidence metrics
- Generating the recommended learning path
- Ordering completed and pending learning objects
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for other usages of this method to verify the eager loading is always needed
ast-grep --pattern 'findByIdWithExercisesAndLectureUnitsElseThrow'
# Search for potential N+1 query patterns in the service
rg -A 5 'courseCompetencySimpleService.*find.*'
Length of output: 8619
Script:
#!/bin/bash
# Check the implementation of getOrderOfLearningObjectsForCompetency to verify if it uses exercises and lecture units
ast-grep --pattern 'getOrderOfLearningObjectsForCompetency'
# Check the implementation of CourseCompetencySimpleService to understand different fetch methods
rg -A 10 'findByIdWithExercises' src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
# Look for repository layer implementation to understand the actual queries
rg -A 5 'CourseCompetencyRepository' --type java
Length of output: 37440
Script:
#!/bin/bash
# Check the implementation of getOrderOfLearningObjectsForCompetency
ast-grep --pattern 'getOrderOfLearningObjectsForCompetency(CourseCompetency competency, User user) {
$$$
}'
# Check if there are any other methods in LearningPathRecommendationService that use exercises or lecture units
rg -A 10 'exercises|lectureUnits' src/main/java/de/tum/cit/aet/artemis/atlas/service/learningpath/LearningPathRecommendationService.java
Length of output: 14185
src/main/java/de/tum/cit/aet/artemis/atlas/web/PrerequisiteResource.java
Show resolved
Hide resolved
I see your point and changed to the |
There hasn't been any activity on this pull request recently. Therefore, this pull request has been automatically marked as stale and will be closed if no further activity occurs within seven days. Thank you for your contributions. |
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: 1
🧹 Nitpick comments (2)
src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleRepositoryArchitectureTest.java (1)
331-358
: Enhance SimpleService validation robustness.While the test correctly enforces the single repository dependency pattern, consider these improvements:
@Test void enforceSimpleServiceSingleAutowire() { classesOfThisModuleThat().resideInAPackage("..repository.simple..").and().areAnnotatedWith(Service.class) - .should(new ArchCondition<>("have a constructor with exactly one parameter of a @Repository type") { + .should(new ArchCondition<>("follow SimpleService injection patterns") { @Override public void check(JavaClass javaClass, ConditionEvents events) { + // Verify no repository field injection + var repositoryFields = javaClass.getFields().stream() + .filter(field -> field.getRawType().isAnnotatedWith(Repository.class)) + .toList(); + if (!repositoryFields.isEmpty()) { + events.add(SimpleConditionEvent.violated(javaClass, + String.format("Class %s uses field injection which is not allowed. Use constructor injection instead.", + javaClass.getName()))); + return; + } + + // Verify only one constructor exists + if (javaClass.getConstructors().size() > 1) { + events.add(SimpleConditionEvent.violated(javaClass, + String.format("Class %s has multiple constructors. SimpleService should have exactly one constructor.", + javaClass.getName()))); + return; + } List<JavaConstructor> constructors = javaClass.getConstructors().stream() .filter(constructor -> constructor.getParameters().size() == 1).toList();src/main/java/de/tum/cit/aet/artemis/core/repository/base/ISimpleService.java (1)
1-2
: Consider simplifying interface naming for improved clarity.While prefixing interface names with "I" (i.e.,
ISimpleService
) is acceptable if it’s a widespread convention within the project, more modern Java conventions often omit this prefix. Confirm that this aligns with team-wide naming standards; otherwise, consider a simpler name likeSimpleService
.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/core/repository/base/ISimpleService.java
(1 hunks)src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleRepositoryArchitectureTest.java
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CompetencySimpleService.java
- src/main/java/de/tum/cit/aet/artemis/atlas/repository/simple/CourseCompetencySimpleService.java
🧰 Additional context used
📓 Path-based instructions (2)
src/test/java/de/tum/cit/aet/artemis/shared/architecture/module/AbstractModuleRepositoryArchitectureTest.java (1)
Pattern src/test/java/**/*.java
: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true
src/main/java/de/tum/cit/aet/artemis/core/repository/base/ISimpleService.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 (3)
src/main/java/de/tum/cit/aet/artemis/core/repository/base/ISimpleService.java (3)
8-11
: Documentation is succinct and follows Javadoc guidelines.
The Javadoc clearly communicates the purpose and usage of this interface. Great job providing context around "repository services" and the rationale for default methods.
16-18
: Ensure consistent usage of utility method.
The default method getValueElseThrow(Optional<U> optional)
is highly useful, but make sure that downstream code calls this method rather than rolling its own checks. This ensures uniform exception handling across the codebase.
20-22
: Well-structured fallback to the second overload.
Reducing duplication in the second default method by using the EntityNotFoundException
is beneficial. This pattern keeps the code minimal and centralizes the not-found logic.
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
andSimpleService
.SimpleService
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 theSimpleService
.SimpleService
s reside in a subpackage of the modulesrepository
packageImplementation detail: The
CompetencySimpleService
has a common abstract superclassAbstractSimpleService
. I am not really attached if this should rather be aggregation over inheritance.Performance Review
Code Review
Manual Tests
Summary by CodeRabbit
Release Notes
New Features
CompetencySimpleService
andCourseCompetencySimpleService
for enhanced competency data retrieval.Bug Fixes
CompetencyRepository
andCourseCompetencyRepository
, streamlining data access.Refactor
Tests