Skip to content

Instantly share code, notes, and snippets.

@ieugen
Last active May 30, 2017 11:02
Show Gist options
  • Save ieugen/12e2ccf078c6d07032cc4a26d6dc53ac to your computer and use it in GitHub Desktop.
Save ieugen/12e2ccf078c6d07032cc4a26d6dc53ac to your computer and use it in GitHub Desktop.
graphql-java schema wiring factory
@Data
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
@Configuration
public class MutateQuestionnaireDataFetchers {
@Autowired
DataCollectionService dataCollectionService;
@Autowired
ItembankRepository itembankRepository;
@Bean
public DataFetcher<Questionnaire> mutateQuestionnaireStart() {
return env -> {
Long id = env.getArgument("id");
String token = env.getArgument("token");
StartQuestionnaireCmd cmd = new StartQuestionnaireCmd(id, token);
Assessment assessment = dataCollectionService.start(cmd);
return Questionnaire.from(assessment);
};
}
@Bean
public DataFetcher<Questionnaire> mutateQuestionnaireSubmit() {
return env -> {
Long id = env.getArgument("id");
String token = env.getArgument("token");
Map<String, Object> context = env.getContext();
String submittedIp = (String) context.get("submittedIp");
SubmitQuestionnaireCmd cmd = new SubmitQuestionnaireCmd(id, token, submittedIp);
Assessment assessment = dataCollectionService.submit(cmd);
return Questionnaire.from(assessment);
};
}
.....
}
# Operations possible on a Questionnaire
type MutateQuestionnaire {
# Start the assessment in order to allow submission of answers.
start(id: Long!, token: String!): Questionnaire @dataFetcher(name: "mutateQuestionnaireStart")
# Submit the Questionnaire as a final version. No actions are allowed after this.
submit(id: Long!, token: String!): Questionnaire @dataFetcher(name: "mutateQuestionnaireSubmit")
# Declines to start the Questionnaire. No actions are allowed after this.
decline(id: Long!, token: String!, message: String): Questionnaire @dataFetcher(name: "mutateQuestionnaireDecline")
# Changes the language of the Questionnaire. Only allowed before starting the Questionnaire. E.g: language = en-US
changeLanguage(id: Long!, token: String!, language: String!): Questionnaire @dataFetcher(name: "mutateQuestionnaireChangeLanguage")
# Submit answers. It will replace older answers. Always adds, never deletes answers.
submitAnswers(id: Long!, token: String!, answers: [InputAnswer!]!): [Answer!]! @dataFetcher(name: "mutateQuestionnaireSubmitAnswers")
}
package gr8pi.graphql.config;
import graphql.InvalidSyntaxError;
import graphql.language.Argument;
import graphql.language.Directive;
import graphql.language.FieldDefinition;
import graphql.language.InterfaceTypeDefinition;
import graphql.language.StringValue;
import graphql.language.UnionTypeDefinition;
import graphql.schema.DataFetcher;
import graphql.schema.TypeResolver;
import graphql.schema.idl.TypeDefinitionRegistry;
import graphql.schema.idl.WiringFactory;
import graphql.schema.idl.errors.SchemaProblem;
import lombok.AccessLevel;
import lombok.Data;
import lombok.NonNull;
import lombok.experimental.FieldDefaults;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
@Component
public class SpringBasedWiringFactory implements WiringFactory {
@Autowired
ApplicationContext applicationContext;
.....
@Override
public boolean providesDataFetcher(TypeDefinitionRegistry registry, FieldDefinition definition) {
return getDirective(definition, "dataFetcher") != null;
}
@Override
public DataFetcher<?> getDataFetcher(TypeDefinitionRegistry registry, FieldDefinition definition) {
Directive directive = getDirective(definition, "dataFetcher");
return createDataFetcher(directive);
}
private DataFetcher<?> createDataFetcher(@NonNull Directive directive) {
log.info("Extract data fetcher for {}", directive);
String beanName = extractDataFetcherName(directive);
try {
return applicationContext.getBean(beanName, DataFetcher.class);
} catch (BeansException e) {
throw new IllegalStateException("Missing DataFetcher instance " + beanName);
}
}
String extractDataFetcherName(@NonNull Directive directive) {
Argument argument = directive.getArguments().stream()
.filter(arg -> "name".equals(arg.getName()))
.findFirst()
.orElseThrow(() -> new SchemaProblem(Arrays.asList(
new InvalidSyntaxError(directive.getSourceLocation()))));
return ((StringValue) argument.getValue()).getValue();
}
private Directive getDirective(@NonNull FieldDefinition definition, @NonNull String directiveName) {
List<Directive> directives = definition.getDirectives();
directives = directives.stream()
.filter(dir -> directiveName.equals(dir.getName()))
.collect(Collectors.toList());
return !directives.isEmpty() ? directives.get(0) : null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment