JAVA-12421 Renamed graphql to graphql-modules
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
## GraphQL Domain Graph Service (DGS)
|
||||
|
||||
This module contains articles about GraphQL using the Netflix Domain Graph Service (DGS).
|
||||
|
||||
## Relevant articles:
|
||||
|
||||
- [An Introduction to Domain Graph Service (DGS) Framework](https://www.baeldung.com/spring-boot-domain-graph-service)
|
||||
@@ -0,0 +1,73 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>graphql-dgs</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>graphql-dgs</name>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.graphql</groupId>
|
||||
<artifactId>graphql-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.netflix.graphql.dgs</groupId>
|
||||
<artifactId>graphql-dgs-platform-dependencies</artifactId>
|
||||
<version>4.1.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.graphql.dgs.codegen</groupId>
|
||||
<artifactId>graphql-dgs-codegen-client-core</artifactId>
|
||||
<version>${graphql-dgs-codegen-client-core.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.netflix.graphql.dgs</groupId>
|
||||
<artifactId>graphql-dgs-spring-boot-starter</artifactId>
|
||||
<version>${graphql-dgs-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>io.github.deweyjose</groupId>
|
||||
<artifactId>graphqlcodegen-maven-plugin</artifactId>
|
||||
<version>1.14</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>generate</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<schemaPaths>
|
||||
<param>src/main/resources/schema/schema.graphqls</param>
|
||||
</schemaPaths>
|
||||
<packageName>com.bealdung.graphqldgs.generated</packageName>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<graphql-dgs-codegen-client-core.version>5.1.14</graphql-dgs-codegen-client-core.version>
|
||||
<graphql-dgs-spring-boot-starter.version>4.9.15</graphql-dgs-spring-boot-starter.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.bealdung.graphqlDGS;
|
||||
|
||||
public class Album {
|
||||
private final String title;
|
||||
private final String artist;
|
||||
private final Integer recordNo;
|
||||
|
||||
public Album(String title, String artist, Integer recordNo) {
|
||||
this.title = title;
|
||||
this.recordNo = recordNo;
|
||||
this.artist = artist;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public String getArtist() {
|
||||
return artist;
|
||||
}
|
||||
|
||||
public Integer getRecordNo() {
|
||||
return recordNo;
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.bealdung.graphqlDGS;
|
||||
|
||||
import com.netflix.graphql.dgs.DgsComponent;
|
||||
import com.netflix.graphql.dgs.DgsQuery;
|
||||
import com.netflix.graphql.dgs.InputArgument;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@DgsComponent
|
||||
public class AlbumsDataFetcher {
|
||||
|
||||
private final List<Album> albums = Arrays.asList(
|
||||
new Album("Rumours", "Fleetwood Mac", 20),
|
||||
new Album("What's Going On", "Marvin Gaye", 10),
|
||||
new Album("Pet Sounds", "The Beach Boys", 12)
|
||||
);
|
||||
|
||||
@DgsQuery
|
||||
public List<Album> albums(@InputArgument String titleFilter) {
|
||||
if(titleFilter == null) {
|
||||
return albums;
|
||||
}
|
||||
return albums.stream()
|
||||
.filter(s -> s.getTitle().contains(titleFilter))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.bealdung.graphqlDGS;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
server.servlet.context-path=
|
||||
@@ -0,0 +1,9 @@
|
||||
type Query {
|
||||
albums(titleFilter: String): [Album]
|
||||
}
|
||||
|
||||
type Album {
|
||||
title: String
|
||||
artist: String
|
||||
recordNo: Int
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
### Relevant Articles:
|
||||
|
||||
- [Error Handling in GraphQL With Spring Boot](https://www.baeldung.com/spring-graphql-error-handling)
|
||||
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>graphql-error-handling</artifactId>
|
||||
<version>1.0</version>
|
||||
<name>graphql-error-handling</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung.graphql</groupId>
|
||||
<artifactId>graphql-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-spring-boot-starter</artifactId>
|
||||
<version>${graphql-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-java-tools</artifactId>
|
||||
<version>${graphql-java-tools.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.h2database</groupId>
|
||||
<artifactId>h2</artifactId>
|
||||
<version>${h2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.graphql-java</groupId>
|
||||
<artifactId>graphql-spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>${graphql-spring-boot-starter.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.skyscreamer</groupId>
|
||||
<artifactId>jsonassert</artifactId>
|
||||
<version>${jsonassert.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<graphql-spring-boot-starter.version>5.0.2</graphql-spring-boot-starter.version>
|
||||
<graphql-java-tools.version>5.2.4</graphql-java-tools.version>
|
||||
<jsonassert.version>1.5.0</jsonassert.version>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package com.baeldung.graphql.error.handling;
|
||||
|
||||
import com.baeldung.graphql.error.handling.exception.GraphQLErrorAdapter;
|
||||
import graphql.ExceptionWhileDataFetching;
|
||||
import graphql.GraphQLError;
|
||||
import graphql.servlet.GraphQLErrorHandler;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SpringBootApplication
|
||||
public class GraphQLErrorHandlerApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(GraphQLErrorHandlerApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GraphQLErrorHandler errorHandler() {
|
||||
return new GraphQLErrorHandler() {
|
||||
@Override
|
||||
public List<GraphQLError> processErrors(List<GraphQLError> errors) {
|
||||
List<GraphQLError> clientErrors = errors.stream()
|
||||
.filter(this::isClientError)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<GraphQLError> serverErrors = errors.stream()
|
||||
.filter(e -> !isClientError(e))
|
||||
.map(GraphQLErrorAdapter::new)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<GraphQLError> e = new ArrayList<>();
|
||||
e.addAll(clientErrors);
|
||||
e.addAll(serverErrors);
|
||||
return e;
|
||||
}
|
||||
|
||||
private boolean isClientError(GraphQLError error) {
|
||||
return !(error instanceof ExceptionWhileDataFetching || error instanceof Throwable);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.graphql.error.handling.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Location {
|
||||
@Id
|
||||
private String zipcode;
|
||||
|
||||
private String city;
|
||||
private String state;
|
||||
|
||||
@OneToMany(mappedBy = "location", fetch = FetchType.EAGER)
|
||||
private List<Vehicle> vehicles = new ArrayList<>();
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
package com.baeldung.graphql.error.handling.domain;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class Vehicle {
|
||||
@Id
|
||||
private String vin;
|
||||
private Integer year;
|
||||
private String make;
|
||||
private String model;
|
||||
private String trim;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "fk_location")
|
||||
private Location location;
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package com.baeldung.graphql.error.handling.exception;
|
||||
|
||||
import graphql.ErrorType;
|
||||
import graphql.GraphQLError;
|
||||
import graphql.language.SourceLocation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AbstractGraphQLException extends RuntimeException implements GraphQLError {
|
||||
private Map<String, Object> parameters = new HashMap();
|
||||
|
||||
public AbstractGraphQLException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public AbstractGraphQLException(String message, Map<String, Object> additionParams) {
|
||||
this(message);
|
||||
if (additionParams != null) {
|
||||
parameters = additionParams;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return super.getMessage();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SourceLocation> getLocations() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorType getErrorType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getExtensions() {
|
||||
return this.parameters;
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.baeldung.graphql.error.handling.exception;
|
||||
|
||||
import graphql.ErrorType;
|
||||
import graphql.ExceptionWhileDataFetching;
|
||||
import graphql.GraphQLError;
|
||||
import graphql.language.SourceLocation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class GraphQLErrorAdapter implements GraphQLError {
|
||||
|
||||
private GraphQLError error;
|
||||
|
||||
public GraphQLErrorAdapter(GraphQLError error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getExtensions() {
|
||||
return error.getExtensions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SourceLocation> getLocations() {
|
||||
return error.getLocations();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErrorType getErrorType() {
|
||||
return error.getErrorType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getPath() {
|
||||
return error.getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> toSpecification() {
|
||||
return error.toSpecification();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return (error instanceof ExceptionWhileDataFetching) ? ((ExceptionWhileDataFetching) error).getException().getMessage() : error.getMessage();
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.baeldung.graphql.error.handling.exception;
|
||||
|
||||
public class InvalidInputException extends RuntimeException {
|
||||
public InvalidInputException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.graphql.error.handling.exception;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class VehicleAlreadyPresentException extends AbstractGraphQLException {
|
||||
|
||||
public VehicleAlreadyPresentException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public VehicleAlreadyPresentException(String message, Map<String, Object> additionParams) {
|
||||
super(message, additionParams);
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.baeldung.graphql.error.handling.exception;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class VehicleNotFoundException extends AbstractGraphQLException {
|
||||
|
||||
public VehicleNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public VehicleNotFoundException(String message, Map<String, Object> params) {
|
||||
super(message, params);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.graphql.error.handling.repository;
|
||||
|
||||
import com.baeldung.graphql.error.handling.domain.Vehicle;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface InventoryRepository extends JpaRepository<Vehicle, String> {
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.baeldung.graphql.error.handling.repository;
|
||||
|
||||
import com.baeldung.graphql.error.handling.domain.Location;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface LocationRepository extends JpaRepository<Location, String> {
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package com.baeldung.graphql.error.handling.resolver;
|
||||
|
||||
import com.baeldung.graphql.error.handling.domain.Location;
|
||||
import com.baeldung.graphql.error.handling.domain.Vehicle;
|
||||
import com.baeldung.graphql.error.handling.service.InventoryService;
|
||||
import com.coxautodev.graphql.tools.GraphQLMutationResolver;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class Mutation implements GraphQLMutationResolver {
|
||||
private InventoryService inventoryService;
|
||||
|
||||
public Mutation(InventoryService inventoryService) {
|
||||
this.inventoryService = inventoryService;
|
||||
}
|
||||
|
||||
public Vehicle addVehicle(String vin, Integer year, String make, String model, String trim, Location location) {
|
||||
return this.inventoryService.addVehicle(vin, year, make, model, trim, location);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
package com.baeldung.graphql.error.handling.resolver;
|
||||
|
||||
import com.baeldung.graphql.error.handling.domain.Vehicle;
|
||||
import com.baeldung.graphql.error.handling.service.InventoryService;
|
||||
import com.coxautodev.graphql.tools.GraphQLQueryResolver;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class Query implements GraphQLQueryResolver {
|
||||
private final InventoryService inventoryService;
|
||||
|
||||
public Query(InventoryService inventoryService) {
|
||||
this.inventoryService = inventoryService;
|
||||
}
|
||||
|
||||
public List<Vehicle> searchAll() {
|
||||
return this.inventoryService.searchAll();
|
||||
}
|
||||
|
||||
public List<Vehicle> searchByLocation(String zipcode) {
|
||||
return this.inventoryService.searchByLocation(zipcode);
|
||||
}
|
||||
|
||||
public Vehicle searchByVin(String vin) {
|
||||
return this.inventoryService.searchByVin(vin);
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
package com.baeldung.graphql.error.handling.service;
|
||||
|
||||
import com.baeldung.graphql.error.handling.domain.Location;
|
||||
import com.baeldung.graphql.error.handling.domain.Vehicle;
|
||||
import com.baeldung.graphql.error.handling.exception.InvalidInputException;
|
||||
import com.baeldung.graphql.error.handling.exception.VehicleAlreadyPresentException;
|
||||
import com.baeldung.graphql.error.handling.exception.VehicleNotFoundException;
|
||||
import com.baeldung.graphql.error.handling.repository.InventoryRepository;
|
||||
import com.baeldung.graphql.error.handling.repository.LocationRepository;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.transaction.Transactional;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
public class InventoryService {
|
||||
private InventoryRepository inventoryRepository;
|
||||
private LocationRepository locationRepository;
|
||||
|
||||
public InventoryService(InventoryRepository inventoryRepository, LocationRepository locationRepository) {
|
||||
this.inventoryRepository = inventoryRepository;
|
||||
this.locationRepository = locationRepository;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Vehicle addVehicle(String vin, Integer year, String make, String model, String trim, Location location) {
|
||||
Optional<Vehicle> existingVehicle = this.inventoryRepository.findById(vin);
|
||||
if (existingVehicle.isPresent()) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("vin", vin);
|
||||
throw new VehicleAlreadyPresentException("Failed to add vehicle. Vehicle with vin " + vin + " already present.", params);
|
||||
}
|
||||
Vehicle vehicle = Vehicle.builder()
|
||||
.vin(vin)
|
||||
.year(year)
|
||||
.make(make)
|
||||
.model(model)
|
||||
.location(location)
|
||||
.trim(trim)
|
||||
.build();
|
||||
|
||||
this.locationRepository.save(location);
|
||||
return this.inventoryRepository.save(vehicle);
|
||||
}
|
||||
|
||||
public List<Vehicle> searchAll() {
|
||||
return this.inventoryRepository.findAll();
|
||||
}
|
||||
|
||||
public List<Vehicle> searchByLocation(String zipcode) {
|
||||
if (StringUtils.isEmpty(zipcode) || zipcode.length() != 5) {
|
||||
throw new InvalidInputException("Invalid zipcode " + zipcode + " provided.");
|
||||
}
|
||||
return this.locationRepository.findById(zipcode)
|
||||
.map(Location::getVehicles)
|
||||
.orElse(new ArrayList<>());
|
||||
}
|
||||
|
||||
public Vehicle searchByVin(String vin) {
|
||||
return this.inventoryRepository.findById(vin).orElseThrow(() -> {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("vin", vin);
|
||||
return new VehicleNotFoundException("Vehicle with vin " + vin + " not found.", params);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
graphql:
|
||||
servlet:
|
||||
mapping: /graphql
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: "jdbc:h2:mem:graphqldb"
|
||||
driverClassName: "org.h2.Driver"
|
||||
username: sa
|
||||
password:
|
||||
|
||||
initialization-mode: always
|
||||
platform: h2
|
||||
|
||||
jpa:
|
||||
show-sql: true
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.H2Dialect
|
||||
ddl-auto: none
|
||||
|
||||
h2:
|
||||
console.enabled: true
|
||||
@@ -0,0 +1,23 @@
|
||||
type Vehicle {
|
||||
vin: ID!
|
||||
year: Int!
|
||||
make: String!
|
||||
model: String!
|
||||
trim: String!
|
||||
}
|
||||
|
||||
input Location {
|
||||
city: String
|
||||
state: String
|
||||
zipcode: String!
|
||||
}
|
||||
|
||||
type Query {
|
||||
searchAll: [Vehicle]!
|
||||
searchByLocation(zipcode: String!): [Vehicle]!
|
||||
searchByVin(vin: String!): Vehicle
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
addVehicle(vin: ID!, year: Int!, make: String!, model: String!, trim: String, location: Location): Vehicle!
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
insert into LOCATION values('07092', 'Mountainside', 'NJ');
|
||||
insert into LOCATION values ('94118', 'San Francisco', 'CA');
|
||||
insert into LOCATION values ('10002', 'New York', 'NY');
|
||||
|
||||
insert into VEHICLE (vin, year, make, model, trim, fk_location) values('KM8JN72DX7U587496', 2007, 'Hyundai', 'Tucson', null, '07092');
|
||||
insert into VEHICLE (vin, year, make, model, trim, fk_location) values('JTKKU4B41C1023346', 2012, 'Toyota', 'Scion', 'Xd', '94118');
|
||||
insert into VEHICLE (vin, year, make, model, trim, fk_location) values('1G1JC1444PZ215071', 2000, 'Chevrolet', 'CAVALIER VL', 'RS', '07092');
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.baeldung.graphql.error.handling;
|
||||
|
||||
import com.graphql.spring.boot.test.GraphQLResponse;
|
||||
import com.graphql.spring.boot.test.GraphQLTestTemplate;
|
||||
import org.json.JSONException;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.skyscreamer.jsonassert.JSONAssert;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static com.baeldung.graphql.error.handling.TestUtils.readFile;
|
||||
import static java.lang.String.format;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, classes = GraphQLErrorHandlerApplication.class)
|
||||
public class GraphQLErrorHandlerApplicationIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private GraphQLTestTemplate graphQLTestTemplate;
|
||||
|
||||
private static final String GRAPHQL_TEST_REQUEST_PATH = "graphql/request/%s.graphql";
|
||||
private static final String GRAPHQL_TEST_RESPONSE_PATH = "graphql/response/%s.json";
|
||||
|
||||
@Test
|
||||
public void whenUnknownOperation_thenRespondWithRequestError() throws IOException, JSONException {
|
||||
String graphqlName = "request_error_unknown_operation";
|
||||
GraphQLResponse actualResponse = graphQLTestTemplate.postForResource(format(GRAPHQL_TEST_REQUEST_PATH, graphqlName));
|
||||
String expectedResponse = readFile(format(GRAPHQL_TEST_RESPONSE_PATH, graphqlName));
|
||||
|
||||
JSONAssert.assertEquals(expectedResponse, actualResponse.getRawResponse().getBody(), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInvalidSyntaxRequest_thenRespondWithRequestError() throws IOException, JSONException {
|
||||
String graphqlName = "request_error_invalid_request_syntax";
|
||||
GraphQLResponse actualResponse = graphQLTestTemplate.postForResource(format(GRAPHQL_TEST_REQUEST_PATH, graphqlName));
|
||||
String expectedResponse = readFile(format(GRAPHQL_TEST_RESPONSE_PATH, graphqlName));
|
||||
|
||||
JSONAssert.assertEquals(expectedResponse, actualResponse.getRawResponse().getBody(), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenRequestAllNonNullField_thenRespondPartialDataWithFieldError() throws IOException, JSONException {
|
||||
String graphqlName = "field_error_request_non_null_fields_partial_response";
|
||||
GraphQLResponse actualResponse = graphQLTestTemplate.postForResource(format(GRAPHQL_TEST_REQUEST_PATH, graphqlName));
|
||||
String expectedResponse = readFile(format(GRAPHQL_TEST_RESPONSE_PATH, graphqlName));
|
||||
|
||||
JSONAssert.assertEquals(expectedResponse, actualResponse.getRawResponse().getBody(), true);
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.baeldung.graphql.error.handling;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class TestUtils {
|
||||
public static String readFile(String path) throws IOException {
|
||||
return IOUtils.toString(
|
||||
new ClassPathResource(path).getInputStream(), Charset.defaultCharset()
|
||||
);
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
# trim is non null but one of the record has null value for trim
|
||||
query {
|
||||
searchAll {
|
||||
vin
|
||||
year
|
||||
make
|
||||
model
|
||||
trim
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
query {
|
||||
searchByVin(vin: "error) {
|
||||
vin
|
||||
year
|
||||
make
|
||||
model
|
||||
trim
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
subscription {
|
||||
searchByVin(vin: "75024") {
|
||||
vin
|
||||
year
|
||||
make
|
||||
model
|
||||
trim
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user