{"id":13499405,"url":"https://github.com/Enigmatis/graphql-java-annotations","last_synced_at":"2025-03-29T04:31:14.513Z","repository":{"id":47238918,"uuid":"54271337","full_name":"Enigmatis/graphql-java-annotations","owner":"Enigmatis","description":"GraphQL Annotations for Java","archived":false,"fork":false,"pushed_at":"2024-08-05T15:01:34.000Z","size":1670,"stargazers_count":387,"open_issues_count":3,"forks_count":96,"subscribers_count":20,"default_branch":"master","last_synced_at":"2025-02-22T09:51:27.695Z","etag":null,"topics":["graphql","graphql-annotations","graphql-java"],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Enigmatis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-03-19T14:56:20.000Z","updated_at":"2024-11-08T11:21:51.000Z","dependencies_parsed_at":"2023-02-10T02:30:35.157Z","dependency_job_id":"4c9df056-912b-4525-8948-91438691de2d","html_url":"https://github.com/Enigmatis/graphql-java-annotations","commit_stats":null,"previous_names":["graphql-java/graphql-java-annotations"],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Enigmatis%2Fgraphql-java-annotations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Enigmatis%2Fgraphql-java-annotations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Enigmatis%2Fgraphql-java-annotations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Enigmatis%2Fgraphql-java-annotations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Enigmatis","download_url":"https://codeload.github.com/Enigmatis/graphql-java-annotations/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246140565,"owners_count":20729797,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql","graphql-annotations","graphql-java"],"created_at":"2024-07-31T22:00:32.844Z","updated_at":"2025-03-29T04:31:14.038Z","avatar_url":"https://github.com/Enigmatis.png","language":"Java","readme":"![logo](graphql-annotations.png?raw=true)\n# GraphQL-Java Annotations\n![build](https://github.com/Enigmatis/graphql-java-annotations/actions/workflows/build.yml/badge.svg)\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.graphql-java/graphql-java-annotations.svg?maxAge=3000)]()\n\n[GraphQL-Java](https://github.com/graphql-java/graphql-java) is a great library, but its syntax is a little bit verbose. This library offers an annotations-based\nsyntax for GraphQL schema definition.\n\nIf you would like to use a tool that creates a graphql spring boot server using graphql-java-annotations, you can view the [graphql-spring-annotations](https://github.com/yarinvak/graphql-spring-annotations) library.\n\n\n## Table Of Contents\n- [Getting Started](#getting-started)\n- [GraphQLAnnotations class](#graphqlannotations-class)\n- [Annotations Schema Creator](#annotations-schema-creator)\n- [Defining Objects](#defining-objects)\n- [Defining Interfaces](#defining-interfaces)\n- [Defining Unions](#defining-unions)\n- [Fields](#fields)\n    - [Custom DataFetcher](#custom-data-fetcher)\n- [Type Extensions](#type-extensions)\n    - [Defining Extensions in Annotation](#defining-extensions-in-annotations)\n    - [Data Fetching with Extensions](#data-fetching-with-extensions)\n- [Type Inference](#type-inference)\n- [Directives](#directives)\n    - [Creating/Defining a GraphQL Directive](#creatingdefining-a-graphqldirective)\n    - [Wiring with Directives](#wiring-with-directives)\n- [Relay Support](#relay-support)\n    - [Mutations](#mutations)\n    - [Connection](#connection)\n    - [Customizing Relay Schema](#customizing-relay-schema)     \n\n## Getting Started\n\n\n(Gradle syntax)\n\n```groovy\ndependencies {\n  compile \"io.github.graphql-java:graphql-java-annotations:21.5\"\n}\n```\n\n(Maven syntax)\n\n```groovy\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.graphql-java\u003c/groupId\u003e\n    \u003cartifactId\u003egraphql-java-annotations\u003c/artifactId\u003e\n    \u003cversion\u003e21.5\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nThe graphql-java-annotations library is able to create GraphQLType objects out of your Java classes.\nThese GraphQLType objects can be later injected into the graphql-java schema.\n\ngraphql-java-annotations also allows you to wire your objects with data fetchers and type resolvers while annotating your fields/types. The result of this process will be a ``GraphQLCodeRegistry.Builder`` object that can be later built and injected to the graphql-java schema.\n\n\n## GraphQLAnnotations class\n\nYou can create an instance of the `GraphQLAnnotations` class in order to create the GraphQL types.\n```java\nGraphQLAnnotations graphqlAnnotations = new GraphQLAnnotations();\n```\n\nUsing this object, you will be able to create the GraphQL types.\nThere are few types that can be generated - a `GraphQLObjectType`, a `GraphQLInterfaceType` and a `GraphQLDirective`.\n\n```java\nGraphQLObjectType query = graphqlAnnotations.object(Query.class);\nGraphQLDirective upperDirective = graphqlAnnotations.directive(UpperDirective.class);\nGraphQLInterfaceType myInterface = graphqlAnnotations.generateInterface(MyInterface.class); \n```\n\nThen you can use these types in order to create a graphql-java schema.\nBut, in order to create a graphql-java schema, you need also the ``GraphQLCodeRegistry``, which contains all the data fetchers mapped to their fields (and also type resolvers).\n\nYou can obtain the code registry this way:\n\n```java\ngraphqlAnnotations.getContainer().getCodeRegistryBuilder().build();\n```\n\n## Annotations Schema Creator\n\nUsing the `GraphQLAnnotations` processor object can be a little bit confusing if you wish to use it to create a GraphQL schema.\nSo we created a util class to help you create your desired GraphQL schema, in a syntax similiar to the graphql-java syntax.\n\nIn order to do so you can use the ``AnnotationsSchemaCreator.Builder`` in the following way:\n\n```java\n    GraphQLSchema schema = AnnotationsSchemaCreator.newAnnotationsSchema()\n        .query(Query.class) // to create you query object\n        .mutation(Mutation.class) // to create your mutation object\n        .subscription(Subscription.class) // to create your subscription object\n        .directive(UpperDirective.class) // to create a directive\n        .additionalType(AdditionalType.class) // to create some additional type and add it to the schema\n        .typeFunction(CustomType.class) // to add a typefunction\n        .setAlwaysPrettify(true) // to set the global prettifier of field names (removes get/set/is prefixes from names)\n        .setRelay(customRelay) // to add a custom relay object\n        .build();  \n```\n\nOf course you can use this builder with only some of the properties, but the query class must be provided.\nnote - The GraphQLSchema is a graphql-java type.\n\nContinue reading in order to understand how your java classes should look in order to be provided to the annotations schema creator.\n\n## Defining Objects\n\nAny regular Java class can be converted to a GraphQL object type. Fields can\nbe defined with a `@GraphQLField` (see more on fields below) annotation:\n\n```java\npublic class SomeObject {\n  @GraphQLField\n  public String field;\n}\n\n// ...\nGraphQLAnnotations graphQLAnnotations = new GraphQLAnnotations();\nGraphQLObjectType object = graphQLAnnotations.object(SomeObject.class);\n```\n\n## Defining Interfaces\n\nThis is very similar to defining objects, with the addition of type resolver : \n\n```java\n@GraphQLTypeResolver(MyTypeResolver.class)\npublic interface SomeInterface {\n  @GraphQLField\n  String field();\n}\n\npublic class MyTypeResolver implements TypeResolver {\n  GraphQLObjectType getType(TypeResolutionEnvironment env) { ... }\n}\n\n// ...\nGraphQLAnnotations graphQLAnnotations = new GraphQLAnnotations();\nGraphQLInterfaceType object = graphQLAnnotations.generateInterface(SomeInterface.class);\n```\n\nAn instance of the type resolver will be created from the specified class. If a `getInstance` method is present on the\nclass, it will be used instead of the default constructor.\n\n## Defining Unions\n\nTo have a union, you must annotate an interface with `@GraphQLUnion`. In the annotation, you must declare all the \npossible types of the union, and a type resolver.\nIf no type resolver is specified, `UnionTypeResolver` is used. It follows this algorithm:\nThe resolver assumes the the DB entity's name is the same as  the API entity's name.\n If so, it takes the result from the dataFetcher and decides to which\nAPI entity it should be mapped (according to the name). \nExample: If you have a `Pet` union type, and the dataFetcher returns `Dog`, the typeResolver\nwill check for each API entity if its name is equal to `Dog`, and returns if it finds something\n\n```java\n@GraphQLUnion(possibleTypes={Dog.class, Cat.class})\npublic interface Pet {}\n``` \nand an example with custom `TypeResovler`:\n```java\n@GraphQLUnion(possibleTypes={DogApi.class, Cat.class}, typeResolver = PetTypeResolver.class)\npublic interface Pet {}\n\n\npublic class PetTypeResolver implements TypeResolver {\n    @Override\n    GraphQLObjectType getType(TypeResolutionEnvironment env) {\n        Object obj = env.getObject();\n        if(obj instanceof DogDB) {\n            return (GraphQLObjectType) env.getSchema().getType(\"DogApi\");\n        }\n        else {\n            return (GraphQLObjectType) env.getSchema().getType(\"Cat\");\n        }\n      \n    }\n}\n```\nNOTE: you can have (but not mandatory) a type resolver with constructor that has `Class\u003c?\u003e[]` as the first parameter and\n`ProcessingElementsContainer` as the second. the `Class\u003c?\u003e[]` parameter contains the possibleTypes class\nand `ProcessingElementsContainer` has all sorts of utils (you can check `UnionTypeResolver` to see how we use it there)\n\n## Fields\n\nIn addition to specifying a field over a Java class field, a field can be defined over a method:\n\n```java\npublic class SomeObject {\n  @GraphQLField\n  public String field() {\n    return \"field\";\n  }\n}\n```\n\nOr a method with arguments:\n\n```java\npublic class SomeObject {\n  @GraphQLField\n  public String field(String value) {\n    return value;\n  }\n}\n```\n\u003e Note: You need to use `-parameters` javac option to compile, which makes argument name as the default GraphQL name. Otherwise, you will need to add the `@GraphQLName(\"value\")` annotation to specify one.\n\nYou can also inject `DataFetchingEnvironment` as an argument, at any position:\n\n```java\npublic class SomeObject {\n  @GraphQLField\n  public String field(DataFetchingEnvironment env, String value) {\n    return value;\n  }\n}\n```\n\nAdditionally, `@GraphQLName` can be used to override field name. You can use `@GraphQLDescription` to set a description.\n\nThese can also be used for field parameters:\n\n```java\npublic String field(@GraphQLName(\"val\") String value) {\n  return value;\n}\n```\n\nIn addition, `@GraphQLDefaultValue` can be used to set a default value to a parameter. Due to limitations of annotations, the default value has to be provided by a class that implements `Supplier\u003cObject\u003e`:\n\n```java\npublic static class DefaultValue implements Supplier\u003cObject\u003e {\n  @Override\n  public Object get() {\n    return \"default\";\n  }\n}\n\n@GraphQLField\npublic String field(@GraphQLDefaultValue(DefaultValue.class) String value) {\n  return value;\n}\n```\n\nThe `DefaultValue` class can define a `getInstance` method that will be called instead of the default constructor.\n\n`@GraphQLDeprecate` and Java's `@Deprecated` can be used to specify a deprecated\nfield or method.\n\n### Custom data fetcher\n\nYou can specify a custom data fetcher for a field with `@GraphQLDataFetcher`. The annotation will reference a class name, \nwhich will be used as data fetcher. \n\nAn instance of the data fetcher will be created. The `args` attribute on the annotation can be used to specify a list of \nString arguments to pass to the constructor, allowing to reuse the same class on different fields, with different parameter.\nThe `firstArgIsTargetName` attribute can also be set on `@GraphQLDataFetcher` to pass the field name as a single parameter of the constructor.\n\nAssuming you are using `@GraphQLDataFetcher` this way:\n\n```java\n@GraphQLField\n@GraphQLDataFetcher(value = HelloWorldDataFetcher.class, args = { \"arg1\", \"arg2\" })\npublic String getHelloWorld(){\n    return null;\n}\n```\n\nThen the class that extends from `DataFetcher.class` will get this args to two supported constructors \u003cbr\u003e\nOr to a constructor that expecting String array that's way (`String[] args` or `String... args`) or for a constructor that expecting the same number of args that you send with in the annotation.\u003cbr\u003e\nYou get to choose which implementation you want.\n```java\npublic class HelloWorldDataFetcher implements DataFetcher\u003cString\u003e {\n\n    public HelloWorldDataFetcher(String[] args){\n        // Do something with your args\n    }\n\n    // Note that you need to expect the same number of args as you send with in the annotation args\n    public HelloWorldDataFetcher(String arg1, String arg2){\n        // Do something with your args\n    }\n\n    @Override\n    public String get(DataFetchingEnvironment environment) {\n        return \"something\";\n    }\n}\n```\n\n\n\nIf no argument is needed and a `getInstance` method is present, this method will be called instead of the constructor.\n\n## Type extensions\n\nHaving one single class declaring all fields in a graphQL object type is not always possible, or can lead to huge classes. \nModularizing the schema by defining fields in different classes allows you to split it in smaller chunks of codes. \nIn IDL, this is usually written by using the `extend` keyword on top of a type definition. So you have a type defined like this :\n\n```\ntype Human {\n    id: ID!\n    name: String!\n}\n```\n\nIt would be possible to extend it later on by using the following syntax :\n\n```\nextend type Human {\n    homePlanet: String\n}\n```\n\n### Defining extensions in annotations\n\nThis is possible when using annotations by registering \"extensions\" classes, corresponding to `extend` clauses, before creating the objects with the GraphQLAnnotationsProcessor.\nExtension classes are simple classes, using the same annotations, with an additional `@GraphQLTypeExtension` on the class itself. The annotation value is required and will be the class that it actually extends.\n\nSo the previous schema could be defined by the following classes : \n  \n```\n@GraphQLName(\"Human\")\npublic class Human {\n    @GraphQLField\n    public String name() { }\n}\n```\n\n```\n@GraphQLTypeExtension(Human.class)\npublic class HumanExtension {\n    @GraphQLField\n    public String homePlanet() { }\n}\n```\n\nClasses marked as \"extensions\" will actually not define a new type, but rather set new fields on the class it extends when it will be created. \nAll GraphQL annotations can be used on extension classes.\n\nExtensions are registered in GraphQLAnnotations object by using `registerTypeExtension`. Note that extensions must be registered before the type itself is requested with `getObject()` :\n\n```\n// Register extensions\ngraphqlAnnotations.registerTypeExtension(HumanExtension.class);\n\n// Create type\nGraphQLObjectType type = processor.getObject(Human.class);\n\n```\n\n### Data fetching with extensions\n\nAs opposed to standard annotated classes mapped to GraphQL types, no instance of the extensions are created by default. \nIn DataFetcher, the source object will still be an instance of the extended class.\nIt is however possible to provide a constructor taking the extended class as parameter. This constructor will be used to create an instance of the extension class when a field with the default DataFetcher (without `@DataFetcher`) will be queried. \nIf no such constructor is provided, the field must either be declared as `static` or marked as `@GraphQLInvokeDetached`. Original source object can be found in the `DataFetchingEnvironment`.\n\n```\n@GraphQLTypeExtension(Human.class)\npublic class HumanExtension {\n    \n    public HumanExtension(Human human) {\n        this.human = human;   \n    }\n    \n    @GraphQLField\n    public String homePlanet() { \n        // get value somehow from human object\n    }\n}\n```\n\n## Type Inference\n\nBy default, standard GraphQL types (String, Integer, Long, Float, Boolean, Enum, List) will be inferred from Java types. Also, it will respect `@GraphQLNonNull` with respect to value's nullability\n\nStream type is also supported and treated as a list.\n\nIf you want to register an additional type (for example, UUID), you have to create a new class implementing `TypeFunction` for it:\n\n```java\npublic class UUIDTypeFunction implements TypeFunction {\n    ...\n}\n```\n\nAnd register it with `GraphQLAnnotations`:\n\n```java\ngraphqlAnnotations.registerType(new UUIDTypeFunction())\n\n// or if not using a static version of GraphQLAnnotations:\n// new GraphQLAnnotations().registerType(new UUIDTypeFunction())\n```\n\nYou can also specify custom type function for any field with `@GraphQLType` annotation.\n\n## Directives\nIn GraphQL, you can add directives to your schema. Directive is a way of adding some logic to your schema or changing your schema.\nFor example, we can create a `@upper` directive, that if we add it to string fields in our schema, they will be transformed to upper cases (its an example, you need to implement it).   \n\n### Declaring a ``GraphQLDirective``\nThere are multiple ways to declare a directive in your schema using graphql-java-annotations.\n\n#### Using a Java Annotation (recommended)\nThis is the most recommended way of creating a directive, because it is very easy to use later in your schema.\nIn order to declare a directive using a java annotation, you first have to create the java annotation, and annotate it with special annotations.\n\nFor example, we wish to create a directive that adds suffix to graphql fields.\n\n```java\n@GraphQLName(\"suffix\")\n@GraphQLDescription(\"this directive adds suffix to a string type\")\n@GraphQLDirectiveDefinition(wiring = SuffixWiring.class)\n@DirectiveLocations({Introspection.DirectiveLocation.FIELD_DEFINITION, Introspection.DirectiveLocation.INTERFACE})\n@Retention(RetentionPolicy.RUNTIME)\n@interface Suffix {\n    @GraphQLName(\"suffixToAdd\")\n    @GraphQLDescription(\"the suffix to add to your type\")\n    boolean suffixToAdd() default true;\n}\n```\n\n- must be annotated with `@GraphQLDirectiveDefinition` and to supply a wiring class to it (will be explained later)\n- the name of the directive will be taken from the class name (`Suffix`) or if annotated with `@GraphQLName` - from its value\n- the description is taken from the `@GraphQLDescription` annotation\n- must be annotated with `@Retention` with a `RUNTIME` policy\n- must be annotated with `@DirectiveLocations` in order to specify where we can put this directive on (for example - field definition, interface)\n\nYou can see that we also defined a ``sufixToAdd`` argument for the directive. We can also use `@GraphQLName` and `@GraphQLDescription` annotations in there.\n\nIn order to define a default value for the argument, use the `default` keyword like in the example.\n\nAfter you created the class, you will be able to create the ``GraphQLDirective`` object using the following code:\n```java\nGraphQLDirective directive = graphqlAnnotations.directive(Suffix.class);\n```\n\n#### Using a method declaration\nYou can also declare an annotation via a method declaration inside some class.\nFor example, we will create a class of directive declarations:\n\n```java\nclass DirectiveDeclarations{\n    @GraphQLName(\"upper\")\n    @GraphQLDescription(\"upper directive\")\n    @GraphQLDirectiveDefinition(wiring = UpperWiring.class)\n    @DirectiveLocations({Introspection.DirectiveLocation.FIELD_DEFINITION, Introspection.DirectiveLocation.INTERFACE})\n    public void upperDirective(@GraphQLName(\"isActive\") @GraphQLDescription(\"is active\") boolean isActive) {\n    }\n    \n    @GraphQLName(\"suffix\")\n    @GraphQLDescription(\"suffix directive\")\n    @GraphQLDirectiveDefinition(wiring = SuffixWiring.class)\n    @DirectiveLocations({Introspection.DirectiveLocation.FIELD_DEFINITION, Introspection.DirectiveLocation.INTERFACE})\n    public void suffixDirective(@GraphQLName(\"suffix\") @GraphQLDescription(\"the suffix\") String suffix) {\n    }\n}\n```\n\n- The methods has to be annotated with the `@GraphQLDirectiveDefinition` annotation, and to be supplied with a wiring class\n- The methods has to be annotated with the `@DirectiveLocations` annotation \n- Can be used: `@GraphQLName` and `@GraphQLDescription` - also inside method parameters (that will be transformed into arguments of the directive)\n\nNotice that method params cannot have default values - so the directive arguments will not have default values.\n\nIn order to create the directives, you need to write:\n```java\nSet\u003cGraphQLDirective\u003e set = graphqlAnnotations.directives(DirectiveDeclarations.class);\n```\n\n#### Using a class declaration\n\nAnother way is to declare the directive using a class.\n\nFor example:\n\n```java\n@GraphQLName(\"upper\")\n@GraphQLDescription(\"upper\")\n@DirectiveLocations({Introspection.DirectiveLocation.FIELD_DEFINITION, Introspection.DirectiveLocation.INTERFACE})\n@GraphQLDirectiveDefinition(wiring = UpperWiring.class)\npublic static class UpperDirective {\n    @GraphQLName(\"isActive\")\n    private boolean isActive = true;\n}\n```\n\nThe name of the directive will be taken from the ``@GraphQLName`` annotation (if not specified, the name will be the class's name).\nThe description of the directive will be taken from the ``@GraphQLDescription`` annotation's value.\nThe valid locations of the directive (locations which the directive can be applied on) will be taken from ``@DirectiveLocations``.\nThe arguments of the directive will be taken from the fields defined in the class - notice that you can only use primitive types as arguments of a directive.\nFor example, we defined an ``isActive`` field - which is boolean, and its default value is true. That's how the argument of the directive will be defined.\nYou can also use ``@GraphQLName`` and ``@GraphQLDescription`` annotations on the field.\n\nAfter you created the class, you will be able to create the ``GraphQLDirective`` object using the following code:\n```java\nGraphQLDirective directive = graphqlAnnotations.directive(UpperDirective.class);\n```\n\n### Wiring with the directives\nIn order to define the wiring logic (what will be executed on top of the graphql type annotated with the directive) we have to create wiring class.\n\nIn order to define a wiring functionality, you have to create a Wiring class matching one of your directives. For example:\n\n```java\npublic class UpperWiring implements AnnotationsDirectiveWiring {\n        @Override\n        public GraphQLFieldDefinition onField(AnnotationsWiringEnvironment environment) {\n            GraphQLFieldDefinition field = (GraphQLFieldDefinition) environment.getElement();\n            boolean isActive = (boolean) environment.getDirective().getArgument(\"isActive\").getValue();\n            CodeRegistryUtil.wrapDataFetcher(field, environment, (((dataFetchingEnvironment, value) -\u003e {\n                if (value instanceof String \u0026\u0026 isActive) {\n                    return ((String) value).toUpperCase();\n                }\n                return value; \n            })));            \n            return field;\n        }\n    }\n```\n\nIn this example we wrap the data fetcher of the field in order to make the resolved value upper case.\n\nYou can also use the `field.transform` method in order to change some of the field's properties.\n\nThis class turns your string field to upper case if the directive argument \"isActive\" is set to true.\n\nPut this class inside the `@GraphQLDirectiveDefinition(wiring = UpperWiring.class)` annotation where you declare your directive (see directive declaration section above).\n\n### Using the directives\n\nThere are 2 ways of using the directives in your graphql types.\n\n#### Using the directive java annotation (RECOMMENDED)\nThis way only works if you declared your directive as a java annotation.\nIn the example above, we created the `@Suffix` annotation as a directive.\nSo now we can put it on top of our graphql field.\n\nFor example:\n\n```java\n@GraphQLField\n@Suffix(suffixToAdd = \" is cool\")\npublic String name(){\n    return \"yarin\";\n}\n```\n\nNow every time the field will be executed, the suffix \" is cool\" will be added to it.\nYou can also use directive on field arguments, interfaces, etc.\n\n#### Using `@GraphQLDirectives` annotation\nThis way works in the 3 methods of declaring directives, but is less recommended because its more complicated and not so nice.\nYou can annotate your graphql field with the `@GraphQLDirectives` annotation and supply it with the directives to use and the arguments values you want to supply.\n\nFor example:\n\n```java\n@GraphQLField\n@GraphQLDirectives(@Directive(name = \"upperCase\", argumentsValues = {\"true\"}))\npublic String name() {\n    return \"yarin\";\n}\n```\n\nWe now wired the field \"name\" - so it will turn upper case when calling the field.\nThe ``Directive`` annotations requires the name of the directive, the wiring class (the ``UpperWiring`` class defined earlier), and the values of the arguments. If an argument has a default value, you don't have to supply a value in the arguments values.\n\nNotice that in any way, the directives are sequential, so the first annotated directive will happen before the second one.\nIf put both java annotation directive and `@GraphQLDirectives` annotation directives, the java annotation directive will be applied first.\n\n## Relay support\n\n### Mutations\n\nYou can use `@GraphQLRelayMutation` annotation to make mutation adhere to\nRelay [specification for mutations](https://facebook.github.io/relay/graphql/mutations.htm)\n\n### Connection\n\nYou can use `@GraphQLConnection` annotation to make a field iterable in adherence to Relay [Connection specification](https://facebook.github.io/relay/graphql/connections.htm).\\\nIf a field is annotated with the annotation, the associated dataFetcher must return an instance of `PaginatedData`.\\\nThe `PaginatedData` class holds the result of the connection:\n1. The data of the page\n2. Whether or not there is a next page and a previous page\n3. A method that returns for each entity the encoded cursor of the entity (it returns string)\n\nFor you convenience, there is `AbstractPaginatedData` that can be extended.\n\nIf you want to use you own implementation of connection, that's fine, just give a value to connection().\\\nPlease note that if you do so, you also have to specify your own connection validator that implements `ConnectionValidator`\\\n(and should throw `@GraphQLConnectionException` if something is wrong) \n\nNOTE: because `PropertyDataFetcher` and `FieldDataFetcher` can't handle connection, this annotation cant be used on a field that doesn't have a dataFetcher\n\n### Customizing Relay schema\n\nBy default, GraphQLAnnotations will use the `graphql.relay.Relay` class to create the Relay specific schema types (Mutations, Connections, Edges, PageInfo, ...).\nIt is possible to set a custom implementation of the Relay class with `graphqlAnnotations.setRelay` method. The class should inherit from `graphql.relay.Relay` and \ncan redefine methods that create Relay types.\n\nIt is also possible to specify for every connection which relay do you want to use, by giving a value to the annotation: \n`@GraphQLConnection(connectionType = customRelay.class)`. If you do that, please also give values to `connectionFetcher`\nand `validator`.\n\nThere is also a support for simple paging, without \"Nodes\" and \"Edges\". To use it, annotate you connection like that:\n`@GraphQLConnection(connectionFetcher = SimplePaginatedDataConnectionFetcher.class, connectionType = SimpleRelay.class, validator = SimplePaginatedDataConnectionTypeValidator.class)`\nand the return type must be of type `SimplePaginatedData`.\nIt has 2 methods:\n1. `getTotalCount` - how many elements are there in total\n2. `getData` - get the data\n\nFor you convenience, there are two classes that you can use: `AbstractSimplePaginatedData` and `SimplePaginatedDataImpl`\nFor examples, look at the tests\n","funding_links":[],"categories":["Libraries","Implementations","Java"],"sub_categories":["Java Libraries","Java"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEnigmatis%2Fgraphql-java-annotations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FEnigmatis%2Fgraphql-java-annotations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FEnigmatis%2Fgraphql-java-annotations/lists"}