Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

2018.4.18 - GraphQLが格好良さそうだったので、Springで入門したら躓いた話

hainet50b
April 18, 2018

2018.4.18 - GraphQLが格好良さそうだったので、Springで入門したら躓いた話

▼開催日▼
2018年4月18日

▼イベント▼
JSUG勉強会 2018年 その3
https://jsug.doorkeeper.jp/events/73144

hainet50b

April 18, 2018
Tweet

More Decks by hainet50b

Other Decks in Programming

Transcript

  1. About me • ∁໺ ͸͍Ͷ • SoftBank Payment Service Corp.

    • ϓϩάϥϚʔ3೥ੜ
 ։ൃϓϩδΣΫτࢧԉ • I — Spring Framework! hainet hainet_g
  2. 2. Describe Schemas type CreditCard { id: ID! number: String!

    goodThru: String! securityCode: String! } type Query { findCreditCards: [CreditCard]! }
  3. 3. Implement Queries @Component public class CreditCardQuery implements GraphQLQueryResolver {

    public List<CreditCard> findCreditCards() { // Find credit cards! return creditCards; } }
  4. Hibernate ValidatorΛ࢖͍͍ͨ public class CreditCardPayload { @NotNull @Size(min = 14,

    max = 16) @Pattern(regexp = "[0-9]*") private String number; // Fields, Getters, Setters } @Component public class CreditCardMutation implements GraphQLMutationResolver { public CreditCard createCreditCard( @Validated final CreditCardPayload payload) { // Create credit card! return creditCard; } }
  5. Hibernate ValidatorΛ࢖͍͍ͨ public class CreditCardPayload { @NotNull @Size(min = 14,

    max = 16) @Pattern(regexp = "[0-9]*") private String number; // Fields, Getters, Setters } @Component public class CreditCardMutation implements GraphQLMutationResolver { public CreditCard createCreditCard( @Validated final CreditCardPayload payload) { // Create credit card! return creditCard; } }
  6. Hibernate ValidatorΛ࢖͍͍ͨ public class CreditCardPayload { @NotNull @Size(min = 14,

    max = 16) @Pattern(regexp = "[0-9]*") private String number; // Fields, Getters, Setters } @Component public class CreditCardMutation implements GraphQLMutationResolver { public CreditCard createCreditCard( @Validated final CreditCardPayload payload) { // Create credit card! return creditCard; } }
  7. Number.javaΛ࡞੒ @Component public class Number extends GraphQLScalarType { public Number()

    { super("Number", "CreditCardPayload.Number", new Coercing() { @Override public String serialize(final Object dataFetcherResult) { return this.serializeNumber(dataFetcherResult); } @Override public String parseValue(final Object input) { return this.parseNumberFromVariable(input); } @Override public String parseLiteral(final Object input) { return this.parseNumberFromAstLiteral(input); } }); } } Serialize Deserialize (AST) Deserialize
  8. input CreditCardPayload { number: Number! goodThru: GoodThru! brand: Brand! securityCode:

    SecurityCode! } Number.java CreditCard.graphqlsఆٛมߋ GoodThru.java SecurityCode.java
  9. type Something { foo: Foo! bar: Bar! baz: Baz! hoge:

    Hoge! fuga: Fuga! piyo: Piyo! fizz: Fizz! bazz: Bazz! } Foo.java Bar.java Baz.java Hoge.java Fuga.java Piyo.java Fizz.java Bazz.java
  10. Τϥʔϋϯυϥͷ࣮૷Λ௥ͬͯɺ ॲཧΛࠩ͠ସ͑ͯΈͨ @Override public List<GraphQLError> processErrors( List<GraphQLError> errors) { errors.add(

    new GenericGraphQLError( "Internal Server Error(s) while executing query" ) ); // Omitted return errors; } DefaultGraphQLErrorHandler.java
  11. Τϥʔϋϯυϥͷ࣮૷Λ௥ͬͯɺ ॲཧΛࠩ͠ସ͑ͯΈͨ @Override public List<GraphQLError> processErrors( List<GraphQLError> errors) { errors.add(

    new GenericGraphQLError( "Internal Server Error(s) while executing query" ) ); // Omitted return errors; } MyGraphQLErrorHandler.java
  12. GraphQLErrorΛద੾ʹϋϯυϦϯά͢Δ GraphQLErrorHandlerΛ࣮૷ @Component @Slf4j public class GraphQLErrorHandlerConfig implements GraphQLErrorHandler {

    @Override public List<GraphQLError> processErrors(final List<GraphQLError> errors) { errors.stream() .filter(this::isServerError) .forEach(error -> { if (error instanceof Throwable) { log.error("Error executing query!", (Throwable) error); } else { log.error( "Error executing query ({}): {}", error.getClass().getSimpleName(), error.getMessage() ); } }); return errors.stream() .map(GraphQLErrorHolder::new) .collect(Collectors.toList()); } private boolean isServerError(final GraphQLError error) { return error instanceof ExceptionWhileDataFetching || error instanceof Throwable; } }
  13. @Component @Slf4j public class GraphQLErrorHandlerConfig implements GraphQLErrorHandler { @Override public

    List<GraphQLError> processErrors(final List<GraphQLError> errors) { errors.stream() .filter(this::isServerError) .forEach(error -> { if (error instanceof Throwable) { log.error("Error executing query!", (Throwable) error); } else { log.error( "Error executing query ({}): {}", error.getClass().getSimpleName(), error.getMessage() ); } }); return errors.stream() .map(GraphQLErrorHolder::new) .collect(Collectors.toList()); } private boolean isServerError(final GraphQLError error) { return error instanceof ExceptionWhileDataFetching || error instanceof Throwable; } } Stack Trace͸ ࣗྗͰग़ྗ GraphQLErrorΛద੾ʹϋϯυϦϯά͢Δ GraphQLErrorHandlerΛ࣮૷
  14. GraphQLErrorHolderΛ࡞੒ public class GraphQLErrorHolder implements GraphQLError { private GraphQLError error;

    public GraphQLErrorHolder( final GraphQLError error) { this.error = error; } // Override getters } ThrowableΛӅṭ
  15. GraphQL Spring Boot Starter͸σϑΥϧτͰ Date and Time APIΛϚοϐϯάग़དྷͳ͍ Spring Boot

    2.0ʹ͸ରԠࡁ jackson-datatype-jsr310͸ೖ͍ͬͯΔ͸ͣ... URL: https://github.com/graphql-java/graphql-spring-boot/pull/63/commits/7eed5c83312c87b1c3fa73416399408570ac079c
  16. ObjectMapperConfigurer͕͋ͬͨ @Component public class GraphQLObjectMapperConfig implements ObjectMapperConfigurer { @Override public

    void configure(final ObjectMapper mapper) { mapper.registerModule(new JavaTimeModule()); } } URL: https://github.com/graphql-java/graphql-java-servlet/issues/42