Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Oct 09 05:50
    hantsy opened #412
  • Oct 09 05:08
    hantsy commented #140
  • Oct 08 10:32
    hantsy commented #283
  • Oct 08 10:32
    hantsy commented #283
  • Oct 08 10:32
    hantsy commented #283
  • Oct 06 21:04
    vadrem opened #411
  • Sep 24 20:37
    ryantw commented #410
  • Sep 24 10:19
    temaslikov opened #410
  • Sep 13 19:09
    stevedefazio commented #407
  • Sep 13 18:40
    stevedefazio commented #407
  • Sep 13 18:37
    stevedefazio commented #407
  • Aug 28 21:10
    kaqqao commented #409
  • Aug 28 21:09
    kaqqao commented #409
  • Aug 27 20:30
    stevedefazio opened #409
  • Aug 27 11:43
    TuomasKiviaho opened #408
  • Aug 27 04:10
    TuomasKiviaho commented #230
  • Aug 27 04:09
    TuomasKiviaho commented #230
  • Aug 26 20:55
    kaqqao commented #230
  • Aug 26 20:55
    kaqqao commented #230
  • Aug 26 10:01
    TuomasKiviaho commented #230
Bojan Tomić
@kaqqao
For fields, you can implement a custom OperationInfoGenerator. Again, you can extend DefaultOperationInfoGenerator and override description.
Bojan Tomić
@kaqqao

There's a bit more theatrics about registering the custom impl (I should probbaly make that global, like for types).
You either create and register new ResolverBuilders with the custom strategy:

AnnotatedResolverBuilder annotated = new AnnotatedResolverBuilder().withOperationInfoGenerator(...);
BeanResolverBuilder bean = new BeanResolverBuilder().withOperationInfoGenerator(...);

generator
    .withResolverBuilders((config, builders) -> Collections.singletonList(annotated))
    .withNestedResolverBuilders((config, builders) -> Arrays.asList(annotated, bean.withBasePackages(config.basePackages)))

or modify the existing ones:

generator
    .withResolverBuilders((config, builders) -> builders
        .modify(AnnotatedResolverBuilder.class, ann -> ann.withOperationInfoGenerator(...)))
    .withNestedResolverBuilders((config, builders) -> builders
        .modify(AnnotatedResolverBuilder.class, ann -> ann.withOperationInfoGenerator(...))
        .modify(BeanResolverBuilder.class, bn -> bn.withOperationInfoGenerator(...)))
James Peters
@JamesPeters98
Oh nice thanks, I actually ended up using a SchemaTransformer and then just using the transformField and transformInputField methods
Bojan Tomić
@kaqqao
Ah, yes, that works fine too :)
Dave Ramirez
@dave-at-season
Is there a way to ignore kotlin companion classes? GraphQLIgnore doesnt seem to do the trick
Rinesh Agnihotri
@rkagni
I am new to graphql-spqr and so please do not mind the naivety of the question question :-). I have an existing spring-boot REST API that I also want to expose as graphql. Essentially the REST needs to be consumed by external third party application whereas grapgql will be exposed to UI layer of the application. The application's current error handling is using @ExceptionHandlers and what I am not able to figure out is how to extend that to graphql error handling mechanism. For example, we orchestrate few APIs to produce final response for the client and today if one of these APIs fail we send error to client (some business rules prohibit sending partial responses) which is not a restriction for our internal UI. How to achieve error handling in the same REST application for graphql layer. Any examples would be very helpful.
Eric Sandusky
@esandusky_configureone_gitlab
I am trying to wrap Exceptions using the schemaGenerator.withOutputConverters, but my exceptions end up without any fields exposed to the API. Is there something obvious that I'm missing?
public class ExceptionOutputConverter implements OutputConverter<Exception, GraphQLExceptionData> {

  @Override
  public GraphQLExceptionData convertOutput(Exception original, AnnotatedType type,
      ResolutionEnvironment resolutionEnvironment) {
    return new GraphQLExceptionData(original);
  }

  @Override
  public boolean supports(AnnotatedType type) {
    return Exception.class.isAssignableFrom(ClassUtils.getRawType(type.getType()));
  }
}
Matthew Lothian
@iamlothian
Hi all, I've uncounted a bit of a catch 22 when using SPQR with Spring reactive WebClient and DataLoaders. One of the downstream API requires that we propagate the security context in the API call. This API is often accessed as a nested resolver via a DataLoader. The problem is as soon as you call .toFuture() on a Mono or Flux you break the reactive context, so when it come time to make the request via WebClient there is no Spring Security Context available anymore. If I use .block() everywhere is can maintain the thread context as long as possible, but a resolver that uses a DataLoader needs to rather a completable future to work right.
I might be wrong, but I can see in MonoAdapter the reactive module uses .toFuture() rather than maintaining the reactive chain currently.
Bojan Tomić
@kaqqao
@iamlothian The Starter does a lot of trickery to stitch the recative context back together, while keepting graphql-java blissfully unaware of Reactor
And I think you should be able to do the same
Now that I think about it... SPQR might need to be doing more out-of-the-box for DataLoaders and CompletableFutures
But... Let's get your thing worked around first 😅
Matthew Lothian
@iamlothian
Honestly a better solution for me is to not pass through the security context and have the repository and application layer decoupled entirely. But This change is dependent on some other team that are fairly slow, and I sure I'm not the first to encounter this need.
Bojan Tomić
@kaqqao
While I'm pretty sure I get exactly what you're facing, would you make me a small example (not a whole runnable thing, just the crux of the problem)?
Matthew Lothian
@iamlothian
@kaqqao is an issue a better place for use to work this through. I am using graphql-spqr-spring-boot-starter:0.6.0
Bojan Tomić
@kaqqao
Yup, an issue is probably better, since this is relevant for other users...
Matthew Lothian
@iamlothian

While I'm pretty sure I get exactly what you're facing, would you make me a small example (not a whole runnable thing, just the crux of the problem)?

Ok i'll find some time to try replicate the issue in issolation and put it in an issue

Bojan Tomić
@kaqqao
Here's some of the trickery I was refering to: MonoInterceptor
This intercepts all resolvers that return a Mono, and reattach the context lost when it got turned into a CompletableFuture for graphql-java to digest
Matthew Lothian
@iamlothian
Yep i'v been debugging through these classes.
Bojan Tomić
@kaqqao
Hard to wrap my mind around it without some code in front of me (and it's super late here 😆), but could you do something like that? The original reactive context is piggy-backed through GraphQL context... so can you reattach it where needed?
Matthew Lothian
@iamlothian
I'm in Canada, It's getting late here also, so something for tomorrow morning.
Bojan Tomić
@kaqqao
I'm in Europe, so almost 1AM :) Alright. Have a good evening/night, and let's see about it tomorrow.
Matthew Lothian
@iamlothian
Thanks and goodnight.
Bojan Tomić
@kaqqao
@esandusky_configureone_gitlab This is a strange use-case for an output converter, I think... Exceptions are not commonly returned from a resolver, so they don't gte converted. A simple way to achieve what you're after is to use an interceptor (ResolverInterceptor). You can catch all exceptions there and turn them into DataFetchingResult with an error.
@esandusky_configureone_gitlab Check out my answer here
Matthew Lothian
@iamlothian
UPDATE: I'm refactoring my application to use reactive e2e as I found I was actually using the web pipeline to handle requests. This may solve my issue, as it forces me to rewrite my authorization checks using the reactive pipeline. Which I have found can work nicely with annotations still @PreAuthorize("@securityContextFacade.isActive(authentication)") you just have to pass in the authentication arg and it will be resolved from the context.
Matthew Lothian
@iamlothian
Took some debugging of the ExpressionBasedPreInvocationAdvice and ReflectiveMethodExecutor classes to discover.
Matthew Lothian
@iamlothian
ok @kaqqao this seems to work as expected now
    public Mono<OrganisationModel> organisation(
        @GraphQLContext AmqpChannelUserModel user,
        @GraphQLEnvironment ResolutionEnvironment env
    ) {
        log.info("amqpChannelUsers.organisation({})", user.getOrganisationId());
        DataLoader<String, Organisation> orgLoader = env.dataFetchingEnvironment.getDataLoader(OrganisationLoader.KEY);
        return Mono.fromFuture(orgLoader.load(user.getOrganisationId())
            .thenApply(organisationMapper::toModel));
    }
Matthew Lothian
@iamlothian
Ahhh bummer the issue persists Context does not contain key: org.springframework.security.SECURITY_CONTEXT_ATTRIBUTES
Nested resolver using @GraphQLContext is missing spring security context in the reactive context. Looks like I create an issue yet.
Matthew Lothian
@iamlothian
Ok, Solved. needed to use ReactiveSecurityContextHolder like this to access the context.
public class DelegatingSecurityExchangeFilter implements ExchangeFilterFunction {

    @Override
    public Mono<ClientResponse> filter(ClientRequest clientRequest, ExchangeFunction next) {
        return getToken().flatMap(token -> next.exchange(RequestWithBearer(clientRequest, token)));
    }

    private ClientRequest RequestWithBearer(ClientRequest request, AbstractOAuth2Token token) {
        return ClientRequest.from(request)
            .headers(headers -> headers.setBearerAuth(token.getTokenValue()))
            .build();
    }

    private Mono<OAuth2AccessToken> getToken() {
        return ReactiveSecurityContextHolder.getContext()
            .map(SecurityContext::getAuthentication)
            .map(Authentication::getCredentials)
            .cast(OAuth2AccessToken.class);
    }
}
Eric Sandusky
@esandusky_configureone_gitlab
@kaqqao Thank you, I already use that method of catching exceptions. For this feature, I wanted to wrap exceptions to provide information in normal query responses, ahead of a call to a specific mutation which may throw that exception. A TypeAdapter appears to work as expected, and applied as a TypeMapper and OutputConverter in the schemaGenerator.
public class ExceptionOutputConverter extends AbstractTypeAdapter<Exception, GraphQLExceptionData>
Bojan Tomić
@kaqqao
@erikwiklander Ah, yes. I am looking into building out-of-the-box support for errors-as-response, btw.
@pradip9102 Yup, that looks legit. Glad to see you got it figured out!
tapanShowbie
@tapanShowbie
Hi what is the status of @defer attribute in graphql-spqr. Is there any documentation on graphql-spqr which I can refer to ?
Bojan Tomić
@kaqqao
@defer was removed from graphql-java...
Here's some more context: graphql-java/graphql-java#1961
It will likely be reintroduced again soon. But for the time being, there's no support for it...
Sarath S Menon
@sarathm09
Hi, I have a scenario where I need to lint the graphql schema in a project. I found SchemaPrinter to get the generated schema, but how do I integrate it with maven builds and incorporate a linter into it?
James Peters
@JamesPeters98
@sarathm09 I just used the exec-maven-plugin to run a custom class that starts Spring Boot and then outputs the string from the SchemaPrinter to a file and then shutdowns the server
Sarath S Menon
@sarathm09

@sarathm09 I just used the exec-maven-plugin to run a custom class that starts Spring Boot and then outputs the string from the SchemaPrinter to a file and then shutdowns the server

interesting, I thought of using exec-maven-plugin, but I'm sure if starting the app during build time is a good option

mailrootone
@mailrootone
Hi all, one doubt.
When we define the description of the query/field, for example @GraphQLQuery(name = "name", description = "A person's name"), is there a way by which I can make the description localized? I mean somehow fetch the description from the message bundle and return it based on user's language.
Kalyan Mantripragada
@kalyan220:matrix.org
[m]
Hi all, is there a way to do file upload using spqr starter? Really helpful if there are any examples
sriram
@sriramsridhar
Hey guys, can anyone share blogs on JWT authentication and authorisation when using spqr?
Matthew Lothian
@iamlothian
@sriramsridhar Are you using spring-boot? If so you can use spring security? Be sure to pick the right flavour (web-mvc, vs web-flux) depending on your chosen stack.
1 reply
Matthew Lothian
@iamlothian
@kalyan220:matrix.org hmm not out of the box, but nothing in SPQR starter is stopping you from exposing another controller post endpoint used to submit files. Or if you need to use the POST /qraphql to get a query response also, you could override the default controller to accept a multipart file and add it into the graphql context. The latter might make for a confusing developer experience.
sriram
@sriramsridhar
hey guys, a newbie doubt - how do i add support for variables in graphql queries?
tapanShowbie
@tapanShowbie

Hi Guys, is there a way in graphql-spqr where we can return both partial result and error.

The feature is that I am trying to do a mutation which is a bulk operation. The mutation will then call an internal api to do the bulk operation. The main issue is that the internal bulk operation api could return a result with partial success and an error. Is there a way to handle such scenario in Graphql-spqr ?