Skip to content

Support "all" in client response projection #300

@jxnu-liguobin

Description

@jxnu-liguobin

Is your feature request related to a problem? Please describe.
Hi, since the last time we used dynamic automatic call, we think it is better to use automatic generation completely because there may be performance problems with the proxy. Now we consider that we can also entrust the implementation to the framework generation. Of course, I think this may have exceeded the responsibility of this framework.

I have roughly written a template and implemented it by associating entity resolver returnType.
In this way all codes will be fully automated,however, I think it may increase the framework coupling.

Describe the solution you'd like
ftl:

<#if package?has_content>
    package ${package};


</#if>
import com.fasterxml.jackson.core.type.TypeReference;
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation;
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperationRequest;
import com.kobylynskyi.graphql.codegen.utils.Utils;
import io.github.dreamylost.OkHttp;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import scala.concurrent.ExecutionContext.Implicits.global;
<#list imports as import>
    import ${import}.*;
</#list>

<#if javaDoc?has_content>
/**
<#list javaDoc as javaDocLine>
 * ${javaDocLine}
</#list>
 */
</#if>
<#if generatedInfo.getGeneratedType()?has_content>
@${generatedInfo.getGeneratedType()}(
    value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen",
    date = "${generatedInfo.getDateTime()}"
)
</#if>
public class ${className}<#if implements?has_content> extends <#list implements as interface>${interface}<#if interface_has_next>, </#if></#list></#if> {

    public ${className}() {
    }

<#list operations as operation>
<#if operation.javaDoc?has_content>
    /**
    <#list operation.javaDoc as javaDocLine>
     * ${javaDocLine}
    </#list>
     */
</#if>
<#if operation.deprecated>
    @Deprecated
</#if>
<#list operation.annotations as annotation>
    @${annotation}
</#list>
    ${operation.type} ${operation.name}(${requestType} operateRequest) throws Exception {
    <#if projectionType?has_content>
        ${projectionType} projection = new ${projectionType}();
        for (Method m : projection.getClass().getDeclaredMethods()) {
            Utils.selectOnProjection(projection, m, 1, ${max});
        }
        <#else>
        Object projection = null;
    </#if>
        GraphQLRequest graphQLRequest = new GraphQLRequest(operateRequest, projection);
        Future<${operation.type}> retFuture = OkHttp.executeRequest(graphQLRequest, new TypeReference[${operation.type}] {});
        ${operation.type} ret = Await.result(retFuture, Duration.Inf());
        return ret;
    }

    ${operation.type} ${operation.name}(${requestType} operateRequest<#if projectionType?has_content>, ${projectionType} projection</#if>) throws Exception {
        GraphQLRequest graphQLRequest = new GraphQLRequest(operateRequest, projection);
        Future<${operation.type}> retFuture = OkHttp.executeRequest(graphQLRequest, new TypeReference[${operation.type}] {});
        ${operation.type} ret = Await.result(retFuture, Duration.Inf());
        return ret;
    }

</#list>
}

will generate code like this :

import com.fasterxml.jackson.core.type.TypeReference;
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperation;
import com.kobylynskyi.graphql.codegen.model.graphql.GraphQLOperationRequest;
import com.kobylynskyi.graphql.codegen.utils.Utils;
import io.github.dreamylost.OkHttp;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import scala.concurrent.ExecutionContext.Implicits.global;

/**
 * Create a new event.
 */
@javax.annotation.Generated(
    value = "com.kobylynskyi.graphql.codegen.GraphQLCodegen",
    date = "2020-12-31T23:59:59-0500"
)
public class CreateEventMutationResolverImpl {

    public CreateEventMutationResolverImpl() {
    }

    /**
     * Create a new event.
     */
    @javax.validation.constraints.NotNull
    Event createEvent(CreateEventMutationRequest operateRequest) throws Exception {
        EventResponseProjection projection = new EventResponseProjection();
        for (Method m : projection.getClass().getDeclaredMethods()) {
           //support response all fields in GraphQLResponseProjection
            Utils.selectOnProjection(projection, m, 1, 3);//Projection will be called recursively
        }
        GraphQLRequest graphQLRequest = new GraphQLRequest(operateRequest, projection);
        Future<Event> retFuture = OkHttp.executeRequest(graphQLRequest, new TypeReference[Event] {});
        Event ret = Await.result(retFuture, Duration.Inf());
        return ret;
    }

    Event createEvent(CreateEventMutationRequest operateRequest, EventResponseProjection projection) throws Exception {
        GraphQLRequest graphQLRequest = new GraphQLRequest(operateRequest, projection);
        Future<Event> retFuture = OkHttp.executeRequest(graphQLRequest, new TypeReference[Event] {});
        Event ret = Await.result(retFuture, Duration.Inf());
        return ret;
    }

}

use it:

//will response all fields and limit depth is` max`, a new option in plugins.
new CreateEventMutationResolverImpl().createEvent(new CreateEventMutationRequest().setId("id222"))
//or select fields
new CreateEventMutationResolverImpl().createEvent(new CreateEventMutationRequest().setId("id222"), new EventResponseProjection().id())

and if GraphQLResponseProjection can provider a selectAll method, do not need invoke Utils.selectOnProjection(projection, m, 1, 3);
so, can implement selectAll ?

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions