Provided SubscriptionExecutionStrategy is not used #430
Description
Hello,
I tried to create a subscription, where I send info every time an Entity (from Hibernate) is updated. I encountered similar problem as with queries - LazyInitializationException. In the case of Queries, it was easily resolved by creating custom execution strategy, where execute is annotated as Transactional:
@Service
open class TransactionalQueryExecutionStrategy : AsyncExecutionStrategy() {
@Transactional
override fun execute(executionContext: ExecutionContext, parameters: ExecutionStrategyParameters): CompletableFuture<ExecutionResult> {
return super.execute(executionContext, parameters)
}
}
For subscription, I created something similar, except executeSubscriptionEvent method is annotated as Transactional.
And is injected by creating DefaultExecutionStrategyProvider:
@Bean
open fun executionStrategies(
queryExecutionStrategy: TransactionalQueryExecutionStrategy,
mutationExecutionStrategy: TransactionalMutationExecutionStrategy,
subscriptionExecutionStrategy: TransactionalSubscriptionExecutionStrategy
) : ExecutionStrategyProvider {
return DefaultExecutionStrategyProvider(queryExecutionStrategy, mutationExecutionStrategy, subscriptionExecutionStrategy)
}
It works for queries and mutations like a charm. But for subscriptions, the problem is still there:
java.util.concurrent.CompletionException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: pl.vinterdo.sto.gamesession.entities.GameSession.invitedPlayers, could not initialize proxy - no Session
at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:331) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.uniApplyNow(CompletableFuture.java:670) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.uniApplyStage(CompletableFuture.java:658) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.thenApply(CompletableFuture.java:2094) ~[na:na]
at graphql.execution.SubscriptionExecutionStrategy.executeSubscriptionEvent(SubscriptionExecutionStrategy.java:104) ~[graphql-java-14.0.jar:na]
at graphql.execution.SubscriptionExecutionStrategy.lambda$null$0(SubscriptionExecutionStrategy.java:47) ~[graphql-java-14.0.jar:na]
at graphql.execution.reactive.CompletionStageMappingPublisher$1.onNext(CompletionStageMappingPublisher.java:47) ~[graphql-java-14.0.jar:na]
at io.reactivex.rxjava3.internal.util.HalfSerializer.onNext(HalfSerializer.java:45) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.internal.subscribers.StrictSubscriber.onNext(StrictSubscriber.java:97) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.internal.operators.flowable.FlowableConcatArray$ConcatArraySubscriber.onNext(FlowableConcatArray.java:77) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.internal.subscriptions.ScalarSubscription.request(ScalarSubscription.java:55) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.internal.subscriptions.SubscriptionArbiter.setSubscription(SubscriptionArbiter.java:99) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.internal.operators.flowable.FlowableConcatArray$ConcatArraySubscriber.onSubscribe(FlowableConcatArray.java:71) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.internal.operators.flowable.FlowableJust.subscribeActual(FlowableJust.java:34) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15750) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15696) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.internal.operators.flowable.FlowableConcatArray$ConcatArraySubscriber.onComplete(FlowableConcatArray.java:140) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.internal.operators.flowable.FlowableConcatArray.subscribeActual(FlowableConcatArray.java:40) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15750) ~[rxjava-3.0.4.jar:na]
at io.reactivex.rxjava3.core.Flowable.subscribe(Flowable.java:15699) ~[rxjava-3.0.4.jar:na]
at graphql.execution.reactive.CompletionStageMappingPublisher.subscribe(CompletionStageMappingPublisher.java:34) ~[graphql-java-14.0.jar:na]
at graphql.kickstart.execution.subscriptions.DefaultSubscriptionSession.subscribe(DefaultSubscriptionSession.java:37) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.execution.subscriptions.apollo.SubscriptionStartCommand.handleSubscriptionStart(SubscriptionStartCommand.java:46) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.execution.subscriptions.apollo.SubscriptionStartCommand.lambda$apply$1(SubscriptionStartCommand.java:32) ~[graphql-java-servlet-9.1.0.jar:na]
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:753) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:731) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2108) ~[na:na]
at graphql.kickstart.execution.subscriptions.apollo.SubscriptionStartCommand.apply(SubscriptionStartCommand.java:32) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.execution.subscriptions.apollo.ApolloSubscriptionConsumer.accept(ApolloSubscriptionConsumer.java:24) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.execution.subscriptions.apollo.ApolloSubscriptionConsumer.accept(ApolloSubscriptionConsumer.java:11) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.servlet.GraphQLWebsocketServlet$1.onMessage(GraphQLWebsocketServlet.java:127) ~[graphql-java-servlet-9.1.0.jar:na]
at graphql.kickstart.servlet.GraphQLWebsocketServlet$1.onMessage(GraphQLWebsocketServlet.java:123) ~[graphql-java-servlet-9.1.0.jar:na]
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.tomcat.websocket.server.WsFrameServer.sendMessageText(WsFrameServer.java:119) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.tomcat.websocket.server.WsFrameServer.onDataAvailable(WsFrameServer.java:82) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.tomcat.websocket.server.WsFrameServer.doOnDataAvailable(WsFrameServer.java:171) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.tomcat.websocket.server.WsFrameServer.notifyDataAvailable(WsFrameServer.java:151) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.upgradeDispatch(WsHttpUpgradeHandler.java:148) ~[tomcat-embed-websocket-9.0.33.jar:9.0.33]
at org.apache.coyote.http11.upgrade.UpgradeProcessorInternal.dispatch(UpgradeProcessorInternal.java:54) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:59) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1594) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.33.jar:9.0.33]
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.33.jar:9.0.33]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
As you can see from stack trace, subscription execution strategy from graphql java is used, not the one I provided.
I also tried using map to inject my strategies, with strategies renamed to expected names:
@Bean
open fun executionStrategies() : ExecutionStrategyProvider {
return DefaultExecutionStrategyProvider(QueryExecutionStrategy(), MutationExecutionStrategy(), SubscriptionExecutionStrategy());
executionStrategyMap[QUERY_EXECUTION_STRATEGY] = QueryExecutionStrategy()
executionStrategyMap[MUTATION_EXECUTION_STRATEGY] =
executionStrategyMap[SUBSCRIPTION_EXECUTION_STRATEGY] =
return executionStrategyMap;
}
But the effect was the same