无法摆脱 graphql-spqr-spring-boot-starter 中的“获取数据时异常(/apiName)”

Posted

技术标签:

【中文标题】无法摆脱 graphql-spqr-spring-boot-starter 中的“获取数据时异常(/apiName)”【英文标题】:Unable to get rid of 'Exception while fetching data(/apiName)' in graphql-spqr-spring-boot-starter无法摆脱 graphql-spqr-spring-boot-starter 中的“获取数据时异常(/apiName)” 【发布时间】:2020-11-04 08:26:08 【问题描述】:

我正在使用“io.leangen.graphql”的“graphql-spqr-spring-boot-starter”库版本 0.0.4。我可以自定义错误。请参阅以下代码和屏幕截图以供参考:

型号:

@Getter
@Setter
@ToString
@Entity
@Accessors
public class Student 
    
    @Id 
    @GraphQLQuery(name = "id", description = "A Student's ID")
    private Long id;
    
    @GraphQLQuery(name = "name", description = "A student's name")
    private String name;    
    
    private String addr;


服务类:

@Service
@GraphQLApi
public class StudentService
    
    private final StudentRepository studentRepository;
    private final AddressRepository addressRepository;
    
    public StudentService(StudentRepository studentRepository, AddressRepository addressRepository) 
        this.addressRepository = addressRepository;
        this.studentRepository = studentRepository;
    
    
    @GraphQLQuery(name = "allStudents")
    public List<Student> getAllStudents() 
        return studentRepository.findAll();
    

    @GraphQLQuery(name = "student")
    public Optional<Student> getStudentById(@GraphQLArgument(name = "id") Long id) 
        if(studentRepository.findById(id) != null)
            return studentRepository.findById(id);
        throw new StudentNotFoundException("We were unable to find a student with the provided id", "id");
    
    
    @GraphQLMutation(name = "saveStudent")
    public Student saveStudent(@GraphQLArgument(name = "student") Student student) 
        if(student.getId() == null)
            throw new NoIdException("Please provide an Id to create a Student entry.");
        return studentRepository.save(student);
    

自定义异常类:

import java.util.List;

import graphql.ErrorType;
import graphql.GraphQLError;
import graphql.language.SourceLocation;

public class NoIdException extends RuntimeException implements GraphQLError 
    
    private String noIdMsg;
    
    public NoIdException(String noIdMsg) 
        this.noIdMsg = noIdMsg;
    

    @Override
    public List<SourceLocation> getLocations() 
        // TODO Auto-generated method stub
        return null;
    

    @Override
    public ErrorType getErrorType() 
        // TODO Auto-generated method stub
        return ErrorType.ValidationError;
    

    @Override
    public String getMessage() 
        // TODO Auto-generated method stub
        return noIdMsg;
    

但是,我不确定如何删除Exception while fetching data (/saveStudent),如上面message 字段的屏幕截图所示。我知道我们可以拥有实现GraphQLErrorHandler (graphql-java-kickstart)GraphQLExceptionHandler 类。但是sqpr-spring-boot-starter 的选项是什么?

import graphql.*;
import graphql.kickstart.execution.error.*;
import org.springframework.stereotype.*;

import java.util.*;
import java.util.stream.*;

@Component
public class GraphQLExceptionHandler implements GraphQLErrorHandler 

    @Override
    public List<GraphQLError> processErrors(List<GraphQLError> list) 
        return list.stream().map(this::getNested).collect(Collectors.toList());
    

    private GraphQLError getNested(GraphQLError error) 
        if (error instanceof ExceptionWhileDataFetching) 
            ExceptionWhileDataFetching exceptionError = (ExceptionWhileDataFetching) error;
            if (exceptionError.getException() instanceof GraphQLError) 
                return (GraphQLError) exceptionError.getException();
            
        
        return error;
    

有人可以帮我删除此声明并仅发送特定消息吗?

【问题讨论】:

【参考方案1】:

您可以创建Bean 并覆盖DataFetcherExceptionHandler。要覆盖它,您也必须覆盖执行策略:

@Bean
public GraphQL graphQL(GraphQLSchema schema) 
    return GraphQL.newGraphQL(schema)
            .queryExecutionStrategy(new AsyncExecutionStrategy(new CustomDataFetcherExceptionHandler()))
            .mutationExecutionStrategy(new AsyncSerialExecutionStrategy(new CustomDataFetcherExceptionHandler()))
            .build();


private static class CustomDataFetcherExceptionHandler implements DataFetcherExceptionHandler 

    @Override
    public DataFetcherExceptionHandlerResult onException(DataFetcherExceptionHandlerParameters handlerParameters) 
        Throwable exception = handlerParameters.getException();
        SourceLocation sourceLocation = handlerParameters.getSourceLocation();
        CustomExceptionWhileDataFetching error = new CustomExceptionWhileDataFetching(exception, sourceLocation);

        return DataFetcherExceptionHandlerResult.newResult().error(error).build();
    


private static class CustomExceptionWhileDataFetching implements GraphQLError 

    private final String message;
    private final List<SourceLocation> locations;

    public CustomExceptionWhileDataFetching(Throwable exception, SourceLocation sourceLocation) 
        this.locations = Collections.singletonList(sourceLocation);
        this.message = exception.getMessage();
    

    @Override
    public String getMessage() 
        return this.message;
    

    @Override
    public List<SourceLocation> getLocations() 
        return this.locations;
    

    @Override
    public ErrorClassification getErrorType() 
        return ErrorType.DataFetchingException;
    

【讨论】:

以上是关于无法摆脱 graphql-spqr-spring-boot-starter 中的“获取数据时异常(/apiName)”的主要内容,如果未能解决你的问题,请参考以下文章

如何摆脱这个??? “无法实例化以下类”

提交按钮有斜面我无法摆脱

我怎样才能摆脱错误-TypeError:无法读取未定义的属性'8'

获得“预期的呼叫签名:'printMe' 有一个 typedef”,我无法摆脱它

Debian上的Apache2,全新安装,无法摆脱默认值

使用 jQuery datepicker 自定义日期格式验证(无法摆脱美国日期验证)