package me.wener.jraphql.example; import static org.springframework.http.MediaType.TEXT_HTML; import static org.springframework.web.reactive.function.server.RequestPredicates.GET; import static org.springframework.web.reactive.function.server.RequestPredicates.method; import static org.springframework.web.reactive.function.server.RequestPredicates.path; import static org.springframework.web.reactive.function.server.RouterFunctions.route; import static org.springframework.web.reactive.function.server.ServerResponse.ok; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.github.wenerme.wava.util.JSON; import java.io.IOException; import java.util.Map; import java.util.concurrent.CompletionStage; import lombok.Data; import lombok.extern.slf4j.Slf4j; import me.wener.jraphql.example.StarWarResolverV1.StarWarData; import me.wener.jraphql.exec.DefaultGraphExecutor; import me.wener.jraphql.exec.ExecuteResult; import me.wener.jraphql.exec.MetaResolver; import me.wener.jraphql.exec.TypeSystemDocument; import me.wener.jraphql.exec.resolver.TableChainFieldResolver; import me.wener.jraphql.parse.GraphParser; import me.wener.jraphql.parse.GraphParser.BatchParseOption; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.core.io.Resource; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; import reactor.core.publisher.Mono; /** * @author wener * @since 2018/4/10 */ @SpringBootApplication @Slf4j public class StarWarApplication { public static void main(String[] args) { SpringApplication.run(StarWarApplication.class, args); } @Bean public RouterFunction gqlRouterFunction() throws IOException { GraphParser parser = GraphParser.load(); TypeSystemDocument document = TypeSystemDocument.builder() // .addMetaDocument() .addDocument( parser .parse( BatchParseOption.builder() .parseSchema() .addResourceContent("jraphql/meta.graphqls") .addResourceContent("starwars.graphqls") .build()) .getOrThrow()) .build(); MetaResolver metaResolver = new MetaResolver(); StarWarResolverV1 starWarResolver = new StarWarResolverV1(); TableChainFieldResolver resolver = TableChainFieldResolver.builder() .forTypes(starWarResolver, document.findTypesBySourceFilename("starwars.graphqls")) .forMeta(metaResolver) .fallback(metaResolver) .build(); StarWarData source = StarWarResolverV1.loadData(); DefaultGraphExecutor executor = DefaultGraphExecutor.builder() .parser(parser) .fieldResolver(resolver) .typeResolver(starWarResolver) .typeSystemDocument(document) .build(); ObjectMapper mapper = new ObjectMapper() .findAndRegisterModules() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); return route( path("/query").and(method(HttpMethod.POST).or(method(HttpMethod.GET))), request -> { Mono requestMono = request.bodyToMono(String.class).map(v -> JSON.parse(v, QueryRequest.class)); return ok().contentType(MediaType.APPLICATION_JSON_UTF8) .body( requestMono .flatMap( r -> { log.info("QUERY {}", r); CompletionStage result = executor.execute( r.getQuery(), r.getOperationName(), r.getVariables(), source); return Mono.fromCompletionStage(result); }) .map( v -> { try { return mapper.writeValueAsString(v); } catch (JsonProcessingException e) { throw new RuntimeException(e); } }), String.class); }); } @Bean public RouterFunction graphiqlRouterFunction( @Value("classpath:/jraphql/graphiql.html") Resource index) { return route(GET("/"), request -> ok().contentType(TEXT_HTML).syncBody(index)); } @Data public static class QueryRequest { private String query; private String operationName; private Map variables; } }