leangen / graphql-spqr-spring-boot-starter Goto Github PK
View Code? Open in Web Editor NEWSpring Boot 2 starter powered by GraphQL SPQR
License: Apache License 2.0
Spring Boot 2 starter powered by GraphQL SPQR
License: Apache License 2.0
I couldn't figure out how to store currently authenticated user in the context so that I can use it for authorisation for example. And does this library provide any easy way to do authorisation?
Thank you for this starter. Could we have a new release with latest changes including spqr 0.10.0 ?
Hi there!
Congratulations on this amazing GraphQL spring boot extension, it was really easy to setup our current spring boot project to use this graphql-spqr-spring-boot-autoconfigure
dependency.
To help this project get even better, I would like to suggest a few improvements:
spring-boot-starter-websocket
dependency. Without this the application crashes after booting up.Best regards,
Rafael Renan Pacheco.
Uploading and downloading binaries is a common enough scenario to mandate out-of-the-box support.
https://github.com/jaydenseric/graphql-multipart-request-spec
Currently the DefaultGraphQLController autowires a GraphQLSchema, and builds a default GraphQL object. This doesn't leave room to configure an ExecutionStrategy or Instrumentation. The DefaultGraphQLController could instead autowire a GraphQL, which can be overridden for custom configuration.
Can you add steps on how to contribute to this project?
Hi, awesome library, thanks for it!
Is it planned to be able to customize ObjectMapper
in the ApolloMessage
class?
My use case is that I'd like to serialize LocalDateTime as a string (by default it is serialized as an Object, it's really weird).
In order to customize any of the following:
ExecutionInput
it is currently necessary to override the whole controller and/or WebSocket handler.
To facilitate easier customization, all of these concerns are now delegated to GraphQLExecutor
implementation that can easily be swapped by the user.
Right now, 3 built-in implementations exist (with at least 1 more to come):
servlet.DefaultGraphQLExecutor
- used by the GraphQL controller in a servlet-based appreactive.DefaultGraphQLExecutor
- used by the GraphQL controller in a reactive appservlet.websocket.DefaultGraphQLExecutor
- used by the WebSocket handler in a servlet-based appOnce WebSockets are supported on the reactive stack, an additional executor will be added.
When is the newest graphql-spqr version (v 0.10.0 with Lombok support) available in the graphql-spqr-spring-boot-starter poject (current v0.9.9)?
As a prerequisite for full WebFlux support #9, Flux
& Mono
should be correctly mapped and adapted out-of-the-box.
Currently, if a bean is wrapped into a proxy for any reason (security interceptors, async support, transactional control etc), SPQR will reject the bean as it's package name can no be reliably determined.
The starter should explicitly specify the real types when registering the discovered beans.
i want to use GraphQLInterface, but throw error 'not implement interface...'.
i search graphql-spqr, set basePackages will resolve this problem.
but i do not know how to set basePackages in this case.
Perhaps not an issue - I'm a bit of a newbie so forgive my ignorance :)
I'm using the new built in subscriptions with Apollo (@GraphQLSubscription). It all works beautifully, unless I add .withOperationsFromSingleton() to the GraphQLSchemaGenerator. I had originally thought the subscriptions stuff was not working at all but since realised it works without that config
Any pointers? Thanks
Hello, I'd like to know how the HttpServletRequest request in the SPQR controller is passed to the service.
When the client sends a GQL_CONNECTION_INIT (connection_init) message to the server, the server now expects (Jackson) an id field to be present in the message. However, the apollo client doesn't seem to send the id field in this message, so the server responds with a GQL_CONNECTION_ERROR (connection_error) response due to Jackson being unable to parse the message.
The problem seems to be in ApolloProtocolHandler:79 :
try {
ApolloMessage apolloMessage;
try {
apolloMessage = ApolloMessage.from(message);
} catch (IOException e) {
session.sendMessage(ApolloMessage.connectionError());
return;
}
Now the question is, is Apollo not following the GraphQL WS specification, or the server is to blame here?
When adding spring-boot-starter-security
you have to disable CSRF protection, because the graphiql user interface doesn't send csrf token when doing requests to POST /graphql
.
Don't know if that's possible at all. Else just close this issue.
how can i upload or download excel by Graphql-spqe-spring-boot-starter
Hi I believe I found a bug, whenever the DefaultGlobalContext is injected without the type being specified for the request object a TypeMappingException is raised:
Caused by: io.leangen.graphql.metadata.exceptions.TypeMappingException: Type io.leangen.graphql.spqr.spring.autoconfigure.DefaultGlobalContext is unbounded or missing generic type parameters
at io.leangen.graphql.util.ClassUtils.completeGenerics(ClassUtils.java:509) ~[spqr-0.9.9.jar:na]
at io.leangen.graphql.metadata.strategy.type.DefaultTypeTransformer.transform(DefaultTypeTransformer.java:28) ~[spqr-0.9.9.jar:na]
at io.leangen.graphql.metadata.strategy.query.AnnotatedArgumentBuilder.buildResolverArguments(AnnotatedArgumentBuilder.java:40) ~[spqr-0.9.9.jar:na]
... 65 common frames omitted
Here's an example to reproduce:
@GraphQLApi
@Service
public class SpqrBugService {
@GraphQLNonNull
@GraphQLQuery(name = "coolPeople")
public List<String> findCoolPeople(@GraphQLArgument(name = "coolnessFactor") final int factor,
@GraphQLRootContext final DefaultGlobalContext ctx) {
if (factor > 5) {
return ImmutableList.of("Me");
}
return ImmutableList.of();
}
}
A workaround is to do:
@GraphQLRootContext final DefaultGlobalContext<Object> ctx
graphql-spqr version 0.9.9
graphql-spqr-spring-boot-starter 0.0.4
Hello, I am trying to use spring boot auto starter in my project. I am not sure what I am missing.
I am getting below error :
JSON parse error: Cannot construct instance of
java.util.LinkedHashMap
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value (''); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance ofjava.util.LinkedHashMap
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('')\n at [Source: (PushbackInputStream); line: 1, column: 70] (through reference chain: io.leangen.graphql.spqr.spring.web.dto.GraphQLRequest["variables"])",
"path": "/graphql"
Below is my service class in spring boot application.
@GraphQLApi
@Service
public class Serviceq {
@Autowired
PRepository pRepo;
@Transactional
@GraphQLQuery(name = "party")
public Test getPByNum(@GraphQLArgument(name = "num") String num)
throws Exception, ExecutionException {
Future<Test> test= partyRepo.findByNum(num);
return test.get();
}
}
I am requesting with GraphiQL.
{
party (num: "1234"){
id
name
number
}
}
@GraphQLDirective(name = "timeout", locations = Introspection.DirectiveLocation.FIELD)
public static class Interrupt {
@GraphQLInputField(name = "afterMillis") //Customize the fields as usual
public int after;
}
{
books(searchString: "Monkey") @timeout(afterMillis: 500) {
title
}
}
throw err:
Validation error of type UnknownDirective: Unknown directive timeout
I am using 0.0.2 version. If I enable websocket support via graphql.spqr.ws.enabled=true
then websockets doesn't work with GraphQL Playground. It appears that SockJsHttpRequestHandler
is being used by the app instead of PerConnectionWebSocketHandler
. See below line from application startup logs -
Mapped URL path [/graphql/**] onto handler of type [class org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler]
Can anyone help with this? I have been using SPQR to build an app from last 3 months but because of Websocket support issues my development work is not crippled. :( I don't want to write a separate NodeJs app with Apollo server.
Hey @kaqqao I've pretty successfully integrated with spring security and SPQR but I just noticed a bug in my code that manifests itself only with subfields that are making use of @GraphQLContext
, and more specifically so far I've discovered this in a Subscription. For this example my subscription is returning the Stuff
objects.
Basically I have something like this:
@PreAuthorize("isAuthenticated()")
@GraphQLQuery
public Stuff getStuff() {
return repository.getStuff();
}
@PreAuthorize("isAuthenticated()")
@GraphQLQuery
public MoreStuff getMoreStuff(@GraphQLContext Stuff stuff) {
final MyAuthentication auth = (MyAuthentication)SecurityContextHolder.getContext().getAuthentication();
return repository.getMoreStuff(stuff.getStuffId(), auth.getUserId());
}
This results in a couple of issues, first the PreAuthorize
on the getMoreStuff query field cannot find an authenticated user in its context. As you may know SecurityContextHolder uses a ThreadLocal variable to keep track of the current security context, and I know that getMoreStuff and getStuff are executed in different threads, so this explains that issue. I tried to enable inheritable thread local strategy on the security context holder but that wouldnt work either because my getStuff thread is not the one initiating this other thread.
I assume you or someone else in the community has probably solved this issue before and I was wondering if I could get some insight on how its been solved for GraphQL. I prototyped something that while would work its also a lot of work...
Basically any parent field would have to do:
@PreAuthorize("isAuthenticated()")
@GraphQLQuery
public Stuff getStuff(@GraphQLRootContext DefaultGlobalContext<HttpServletRequest> context) {
// Store the authenticated user in the GraphQL DefaultGlobalContext so that it can be retrieved by sub fields
ContextUtils.saveAuthenticatedUser(context, authenticatedUser);
return repository.getStuff();
}
Then in my subfield I can do:
@GraphQLQuery
public MoreStuff getMoreStuff(@GraphQLRootContext DefaultGlobalContext<HttpServletRequest> context, @GraphQLContext Stuff stuff) {
final MyAuthentication auth = ContextUtils.getAuthenticatedUser(context);
return repository.getMoreStuff(stuff.getStuffId(), auth.getUserId());
}
As you can imagine this is very error prone and most likely I'm bruteforcing something in a way that can probably be done a lot easier. I was thinking of maybe an argument injector could be the way, basically create an argument injector that propagates the security context to subfields? I haven't found an example of something like this just yet but perhaps you have some pointers.
Thanks
Hello,
does it support for Relay framwork? Or is some way to solve specification on server from Relay? https://facebook.github.io/relay/docs/en/graphql-server-specification
I can't authenticate over websocket using Apollo aproach:
const wsLink = new WebSocketLink({
uri: 'ws://localhost:9090/graphql',
options: {
reconnect: true,
connectionParams: {
authToken: user.authToken,
},
});
The response is "HTTP Authentication failed; no valid credentials available"
How I can manage the connection params 'authToken' in Spring?
Add Support for apollo multipart file uploads.
See also:
When the variables
parameter is not being passed as part of the request, graphql-java
throws the following exception. This, in particular, is a nightly version of graphql-java
which makes the issue explicit (graphql-java/graphql-java#1596). Earlier versions of graphql-java
(from 11 on) fail with more obscure errors.
Would it make sense to ensure the propagated variables
instance is never null and rather an empty map?
graphql.AssertException: variables map can't be null
at graphql.Assert.assertNotNull(Assert.java:15)
at graphql.ExecutionInput$Builder.variables(ExecutionInput.java:215)
at io.leangen.graphql.spqr.spring.web.GraphQLExecutor.buildInput(GraphQLExecutor.java:20)
at io.leangen.graphql.spqr.spring.web.servlet.DefaultGraphQLExecutor.execute(DefaultGraphQLExecutor.java:23)
at io.leangen.graphql.spqr.spring.web.servlet.DefaultGraphQLExecutor.execute(DefaultGraphQLExecutor.java:11)
at io.leangen.graphql.spqr.spring.web.GraphQLController.executeJsonPost(GraphQLController.java:42)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
The above issue, in particular, is triggered simply loading a GraphiQL page which attempts an introspection query that doesn't include a variables
field in the request.
Hi!
I'm trying to use subscriptions with this library, but unfortunately it seems that data loaders are not working with subscriptions. The problem seems to be that the code in ApolloProtocolHandler
doesn't pass the dataLoaderRegistry
to the ExecutionInput.Builder
.
ApolloProtocolHandler line 91:
ExecutionResult result = graphQL.execute(ExecutionInput.newExecutionInput()
.query(request.getQuery())
.operationName(request.getOperationName())
.variables(request.getVariables()));
The missing lines are (copied from GraphQLController
:
if (dataLoaderRegistryFactory != null) {
inputBuilder.dataLoaderRegistry(dataLoaderRegistryFactory.createDataLoaderRegistry());
}
@kaqqao can you take a look at it?
Thanks,
Gabor
Hi,
thanks for this library. I'm using method level security to restrict the graphql endpoints. So far this works great. However, if a user lacks authentication the application returns an AccessDeniedException
(as expected) which I can't seem to catch.
I'd greatly appreciate any advice.
Example code:
@GraphQLApi
@Component
public class UserGraphQLService {
@PreAuthorize("hasRole('ROLE_USER')")
@GraphQLQuery
public String someMethod() {
//...
}
}
Results in:
org.springframework.security.access.AccessDeniedException: Access Denied
at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:65) ~[spring-security-core-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at my.application.UserGraphQLService$$EnhancerBySpringCGLIB$$a4cbe9c.someMethod(<generated>) ~[main/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at io.leangen.graphql.metadata.execution.SingletonMethodInvoker.execute(SingletonMethodInvoker.java:21) ~[spqr-0.9.9.jar:na]
at io.leangen.graphql.metadata.Resolver.resolve(Resolver.java:100) ~[spqr-0.9.9.jar:na]
at io.leangen.graphql.execution.OperationExecutor.lambda$execute$1(OperationExecutor.java:93) ~[spqr-0.9.9.jar:na]
at io.leangen.graphql.execution.OperationExecutor.execute(OperationExecutor.java:98) ~[spqr-0.9.9.jar:na]
at io.leangen.graphql.execution.OperationExecutor.execute(OperationExecutor.java:94) ~[spqr-0.9.9.jar:na]
at io.leangen.graphql.execution.OperationExecutor.execute(OperationExecutor.java:59) ~[spqr-0.9.9.jar:na]
at graphql.execution.instrumentation.dataloader.DataLoaderDispatcherInstrumentation.lambda$instrumentDataFetcher$0(DataLoaderDispatcherInstrumentation.java:86) ~[graphql-java-11.0.jar:na]
at graphql.execution.ExecutionStrategy.fetchField(ExecutionStrategy.java:261) ~[graphql-java-11.0.jar:na]
at graphql.execution.ExecutionStrategy.resolveFieldWithInfo(ExecutionStrategy.java:202) ~[graphql-java-11.0.jar:na]
at graphql.execution.ExecutionStrategy.resolveField(ExecutionStrategy.java:175) ~[graphql-java-11.0.jar:na]
at graphql.execution.AsyncSerialExecutionStrategy.lambda$execute$1(AsyncSerialExecutionStrategy.java:43) ~[graphql-java-11.0.jar:na]
at graphql.execution.Async.eachSequentiallyImpl(Async.java:75) ~[graphql-java-11.0.jar:na]
at graphql.execution.Async.eachSequentially(Async.java:64) ~[graphql-java-11.0.jar:na]
at graphql.execution.AsyncSerialExecutionStrategy.execute(AsyncSerialExecutionStrategy.java:38) ~[graphql-java-11.0.jar:na]
at graphql.execution.Execution.executeOperation(Execution.java:159) ~[graphql-java-11.0.jar:na]
at graphql.execution.Execution.execute(Execution.java:101) ~[graphql-java-11.0.jar:na]
at graphql.GraphQL.execute(GraphQL.java:573) ~[graphql-java-11.0.jar:na]
at graphql.GraphQL.parseValidateAndExecute(GraphQL.java:515) ~[graphql-java-11.0.jar:na]
at graphql.GraphQL.executeAsync(GraphQL.java:489) ~[graphql-java-11.0.jar:na]
at graphql.GraphQL.execute(GraphQL.java:420) ~[graphql-java-11.0.jar:na]
at io.leangen.graphql.spqr.spring.web.servlet.DefaultGraphQLExecutor.execute(DefaultGraphQLExecutor.java:23) ~[graphql-spqr-spring-boot-autoconfigure-0.0.4.jar:na]
at io.leangen.graphql.spqr.spring.web.servlet.DefaultGraphQLExecutor.execute(DefaultGraphQLExecutor.java:11) ~[graphql-spqr-spring-boot-autoconfigure-0.0.4.jar:na]
at io.leangen.graphql.spqr.spring.web.GraphQLController.executeJsonPost(GraphQLController.java:42) ~[graphql-spqr-spring-boot-autoconfigure-0.0.4.jar:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:892) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1039) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882) ~[spring-webmvc-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:320) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:119) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.7.RELEASE.jar:5.1.7.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:200) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:490) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:836) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1747) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.19.jar:9.0.19]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
I have a need that get authentication inside @GraphQLMutation
method, this might be a common need, as was mentioned in #11, However when using with WebFlux, the solution mentioned there is out of style.
SecurityContextHolder.getContext().getAuthentication()
will return null
in WebFlux, as explained in this StackOverflow post
Because there is no way to use ThreadLocal objects anymore. The only way to get Authentication for you, is to ask for it in controller's method signature, or...
Return a reactive-chain from method, that is making aReactiveSecurityContextHolder.getContext()
call.
In the case of this project, however, I cannot modify the Controller method, or return the reactive-chain that is making ReactiveSecurityContextHolder.getContext()
call.
I found a workaround to return the reactive-chain, by providing a custom GraphQLReactiveExecutor
, like this:
@Component
public class DefaultGraphQLExecutor implements GraphQLReactiveExecutor {
@Autowired(required = false)
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
private DataLoaderRegistryFactory dataLoaderRegistryFactory;
@Override
public Mono<Map<String, Object>> execute(GraphQL graphQL, GraphQLRequest graphQLRequest, ServerWebExchange request) {
return ReactiveSecurityContextHolder.getContext()
.flatMap(securityContext -> Mono.fromFuture(
graphQL.executeAsync(
buildInput(
graphQLRequest,
request,
(params -> {
DefaultGlobalContext<ServerWebExchange> context = new DefaultGlobalContext<>(params.getNativeRequest());
context.setExtension("authentication", securityContext);
return context;
}),
dataLoaderRegistryFactory)
).thenApply(ExecutionResult::toSpecification)));
}
}
Then I will be able to get authentication information inside @GraphQLMutation
method by injecting:@GraphQLRootContext DefaultGlobalContext<SecurityContextServerWebExchange> context
and calling context.getExtension("authentication").getAuthentication()
,
@Transactional
@GraphQLMutation
public Authentication getAuthentication(
@GraphQLRootContext DefaultGlobalContext<SecurityContextServerWebExchange> context) {
SecurityContext securityContext = context.getExtension("authentication");
return securityContext.getAuthentication();
}
Is there any better way to achieve that?
Hi, this is kind of the same issue raised here in graphql-spqr, but the solution provided by kaqqao in that issue seems not available with graphql-spqr-spring-boot-starter. Basically kaqqao suggested to implement a custom mapper and register it when generating schema. However while using graphql-spqr-spring-boot-starter, schema is automatically generated and configured. So can we have this feature supported in this spring-boot-starter in the future?
To make the issue clear, suppose I have a Pet
class with PetType
enum:
public class Pet implements Serializable {
private String name;
private PetType type;
}
public enum PetType implements Serializable {
PUPPY("Dog"),
KITTY("Cat");
private final String value;
PetType(String value) {
this.value = value;
}
}
and I have a PetStoreService
:
@GraphqlApi
public class PetStoreService {
@AutoWired
private PetService petService;
@GraphQLQuery(name = "getPetsByType")
public List<Pet> getPetsByType(@GraphqlQLArgument(name = "petType") PetType type) {
return petService.getPetsByType(type);
}
}
Now I want my customers to fire GraphQL queries like this:
query {
getPetsByType(petType: "Dog") {
name
type
}
}
that is, use "Dog"
or "Cat"
rather than PUPPY
or KITTY
in queries. Kaqqao mentioned another solution in the previous issue, which is to use @GraphQLEnumValue(name = "Dog") PUPPY
. However this annotation just gives each enum type an alias, not a String value. Customers still have to fire queries like this:
query {
getPetsByType(petType: Dog) {
name
type
}
}
Which is not what I expected. How can I achieve this with graphql-spqr-spring-boot-starter? Thanks a lot!
I have a UserDto.class which implements two interfaces which both are used as union-interfaces (to handle errors in the response instead of throwing an exception).
public class UserDto implements IUserResult, IFindUserResult { // fields/getter/setter }
@GraphQLUnion(possibleTypes = {UserDto.class, UserRegistrationErrorDto.class})
public interface IUserResult {}
@GraphQLUnion(possibleTypes = {UserDto.class, UserNotFoundDto.class})
public interface IFindUserResult {}
In the service class i try to return the UserDto object but get the following error:
java.util.concurrent.CompletionException: java.lang.ClassCastException: graphql.schema.GraphQLTypeReference cannot be cast to graphql.schema.GraphQLObjectType
Method in service class:
Returns interface type. Returning a UserRegistrationError object works, but returning the UserDto object throws the above mentioned error. :
@GraphQLMutation
public IUserResult registerUserAccount(
@GraphQLArgument(name = "user") UserRegistrationInputDto user) {
// validation omitted
List<ErrorDto> errors = new ArrayList<>();
//check duplicate email addresses
if(userRepository.findByEmail(user.getEmail()).isPresent()){
errors.add(new ErrorDto("email", "user already registered with this email address"));
return new UserRegistrationErrorDto(errors);
}
User toRegister = modelMapper.map(user, User.class);
User registered = userRepository.save(toRegister);
return modelMapper.map(registered, UserDto.class);
}
This error does not occur when UserDto.class only implements one interface, but this would break the ability to return error types/messages without throwing exceptions.
See example project at https://github.com/ssiemens-hm/spgr-graphql-test
Used GraphQL-Mutation:
mutation {
registerUserAccount(
user: {
firstName: "firstname"
lastName: "lastname"
email: "[email protected]"
password: "password"
matchingPassword: "password"
}
) {
__typename
... on User {
id
firstName
lastName
}
... on UserRegistrationError {
errors {
field
reason
}
}
}
}
Opening this issue to track Spring 5 Reactive support to this library.
Issue was initially reported on leangen/graphql-spqr#185
Hello, I'm trying to solve existing issue with provided approach https://github.com/leangen/graphql-spqr/wiki/Errors#operation-with-multiple-resolver-methods-of-different-types
However I'm using the spring boot starter which seems that it does not configure it, just uses the default.
Hi there,
I am struggling to get my API to work with org.springframework.data.domain.PageRequest as input to a graphql query resolver.
public Page<Discussion> getPagedDiscussions(@GraphQLArgument(name = "pagingInfo") PageRequest pageRequest) {}
When I load graphiql I get a message saying "SortInput fields must be an object with field names as keys or a function which returns such an object."
I tried custom InputFieldBuilders but it doesn't work :(
inputFieldBuilders.add(new InputFieldBuilder() {
@Override
public Set<InputField> getInputFields(InputFieldBuilderParams params) {
AnnotatedType type = params.getType();
Set<InputField> fields = new HashSet<>();
fields.add(new InputField("pageNumber", "Page number", GenericTypeReflector.annotate(Integer.class), GenericTypeReflector.annotate(Integer.class), 0));
fields.add(new InputField("pageSize", "Page size", GenericTypeReflector.annotate(Integer.class), GenericTypeReflector.annotate(Integer.class), 20));
fields.add(new InputField("sort", "Page sorting", GenericTypeReflector.annotate(Sort.class), GenericTypeReflector.annotate(Sort.class), null));
return fields;
}
@Override
public boolean supports(AnnotatedType type) {
return PageRequest.class.equals(type.getType());
}
});
inputFieldBuilders.add(new InputFieldBuilder() {
@Override
public Set<InputField> getInputFields(InputFieldBuilderParams params) {
AnnotatedType type = params.getType();
Set<InputField> fields = new HashSet<>();
fields.add(new InputField("orders", "Orders for sorting", GenericTypeReflector.annotate(Sort.Order[].class), GenericTypeReflector.annotate(Sort.Order[].class), 20));
return fields;
}
@Override
public boolean supports(AnnotatedType type) {
return Sort.class.equals(type.getType());
}
});
inputFieldBuilders.add(new InputFieldBuilder() {
@Override
public Set<InputField> getInputFields(InputFieldBuilderParams params) {
AnnotatedType type = params.getType();
Set<InputField> fields = new HashSet<>();
fields.add(new InputField("direction", "Sorting order direction", GenericTypeReflector.annotate(String.class), GenericTypeReflector.annotate(String.class), 20));
fields.add(new InputField("property", "Sorting order property", GenericTypeReflector.annotate(String.class), GenericTypeReflector.annotate(String.class), 20));
return fields;
}
@Override
public boolean supports(AnnotatedType type) {
return Sort.Order.class.equals(type.getType());
}
});
scanPackages is not work
set package , but throw error "not implement interface...", these bean is not in same directory
We already support Spring WebFlux for queries and mutations (#9), but Apollo graphql-ws only works with Spring MVC.
We need a reactive WebSocket implementation to complete the WebFlux support.
reported at #52 (comment)
Currently the transmission of variables in the request via puery param does not work either. When I send a request (as defined in the docu https://graphql.org/learn/serving-over-http/), the following error occurs
Field error in object 'graphQLRequest' on field 'variables': rejected value [{
"$content": "123"
}]; codes [typeMismatch.graphQLRequest.variables,typeMismatch.variables,typeMismatch.java.util.Map,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [graphQLRequest.variables,variables]; arguments []; default message [variables]]; default message [Failed to convert value of type 'java.lang.String[]' to required type 'java.util.Map'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String[]' to required type 'java.util.Map': no matching editors or conversion strategy found]]@Test public void defaultControllerTest_GET_with_variables() throws Exception { mockMvc.perform( get("/"+apiContext) .param("query","query echo($content: String) {echo(content: $content)}") .param("variables", "{\n" + " \"$content\": \"123\"\n" + "}") ) .andExpect(status().isOk()) .andExpect(content().string(containsString("Hello world"))); }
reason: Jackson databiner doesn't know how to convert String to Map.
We should look into supporting Apollo Engine's cache control directives.
It would be nice to have annotations in a different module, so to have a lightweight dependency in service modules and the Spring Boot autoconfiguration in the WAR only.
(Same as leangen/graphql-spqr#170 for SPQR core.)
Firstly, we must make sure Spring Data paging types (Page
, Pageable
) map nicely out of the box.
Additionally, we should have custom mappers, and whatever else necessary, to optionally automatically map Spring paging style to Relay Connection style.
A similar issue was raised in SPQR (leangen/graphql-spqr#127).
In an application with @EnableScheduling annotation, I'm facing the following error:
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'defaultSockJsTaskScheduler' is expected to be of type 'org.springframework.scheduling.TaskScheduler' but was actually of type 'org.springframework.beans.factory.support.NullBean'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:392)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:224)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1115)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1082)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.resolveSchedulerBean(ScheduledAnnotationBeanPostProcessor.java:313)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.finishRegistration(ScheduledAnnotationBeanPostProcessor.java:254)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:231)
at org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor.onApplicationEvent(ScheduledAnnotationBeanPostProcessor.java:103)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:163)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
When I import dependencies, my project not finding annotations, like @GraphQLAp
, how I setup it?
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Will be optional as of 0.0.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>io.leangen.graphql</groupId>
<artifactId>graphiql-spring-boot-starter</artifactId>
<version>0.0.1</version>
</dependency>
<!--Will be implicit as of 0.0.2-->
<dependency>
<groupId>io.leangen.graphql</groupId>
<artifactId>spqr</artifactId>
<version>0.9.7</version>
</dependency>
</dependencies>
Usually, in Spring Boot starters there's a @EnableXyz
annotation you use to enable the autoconfiguration and set the packages to scan. It would be useful for this starter to conform to this convention! For example:
@SpringApplication
@EnableSpqr("my.package")
public class MyApplication {}
This also let one enable SPQR in its own starters, without the need to specify the packages in a configuration file.
Hi,
I'm newbie to spring reactive so this question can be silly, sorry for that.
I'm trying to use graphqlsubscription from looking to the example.
Here is my code:
`private final ConcurrentMultiMap<String, FluxSink> subscribers = new ConcurrentMultiMap<>();
@GraphQLSubscription
public Publisher expUpdated(String code) {
return Flux.create(subscriber -> subscribers.add(code, subscriber.onDispose(() -> subscribers.remove(code, subscriber))), FluxSink.OverflowStrategy.LATEST);
}`
And here is the error:
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class graphql.execution.reactive.CompletionStageMappingPublisher]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class graphql.execution.reactive.CompletionStageMappingPublisher and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.LinkedHashMap["data"])
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:293) ~[spring-web-5.0.7.RELEASE.jar:5.0.7.RELEASE]
Firefox sends "Connection: keep-alive, Upgrade" instead of "Connection: Upgrade" hence the headers Mapping in GraphQLController does not work with Firefox (at least version 69.0.1).
See PR #53
See leangen/graphql-spqr#140
I just created two @Service
s with clashing method names:
@Service
@GraphQLApi
public class MyService1 {
@GraphQLMutation
public String foo() {
return "1";
}
}
@Service
@GraphQLApi
public class MyService2 {
@GraphQLMutation
public String foo() {
return "2";
}
}
Now it's completely random (changes every time I restart the application) which of those 2 methods gets called.
I think it would be best, if the auto configuration throws an exception, when adding a GraphQL Type that already exists.
Dear bro,
I have issue with auto generator input type such as:
I have class CreateCompanyInput
And SPQR auto generator CreateCompanyInputInput. How can i fix it?
Apollo's graphql-ws protocol for GraphQl over WebSocket is currently the only way to get subscriptions working out of the box.
This starter should thus implement it.
So I look around and played around a bit and I think letting users customize/have their own url endpoints is also a great addition to this awsome library.
I can push to this repo but if you can just take out the /graphql
in the GrpahQLController
class and then specify the property in your application.properties
file. Sample below
change below
@PostMapping(
value = "${graphql.spqr.http.endpoint:/graphql}",
consumes = {"application/graphql", "application/graphql;charset=UTF-8"},
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
to
@PostMapping(
value = "${graphql.spqr.http.endpoint}",
consumes = {"application/graphql", "application/graphql;charset=UTF-8"},
produces = MediaType.APPLICATION_JSON_UTF8_VALUE
)
and then place this graphql.spqr.http.endpoint=/customUrl
in your projects application.properties
file
Hello,
In ApolloMessage the object mapper does not include null.
private static final ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
When null value are not included apollo-client is warning about missing fields in queries causing some weird behaviours when updatingQueries.
Is there a good reason to configure the mapper like that?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.