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

PR to support Model enhancements #2056

Open
wants to merge 79 commits into
base: master
from

Conversation

Projects
None yet
7 participants
@dilipkrish
Member

dilipkrish commented Oct 1, 2017

#Model enhancements include

  • Support for JsonView

Part of a different effort (these are different concepts) edited 2017-10-07 10:51:59

  • Support for spring data rest projects
  • Support for inheritance
  • Possibly support all of these in the light of OAS 3.0
@dilipkrish

I made it a PR so we can add comments etc. I added some initial thoughts. I feel like the plugin still needs some tweaking. Let me know what you think?

public Optional<ResolvedType> extractProjection(ResolvedType type, List<Annotation> annotations, DocumentationType documentationType) {
ModelProjectionProviderPlugin selected =
modelProjectionProviders.getPluginFor(documentationType, new JacksonJsonViewProjectionProvider());

This comment has been minimized.

@dilipkrish

dilipkrish Oct 1, 2017

Member

I think if there are plugin extensibility's we should use all of them not just the first one. That way we can layer information via plugins.

}
@Override
public Optional<Class<?>> projectionFor(ResolvedType type, List<Annotation> typeAnnotations) {

This comment has been minimized.

@dilipkrish

dilipkrish Oct 1, 2017

Member

This should return a ResolvedType IMO.

Also have you thought about how we might influence a projection not using annotations (I don't know how gson handles this)? I think it might be a good idea to extract a parameter object i.e. projection context that gives it access to/or parts of the RequestMappingContext

This comment has been minimized.

@dilipkrish

dilipkrish Oct 1, 2017

Member

Oh never mind... I see what this is doing. I don't think this interface is accurate. I'm thinking of the return value as an alternate type for the type. This makes this interface is jackson specific and will not work for spring-data-rest I think.

I was thinking more in these terms. Lets take this example from here

public class Views {
    public static class Public {
    }
 
    public static class Internal extends Public {
    }
}

public class Item {
  
    @JsonView(Views.Public.class)
    public int id;
 
    @JsonView(Views.Public.class)
    public String itemName;
 
    @JsonView(Views.Internal.class)
    public String ownerName;
}

I would think that this interface would behave something like this.

//Pseudo code on how this should be used.

ProjectionContext context = new ProjectionContext(
          type, //Type to find a projection type
          annotations, //Annotations to help finding projections
          ... more params as needed
         );
JacksonJsonViewProjectionProvider plugin = createInstanceOfPlugin(); 
Optional<ResolvedType> projection = instance.projectionFor(context);
//OR
Optional<Model> projection = instance.projectionFor(context);

Here projection would be a either a in-memory ResolvedType of type ItemPublicView built using AlternateTypeBuilder or straight away building the Model object via the ModelBuilder, that has the public properties as we do here. What do you think?

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

As i know, Gson does not have full projection support. Just only SerializationStrategy to determine which properties will be serialized.

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

There is a method Optional <Class<?> getRequiredAnnotation() that will handle case with JsonView, and will be ignored in case of Spring Data Rest

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

And we might have a case, where there won't be any projection, just all Class... For example, no defined @Projection classes, or no @JsonView annotation on field.

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

Dilip, that is outdated code....

 @Override
  public List<ResolvedType> projectionsFor(ResolvedType type, Optional<? extends Annotation> requiredAnnotation) {
    List<Class<?>> projections = newArrayList();
    if (requiredAnnotation.isPresent() &&
        requiredAnnotation.get() instanceof JsonView) {
      projections = newArrayList(((JsonView)requiredAnnotation.get()).value());
    }
    return from(projections).transform(toResolvedType()).toList();
  }

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

In last commit I changed interface and implementation

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

I agreed, ProjectionContext is a good idea, to consolidate all required information to determine projection

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

But, for me Projection is ONLY a part of ModelContext, just additional information, to determine which properties must be serialized or deserialized.

@@ -187,6 +187,10 @@ public String getGroupName() {
public <T extends Annotation> Optional<T> findControllerAnnotation(Class<T> annotation) {
return handler.findControllerAnnotation(annotation);
}
public List<Annotation> getAnnotations() {

This comment has been minimized.

@dilipkrish

dilipkrish Oct 1, 2017

Member

Does the findControllerAnnotation findAnnotations not work? I feel like a plugin should request only annotations it knows about. This is very open interface in my opinion.

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

I've deleted that already. The main idea is to make common interface to handle all cases with projections.

@@ -114,6 +116,11 @@ public String getName() {
}
@Override
public List<Annotation> getAnnotations() {

This comment has been minimized.

@dilipkrish

dilipkrish Oct 1, 2017

Member

Same here... I feel like a plugin should request only annotations it knows about. This is very open interface in my opinion.

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

Agreed, last commit restored that.

@@ -0,0 +1 @@
/OperationResponseClassReader.java

This comment has been minimized.

@dilipkrish

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

Something wrong, I accidentally ignored.... I will fix it

This comment has been minimized.

@MaksimOrlov
import springfox.documentation.spi.DocumentationType;
public interface ProjectionProviderPlugin extends Plugin<DocumentationType> {

This comment has been minimized.

@dilipkrish

dilipkrish Oct 1, 2017

Member

I feel like this plugin shouldn have something other thanDocumentationType as the discriminator. It should be something like ProjectionType which can have one of the following types

  • Jackson
  • Spring-Data-Rest
  • Something we haven't thought off.

Then we can select the right plugin rather than pick the first one the pluginManager finds.Thoughts?

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

For that we should have some explicit configuration. Any way we won't have all plugins at one time. So, JacksonJsonViewPlugin has the lowest priority. If Spring-Data-Rest is included in classpath it will overwrites with its own plugin with higher priority. And custom plugin has the highest priority will overwrite all plugins.

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

ProjectionType - will be auto configurable. And Spring-Data-Rest will rewrite it with it's name. But I think it is better to overwrite all plugin, and use priority then to use the configuration plugin name.

* @param annotation - projections of type
* @return resolved projection names
*/
boolean applyProjection(ResolvedType activeProjection, ResolvedType typeToApply, List<ResolvedType> typeProjections);

This comment has been minimized.

@dilipkrish

dilipkrish Oct 1, 2017

Member

I did not understand this method. I'll bring up the code and take a look at it again.

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member
 @Override
  public boolean applyProjection(ResolvedType activeProjection, ResolvedType typeToApply,
      Optional<? extends Annotation> requiredAnnotation) {
    final Class<?> activeView = activeProjection.getErasedType();
    if (requiredAnnotation.isPresent() &&
        requiredAnnotation.get() instanceof JsonView &&
        activeView != null) {
      final Class<?>[] typeProjections = ((JsonView)requiredAnnotation.get()).value();
      int i = 0, len = typeProjections.length;
      for (; i < len; ++i) {
        if (typeProjections[i].isAssignableFrom(activeView)) {
          return true;
        }
      }
    }
    return false;
  }

This comment has been minimized.

@MaksimOrlov

MaksimOrlov Oct 1, 2017

Member

Determine if class field belongs to given projection or not

@springfox springfox deleted a comment from codacy-bot Oct 1, 2017

@springfox springfox deleted a comment from codacy-bot Oct 1, 2017

@springfox springfox deleted a comment from codacy-bot Oct 1, 2017

@springfox springfox deleted a comment from codacy-bot Oct 1, 2017

@springfox springfox deleted a comment from codacy-bot Oct 1, 2017

@springfox springfox deleted a comment from codacy-bot Oct 1, 2017

@springfox springfox deleted a comment from codacy-bot Oct 1, 2017

@springfox springfox deleted a comment from codacy-bot Oct 1, 2017

@springfox springfox deleted a comment from codacy-bot Oct 13, 2017

@springfox springfox deleted a comment from codacy-bot Oct 13, 2017

@springfox springfox deleted a comment from codacy-bot Oct 13, 2017

@springfox springfox deleted a comment from codacy-bot Oct 13, 2017

@springfox springfox deleted a comment from codacy-bot Oct 13, 2017

@springfox springfox deleted a comment from codacy-bot Oct 13, 2017

@springfox springfox deleted a comment from codacy-bot Oct 13, 2017

@springfox springfox deleted a comment from codacy-bot Oct 13, 2017

@jcarnus

This comment has been minimized.

jcarnus commented Jul 10, 2018

Hi @dilipkrish ,
Is it possible to get a status on this PR and the original one ?
Thanks

@MaksimOrlov

This comment has been minimized.

Member

MaksimOrlov commented Jul 10, 2018

Hi, @jcarnus
It is being merged with 2.9.2 tag.

@jcarnus

This comment has been minimized.

jcarnus commented Jul 10, 2018

2.9.2 ? It's already out ?

@MaksimOrlov

This comment has been minimized.

Member

MaksimOrlov commented Jul 10, 2018

Yes, 2.9.2 version was released on the begging of the month. But that PR was not in this version. I'm currently merging it and providing optimization and some other stuff for cyclic links between types.

@jcarnus

This comment has been minimized.

jcarnus commented Jul 10, 2018

Thanks, let me know when the 2.9.2 is updated or 2.9.3 released
Thanks

@MaksimOrlov

This comment has been minimized.

Member

MaksimOrlov commented Jul 10, 2018

ok, sure.

@dilipkrish

This comment has been minimized.

Member

dilipkrish commented Jul 11, 2018

@jcarnus Just to clarify... There is no plan to release 2.9.3. This PR will be part of 3.0.0. /c @MaksimOrlov

To explain it a little further, this PR has been open for a while, and there are breaking changes in master that this PR does not have. To make it easier/simpler to get this in master sooner, I suggested, not rebasing with 3.0.0-SNAPSHOT(master). Once this PR works with the 2.9.3-SNAPSHOT codebase (2.9.2 tag), I'm happy to resolve the conflicts with master in a separate step and merge it in. That way we isolate this PR and not mix changes from master like java 8 support, spring 5/spring boot 2.0 etc.

Merge tag '2.9.2' into feature/model-enhancements
Conflicts:
	springfox-schema/src/main/java/springfox/documentation/schema/configuration/ModelsConfiguration.java
	springfox-schema/src/main/java/springfox/documentation/schema/plugins/SchemaPluginsManager.java
	springfox-schema/src/main/java/springfox/documentation/schema/property/OptimizedModelPropertiesProvider.java
	springfox-schema/src/test/groovy/springfox/documentation/schema/mixins/SchemaPluginsSupport.groovy
	springfox-schema/src/test/groovy/springfox/documentation/schema/plugins/SchemaPluginsManagerSpec.groovy
	springfox-schema/src/test/groovy/springfox/documentation/schema/property/CachingModelPropertiesProviderSpec.groovy
	springfox-schema/src/test/groovy/springfox/documentation/schema/property/OptimizedModelPropertiesProviderSpec.groovy
	springfox-spi/src/main/java/springfox/documentation/spi/schema/contexts/ModelContext.java
	springfox-spring-web/src/main/java/springfox/documentation/spring/web/scanners/ApiListingScanner.java
	springfox-spring-web/src/main/java/springfox/documentation/spring/web/scanners/ApiModelReader.java
	springfox-spring-web/src/test/groovy/springfox/documentation/spring/web/mixins/ModelProviderForServiceSupport.groovy
	springfox-spring-web/src/test/groovy/springfox/documentation/spring/web/readers/ApiModelReaderSpec.groovy
	springfox-spring-web/src/test/groovy/springfox/documentation/spring/web/readers/ApiOperationReaderSpec.groovy
	springfox-spring-web/src/test/groovy/springfox/documentation/spring/web/readers/parameter/ExpandedParameterBuilderSpec.groovy
	springfox-spring-web/src/test/groovy/springfox/documentation/spring/web/readers/parameter/ParameterDataTypeReaderSpec.groovy
	springfox-spring-web/src/test/groovy/springfox/documentation/spring/web/scanners/ApiListingScannerSpec.groovy
	springfox-spring-web/src/test/groovy/springfox/documentation/spring/web/scanners/CachingOperationReaderSpec.groovy
	springfox-swagger-common/src/test/groovy/springfox/documentation/swagger/mixins/SwaggerPluginsSupport.groovy
	springfox-swagger-common/src/test/groovy/springfox/documentation/swagger/readers/operation/SwaggerOperationModelsProviderSpec.groovy
	springfox-swagger-common/src/test/groovy/springfox/documentation/swagger/schema/ApiModelBuilderSpec.groovy
	springfox-swagger1/src/test/groovy/springfox/documentation/spring/web/scanners/SwaggerApiModelReaderSpec.groovy
	springfox-swagger1/src/test/groovy/springfox/documentation/swagger1/readers/parameter/OperationParameterReaderSpec.groovy
	swagger-contract-tests/src/test/groovy/springfox/test/contract/swaggertests/FunctionContractSpec.groovy
	swagger-contract-tests/src/test/resources/contract/swagger/declaration-concrete-controller.json
	swagger-contract-tests/src/test/resources/contract/swagger/declaration-fancy-pet-service.json
	swagger-contract-tests/src/test/resources/contract/swagger/declaration-feature-demonstration-service.json
	swagger-contract-tests/src/test/resources/contract/swagger/declaration-groovy-service.json
	swagger-contract-tests/src/test/resources/contract/swagger/declaration-pet-service.json
	swagger-contract-tests/src/test/resources/contract/swagger/resource-listing.json
	swagger-contract-tests/src/test/resources/contract/swagger2/declaration-bugs-different-service.json
	swagger-contract-tests/src/test/resources/contract/swagger2/declaration-bugs-service.json
	swagger-contract-tests/src/test/resources/contract/swagger2/declaration-concrete-controller.json
	swagger-contract-tests/src/test/resources/contract/swagger2/declaration-feature-demonstration-service-codeGen.json
	swagger-contract-tests/src/test/resources/contract/swagger2/declaration-feature-demonstration-service.json
	swagger-contract-tests/src/test/resources/contract/swagger2/declaration-spring-data-rest.json
	swagger-contract-tests/src/test/resources/contract/swagger2/swagger.json

@springfox springfox deleted a comment from codacy-bot Sep 12, 2018

@dilipkrish dilipkrish referenced this pull request Sep 16, 2018

Open

Model Scene #2662

0 of 2 tasks complete
@Splash34

This comment has been minimized.

Splash34 commented Sep 28, 2018

Any expected date of releasing this?

@MaksimOrlov

This comment has been minimized.

Member

MaksimOrlov commented Sep 28, 2018

@Splash34, I'm working on some enhancements, and going to finish around beginning of November. If @dilipkrish will approve, then PR will be merged.

@jcarnus

This comment has been minimized.

jcarnus commented Nov 19, 2018

Hi any news on this ?

@dilipkrish

This comment has been minimized.

Member

dilipkrish commented Nov 28, 2018

@jcarnus @MaksimOrlov is finishing up with the changes so that it can be pulled in.

@springfox springfox deleted a comment from codacy-bot Dec 2, 2018

@springfox springfox deleted a comment from codacy-bot Dec 2, 2018

@leishiyao

This comment has been minimized.

leishiyao commented Dec 7, 2018

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment