Skip to content
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

Error code parsing is recommended to support custom parser configurations #338

Closed
ddphin opened this issue Sep 2, 2022 · 2 comments
Closed
Labels
enhancement New feature or request

Comments

@ddphin
Copy link

ddphin commented Sep 2, 2022

Summary (Description of this PR)

It is recommended to add a custom resolver configuration for the data dictionary and error codes.

The original configuration method is as follows:

{
  "errorCodeDictionaries": [
      {
        "title": "title",
        "enumClassName": "com.power.common.enums.HttpCodeEnum", // Error code enumeration class
        "codeField": "code", // Field name for the error code's code
        "descField": "message" // Field name corresponding to the description information of the error code
      }
  ]
}

A new custom resolver configuration parameter valuesResolverClass is suggested, as shown below:

{
  "errorCodeDictionaries": [
      {
          "title": "title",
          "enumClassName": "com.power.common.notenums.EException", // Error code class (not an Enum)
          "valuesResolverClass": "com.power.common.notenums.EExceptionValuesResolver", // Error code resolution class
      }
  ]
}

Additionally, it is hoped that smart-doc will provide an interface SmartValuesResolver, as follows:

public interface SmartValuesResolver {
    <T extends EnumDictionary> Collection<T> resolve();
}

The functionality of the newly added valuesResolverClass parameter's corresponding class EExceptionValuesResolver implementing the SmartValuesResolver interface is as follows:

public class EExceptionValuesResolver implements SmartValuesResolver {
    @Override
    public <T extends EnumDictionary> Collection<T> resolve() {
        List<EnumDictionary> list = new ArrayList<>();
        // Technical processing
        return list;
    }
}

Then, in the com.power.doc.utils.DocUtil#errorCodeDictToList method, add a judgment and handling for the valuesResolverClass parameter. The original key code location is as follows:

if (clzz.isInterface()) {
    Set<Class<? extends Enum>> enumImplementSet = dictionary.getEnumImplementSet();
    if (CollectionUtil.isEmpty(enumImplementSet)) {
        continue;
    }

    for (Class<? extends Enum> enumClass : enumImplementSet) {
        JavaClass interfaceClass = javaProjectBuilder.getClassByName(enumClass.getCanonicalName());
        if (Objects.nonNull(interfaceClass.getTagByName(DocTags.IGNORE))) {
            continue;
        }
        List<ApiErrorCode> enumDictionaryList = EnumUtil.getEnumInformation(enumClass, dictionary.getCodeField(),
                dictionary.getDescField());
        errorCodeList.addAll(enumDictionaryList);
    }

} else {
    JavaClass javaClass = javaProjectBuilder.getClassByName(clzz.getCanonicalName());
    if (Objects.nonNull(javaClass.getTagByName(DocTags.IGNORE))) {
        continue;
    }
    List<ApiErrorCode> enumDictionaryList = EnumUtil.getEnumInformation(clzz, dictionary.getCodeField(),
            dictionary.getDescField());
    errorCodeList.addAll(enumDictionaryList);
}

At the beginning, add an extended branch and modify as follows:

Class<?> valuesResolverClass = null;
if (StringUtil.isNotEmpty(dictionary.getValuesResolverClass())) {
    valuesResolverClass = classLoader.loadClass(dictionary.getValuesResolverClass());
}
if (null != valuesResolverClass && SmartValuesResolver.class.isAssignableFrom(valuesResolverClass)) {
    List<ApiErrorCode> enumDictionaryList = valuesResolverClass.getConstructor().newInstance().resolve();
    errorCodeList.addAll(enumDictionaryList);
}
else if (clzz.isInterface()) {
    // Original code

} else {
    // Original code
}

Basic Example (PR Use Case)

If the proposal involves a new or changed API, include a basic code example. Omit this section if it's not applicable.

Motivation (Purpose of this PR)

Company A has unified coding standards, and all exceptions (including error codes) inherit from an abstract base class (parent class) EException (not an interface, not an enum).

@Getter
public class EException {
    private final int code; // Unique within the inheritance system, throw an exception if constraints are violated upon initialization
    private final String name; // Unique within the inheritance system, throw an exception if constraints are violated upon initialization
    private String description;
    private String solution;
    // Some technical processing, this class cannot be instantiated with new, allowing it to be inherited, only through the following of method to create

    protected static EException of(String name, int code, String description, String solution) {
      // Technical processing
    }
    public static EException valueOf(int code) {
      // Technical processing
    }
    public static EException valueOf(String name) {
      // Technical processing
    }
    public static Set<EException> values() {
      // Technical processing, this method returns all defined exceptions (including parent and child classes (as long as the ancestor is this class, its defined exceptions will be returned))
    }
}

Basic public exception definition (inheriting from EException)

@NoArgsConstructor(access = AccessLevel.PROTECTED) // Can continue to be inherited
public class BaseEException extend EException {
    public static final EException BAD_REQUEST = of("BAD_REQUEST", 400000, "Request syntax error: {0}", "Syntax format: {1}");
    public static final EException UNAUTHORIZED = of("UNAUTHORIZED", 401000, "The request requires user authentication", "Please log in first");
    public static final EException SYSTEM_ERROR = of("SYSTEM_ERROR", 500000, "System exception:{0}", "Please try again later or contact the administrator");
    // And so on
}

Custom exception definition for microservices (inheriting from BaseEException)

@NoArgsConstructor(access = AccessLevel.PRIVATE) // Cannot continue to be inherited
public class BizEException extend BaseEException {
    public static final EException PARAM_NAME_EXIST = of("PARAM_NAME_EXIST", 400100, "Parameter name already exists!", "Please use another name or contact the administrator");
    // And so on
}

Through subclasses, all defined static exceptions in the inheritance relationship can be referenced, and all exceptions within a microservice are gathered together through BizEException. Moreover, this technology also achieves the aggregation of all exceptions through the values method for global maintenance. However, the traditional use of enum to implement the interface method results in each enum being independent and not interoperable, preventing inheritance, resulting in scattered definitions of exceptions within the same application and hindering global maintenance.

@ddphin ddphin added the enhancement New feature or request label Sep 2, 2022
@ddphin ddphin changed the title 数据子弹 数据字典和错误码,建议新增自定义解析器 Sep 2, 2022
@ddphin ddphin changed the title 数据字典和错误码,建议新增自定义解析器 数据字典和错误码,建议新增自定义解析器【如果建议被采纳恳请加急】 Sep 2, 2022
@ddphin ddphin changed the title 数据字典和错误码,建议新增自定义解析器【如果建议被采纳恳请加急】 错误码解析建议支持新增自定义解析器配置参数【如果建议被采纳恳请加急】 Sep 2, 2022
@ddphin ddphin changed the title 错误码解析建议支持新增自定义解析器配置参数【如果建议被采纳恳请加急】 错误码解析建议支持自定义解析器配置【如果建议被采纳恳请加急】 Sep 2, 2022
@shalousun
Copy link
Collaborator

@ddphin 建议自行提pr,接口名改成DictionaryValuesResolver

ddphin pushed a commit to ddphin/smart-doc that referenced this issue Sep 3, 2022
@ddphin
Copy link
Author

ddphin commented Sep 3, 2022

@shalousun PR已经提交。

shalousun added a commit that referenced this issue Sep 3, 2022
#338 错误码解析支持自定义解析器
@shalousun shalousun changed the title 错误码解析建议支持自定义解析器配置【如果建议被采纳恳请加急】 Error code parsing is recommended to support custom parser configurations Jul 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants