oracle / oracle-r2dbc

R2DBC Driver for Oracle Database
https://oracle.com
Other
194 stars 40 forks source link

java.lang.UnsupportedOperationException: This method is deprecated for removal #71

Closed mofeed-hassan closed 1 year ago

mofeed-hassan commented 2 years ago

Hi, Although the existing previous issues but I feel confused about what to do. So In this issue I will summarize what I am facing. Development environment: Spring, R2DBC, Oracle DB Versions: spring boot --> 2.7.0 , Oracle R2DBC --> 0.4.0 Task Objective: reading a specific entity from the db with its related entities using a customized written sql statement to make one single DB query for all data. The repository code that retrieves the data: @repository public class MyCustomRepository { private static final String query ="..."; private final DatabaseClient databaseClient; //org.springframework.r2dbc.core.DatabaseClient this.databaseClient.sql(query) // .bind("fName", fName) // .bind("lName", lName) // .fetch().all() // s .bufferUntilChanged(person -> person.get("id")) // .map(.......) } Observations:

I think this method is called in bufferUntilChanged(), so execluding it exciplicitly is not possible. The method bufferUntilChanged() helps me to aggregate each person entity with its related entities in map(). Questions:

  1. Is my thought that bufferUntilChanged() call getColumnNames() right? Should it be changed in bufferUntilChanged() implementation?
  2. Is there any way to decouple getColumnName() from bufferUntilChanged()?
  3. Is there any alternative to the method bufferUntilChanged() that does not raise such exception?

Sorry for the long description but as I am new to the thema I wanted o make sure to pull all the info. as much as spossible

Michael-A-McMahon commented 2 years ago

I think you're right; The bufferUntilChanged operator has a call to person.get("id"). I suspect the get(String) method is implemented to call getColumnNames(), as the "id" string looks like a column name. If you can share a stack trace for the UnsupportedOperationException, then we can confirm where the call to getColumnNames is coming from.

Standard disclaimer: I have almost no experience working with Spring. However, I think the person object is implemented or generated by Spring Data R2DBC? If so, that would mean the version of Spring Data R2DBC you have is calling getColumnNames. I'd wonder then if there is a newer version of Spring Data R2DBC you can use? A newer version should not be calling the deprecated method.

BTW, no need to apologize for long descriptions; Detail is something that I appreciate :)

mofeed-hassan commented 2 years ago

@Michael-A-McMahon I checked the stack trace and the ,method calls sequence. It seems that the method org.springframework.r2dbc.core.ColumnMapRowMapper.apply(Row row, RowMetadata rowMetadata) uses the depricated method oracle.r2dbc.impl.ReadablesMetadata.RowMetadataImpl.getColumnNames(). The interface that is implemented by this class stated that it is a deprecated method and other alternatives should be used like {@link #contains(String)} or {@link #getColumnMetadatas()} instead. The class is implemented by Mark Paluch (@mp911de).

mofeed-hassan commented 2 years ago

Original Stack Trace: at oracle.r2dbc.impl.ReadablesMetadata$RowMetadataImpl.getColumnNames(ReadablesMetadata.java:253) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at org.springframework.r2dbc.core.ColumnMapRowMapper.apply(ColumnMapRowMapper.java:57) ~[spring-r2dbc-5.3.20.jar:5.3.20] at org.springframework.r2dbc.core.ColumnMapRowMapper.apply(ColumnMapRowMapper.java:49) ~[spring-r2dbc-5.3.20.jar:5.3.20] at oracle.r2dbc.impl.OracleResultImpl.lambda$map$5(OracleResultImpl.java:222) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.OracleResultImpl.lambda$publishSegments$1(OracleResultImpl.java:152) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.OracleResultImpl$ResultSetResult.lambda$publishSegments$0(OracleResultImpl.java:481) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.OracleReactiveJdbcAdapter.lambda$publishRows$13(OracleReactiveJdbcAdapter.java:751) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.jdbc.driver.InsensitiveScrollableResultSet$RowPublisher.mapCurrentRow(InsensitiveScrollableResultSet.java:1329) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at oracle.jdbc.driver.InsensitiveScrollableResultSet$RowPublisher.lambda$enqueueMapCurrentRow$3(InsensitiveScrollableResultSet.java:1314) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at oracle.jdbc.driver.RestrictedLock.lockAsync(RestrictedLock.java:506) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at oracle.jdbc.driver.PhysicalConnection.enqueueTask(PhysicalConnection.java:11750) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at oracle.jdbc.driver.InsensitiveScrollableResultSet$RowPublisher.enqueueMapCurrentRow(InsensitiveScrollableResultSet.java:1312) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at oracle.jdbc.driver.InsensitiveScrollableResultSet$RowPublisher.advancePhaseAsync(InsensitiveScrollableResultSet.java:1277) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at oracle.jdbc.driver.PhasedPublisher$PublishingPhaser.onAdvance(PhasedPublisher.java:194) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at java.util.concurrent.Phaser.doArrive(Phaser.java:389) ~[?:?] at java.util.concurrent.Phaser.arrive(Phaser.java:624) ~[?:?] at oracle.jdbc.driver.PhasedPublisher$PhasedSubscription.arriveForNextPhase(PhasedPublisher.java:569) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at oracle.jdbc.driver.PhasedPublisher$PhasedSubscription.request(PhasedPublisher.java:525) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at org.reactivestreams.FlowAdapters$ReactiveToFlowSubscription.request(FlowAdapters.java:189) ~[reactive-streams-1.0.3.jar:?] at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2194) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onSubscribe(FluxOnErrorResume.java:74) ~[reactor-core-3.4.18.jar:3.4.18] at org.reactivestreams.FlowAdapters$FlowToReactiveSubscriber.onSubscribe(FlowAdapters.java:213) ~[reactive-streams-1.0.3.jar:?] at oracle.jdbc.driver.PhasedPublisher.subscribe(PhasedPublisher.java:344) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at org.reactivestreams.FlowAdapters$ReactivePublisherFromFlow.subscribe(FlowAdapters.java:355) ~[reactive-streams-1.0.3.jar:?] at oracle.r2dbc.impl.OracleReactiveJdbcAdapter.lambda$deferOnce$26(OracleReactiveJdbcAdapter.java:1108) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at reactor.core.publisher.FluxSource.subscribe(FluxSource.java:67) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.Flux.subscribe(Flux.java:8469) ~[reactor-core-3.4.18.jar:3.4.18] at oracle.r2dbc.impl.AsyncLock.lambda$lock$4(AsyncLock.java:203) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.AsyncLock.lock(AsyncLock.java:99) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.AsyncLock.lambda$lock$5(AsyncLock.java:202) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.OracleReactiveJdbcAdapter.lambda$publishRows$15(OracleReactiveJdbcAdapter.java:759) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at reactor.core.publisher.FluxSource.subscribe(FluxSource.java:67) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.Flux.subscribe(Flux.java:8469) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxConcatArray$ConcatArrayDelayErrorSubscriber.onComplete(FluxConcatArray.java:443) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxConcatArray.subscribe(FluxConcatArray.java:73) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:62) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:54) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.Flux.subscribe(Flux.java:8469) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxFlatMap$FlatMapMain.onNext(FluxFlatMap.java:426) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxUsingWhen$UsingWhenSubscriber.onNext(FluxUsingWhen.java:345) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onNext(FluxPeekFuseable.java:210) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onNext(FluxConcatArray.java:201) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.MonoFlatMapMany$FlatMapManyInner.onNext(MonoFlatMapMany.java:250) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2398) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onSubscribeInner(MonoFlatMapMany.java:150) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onNext(MonoFlatMapMany.java:189) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.MonoCreate$DefaultMonoSink.success(MonoCreate.java:172) ~[reactor-core-3.4.18.jar:3.4.18] at oracle.r2dbc.impl.AsyncLock.lambda$get$2(AsyncLock.java:163) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.AsyncLock.unlock(AsyncLock.java:122) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.AsyncLock$UsingConnectionSubscriber.terminate(AsyncLock.java:510) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at oracle.r2dbc.impl.AsyncLock$UsingConnectionSubscriber.onComplete(AsyncLock.java:496) ~[oracle-r2dbc-0.4.0.jar:0.4.0] at reactor.core.publisher.StrictSubscriber.onComplete(StrictSubscriber.java:123) ~[reactor-core-3.4.18.jar:3.4.18] at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onComplete(Operators.java:2058) ~[reactor-core-3.4.18.jar:3.4.18] at org.reactivestreams.FlowAdapters$FlowToReactiveSubscriber.onComplete(FlowAdapters.java:228) ~[reactive-streams-1.0.3.jar:?] at oracle.jdbc.internal.CompletionStageUtil$IteratorSubscription.emitComplete(CompletionStageUtil.java:805) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at oracle.jdbc.internal.CompletionStageUtil$IteratorSubscription.emitItems(CompletionStageUtil.java:752) ~[ojdbc11-21.5.0.0.jar:21.5.0.0.0] at java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1426) ~[?:?] at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290) ~[?:?] at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020) ~[?:?] at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656) ~[?:?] at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594) ~[?:?]

Michael-A-McMahon commented 2 years ago

Spring R2DBC v5.3.20 depends on R2DBC-BOM vArabba-SR13 https://github.com/spring-projects/spring-framework/blob/e0f56e7d80a4e1248198e40be99157dbd8f594af/build.gradle#L33

R2DBC-BOM vArabba-SR13 depends on R2DBC-SPI 0.8.6.RELEASE https://github.com/r2dbc/r2dbc-bom/blob/7f814fe16d7edbb1a25e58a61e2a84400a84573b/pom.xml#L44

So it is "correct" for Spring R2DBC 5.3.20 to call the deprecated method. In the 0.8.6.RELEASE of the SPI, the method is not deprecated.

I see that Spring R2DBC 6.0.0 is getting staged for release. In v6.0.0.M4, the R2DBC-BOM dependency is updated to vBorca-SR1 https://github.com/spring-projects/spring-framework/blob/9215568881ee06e0848e4d2ee3298bc7b2bc8c69/build.gradle#L33

And R2DBC-BOM vBorca-SR1 will update R2DBC-SPI to v0.9.1.RELEASE, and will also update Oracle-R2DBC to v0.4.0 https://github.com/r2dbc/r2dbc-bom/blob/8c2c9d8f6ebf4a3e739455f7af1918ff7825c10f/pom.xml#L42

We can see that in 6.0.0.M4, ColumnMapRowMapper is updated to no longer use the deprecated method. https://github.com/spring-projects/spring-framework/blob/9215568881ee06e0848e4d2ee3298bc7b2bc8c69/spring-r2dbc/src/main/java/org/springframework/r2dbc/core/ColumnMapRowMapper.java#L58

So I think you'll need to update to Spring R2DBC v6.0.0 then. Looks like the .M4 (milestone 4) release is as close as you can get for now. But if you can get stuff working with .M4, I would expect that updating to v6.0.0.RELEASE, once that's available, will be painless.

Michael-A-McMahon commented 1 year ago

Closing this issue as it is due to an SPI version incompatibility. I think it will be resolved with the next Spring release.