You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fesod.apache.org by "bengbengbalabalabeng (via GitHub)" <gi...@apache.org> on 2025/12/17 13:24:49 UTC
[I] [Enhancement] Introduce standard Bean Validation API support for excel reading [fesod]
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: commits-unsubscribe@fesod.apache.org.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fesod.apache.org
For additional commands, e-mail: commits-help@fesod.apache.org
Re: [I] [Discussions] Introduce standard Bean Validation API support for excel reading [fesod]
Posted by "bengbengbalabalabeng (via GitHub)" <gi...@apache.org>.
bengbengbalabalabeng commented on issue #741:
URL: https://github.com/apache/fesod/issues/741#issuecomment-4273516704
I’ll close this issue for now. If there is renewed interest or new use cases, we can revisit it anytime.
--
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: commits-unsubscribe@fesod.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fesod.apache.org
For additional commands, e-mail: commits-help@fesod.apache.org
Re: [I] [Enhancement] Introduce standard Bean Validation API support for excel reading [fesod]
Posted by "mymx2 (via GitHub)" <gi...@apache.org>.
mymx2 commented on issue #741:
URL: https://github.com/apache/fesod/issues/741#issuecomment-3736820771
我的意见是不引入,除了常见的输入校验,用户可能还存在业务校验,这是最麻烦的一点。就像上面说的,使用者更希望的是一次性知晓导入中所发生的所有错误。
如果仅仅想要自己校验。完全可以通过对解析后的对象调用validator来完成。
使用者可能更关注一次性导入结果,例如:
```
/** 导入结果 */
class ResultData<T> {
/** 表格数据 */
var data = mutableMapOf<Int, MutableList<T>>()
/** 表格错误 */
var error = mutableMapOf<Int, MutableList<ExcelErrorData>>()
}
```
一次性错误收集:
```
data class ExcelErrorData(
/** 页数 */
@ExcelProperty("页数") @ColumnWidth(15) var sheetNo: Int,
/** 行数 */
@ExcelProperty("行数") @ColumnWidth(15) var rowIndex: Int,
/** 列数 */
@ExcelProperty("列数") @ColumnWidth(15) var columnIndex: Int,
/** 单元格数据 */
@ExcelProperty("错误数据") @ColumnWidth(15) var cellData: String,
/** 错误描述 */
@ExcelProperty("错误描述") @ColumnWidth(100) var errorMsg: String,
/** 单元格位置 */
@ExcelProperty("位置") @ColumnWidth(15) var cellPosition: String,
/** 正确示例 */
@ExcelSelectCell @ExcelProperty("正确示例") @ColumnWidth(15) var exampleData: String,
) {
/** 生成excel行列的中文表述 例如: 1-10-M 表示 sheet1的第10行的M列 */
fun transCellPosition(): ExcelErrorData {
this.cellPosition =
"【sheet${sheetNo + 1}-${rowIndex + 1}行-${ExcelUtil.calcNumToLetter(columnIndex)}列】"
return this
}
}
```
--
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: commits-unsubscribe@fesod.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fesod.apache.org
For additional commands, e-mail: commits-help@fesod.apache.org
Re: [I] [Enhancement] Introduce standard Bean Validation API support for excel reading [fesod]
Posted by "bengbengbalabalabeng (via GitHub)" <gi...@apache.org>.
bengbengbalabalabeng commented on issue #741:
URL: https://github.com/apache/fesod/issues/741#issuecomment-3670557212
@alaahong Thank you for getting back to me. I’ve reviewed your points and would like to share some ideas:
> 1. Both Apache Bval and Hibernate Validator might tricky on the version ......
Re: My idea is that the `fesod-bval` module should only depend on the standard `jakarta.validation-api`, and `fesod-bval-javax` only on `javax.validation-api`. We will not declare a direct, transitive dependency on any specific version of Hibernate Validator or Apache BVal.
The decision of which validation implementation to use—and which version—should be left entirely to the end-user.
> 2. It's also easy to work with customized validator in invoke, otherwise, you have to leave slot in such JSR 380/349/303 implementation for additional logic injection
> e.g. skip or blocking exception row/file, this is a normal next step if any validation failed
Re:
- In my experience, a common use case is to read the entire file, collect all validation failures, and then return a complete report to the user. Reporting only the first error found forces the user into a frustrating cycle of fixing one issue at a time and re-uploading the file repeatedly. However, I agree that different users may have different needs. We can certainly provide an enumeration-based strategy to support both modes: `FAIL_FAST` on the first validation error, and `COLLECT_ALL` (the default) to gather all errors.
- The `ValidationErrors` object is bound to the `AnalysisContext`. This means that even if users choose not to use the new `ValidatingAnalysisEventListener`, they can still access the validation results within the standard `invoke` method of their own listeners, preserving maximum flexibility.
> 3. Business validator is not less than rule
> e.g. in Chinese requirement, we might meet such logic --> validate row A via B or C, any practice?
Re: The Bean Validation support this. Users can create a custom annotation and implement the `ConstraintValidator` interface to handle complex, cross-field validation logic.
For example, to validate that a `discountCode` is not empty when the `cardType` is 'VIP':
```java
@CompositeValidAnnotation(message = "Discount code is required when card type is 'VIP'")
@Data
public class ExcelModel {
private String cardType;
private String discountCode;
}
public class CompositeValidValidator implements ConstraintValidator<CompositeValidAnnotation, ExcelModel> {
@Override
public boolean isValid(ExcelModel value, ConstraintValidatorContext context) {
if ("VIP".equals(value.getCardType())) {
return value.getDiscountCode() != null && !value.getDiscountCode().isEmpty();
}
return true;
}
}
// ... Annotation definition ...
@Constraint(validatedBy = CompositeValidValidator.class)
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface CompositeValidAnnotation {
// ... standard annotation attributes ...
}
```
My proposed error model directly supports this. The `PropertyError` class is designed to capture field-level validation failures, while the base `RowError` class is used to hold the results of these class-level.
--
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: commits-unsubscribe@fesod.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fesod.apache.org
For additional commands, e-mail: commits-help@fesod.apache.org
Re: [I] [Discussions] Introduce standard Bean Validation API support for excel reading [fesod]
Posted by "bengbengbalabalabeng (via GitHub)" <gi...@apache.org>.
bengbengbalabalabeng closed issue #741: [Discussions] Introduce standard Bean Validation API support for excel reading
URL: https://github.com/apache/fesod/issues/741
--
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: commits-unsubscribe@fesod.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fesod.apache.org
For additional commands, e-mail: commits-help@fesod.apache.org
Re: [I] [Enhancement] Introduce standard Bean Validation API support for excel reading [fesod]
Posted by "alaahong (via GitHub)" <gi...@apache.org>.
alaahong commented on issue #741:
URL: https://github.com/apache/fesod/issues/741#issuecomment-3666272488
Leave the comment for open discussion.
1. Both Apache Bval and Hibernate Validator might tricky on the version
e.g. hibernate validator
| Hibernate Validator Version | Minimum Java Version | Typical Supported Java Versions | Bean / Jakarta Validation Version | Target Jakarta / Java EE | Recommended use / notes |
|---:|:---:|:---|:---|:---|:---|
| 9.x | 17 | 17, 21, 23, 24 (and newer) | Jakarta Validation 3.1 | Jakarta EE 11 | For new projects on Java 17+ or upgrading to Jakarta EE 11. |
| 8.x | 11 | 11, 17 (and newer) | Jakarta Validation 3.0 | Jakarta EE 10 | For projects migrating to the Jakarta namespace with JDK ≥ 11. |
| 7.x | 8 | 8, 11, 17 | Bean Validation 2.0 / transitional to 3.0 | Jakarta EE 9 (migration era) | Can be used on Java 8 while adapting to newer validation APIs. |
| 6.x | 8 | 8, 11, 17 | Bean Validation 2.0 | Java EE 8 | Recommended for legacy projects that must remain on Java 8. |
| 5.x | 6 | 6, 7, 8 | Bean Validation 1.1 | Java EE 7 | For very old legacy environments; generally recommended to upgrade. |
2. It's also easy to work with customized validator in invoke, otherwise, you have to leave slot in such JSR 380/349/303 implementation for additional logic injection
e.g. skip or blocking exception row/file, this is a normal next step if any validation failed
3. Business validator is not less than rule
e.g. in Chinese requirement, we might meet such logic --> validate row A via B or C, any practice?
--
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: commits-unsubscribe@fesod.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fesod.apache.org
For additional commands, e-mail: commits-help@fesod.apache.org