Skip to content

QuerydslPredicateOperationCustomizer exclude static fields and support QuerydslBindings#excludeUnlistedProperties feature #866

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

Closed
noahlann opened this issue Sep 15, 2020 · 3 comments
Labels
enhancement New feature or request

Comments

@noahlann
Copy link

noahlann commented Sep 15, 2020

Situation 1:

i have a entity like this:

// ignore package & import

@Data
@Entity
@Table(schema = "application", name = "application")
@Schema(description = "app")
@EntityListeners(AuditingEntityListener.class)
@NamedEntityGraph(name = "Application.Graph", attributeNodes = {@NamedAttributeNode("oauth2")})
public class Application implements Serializable {
    private static final long serialVersionUID = 6582562282311194139L;

    @Id
    @Column(length = 64)
    @GeneratedValue(generator = "snowflakeId")
    @GenericGenerator(name = "snowflakeId", strategy = "org.lan.iti.common.data.orm.jpa.generator.SnowflakeId")
    @Schema(description = "id")
    private String id;

    @Column(nullable = false, length = 64)
    @Schema(description = "name")
    private String name;

    @Column(length = 1024)
    @Schema(description = "description")
    private String description;

    @Column(length = 32)
    @Schema(description = "app type")
    @Enumerated(EnumType.STRING)
    private AppType type = AppType.EXTERNAL;

    @Column
    @Schema(description = "icon")
    private String icon;

    @Column(nullable = false)
    @CreatedDate
    @Schema(description = "createTime")
    private LocalDateTime createTime;

    @Column(length = 1024)
    @Schema(description = "rsa-publicKey")
    private String publicKey;

    @Column(length = 16, nullable = false)
    @Enumerated(EnumType.STRING)
    @Schema(description = "status")
    private AuditStatus auditStatus = AuditStatus.UN_SUBMITTED;

    @Column
    @Schema(description = "auditTime")
    private LocalDateTime auditTime;

    // region associate...
    @OneToOne(mappedBy = "application", fetch = FetchType.LAZY,
            cascade = {CascadeType.PERSIST, CascadeType.REMOVE})
    @JsonManagedReference("app_oauth2")
    private OAuthClientDetails oauth2;
    // endregion

    public enum AuditStatus {
        UN_SUBMITTED,
        PENDING,
        APPROVED,
        FAILED
    }

    public enum AppType {
        INNER,
        EXTERNAL
    }
}

normally, QuerydslPredicateOperationCustomizer add all the entity fields, include static fields...

i get this
image

we don't need static fields of the entity in usually.

so we need exclude these static fields.

// org.springdoc.data.rest.customisers.QuerydslPredicateOperationCustomizer#customize

Set<String> fieldsToAdd = Arrays.stream(predicate.root().getDeclaredFields())
                        .filter(field -> !Modifier.isStatic(field.getModifiers()))
                        .map(Field::getName).collect(Collectors.toSet());

Situation 2:

Support QuerydslBindings.excludeUnlistedProperties feature.

i have customize QuerydslBindings with bindings.excludeUnlistedProperties(true);

    @Override
    default void customize(@NonNull QuerydslBindings bindings, @NonNull QApplication root) {
        bindings.excludeUnlistedProperties(true);
        // bind...
        bindings.bind(root.name).first(StringExpression::containsIgnoreCase);
//        bindings.excluding(root.icon, root.publicKey, root.description);
    }

i just want the field that root.name for query parameter.

maybe this way:

org.springdoc.data.rest.customisers.QuerydslPredicateOperationCustomizer#customize

boolean excludeUnlistedProperties = getFieldValueOfBoolean(bindings, "excludeUnlistedProperties", null);
            for (String fieldName : fieldsToAdd) {
                Type type = getFieldType(fieldName, pathSpecMap, predicate.root(), excludeUnlistedProperties);
                if (type != null) {
                    Parameter newParameter = buildParam(type, fieldName);

                    parametersToAddToOperation.add(newParameter);
                }
            }
private Type getFieldType(String fieldName, Map<String, Object> pathSpecMap, Class<?> root, boolean excludeUnlistedProperties) {
        try {
            Object pathAndBinding = pathSpecMap.get(fieldName);
            Optional<Path<?>> path = getPathFromPathSpec(pathAndBinding);

            Type genericType;
            Field declaredField = null;
            if (path.isPresent()) {
                genericType = path.get().getType();
            } else if (!excludeUnlistedProperties) {
                declaredField = root.getDeclaredField(fieldName);
                genericType = declaredField.getGenericType();
            } else {
                return null;
            }
            if (genericType != null) {
                return genericType;
            }
        } catch (NoSuchFieldException e) {
            LOGGER.warn("Field {} not found on {} : {}", fieldName, root.getName(), e.getMessage());
        }
        return String.class;
    }

i got what i want:

image

sorry for my poor english.

@noahlann noahlann changed the title QuerydslPredicateOperationCustomizer exclude static fields. QuerydslPredicateOperationCustomizer exclude static fields and support QuerydslBindings#excludeUnlistedProperties feature Sep 15, 2020
@bnasslahsen
Copy link
Collaborator

@crazy6995,

Why don't you use @Schema(hidden = true) to exclude your desired field?

@chrisupb
Copy link
Contributor

I have exactly the same problem, like crazy6995! hidden=true is not possible because QueryDSL-Binding classes are generated and should not be edited manually.

It would be a killer feature if springdoc-openapi could evaluate the QuerydslBindings.excludeUnlistedProperty and ONLY put the included fields in the OpenAPI. This would be a consistent "mapping" between allowed QueryDSL fields and the OpenAPI request documentation.

If bindings.excludeUnlistedProperties(true); --> ONLY add the allowList to fieldsToAdd.
If bindings.excludeUnlistedProperties(false); --> execute existing code and maybe always exclude static fields.

@bnasslahsen
Copy link
Collaborator

bnasslahsen commented Sep 23, 2020

@chrisupb, @crazy6995,

The support will be available for the next realase.

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

3 participants