bengbengbalabalabeng opened a new issue, #741: URL: https://github.com/apache/fesod/issues/741
### Search before asking - [x] I searched in the [issues](https://github.com/apache/fesod/issues) and found nothing similar. ### Motivation This enhancement aims to integrate the **Bean Validation API** into the Fesod reading lifecycle, allowing users to define validation rules declaratively using annotations on their POJOs. This will eliminate the need for redundant and complex validation logic—such as long chains of `if-else` statements—within `ReadListener` implementations, resulting in a more robust and maintainable data validation solution. ### Solution To provide comprehensive support for Bean Validation, we must address the namespace change from `javax.validation` to `jakarta.validation` that occurred after Java 8. Given that Fesod supports a wide range of JDKs (8 through 25), a flexible, multi-module approach is required. ### Content 1. A `Validator` SPI (Service Provider Interface) will be defined within the main `fesod` module. This ensures the core library remains decoupled from any specific validation API. 2. Create two separate adapter modules: - `fesod-bval` will adapt Fesod's SPI to the **`jakarta.validation`** API. - `fesod-bval-javax` will be created by duplicating `fesod-bval` and modifying the imports to support the legacy **`javax.validation`** API. 3. The adapter modules will only depend on the standard Bean Validation APIs. The user is free to choose and provide any compliant implementation (e.g., Hibernate Validator, Apache BVal). ```mermaid graph TD app["Application"] subgraph "SPI Definition" A["fesod"] end subgraph " " B["fesod-bval (for jakarta)"] C["fesod-bval-javax (for javax)"] end subgraph " " D["hibernate-validator"] E["apache bval-jsr"] F["others"] end A --> B A --> C app -.-> A app -.-> adapters{"Choose One SPI Implementation"} adapters -.-> B adapters -.-> C app -.-> beanvalidation{"Choose One Bean Validation Implementation"} beanvalidation -.-> D beanvalidation -.-> E beanvalidation -.-> F ``` ### API Usage Example #### 1. Add Dependencies ```xml <dependency> <groupId>org.apache.fesod</groupId> <artifactId>fesod</artifactId> <version>${fesod.version}</version> </dependency> <dependency> <groupId>org.apache.fesod</groupId> <artifactId>fesod-bval</artifactId> <version>${fesod.version}</version> </dependency> <!-- Users provide their chosen Bean Validation implementation, e.g., Hibernate Validator, Apache BVal --> <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate-validator.version}</version> </dependency> <!-- EL Support --> <dependency> <groupId>org.glassfish.expressly</groupId> <artifactId>expressly</artifactId> <version>${expressly.version}</version> </dependency> ``` #### 2. Define the POJO with Validation Annotations ```java public class ExcelModel { @NotBlank(message = "In sheet '{sheetName}', row {rownum}, column {column}: Name is required") @ExcelProperty("Name") private String name; @Min(value = 20, message = "Age must be greater than or equal to {value}") @ExcelProperty("Age") private Integer age; } ``` #### 3. Read the Excel File ```java File file = new File("file.xlsx"); Fesod.read(file, ExcelModel.class, new CustomAnalysisEventListener()) .useValidation(true) .sheet() .doRead(); ``` The `ValidatingAnalysisEventListener` provides precise error information through its callback methods. After the entire analysis is complete, a comprehensive `Errors` object containing all validation failures can be retrieved via a new convenience method on the `AnalysisContext`. The `Errors` object contains a detailed list of `RowError` (for row-level validation) and `PropertyError` (for cell-level validation) objects. ```java public class CustomAnalysisEventListener extends ValidatingAnalysisEventListener<ExcelModel> { @Override public void onValidated(ExcelModel data, AnalysisContext context) { // Called for each row that successfully passes validation. } @Override public void onValidated(ExcelModel data, List<RowError> validationErrors, AnalysisContext context) { // Called for each row that fails validation. // Each error in validationErrors contains detailed context like sheetNo, sheetName, rownum... } @Override public void doAfterAllAnalysed(AnalysisContext context) { // Retrieve the full report of all errors Errors validatedErrors = context.getValidationErrors(); if (validatedErrors.hasErrors) { // ... } } } ``` #### 4. Support Fesod-Specific Parameters Expression (such as `{sheetNo}`, `{sheetName}`, `{rownum}`, and `{column}` ...) ```txt Before > "In sheet '{sheetName}', row {rownum}, column {column}: Name is required" After > "In sheet 'Sheet1', row 1, column 1: Name is required" ``` ### Alternatives Regarding compatibility support for the `javax.validation` namespace, an alternative approach was considered: maintaining only a single source module, `fesod-bval` (for Jakarta), and then leveraging a build plugin like `maven-shade-plugin`, `transformer-maven-plugin` to dynamically transform the `jakarta.*` namespace into `javax.*` during the packaging phase. The intended outcome of this strategy was to generate two distinct artifacts using a classifier, allowing users to choose the one that fits their environment: ```xml <!-- For Jakarta support --> <dependency> <groupId>org.apache.fesod</groupId> <artifactId>fesod-bval</artifactId> <version>${fesod.version}</version> </dependency> <!-- For Javax support --> <dependency> <groupId>org.apache.fesod</groupId> <artifactId>fesod-bval</artifactId> <version>${fesod.version}</version> <classifier>javax</classifier> </dependency> ``` Problem: The build plugins are unable to modify the dependency declarations within the generated `pom.xml` file. This would require manual intervention after the build, which is incompatible with and unfriendly to our automated CI/CD processes, such as the GitHub workflows. ### Anything else? _No response_ ### Are you willing to submit a PR? - [x] I'm willing to submit a PR! -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
