Рубрики
Без рубрики

Создайте GraphQL API с помощью Spring Boot

Введение В этом руководстве мы создадим Pokemon API, который использует данные из Postgr… С тегом tutorial, java, graphql.

В этом руководстве мы создадим Pokemon API, который использует данные из базы данных Postgres, с простой конечной точкой, которая выполняет поиск по идентификатору.

Окончательный код находится в этом Репозиторий Github .

Если у вас уже установлен Postgres локально, вы можете пропустить эту часть, в противном случае самый простой способ сделать это – запустить образ Docker. Просто установите Docker , а затем:

docker run -p5432:5432 -d postgres:11.4-alpine

Эта команда запустит экземпляр Postgres на порту 5432 с пользователем по умолчанию postgres и базой данных по умолчанию postgres .

Мы начнем с создания начальных файлов проекта с помощью Spring Initializr . Я выбрал:

  • Градация
  • Ява
  • Пружинный ботинок 2.1.6
  • Пускатель пружинного полотна
  • Spring Data JPA
  • PostgreSQL Водитель

Помимо зависимостей Spring, нам нужно добавить библиотеки GraphQL:

  • GraphQL Spring Boot Starter: автоматически создаст конечную точку /graphql
  • Начальный тест GraphQL Spring Boot Starter: для наши модульные тесты
  • GraphQL Java Tools: из его собственной документации : “сопоставляет поля ваших объектов GraphQL с методами и свойствами ваших объектов java”. Для этой библиотеки требуется версия 1.3. * из Kotlin, поэтому вам нужно создать файл gradle.properties в корневом каталоге проекта с содержимым:
kotlin.version=1.3.10

Подключение к базе данных

После добавления зависимостей вы можете отредактировать файл src/main/resources/application.properties , чтобы добавить конфигурацию Postgres. Если вы используете приведенную выше команду Docker для локального запуска Postgres, ваш файл должен выглядеть следующим образом:

## PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=

#drop n create table again, good for testing, comment this in production
spring.jpa.hibernate.ddl-auto=create-drop

Запустите свое приложение, чтобы проверить, все ли работает до сих пор: ./gradlew bootRun .

GraphQL имеет отличный язык схем, который добавляет объявления типов к своим запросам и возвращаемым значениям и связывает это с реализацией API. Это означает, что то, что вы объявляете в схеме, должно быть реализовано.

Если мы хотим добавить конечную точку для поиска покемона по его идентификатору, мы должны объявить в файле src/main/resources/schema.graphql :

type Pokemon {
    id: ID!
    name: String!
}

type Query {
    pokemon(id: ID!): Pokemon
}

Нашим следующим шагом теперь должен быть поиск экземпляра Pokemon в базе данных по его идентификатору, иначе приложение не запустится.

Объявленная схема ожидает возврата Pokemon type , который содержит требуемые атрибуты id и имя .

Для нашего приложения это означает, что Pokemon – это класс Java с идентификатор и имя свойства, а также таблица базы данных. Мы можем использовать javax.persistence аннотации для автоматического сопоставления покемонов с таблицей базы данных со столбцами идентификатор и имя :

@Entity
@Table(name = "pokemon")
public class Pokemon {

    public Pokemon(final Long id, final String name) {
        this.id = id;
        this.name = name;
    }

    @Id
    public Long id;

    @Column
    public String name;
}

Другим ожидаемым классом должен быть Spring Bean , который реализует Распознаватель запросов GraphQL интерфейс и должен иметь метод с именем получить покемона , который соответствует параметрам и ответу точно так , как мы определили в схеме:

@Component
public class Query implements GraphQLQueryResolver {

    public Pokemon getPokemon(Long id) {
        return new Pokemon(1L, "Pikachu");
    }
}

Теперь мы можем выполнить запрос на нашей новой конечной точке, чтобы проверить, является ли его ответ нашим Пикачу.

GraphiQL настраивает конечную точку в нашем API, которая позволяет нам тестировать любой запрос. В нашем проекте он будет работать по адресу http://localhost:8080/graphiql .

В левом столбце мы должны записывать запросы, а в правом – результаты. Например, если мы введем запрос:

# Searches a Pokemon with id 25 and returns its field 'name'
query {
  pokemon(id: 25){
    name
  }
}

Мы должны ожидать результата в правой колонке:

{
  "data": {
    "pokemon": {
      "name": "Pikachu"
    }
  }
}

Пока не имеет значения, какой параметр i d мы проходим, потому что мы исправили объект ответа, но теперь мы реализуем поиск в базе данных.

В настоящее время наше приложение не выполняет реальный поиск в базе данных, а возвращает фиксированный экземпляр. Давайте теперь реализуем эту часть.

Сначала мы создаем PokemonRepository интерфейс, который расширяет JpaRepository :

@Repository
public interface PokemonRepository extends JpaRepository {
}

Затем мы меняем наш класс Query на автоматическое подключение этого компонента и выполняем реальную выборку базы данных:

@Component
public class Query implements GraphQLQueryResolver {

    @Autowired
    private PokemonRepository repository;

    public Pokemon getPokemon(Long id) {
        // Not returning a fixed instance anymore
        return repository.findById(id).orElse(null);
    }
}

Наш автоматический тест будет использовать класс GraphQLTestTemplate , который позволяет нам вводить запрос и проверять его ответ. Например, если мы хотим протестировать поиск pokemon по запросу id, нам сначала нужно создать файл в src/test/resources с этим запросом:

# src/test/resources/get-pokemon-by-id.graphql
query {
    pokemon(id: "1") {
        id
        name
    }
}

Тестовый класс должен быть аннотирован с помощью @GraphQLTest таким образом, он может разрешить экземпляр GraphQLTestTemplate и PokemonRepository должен быть помечен @MockBean таким образом, мы можем имитировать его ответ, используя Мокито

@RunWith(SpringRunner.class)
@GraphQLTest
public class DemoApplicationTests {

    @Autowired
    private GraphQLTestTemplate graphQLTestTemplate;

    @MockBean
    private PokemonRepository pokemonRepository;

    @Test
    public void getById() throws IOException {
        Pokemon pokemon = new Pokemon(1L, "Pikachu");
        when(pokemonRepository.findById(any()))
                .thenReturn(Optional.of(pokemon));

        GraphQLResponse response =
                graphQLTestTemplate.postForResource("get-pokemon-by-id.graphql");

        assertTrue(response.isOk());
        assertEquals("1", response.get("$.data.pokemon.id"));
        assertEquals("Pikachu", response.get("$.data.pokemon.name"));
    }
}

В основном сценарий, который мы здесь тестируем, выглядит следующим образом:

  • Учитывая, что репозиторий возвращает пикачу при вызове метода findById
  • Когда мы запрашиваем GraphQL Api с помощью get-pokemon-by-id.graphql
  • Затем мы ожидаем, что ответом будет JSON, содержащий пикачу из репозитория

Задача реализации GraphQL Api с использованием Spring Boot зависит в основном от конфигурации и мелких деталей функциональности Spring Boot. В целом я думаю, что интеграция работает очень хорошо, особенно инструменты GraphQL Java, которые обеспечивают реализацию кода.

Оригинал: “https://dev.to/fabiothiroki/create-a-graphql-api-using-spring-boot-32o2”