DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • How To Build Web Service Using Spring Boot 2.x
  • GraphQL With Java Spring Boot and Postgres or MySQL Made Easy!
  • How To Best Use Java Records as DTOs in Spring Boot 3
  • Spring Boot: How To Use Java Persistence Query Language (JPQL)

Trending

  • Unlocking the Benefits of a Private API in AWS API Gateway
  • Event-Driven Architectures: Designing Scalable and Resilient Cloud Solutions
  • Non-Project Backlog Management for Software Engineering Teams
  • Role of Cloud Architecture in Conversational AI
  1. DZone
  2. Data Engineering
  3. Databases
  4. Java and GraphQL: A Guide

Java and GraphQL: A Guide

Learn how to use Java, Spring Boot, and JUnit 5 to build and test a GraphQL API.

By 
Thiago Negri user avatar
Thiago Negri
·
Dec. 19, 20 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
11.7K Views

Join the DZone community and get the full member experience.

Join For Free

It is quite difficult to design REST APIs as they need to serve multiple clients efficiently. Each client has their own needs, and therefore requires different parameters around data filtering and searching, which is where a traditional rest API comes in. Clients can navigate the single version, picking and choosing the data they want.

Developed by Facebook to overcome the shortcomings of REST API, GraphQL acts as a query language for APIs, as well as a runtime for fulfilling those queries with your extant data. When you provide a complete and clear description of the data in your API, clients can utilize that to ask for exactly what they need. When you expose your schema, the evolution of APIs becomes much easier. Clients can still navigate the schema to fit their needs, even if you add more fields and relations over time.

In this article, I will be walking you through the process of using Java and Spring Boot to build a GraphQL API. In addition, I will also go through the steps to test your GraphQL API using Java’s most popular testing library: JUnit 5.

If you would rather watch a video or follow along with the audio, you can watch this tutorial as a screencast.


Create a GraphQL API With Java and Spring Boot

Let’s start with an initialized app by going to Spring Initializr and defining your app data as follows:

  • Project: Maven Project
  • Language: Java
  • Spring Boot: 2.2.2
  • Project Metadata:
    • Group: com.oktadeveloper
    • Artifact: graphqldemo
  • Dependencies:
    • Add Spring Web
    • Add Spring Data JPA
    • Add H2 Database

You may also follow this link, it will take you to a pre-configured Spring Initializr page.


Expand the downloaded package and add GraphQL SPQR as a dependency to your pom.xml:

XML
 




x


 
1
<dependency>
2
    <groupId>io.leangen.graphql</groupId>
3
    <artifactId>graphql-spqr-spring-boot-starter</artifactId>
4
    <version>0.0.4</version>
5
</dependency>



Then create a Food entity class:

Java
 




xxxxxxxxxx
1
43


 
1
package com.oktadeveloper.graphqldemo;
2

          
3
import io.leangen.graphql.annotations.GraphQLQuery;
4

          
5
import javax.persistence.Id;
6
import javax.persistence.GeneratedValue;
7
import javax.persistence.Entity;
8

          
9
@Entity
10
public class Food {
11

          
12
    @Id @GeneratedValue
13
    @GraphQLQuery(name = "id", description = "A food's id")
14
    private Long id;
15

          
16
    @GraphQLQuery(name = "name", description = "A food's name")
17
    private String name;
18

          
19
    public Long getId() {
20
        return id;
21
    }
22

          
23
    public void setId(Long id) {
24
        this.id = id;
25
    }
26

          
27
    public String getName() {
28
        return name;
29
    }
30

          
31
    public void setName(String name) {
32
        this.name = name;
33
    }
34

          
35
    @Override
36
    public String toString() {
37
        return "Food{" +
38
            "id=" + id +
39
            ", name='" + name + '\'' +
40
            '}';
41
    }
42

          
43
}



Notice that you are already using GraphQL SPQR (GraphQL Schema Publisher & Query Resolver, pronounced like speaker) annotations (i.e. @GraphQLQuery) on the entity. This is how it will know to expose those entities in the API.

Create the respective repository:

Java
 




xxxxxxxxxx
1


 
1
package com.oktadeveloper.graphqldemo;
2

          
3
import org.springframework.data.jpa.repository.JpaRepository;
4
import org.springframework.stereotype.Repository;
5

          
6
@Repository
7
interface FoodRepository extends JpaRepository<Food, Long> {
8
}



In GraphQL you can either define a query which will only load data, or define a mutation which will also change the underlying data that feeds the API. For this sample app, you will define the basic read, save and delete functionality for food entities. For that, create a service class:

Java
 




xxxxxxxxxx
1
49


 
1
package com.oktadeveloper.graphqldemo;
2

          
3
import io.leangen.graphql.annotations.GraphQLArgument;
4
import io.leangen.graphql.annotations.GraphQLContext;
5
import io.leangen.graphql.annotations.GraphQLMutation;
6
import io.leangen.graphql.annotations.GraphQLQuery;
7
import io.leangen.graphql.spqr.spring.annotations.GraphQLApi;
8
import org.springframework.stereotype.Service;
9

          
10
import java.util.Arrays;
11
import java.util.List;
12
import java.util.Optional;
13

          
14
@Service
15
@GraphQLApi
16
public class FoodService {
17

          
18
    private final FoodRepository foodRepository;
19

          
20
    public FoodService(FoodRepository foodRepository) {
21
        this.foodRepository = foodRepository;
22
    }
23

          
24
    @GraphQLQuery(name = "foods") // READ ALL
25
    public List<Food> getFoods() {
26
        return foodRepository.findAll();
27
    }
28

          
29
    @GraphQLQuery(name = "food") // READ BY ID
30
    public Optional<Food> getFoodById(@GraphQLArgument(name = "id") Long id) {
31
        return foodRepository.findById(id);
32
    }
33

          
34
    @GraphQLMutation(name = "saveFood") // CREATE
35
    public Food saveFood(@GraphQLArgument(name = "food") Food food) {
36
        return foodRepository.save(food);
37
    }
38

          
39
    @GraphQLMutation(name = "deleteFood") // DELETE
40
    public void deleteFood(@GraphQLArgument(name = "id") Long id) {
41
        foodRepository.deleteById(id);
42
    }
43

          
44
    @GraphQLQuery(name = "isGood") // Calculated property of Food
45
    public boolean isGood(@GraphQLContext Food food) {
46
        return !Arrays.asList("Avocado", "Spam").contains(food.getName());
47
    }
48

          
49
}



Notice that you are also able to define calculated properties to entities. In the above class, you declared the method isGood() as a property that can be queried for each food. You will see ahead that you can read it just like you read the food’s id and name fields.

To initialize the app with sample data, add an ApplicationRunner bean definition in GraphqldemoApplication:

Java
 




xxxxxxxxxx
1
11


 
1
@Bean
2
ApplicationRunner init(FoodService foodService) {
3
    return args -> {
4
        Stream.of("Pizza", "Spam", "Eggs", "Avocado").forEach(name -> {
5
            Food food = new Food();
6
            food.setName(name);
7
            foodService.saveFood(food);
8
        });
9
        foodService.getFoods().forEach(System.out::println);
10
    };
11
}



Also, add the following line to application.properties to enable the web UI to test the GraphQL API:

Properties files
 




xxxxxxxxxx
1


 
1
graphql.spqr.gui.enabled=true


Run Your Java GraphQL API

Run the project with ./mvnw spring-boot:run. Head over to http://localhost:8080/gui and you should see a web UI to test your GraphQL API. Run a sample query by typing on the left-side panel:

JSON
 




xxxxxxxxxx
1


 
1
{
2
  foods {
3
    id
4
    name
5
    isGood
6
  }
7
}



Click the play button and you should see a result similar to this:

JSON
 




xxxxxxxxxx
1
26


 
1
{
2
  "data": {
3
    "foods": [
4
      {
5
        "id": 1,
6
        "name": "Pizza",
7
        "isGood": true
8
      },
9
      {
10
        "id": 2,
11
        "name": "Spam",
12
        "isGood": false
13
      },
14
      {
15
        "id": 3,
16
        "name": "Eggs",
17
        "isGood": true
18
      },
19
      {
20
        "id": 4,
21
        "name": "Avocado",
22
        "isGood": false
23
      }
24
    ]
25
  }
26
}



You can also find a specific food by ID using a query like the following:

JSON
 




xxxxxxxxxx
1


 
1
{ food(id: 1) { name } }



And seeing that result:

JSON
 




xxxxxxxxxx
1


 
1
{
2
  "data": {
3
    "food": {
4
      "name": "Pizza"
5
    }
6
  }
7
}



Notice that you are able to manipulate the response. On that last query, you asked only for the name of the food and the API didn’t return the id nor the isGood property.

Create a new food by running the saveFood() mutation:

JSON
 




xxxxxxxxxx
1


 
1
mutation {
2
  saveFood(food: { name: "Pasta" }) {
3
    id
4
    isGood
5
  }
6
}



And you will see a result like:

JSON
 




xxxxxxxxxx
1


 
1
{
2
  "data": {
3
    "saveFood": {
4
      "id": 5,
5
      "isGood": true
6
    }
7
  }
8
}
9

          



If you query all the foods again you should see the newly added “Pasta” there.

Test Your Java GraphQL API with JUnit 5

You can write tests for your API with JUnit 5 and Spring Mock MVC. To do this, you can call your API via HTTP, wrap the query in a JSON object with a single property called "query", and the response should be similar to what you were seeing in the web UI. For example, the following class tests that you can retrieve all registered foods:

Java
 




xxxxxxxxxx
1
39


 
1
package com.oktadeveloper.graphqldemo;
2

          
3
import org.junit.jupiter.api.Test;
4
import org.springframework.beans.factory.annotation.Autowired;
5
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
6
import org.springframework.boot.test.context.SpringBootTest;
7
import org.springframework.http.MediaType;
8
import org.springframework.test.web.servlet.MockMvc;
9
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
10

          
11
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
12
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
13

          
14
@SpringBootTest
15
@AutoConfigureMockMvc
16
class GraphqldemoApplicationTests {
17

          
18
    @Autowired
19
    MockMvc mockMvc;
20

          
21
    @Test
22
    void listFoods() throws Exception {
23
        String expectedResponse = "{\"data\":{\"foods\":[" +
24
                "{\"id\":1,\"name\":\"Pizza\",\"isGood\":true}," +
25
                "{\"id\":2,\"name\":\"Spam\",\"isGood\":false}," +
26
                "{\"id\":3,\"name\":\"Eggs\",\"isGood\":true}," +
27
                "{\"id\":4,\"name\":\"Avocado\",\"isGood\":false}" +
28
                "]}}";
29

          
30
        mockMvc.perform(MockMvcRequestBuilders.post("/graphql")
31
                .content("{\"query\":\"{ foods { id name isGood } }\"}")
32
                .contentType(MediaType.APPLICATION_JSON)
33
                .accept(MediaType.APPLICATION_JSON))
34
                .andExpect(status().isOk())
35
                .andExpect(content().json(expectedResponse))
36
                .andReturn();
37
    }
38

          
39
}



You can replace src/test/java/com/.../GraphqldemoApplicationTests.java with the code above and run ./mvnw test to see it in action.

Shell
 




xxxxxxxxxx
1


 
1
[INFO] Results:
2
[INFO] 
3
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
4
[INFO] 
5
[INFO] ------------------------------------------------------------------------
6
[INFO] BUILD SUCCESS
7
[INFO] ------------------------------------------------------------------------



For a client to use your GraphQL API, it just needs to call it as a standard HTTP API: send a POST request with the query or mutation and parse the result as JSON.

Secure Your Java GraphQL API


So far, your API is open to whoever has its endpoint URI. Let’s change that by adding proper security.

Okta offers a very handy Maven plugin to set up your app’s security quickly and easily. First, add Okta as a dependency in pom.xml. While you’re at it, add Spring Security’s testing library.

XML
 




xxxxxxxxxx
1
10


 
1
<dependency>
2
    <groupId>com.okta.spring</groupId>
3
    <artifactId>okta-spring-boot-starter</artifactId>
4
    <version>1.3.0</version>
5
</dependency>
6
<dependency>
7
    <groupId>org.springframework.security</groupId>
8
    <artifactId>spring-security-test</artifactId>
9
    <scope>test</scope>
10
</dependency>



Then run the Okta Maven plugin from your app’s folder:

Shell
 




xxxxxxxxxx
1


 
1
./mvnw com.okta:okta-maven-plugin:register



Answer a few questions (name, email, and company), and it will generate a new Okta developer account for you.

Run the following command to register a new OIDC application, and add the correct properties into your application.properties file.

Shell
 




xxxxxxxxxx
1


 
1
./mvnw com.okta:okta-maven-plugin:spring-boot



If you start your app again, you’ll notice that you can’t run GraphQL queries anymore. That’s because you’re not authenticated.

To authenticate and see your access token (required to use the API), create a very simple controller that displays the access token. Add the following class to your project:

Java
 




xxxxxxxxxx
1
27


 
1
package com.oktadeveloper.graphqldemo;
2

          
3
import org.springframework.beans.factory.annotation.Autowired;
4
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
5
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
6
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
7
import org.springframework.web.bind.annotation.RequestMapping;
8
import org.springframework.web.bind.annotation.RestController;
9

          
10
import java.security.Principal;
11

          
12
@RestController
13
class MyAccessTokenController {
14

          
15
    @Autowired
16
    private OAuth2AuthorizedClientService clientService;
17

          
18
    @RequestMapping("/my-access-token")
19
    String home(Principal user) {
20
        OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) user;
21
        String authorizedClientRegistrationId = token.getAuthorizedClientRegistrationId();
22
        String name = user.getName();
23
        OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(authorizedClientRegistrationId, name);
24
        return "token: " + client.getAccessToken().getTokenValue();
25
    }
26

          
27
}



Start your app again and go to http://localhost:8080/my-access-token. If you are not authenticated, it will present you with a login form. After authenticating, you will see your token displayed on the web page. Copy the token value as you will use it next.

If you want to use the web UI (http://localhost:8080/gui), click on HTTP HEADERS at the bottom left and add the following, replacing <your_access_token> with the actual value of your access token that you got in the previous step:

JSON
 




xxxxxxxxxx
1


 
1
{ "Authorization": "Bearer <your_access_token>" }



If you are calling the API directly through HTTP, simply add the Authorization header with value Bearer <your_access_token>. You can click the Copy CURL button in the top right of the web UI to see an example.

Shell
 




xxxxxxxxxx
1


 
1
curl 'http://localhost:8080/graphql' -H 'Accept-Encoding: gzip, deflate, br' -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Connection: keep-alive' -H 'DNT: 1' -H 'Origin: http://localhost:8080' -H 'Authorization: Bearer <your_access_token>' --data-binary '{"query":"{\n  foods {\n    id\n    name\n  }\n}"}' --compressed



Or you can use HTTPie:

Plain Text
 




xxxxxxxxxx
1


 
1
http POST http://localhost:8080/graphql query='{foods{id,name}}' 'Authorization: <your_access_token>'



Now you have a fully secured GraphQL API!

If you try running your tests (./mvnw test), you will notice they are failing because the API will now answer with 403 Forbidden instead of 200 OK:

Shell
 




xxxxxxxxxx
1


 
1
$ ./mvnw test
2
...
3
[INFO] Results:
4
[INFO]
5
[ERROR] Failures:
6
[ERROR]   GraphqldemoApplicationTests.listFoods:34 Status expected:<200> but was:<403>
7
[INFO]
8
[ERROR] Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
9
...



That happens because your tests are not security-aware. To fix that, you need to add the method call .with(SecurityMockMvcRequestPostProcessors.jwt()) to each of your mockMvc.perform() chains, for example:

Java
 




xxxxxxxxxx
1


 
1
mockMvc.perform(MockMvcRequestBuilders.post("/graphql")
2
        .with(SecurityMockMvcRequestPostProcessors.jwt()) // <- ADD THIS LINE
3
        .content("{\"query\":\"{ foods { id name isGood } }\"}")
4
        .contentType(MediaType.APPLICATION_JSON)
5
        .accept(MediaType.APPLICATION_JSON))
6
        .andExpect(status().isOk())
7
        .andExpect(content().json(expectedResponse))
8
        .andReturn();



Both MockMvcRequestBuilders.post() and SecurityMockMvcRequestPostProcessors.jwt() can be static imports, so you can make this code a bit easier to read. Add the imports:

Java
 




xxxxxxxxxx
1


 
1
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
2
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;



Then remove the class names from the test:

Java
 




xxxxxxxxxx
1


 
1
mockMvc.perform(post("/graphql")
2
        .with(jwt())
3
        ...



The jwt() method instructs the test to inject a JWT authentication and act accordingly as if a user is authenticated.

Below is a full test class that verifies the GraphQL API you wrote works as expected:

Java
 




xxxxxxxxxx
1
114


 
1
package com.oktadeveloper.graphqldemo;
2

          
3
import org.junit.jupiter.api.MethodOrderer;
4
import org.junit.jupiter.api.Order;
5
import org.junit.jupiter.api.Test;
6
import org.junit.jupiter.api.TestMethodOrder;
7
import org.springframework.beans.factory.annotation.Autowired;
8
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
9
import org.springframework.boot.test.context.SpringBootTest;
10
import org.springframework.http.MediaType;
11
import org.springframework.test.web.servlet.MockMvc;
12

          
13
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
14
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
15
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
16
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
17

          
18
@SpringBootTest
19
@AutoConfigureMockMvc
20
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
21
class GraphqldemoApplicationTests {
22

          
23
    @Autowired
24
    MockMvc mockMvc;
25

          
26
    @Test
27
    @Order(0)
28
    void listFoods() throws Exception {
29

          
30
        String expectedResponse = "{\"data\":{\"foods\":[" +
31
                "{\"id\":1,\"name\":\"Pizza\",\"isGood\":true}," +
32
                "{\"id\":2,\"name\":\"Spam\",\"isGood\":false}," +
33
                "{\"id\":3,\"name\":\"Eggs\",\"isGood\":true}," +
34
                "{\"id\":4,\"name\":\"Avocado\",\"isGood\":false}" +
35
                "]}}";
36

          
37
        mockMvc.perform(post("/graphql")
38
                .with(jwt())
39
                .content("{\"query\":\"{ foods { id name isGood } }\"}")
40
                .contentType(MediaType.APPLICATION_JSON)
41
                .accept(MediaType.APPLICATION_JSON))
42
                .andExpect(status().isOk())
43
                .andExpect(content().json(expectedResponse))
44
                .andReturn();
45
    }
46

          
47
    @Test
48
    @Order(1)
49
    void addAndRemoveFood() throws Exception {
50
        String expectedResponseBefore = "{\"data\":{\"foods\":[" +
51
                "{\"id\":1,\"name\":\"Pizza\"}," +
52
                "{\"id\":2,\"name\":\"Spam\"}," +
53
                "{\"id\":3,\"name\":\"Eggs\"}," +
54
                "{\"id\":4,\"name\":\"Avocado\"}" +
55
                "]}}";
56
        String expectedResponseAfter = "{\"data\":{\"foods\":[" +
57
                "{\"id\":1,\"name\":\"Pizza\"}," +
58
                "{\"id\":2,\"name\":\"Spam\"}," +
59
                "{\"id\":3,\"name\":\"Eggs\"}," +
60
                "{\"id\":4,\"name\":\"Avocado\"}," +
61
                "{\"id\":5,\"name\":\"Pasta\"}" +
62
                "]}}";
63

          
64
        // List foods, expect 'New Food' to not be there
65
        mockMvc.perform(post("/graphql")
66
                .with(jwt())
67
                .content("{\"query\":\"{ foods { id name } }\"}")
68
                .contentType(MediaType.APPLICATION_JSON)
69
                .accept(MediaType.APPLICATION_JSON))
70
                .andExpect(status().isOk())
71
                .andExpect(content().json(expectedResponseBefore))
72
                .andReturn();
73

          
74
        // Add 'New Food'
75
        mockMvc.perform(post("/graphql")
76
                .with(jwt())
77
                .content("{\"query\":\"mutation { saveFood(food: { name: \\\"Pasta\\\" }) { id name } }\"}")
78
                .contentType(MediaType.APPLICATION_JSON)
79
                .accept(MediaType.APPLICATION_JSON))
80
                .andExpect(status().isOk())
81
                .andExpect(content().json("{\"data\":{\"saveFood\":{\"id\":5,\"name\":\"Pasta\"}}}"))
82
                .andReturn();
83

          
84
        // List foods, expect 'New Food' to be there
85
        mockMvc.perform(post("/graphql")
86
                .with(jwt())
87
                .content("{\"query\":\"{ foods { id name } }\"}")
88
                .contentType(MediaType.APPLICATION_JSON)
89
                .accept(MediaType.APPLICATION_JSON))
90
                .andExpect(status().isOk())
91
                .andExpect(content().json(expectedResponseAfter))
92
                .andReturn();
93

          
94
        // Remove 'New Food'
95
        mockMvc.perform(post("/graphql")
96
                .with(jwt())
97
                .content("{\"query\":\"mutation { deleteFood(id: 5) }\"}")
98
                .contentType(MediaType.APPLICATION_JSON)
99
                .accept(MediaType.APPLICATION_JSON))
100
                .andExpect(status().isOk())
101
                .andReturn();
102

          
103
        // List foods, expect 'New Food' to not be there
104
        mockMvc.perform(post("/graphql")
105
                .with(jwt())
106
                .content("{\"query\":\"{ foods { id name } }\"}")
107
                .contentType(MediaType.APPLICATION_JSON)
108
                .accept(MediaType.APPLICATION_JSON))
109
                .andExpect(status().isOk())
110
                .andExpect(content().json(expectedResponseBefore))
111
                .andReturn();
112
    }
113

          
114
}


Further Reading on GraphQL and Java

In this tutorial, you learned how to create your GraphQL API in Java with Spring Boot. But you are not limited to Spring Boot for that. You can use the GraphQL SPQR in pretty much any Java environment, even with Micronaut.

If you are using Quarkus and natively compiling your code, GraphQL SPQR wouldn’t work as it depends on reflection. But on that environment (and others) you could use the less-magic GraphQL Java, it’s a bit more verbose as you need to manually declare your schema, but it gets the job done as well as GraphQL SPQR. And don’t worry, we have a tutorial for GraphQL Java as well:

  • Build a Secure API with Spring Boot and GraphQL

If you want to keep reading about Java, Security, and Spring, here are some other links for you:

  • Build a Java REST API with Java EE and OIDC
  • Java + Spring Tutorials
  • 10 Myths About Java in 2019
  • Use React and Spring Boot to Build a Simple CRUD App

The source code for this post is available on GitHub in the oktadeveloper/okta-graphql-java-example repository.

If you have any questions about this post, please add a comment below. For more awesome content, follow @oktadev on Twitter, like us on Facebook, or subscribe to our YouTube channel.

Java (programming language) GraphQL Spring Framework Database API Spring Boot

Published at DZone with permission of Thiago Negri. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How To Build Web Service Using Spring Boot 2.x
  • GraphQL With Java Spring Boot and Postgres or MySQL Made Easy!
  • How To Best Use Java Records as DTOs in Spring Boot 3
  • Spring Boot: How To Use Java Persistence Query Language (JPQL)

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!