Exception is not thrown when do SQL insert through ReactiveCrudRepository's save method.
See original GitHub issue- Driver: r2dbc-mssql 0.8.5.RELEASE, r2dbc-pool 0.8.5.RELEASE, r2dbc-spi 0.8.3.RELEASE, spring-data-r2dbc 1.1.5.RELEASE
- Database: MS SQL Server 2017
- Java: Java 11.0.8
- OS: Windows 10, macOS
##############
Exception is not thrown when do SQL insert through ReactiveCrudRepository’s save method on MS SQL, others database is fine, exception is thrown as expected.
Insert failed with GENERAL_ERROR but no exception thrown.
2020-11-06 10:15:07,449 [reactor-http-nio-2] DEBUG HttpServerOperations - [id: 0x02619bd6, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:55914] Increasing pending responses, now 1 2020-11-06 10:15:07,449 [reactor-http-nio-2] DEBUG HttpServer - [id: 0x02619bd6, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:55914] Handler is being applied: org.springframework.http.server.reactive.ReactorHttpHandlerAdapter@59fb2723 2020-11-06 10:15:07,449 [reactor-http-nio-2] DEBUG HttpWebHandlerAdapter - [02619bd6-2] HTTP POST “/api/1.0/test_record” 2020-11-06 10:15:07,450 [boundedElastic-1] DEBUG DefaultWebSessionManager - Created new WebSession. … … 2020-11-06 10:15:07,507 [reactor-http-nio-2] DEBUG Jackson2JsonDecoder - [02619bd6-2] Decoded [Customer(customerId=null, name=XVeryGeorge)] 2020-11-06 10:15:07,507 [reactor-http-nio-2] INFO TestHandler - Request data -> Customer(customerId=null, name=XVeryGeorge) 2020-11-06 10:15:07,507 [reactor-http-nio-2] DEBUG ConnectionPool - Obtaining new connection from the driver 2020-11-06 10:15:07,507 [reactor-http-nio-2] DEBUG DefaultDatabaseClient - Executing SQL statement [INSERT INTO customer (name) VALUES (@P0_name)] 2020-11-06 10:15:07,507 [reactor-http-nio-2] DEBUG MssqlConnection - [cid: 0x5] Creating statement for SQL: [INSERT INTO customer (name) VALUES (@P0_name)] 2020-11-06 10:15:07,508 [reactor-http-nio-2] DEBUG ParametrizedMssqlStatement - [cid: 0x5] Start direct exchange for INSERT INTO customer (name) VALUES (@P0_name) SELECT SCOPE_IDENTITY() AS GENERATED_KEYS 2020-11-06 10:15:07,508 [reactor-http-nio-2] DEBUG ReactorNettyClient - [cid: 0x5] exchange() 2020-11-06 10:15:07,508 [reactor-http-nio-2] DEBUG MssqlResult - [cid: 0x5] Creating new result 2020-11-06 10:15:07,508 [reactor-http-nio-2] DEBUG QUERY - [cid: 0x5] Executing query: INSERT INTO customer (name) VALUES (@P0_name) SELECT SCOPE_IDENTITY() AS GENERATED_KEYS 2020-11-06 10:15:07,508 [reactor-http-nio-2] DEBUG ReactorNettyClient - [cid: 0x5] exchange(subscribed) 2020-11-06 10:15:07,508 [reactor-http-nio-2] DEBUG ReactorNettyClient - [cid: 0x5] Initiating exchange 2020-11-06 10:15:07,508 [reactor-http-nio-2] DEBUG ReactorNettyClient - [cid: 0x5] Request: RPCRequest [procName=‘null’, procId=10, optionFlags=io.r2dbc.mssql.message.token.RpcRequest$OptionFlags@12de1291, statusFlags=0, parameterDescriptors=[RpcString [name=‘null’, value=INSERT INTO customer (name) VALUES (@P0_name) SELECT SCOPE_IDENTITY() AS GENERATED_KEYS], RpcString [name=‘null’, value=@P0_name nvarchar(4000)], EncodedRpcParameter [name=‘P0_name’, value=io.r2dbc.mssql.codec.CharacterEncoder$NvarcharEncoded@7a295649]]] 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: ErrorToken [number=8152, state=2, infoClass=16, message=‘String or binary data would be truncated.“, serverName='SRV_TEST”, procName=’“, lineNumber=16777216] 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Warning: Code [8152] Severity [GENERAL_ERROR]: String or binary data would be truncated. 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: InfoToken [number=3621, state=0, infoClass=0, message='The statement has been terminated.”, serverName=‘SRV_TEST", procName=’“, lineNumber=16777216] 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Info: Code [3621] Severity [INFORMATIONAL]: The statement has been terminated. 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: DoneInProcToken [done=false, hasCount=false, rowCount=0, hasMore=true, currentCommand=195] 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: ColumnMetadataToken [columns=[Column [name='GENERATED_KEYS”, type=MutableTypeInformation [maxLength=17, lengthStrategy=BYTELENTYPE, precision=38, displaySize=40, scale=0, flags=33, serverType=numeric, userType=0, udtTypeName=“null”, collation=null, charset=null], table=null]]] 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG MssqlResult - [cid: 0x5] Result column definition: ColumnMetadataToken [columns=[Column [name='GENERATED_KEYS", type=MutableTypeInformation [maxLength=17, lengthStrategy=BYTELENTYPE, precision=38, displaySize=40, scale=0, flags=33, serverType=numeric, userType=0, udtTypeName=“null”, collation=null, charset=null], table=null]]] 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: io.r2dbc.mssql.message.token.RowToken@5d054679 2020-11-06 10:15:07,523 [reactor-tcp-nio-1] DEBUG PooledConnection - Releasing connection 2020-11-06 10:15:07,524 [reactor-tcp-nio-1] INFO TestHandler - >>>>>>>>> Recorded -> Customer(customerId=null, name=XVeryGeorge) 2020-11-06 10:15:07,524 [reactor-tcp-nio-1] DEBUG Jackson2JsonEncoder - [02619bd6-2] Encoding [CommonRespMessage(code=null, status=OK, message=null, reference=null)] 2020-11-06 10:15:07,524 [reactor-tcp-nio-1] DEBUG FluxDiscardOnCancel - received cancel signal 2020-11-06 10:15:07,524 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: DoneInProcToken [done=false, hasCount=true, rowCount=1, hasMore=true, currentCommand=0] 2020-11-06 10:15:07,524 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: ReturnStatus [status=0] 2020-11-06 10:15:07,525 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: DoneProcToken [done=true, hasCount=false, rowCount=0, hasMore=false, currentCommand=0] 2020-11-06 10:15:07,525 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Conversation complete 2020-11-06 10:15:07,525 [reactor-http-nio-2] DEBUG HttpServerOperations - [id: 0x02619bd6, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:55914] Decreasing pending responses, now 0 2020-11-06 10:15:07,525 [reactor-http-nio-2] DEBUG HttpWebHandlerAdapter - [02619bd6-2] Completed 200 OK 2020-11-06 10:15:07,525 [reactor-http-nio-2] DEBUG HttpServerOperations - [id: 0x02619bd6, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:55914] Last HTTP response frame 2020-11-06 10:15:07,525 [reactor-http-nio-2] DEBUG HttpServerOperations - [id: 0x02619bd6, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:55914] Last HTTP packet was sent, terminating the channel
Update failed with same GENERAL_ERROR, the exception thrown and can be handled as expected.
2020-11-06 10:21:26,159 [reactor-http-nio-2] DEBUG HttpServerOperations - [id: 0x086448f9, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:56012] Increasing pending responses, now 1 2020-11-06 10:21:26,159 [reactor-http-nio-2] DEBUG HttpServer - [id: 0x086448f9, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:56012] Handler is being applied: org.springframework.http.server.reactive.ReactorHttpHandlerAdapter@76960762 2020-11-06 10:21:26,159 [reactor-http-nio-2] DEBUG HttpWebHandlerAdapter - [086448f9-2] HTTP POST “/api/1.0/test_record” 2020-11-06 10:21:26,160 [boundedElastic-2] DEBUG DefaultWebSessionManager - Created new WebSession. … … 2020-11-06 10:21:26,224 [reactor-http-nio-2] DEBUG Jackson2JsonDecoder - [086448f9-2] Decoded [Customer(customerId=c016d098-0449-4851-b4a4-72472c410448, name=XVeryGeorge)] 2020-11-06 10:21:26,224 [reactor-http-nio-2] INFO TestHandler - Request data -> Customer(customerId=c016d098-0449-4851-b4a4-72472c410448, name=XVeryGeorge) 2020-11-06 10:21:26,224 [reactor-http-nio-2] DEBUG ConnectionPool - Obtaining new connection from the driver 2020-11-06 10:21:26,224 [reactor-http-nio-2] DEBUG DefaultDatabaseClient - Executing SQL statement [UPDATE customer SET name = @P0_name WHERE customer.customer_id = @P1_customerid] 2020-11-06 10:21:26,224 [reactor-http-nio-2] DEBUG MssqlConnection - [cid: 0x5] Creating statement for SQL: [UPDATE customer SET name = @P0_name WHERE customer.customer_id = @P1_customerid] 2020-11-06 10:21:26,225 [reactor-http-nio-2] DEBUG ParametrizedMssqlStatement - [cid: 0x5] Start direct exchange for UPDATE customer SET name = @P0_name WHERE customer.customer_id = @P1_customerid 2020-11-06 10:21:26,225 [reactor-http-nio-2] DEBUG ReactorNettyClient - [cid: 0x5] exchange() 2020-11-06 10:21:26,225 [reactor-http-nio-2] DEBUG MssqlResult - [cid: 0x5] Creating new result 2020-11-06 10:21:26,225 [reactor-http-nio-2] DEBUG QUERY - [cid: 0x5] Executing query: UPDATE customer SET name = @P0_name WHERE customer.customer_id = @P1_customerid 2020-11-06 10:21:26,225 [reactor-http-nio-2] DEBUG ReactorNettyClient - [cid: 0x5] exchange(subscribed) 2020-11-06 10:21:26,225 [reactor-http-nio-2] DEBUG ReactorNettyClient - [cid: 0x5] Initiating exchange 2020-11-06 10:21:26,225 [reactor-http-nio-2] DEBUG ReactorNettyClient - [cid: 0x5] Request: RPCRequest [procName=‘null’, procId=10, optionFlags=io.r2dbc.mssql.message.token.RpcRequest$OptionFlags@6ce647a6, statusFlags=0, parameterDescriptors=[RpcString [name=‘null’, value=UPDATE customer SET name = @P0_name WHERE customer.customer_id = @P1_customerid], RpcString [name=‘null’, value=@P0_name nvarchar(4000),@P1_customerid uniqueidentifier], EncodedRpcParameter [name=‘P0_name’, value=io.r2dbc.mssql.codec.CharacterEncoder$NvarcharEncoded@3432848f], EncodedRpcParameter [name=‘P1_customerid’, value=io.r2dbc.mssql.codec.RpcEncoding$HintedEncoded@3515a4a]]] 2020-11-06 10:21:26,249 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: ErrorToken [number=8152, state=2, infoClass=16, message=‘String or binary data would be truncated.“, serverName='SRV_TEST”, procName=’“, lineNumber=16777216] 2020-11-06 10:21:26,249 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Warning: Code [8152] Severity [GENERAL_ERROR]: String or binary data would be truncated. 2020-11-06 10:21:26,249 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: InfoToken [number=3621, state=0, infoClass=0, message='The statement has been terminated.”, serverName=‘SRV_TEST", procName=’", lineNumber=16777216] 2020-11-06 10:21:26,249 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Info: Code [3621] Severity [INFORMATIONAL]: The statement has been terminated. 2020-11-06 10:21:26,249 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: DoneInProcToken [done=false, hasCount=false, rowCount=0, hasMore=true, currentCommand=197] 2020-11-06 10:21:26,250 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: ReturnStatus [status=8152] 2020-11-06 10:21:26,250 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Response: DoneProcToken [done=true, hasCount=false, rowCount=0, hasMore=false, currentCommand=0] 2020-11-06 10:21:26,250 [reactor-tcp-nio-1] DEBUG FluxDiscardOnCancel - received cancel signal 2020-11-06 10:21:26,250 [reactor-tcp-nio-1] DEBUG PooledConnection - Releasing connection 2020-11-06 10:21:26,250 [reactor-tcp-nio-1] DEBUG SqlStateR2dbcExceptionTranslator - Extracted SQL state class ‘22’ from value ‘22001’ 2020-11-06 10:21:26,251 [reactor-tcp-nio-1] ERROR TestHandler - >>>>>>>>> Error -> execute; SQL [UPDATE customer SET name = @P0_name WHERE customer.customer_id = @P1_customerid]; String or binary data would be truncated.; nested exception is io.r2dbc.mssql.ExceptionFactory$MssqlNonTransientException: [8152] [22001] String or binary data would be truncated. org.springframework.dao.DataIntegrityViolationException: execute; SQL [UPDATE customer SET name = @P0_name WHERE customer.customer_id = @P1_customerid]; String or binary data would be truncated.; nested exception is io.r2dbc.mssql.ExceptionFactory$MssqlNonTransientException: [8152] [22001] String or binary data would be truncated. at org.springframework.data.r2dbc.support.SqlStateR2dbcExceptionTranslator.doTranslate(SqlStateR2dbcExceptionTranslator.java:98) at org.springframework.data.r2dbc.support.AbstractFallbackR2dbcExceptionTranslator.translate(AbstractFallbackR2dbcExceptionTranslator.java:67) at org.springframework.data.r2dbc.support.AbstractFallbackR2dbcExceptionTranslator.translate(AbstractFallbackR2dbcExceptionTranslator.java:76) at org.springframework.data.r2dbc.core.DefaultDatabaseClient.translateException(DefaultDatabaseClient.java:264) at org.springframework.data.r2dbc.core.DefaultDatabaseClient.lambda$inConnection$4(DefaultDatabaseClient.java:172) at reactor.core.publisher.Mono.lambda$onErrorMap$29(Mono.java:3272) at reactor.core.publisher.Mono.lambda$onErrorResume$31(Mono.java:3362) at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:88) at reactor.core.publisher.MonoUsingWhen$MonoUsingWhenSubscriber.deferredError(MonoUsingWhen.java:285) at reactor.core.publisher.FluxUsingWhen$RollbackInner.onComplete(FluxUsingWhen.java:485) at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2016) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252) at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2016) at reactor.core.publisher.Operators$MonoSubscriber.onComplete(Operators.java:1824) at reactor.core.publisher.MonoIgnoreThen$ThenAcceptInner.onComplete(MonoIgnoreThen.java:314) at reactor.core.publisher.Operators$MonoSubscriber.onComplete(Operators.java:1824) at reactor.core.publisher.MonoIgnoreThen$ThenAcceptInner.onComplete(MonoIgnoreThen.java:314) at reactor.pool.SimpleDequePool$QueuePoolRecyclerInner.onComplete(SimpleDequePool.java:624) at reactor.core.publisher.Operators.complete(Operators.java:135) at reactor.core.publisher.MonoEmpty.subscribe(MonoEmpty.java:45) at reactor.core.publisher.Mono.subscribe(Mono.java:4213) at reactor.pool.SimpleDequePool$QueuePoolRecyclerMono.subscribe(SimpleDequePool.java:736) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:153) at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.drain(MonoIgnoreThen.java:153) at reactor.core.publisher.MonoIgnoreThen.subscribe(MonoIgnoreThen.java:56) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) at reactor.core.publisher.Mono.subscribe(Mono.java:4213) at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:97) at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onError(MonoIgnoreElements.java:76) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:134) at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onError(FluxFilterFuseable.java:156) at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onError(FluxFilterFuseable.java:375) at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onError(FluxMapFuseable.java:326) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:185) at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2344) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.request(FluxHandleFuseable.java:243) at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.request(FluxMapFuseable.java:346) at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.request(FluxFilterFuseable.java:403) at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.request(FluxFilterFuseable.java:184) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.request(FluxMapFuseable.java:162) at reactor.core.publisher.MonoIgnoreElements$IgnoreElementsSubscriber.onSubscribe(MonoIgnoreElements.java:64) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onSubscribe(FluxMapFuseable.java:90) at reactor.core.publisher.FluxFilterFuseable$FilterFuseableSubscriber.onSubscribe(FluxFilterFuseable.java:81) at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onSubscribe(FluxFilterFuseable.java:298) at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onSubscribe(FluxMapFuseable.java:255) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onSubscribe(FluxHandleFuseable.java:148) at reactor.core.publisher.MonoCurrentContext.subscribe(MonoCurrentContext.java:35) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) at reactor.core.publisher.Mono.subscribe(Mono.java:4213) at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.onError(FluxUsingWhen.java:374) at reactor.core.publisher.MonoStreamCollector$StreamCollectorSubscriber.onError(MonoStreamCollector.java:143) at reactor.core.publisher.FluxFlatMap$FlatMapMain.checkTerminated(FluxFlatMap.java:834) at reactor.core.publisher.FluxFlatMap$FlatMapMain.drainLoop(FluxFlatMap.java:600) at reactor.core.publisher.FluxFlatMap$FlatMapMain.drain(FluxFlatMap.java:580) at reactor.core.publisher.FluxFlatMap$FlatMapMain.innerError(FluxFlatMap.java:855) at reactor.core.publisher.FluxFlatMap$FlatMapInner.onError(FluxFlatMap.java:1006) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:134) at reactor.core.publisher.MonoReduce$ReduceSubscriber.onError(MonoReduce.java:121) at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onError(FluxPeekFuseable.java:227) at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onComplete(FluxPeekFuseable.java:264) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onComplete(FluxHandleFuseable.java:223) at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onComplete(FluxContextStart.java:115) at io.r2dbc.mssql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onComplete(FluxDiscardOnCancel.java:104) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252) at reactor.core.publisher.FluxPeek$PeekSubscriber.onComplete(FluxPeek.java:252) at reactor.core.publisher.FluxFilter$FilterSubscriber.onComplete(FluxFilter.java:160) at reactor.core.publisher.FluxHandle$HandleConditionalSubscriber.onComplete(FluxHandle.java:416) at reactor.core.publisher.EmitterProcessor.checkTerminated(EmitterProcessor.java:495) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:417) at reactor.core.publisher.EmitterProcessor.onNext(EmitterProcessor.java:274) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192) at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:112) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:242) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:432) at reactor.core.publisher.EmitterProcessor.onNext(EmitterProcessor.java:274) at io.r2dbc.mssql.client.ReactorNettyClient$1.next(ReactorNettyClient.java:244) at io.r2dbc.mssql.client.ReactorNettyClient$1.next(ReactorNettyClient.java:204) at io.r2dbc.mssql.message.token.Tabular$TabularDecoder.decode(Tabular.java:424) at io.r2dbc.mssql.client.ConnectionState$4$1.decode(ConnectionState.java:206) at io.r2dbc.mssql.client.StreamDecoder.withState(StreamDecoder.java:137) at io.r2dbc.mssql.client.StreamDecoder.decode(StreamDecoder.java:109) at io.r2dbc.mssql.client.ReactorNettyClient.lambda$new$6(ReactorNettyClient.java:254) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:177) at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:256) at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:362) at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:358) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:96) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93) at io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:380) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:834) Caused by: io.r2dbc.mssql.ExceptionFactory$MssqlNonTransientException: String or binary data would be truncated. at io.r2dbc.mssql.ExceptionFactory.createException(ExceptionFactory.java:152) at io.r2dbc.mssql.MssqlResult.lambda$getRowsUpdated$0(MssqlResult.java:112) at reactor.core.publisher.FluxHandleFuseable$HandleFuseableSubscriber.onNext(FluxHandleFuseable.java:163) at reactor.core.publisher.FluxContextStart$ContextStartSubscriber.onNext(FluxContextStart.java:96) at io.r2dbc.mssql.util.FluxDiscardOnCancel$FluxDiscardOnCancelSubscriber.onNext(FluxDiscardOnCancel.java:89) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:192) at reactor.core.publisher.FluxFilter$FilterSubscriber.onNext(FluxFilter.java:107) at reactor.core.publisher.FluxHandle$HandleConditionalSubscriber.onNext(FluxHandle.java:319) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:432) … 42 common frames omitted 2020-11-06 10:21:26,251 [reactor-tcp-nio-1] DEBUG Jackson2JsonEncoder - [086448f9-2] Encoding [CommonRespMessage(code=null, status=ERROR, message=null, reference=null)] 2020-11-06 10:21:26,251 [reactor-tcp-nio-1] DEBUG ReactorNettyClient - [cid: 0x5] Conversation complete 2020-11-06 10:21:26,252 [reactor-http-nio-2] DEBUG HttpServerOperations - [id: 0x086448f9, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:56012] Decreasing pending responses, now 0 2020-11-06 10:21:26,252 [reactor-http-nio-2] DEBUG HttpWebHandlerAdapter - [086448f9-2] Completed 200 OK 2020-11-06 10:21:26,252 [reactor-http-nio-2] DEBUG HttpServerOperations - [id: 0x086448f9, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:56012] Last HTTP response frame 2020-11-06 10:21:26,252 [reactor-http-nio-2] DEBUG HttpServerOperations - [id: 0x086448f9, L:/0:0:0:0:0:0:0:1:8104 - R:/0:0:0:0:0:0:0:1:56012] Last HTTP packet was sent, terminating the channel
Table schema
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[customer](
[customer_id] [char](36) NOT NULL,
[name] [varchar](10) NOT NULL,
PRIMARY KEY CLUSTERED
(
[customer_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
Steps to reproduce
The domain “Customer”…
@Table("customer")
data class Customer(
@Id @Column("customer_id") val customerId: UUID? = null,
@Column("name") val name: String
) : Persistable<UUID> {
override fun getId(): UUID? {
return UUID.randomUUID()
}
override fun isNew(): Boolean {
return customerId == null
}
}
The controller…
@Transactional
fun record(request: ServerRequest): Mono<ServerResponse> {
val returnData = request.bodyToMono(Customer::class.java).flatMap { recordRequest ->
log.info("Request data -> $recordRequest")
customerRepository.save(recordRequest)
.flatMap { customer ->
log.info(">>>>>>>>> Recorded -> $customer")
CommonRespMessage(status = "OK").toMono()
}
.onErrorResume { throwable ->
log.error(">>>>>>>>> Error -> ${throwable.message}", throwable)
CommonRespMessage(status = "ERROR").toMono()
}
}
return ServerResponse.ok()
.contentType(MediaType.APPLICATION_JSON)
.body(returnData, CommonRespMessage::class.java)
}
Expected behavior/code
Exception must be thrown when r2dbc-mssql receive SQL Error from MS SQL Server.
Possible Solution
Make SQL error handling of INSERT flow the same as UPDATE flow.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:5 (1 by maintainers)
Top GitHub Comments
Duplicates https://github.com/spring-projects/spring-data-r2dbc/issues/552. The driver emits the row and then sends an error signal which models somewhat the flow within the results. That behavior makes it difficult for consumers to rely on the first result (consume first and then ignore the rest of the response) as the query actually has failed.
I think it’s fair to suppress row emission in case of preceding errors.
I didn’t look in to the fix #162 yet but I tried downgrading to r2dbc-mssql 0.8.3 to test the same behavior and expected exception thrown via onErrorDropped. So the fix #162 or maybe other fixes on 0.8.4, 0.8.5 broke this?
From my testing, I think I can confirm that the issue exists on 0.8.4+.
2021-01-06 11:54:14,912 [reactor-tcp-nio-2] ERROR Operators - Operator called default onErrorDropped io.r2dbc.mssql.ExceptionFactory$MssqlNonTransientException: String or binary data would be truncated. at io.r2dbc.mssql.ExceptionFactory.createException(ExceptionFactory.java:152) at io.r2dbc.mssql.ExceptionFactory.createException(ExceptionFactory.java:181) at io.r2dbc.mssql.RpcQueryMessageFlow.lambda$exchange$1(RpcQueryMessageFlow.java:148) at reactor.core.publisher.FluxHandle$HandleConditionalSubscriber.onNext(FluxHandle.java:310) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:491) at reactor.core.publisher.EmitterProcessor.tryEmitNext(EmitterProcessor.java:299) at reactor.core.publisher.InternalManySink.emitNext(InternalManySink.java:27) at reactor.core.publisher.EmitterProcessor.onNext(EmitterProcessor.java:265) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxHandle$HandleSubscriber.onNext(FluxHandle.java:118) at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:491) at reactor.core.publisher.EmitterProcessor.tryEmitNext(EmitterProcessor.java:299) at reactor.core.publisher.InternalManySink.emitNext(InternalManySink.java:27) at reactor.core.publisher.EmitterProcessor.onNext(EmitterProcessor.java:265) at io.r2dbc.mssql.client.ReactorNettyClient$1.next(ReactorNettyClient.java:241) at io.r2dbc.mssql.client.ReactorNettyClient$1.next(ReactorNettyClient.java:201) at io.r2dbc.mssql.message.token.Tabular$TabularDecoder.decode(Tabular.java:425) at io.r2dbc.mssql.client.ConnectionState$4$1.decode(ConnectionState.java:206) at io.r2dbc.mssql.client.StreamDecoder.withState(StreamDecoder.java:137) at io.r2dbc.mssql.client.StreamDecoder.decode(StreamDecoder.java:109) at io.r2dbc.mssql.client.ReactorNettyClient.lambda$new$6(ReactorNettyClient.java:251) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:184) at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:265) at reactor.netty.channel.FluxReceive.onInboundNext(FluxReceive.java:371) at reactor.netty.channel.ChannelOperations.onInboundNext(ChannelOperations.java:381) at reactor.netty.channel.ChannelOperationsHandler.channelRead(ChannelOperationsHandler.java:94) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93) at io.r2dbc.mssql.client.ssl.TdsSslHandler.channelRead(TdsSslHandler.java:380) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719) at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493) at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) at java.base/java.lang.Thread.run(Thread.java:834) 2021-01-06 11:54:14,912 [reactor-tcp-nio-2] DEBUG ReactorNettyClient - [cid: 0x1] Conversation complete