-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spring Data R2DBC ReactiveCrudRepository.save() method is not working even with method / class level @Transactional annotation #218
Comments
R2DBC transactions use regular database transactions underneath.
Care to elaborate on |
Hello @mp911de , |
I also tried this: @Inject ReactiveTransactionManager rtm;
/**
* Also doesn't work...
*/
@ResponseBody
@Transactional
@PostMapping("/sessions")
public Mono<Void> save(@RequestBody Session session) {
TransactionalOperator rtx = TransactionalOperator.create(rtm);
return rtx.execute(status -> Mono.just(session)
.filter(s -> Objects.nonNull(s.getName()))
.filter(s -> Objects.nonNull(s.getSpeakers()))
.map(s -> Objects.isNull(s.getId()) ? s.setId(UUID.randomUUID()) : s)
.flatMap(sessionRepository::save)
.then())
.then();
} and got "same success" result in response... /**
* Failed with: NoSuchBeanDefinitionException:
* No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available
*/
@ResponseBody
@Transactional
@PostMapping("/sessions")
public Disposable save(@RequestBody Session session) {
return Mono.just(session)
.filter(s -> Objects.nonNull(s.getName()))
.filter(s -> Objects.nonNull(s.getSpeakers()))
.map(s -> Objects.isNull(s.getId()) ? s.setId(UUID.randomUUID()) : s)
.flatMap(sessionRepository::save)
.subscribe(log::info);
} ie subscribing on result after save in a pipeline processing flow and returning disposable, I can get error related to not configured PlatformTransactionManager bean: POST http://127.0.0.1:8087/sessions
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 241
{
"timestamp": "2019-10-23T23:32:01.798+0000",
"path": "/sessions",
"status": 500,
"error": "Internal Server Error",
"message": "No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available",
"requestId": "3b9cd0fe"
} server logs: 2019-10-24 02:32:01.806 ERROR 84269 --- [ctor-http-nio-2] a.w.r.e.AbstractErrorWebExceptionHandler : [3b9cd0fe] 500 Server Error for HTTP POST "/sessions"
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP POST "/sessions" [ExceptionHandlingWebHandler]
Stack trace:
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:351) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:342) ~[spring-beans-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:468) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:342) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99) ~[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) ~[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at com.github.daggerok.hero.rsocket.RSocketSessions$$EnhancerBySpringCGLIB$$978e4fe7.save(<generated>) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_222]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_222]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_222]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_222]
at org.springframework.web.reactive.result.method.InvocableHandlerMethod.lambda$invoke$0(InvocableHandlerMethod.java:146) ~[spring-webflux-5.2.0.RELEASE.jar:5.2.0.RELEASE]
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:118) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1592) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.MonoZip$ZipCoordinator.signal(MonoZip.java:247) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.MonoZip$ZipInner.onNext(MonoZip.java:329) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.MonoPeekTerminal$MonoTerminalPeekSubscriber.onNext(MonoPeekTerminal.java:173) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:92) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:67) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:73) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:121) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onNext(FluxContextStart.java:103) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:287) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:330) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1592) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.MonoCollectList$MonoCollectListSubscriber.onComplete(MonoCollectList.java:121) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.core.publisher.FluxMap$MapSubscriber.onComplete(FluxMap.java:136) ~[reactor-core-3.3.0.RELEASE.jar:3.3.0.RELEASE]
at reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:397) ~[reactor-netty-0.9.0.RELEASE.jar:0.9.0.RELEASE]
at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:197) ~[reactor-netty-0.9.0.RELEASE.jar:0.9.0.RELEASE]
at reactor.netty.channel.FluxReceive.onInboundComplete(FluxReceive.java:345) ~[reactor-netty-0.9.0.RELEASE.jar:0.9.0.RELEASE]
at reactor.netty.channel.ChannelOperations.onInboundComplete(ChannelOperations.java:363) ~[reactor-netty-0.9.0.RELEASE.jar:0.9.0.RELEASE]
at reactor.netty.http.server.HttpServerOperations.onInboundNext(HttpServerOperations.java:453) ~[reactor-netty-0.9.0.RELEASE.jar:0.9.0.RELEASE]
at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:91) ~[reactor-netty-0.9.0.RELEASE.jar:0.9.0.RELEASE]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at reactor.netty.http.server.HttpTrafficHandler.channelRead(HttpTrafficHandler.java:208) ~[reactor-netty-0.9.0.RELEASE.jar:0.9.0.RELEASE]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:438) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:328) ~[netty-codec-4.1.42.Final.jar:4.1.42.Final]
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:302) ~[netty-codec-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:253) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:352) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1422) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:374) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:360) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:931) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:700) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:635) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:552) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:514) ~[netty-transport-4.1.42.Final.jar:4.1.42.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$6.run(SingleThreadEventExecutor.java:1044) ~[netty-common-4.1.42.Final.jar:4.1.42.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.42.Final.jar:4.1.42.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.42.Final.jar:4.1.42.Final]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_222] don't know if it helps to understand what is missing... Thanks |
Thanks a lot. Calling Reactive transactions work only on methods returning |
Hello @mp911de Regards |
Hello again! Your recommendation does helped me to save my Session POJO, awesome! @ResponseBody
@PostMapping("/sessions")
public Mono<Session> save(@RequestBody Session session) {
return Mono.just(session)
.filter(s -> Objects.nonNull(s.getName()))
.filter(s -> Objects.nonNull(s.getSpeakers()))
.flatMap(sessionRepository::save);
} Anyway, one problem is still left for me:
This is happening if my id UUID doesn't provided (because otherwise it wont be result to At the moment I can see two choices here:
@Data
@Table("sessions")
@NoArgsConstructor
public class Session implements Persistable<UUID> {
@Id
private UUID id;
private String name, speakers;
@Override
public boolean isNew() {
boolean result = Objects.isNull(id);
this.id = result ? UUID.randomUUID() : this.id;
return result;
}
}
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- required by uuid_generate_v1
DROP TABLE IF EXISTS sessions;
CREATE TABLE sessions (
-- id UUID PRIMARY KEY,
id UUID NOT NULL DEFAULT uuid_generate_v1(),
name VARCHAR NOT NULL,
speakers VARCHAR NOT NULL,
CONSTRAINT sessions_pk PRIMARY KEY ( id )
); @mp911de, please, let me know if you have better workaround in your mind, or maybe I can implement some UUID generation mechanism using spring functionality? Thank you! Regards, |
There's nothing wrong in assigning an Id if the database does not generate it for you. If you're using repositories, then the implementation with In Closing this ticket as there is no general issue with Spring Data R2DBC. |
@mp911de, thanks for help |
Hello again, @mp911de |
I had this exact same issue! Thank you so much for sharing @daggerok and @mp911de ... I was wondering if one of you can explain to me why we do |
You should use So to pipe correctly save result to next |
Fantastic, this worked. Thank you very much. |
Hello,
Please, let me know if spring-data-r2dbc transactions by default are read only?
For some reasons, data cannot be saved when I do it using ReactiveCrudRepository like so:
I have prepared a repo, and that par is present, but commented here. Cannot understand, why it cannot be committed... but anyway, data can be successfully saved in database if I'm using DatabaseClient for that:
full code located here
versions
Is it bug or I missed something?
Thanks!
Regards,
Maksim
The text was updated successfully, but these errors were encountered: