micronaut-projects / micronaut-projects/micronaut-data

generated CrudRepository finder fails on setting connection read-only on postgres DB

Open
#2,402 6 comments 0 reactions 0 assignees View on GitHub
status: example attached type: bug
Dominant language
Java
Stars
482
Forks
229
Avg merge
1d 7h
Merged PRs (30d)
32

Description

### Expected Behavior

An auto-implemented read-only method (e. g. findById) should create a read-only transaction by default without throwing an exception.

### Actual Behaviour

The auto-implemented method first creates a connection then tries to modify it to read-only later, which the postgres driver rejects. Stacktrace:

```
Could not set JDBC Connection [HikariProxyConnection@625868084 wrapping org.postgresql.jdbc.PgConnection@7262532a] read-only: Cannot change transaction read-only property in the middle of a transaction.
io.micronaut.data.connection.exceptions.ConnectionException: Could not set JDBC Connection [HikariProxyConnection@625868084 wrapping org.postgresql.jdbc.PgConnection@7262532a] read-only: Cannot change transaction read-only property in the middle of a transaction.
at app//io.micronaut.data.connection.support.JdbcConnectionUtils.setConnectionReadOnly(JdbcConnectionUtils.java:170)
at app//io.micronaut.data.connection.support.JdbcConnectionUtils.applyReadOnly(JdbcConnectionUtils.java:75)
at app//io.micronaut.data.connection.jdbc.operations.DefaultDataSourceConnectionOperations.lambda$setupConnection$0(DefaultDataSourceConnectionOperations.java:67)
at java.base@17.0.7/java.util.Optional.ifPresent(Optional.java:178)
at app//io.micronaut.data.connection.jdbc.operations.DefaultDataSourceConnectionOperations.setupConnection(DefaultDataSourceConnectionOperations.java:65)
at app//io.micronaut.data.connection.support.AbstractConnectionOperations.executeWithNewConnection(AbstractConnectionOperations.java:142)
at app//io.micronaut.data.connection.support.AbstractConnectionOperations.execute(AbstractConnectionOperations.java:90)
at app//io.micronaut.data.connection.ConnectionOperations.executeRead(ConnectionOperations.java:71)
at app//io.micronaut.data.jdbc.operations.DefaultJdbcRepositoryOperations.executeRead(DefaultJdbcRepositoryOperations.java:765)
at app//io.micronaut.data.jdbc.operations.DefaultJdbcRepositoryOperations.findOne(DefaultJdbcRepositoryOperations.java:310)
at app//io.micronaut.data.runtime.intercept.DefaultFindOptionalInterceptor.intercept(DefaultFindOptionalInterceptor.java:47)
at app//io.micronaut.data.runtime.intercept.DefaultFindOptionalInterceptor.intercept(DefaultFindOptionalInterceptor.java:34)
at app//io.micronaut.data.runtime.intercept.DataIntroductionAdvice.intercept(DataIntroductionAdvice.java:83)
at app//io.micronaut.aop.chain.MethodInterceptorChain.proceed(MethodInterceptorChain.java:137)
...
Caused by: org.postgresql.util.PSQLException: Cannot change transaction read-only property in the middle of a transaction.
at app//org.postgresql.jdbc.PgConnection.setReadOnly(PgConnection.java:897)
at app//com.zaxxer.hikari.pool.ProxyConnection.setReadOnly(ProxyConnection.java:410)
at app//com.zaxxer.hikari.pool.HikariProxyConnection.setReadOnly(HikariProxyConnection.java)
at app//io.micronaut.data.connection.support.JdbcConnectionUtils.setConnectionReadOnly(JdbcConnectionUtils.java:167)
... 23 more
```

In Micronaut 3 this was swallowed (not great, either, we didn't notice).

### Steps To Reproduce

1. Have a Postgres DB with a simple table
2. Write a CrudRepository that extends io.micronaut.data.repository.CrudRepository using `@JdbcRepository(dialect = Dialect.POSTGRES)`
3. Set `datasources.default.auto-commit=false` in the application.properties
4. Call `repo.findById()` in a `@MicronautTest(transactional=false)`

### Environment Information

OS: MacOS VEntura 13.4.1
Java: 17

### Example Application

_No response_

### Version

4.0.1

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the CrudRepository findById call with PostgreSQL, auto-commit=false, and @MicronautTest(transactional=false). Read JdbcConnectionUtils and DefaultDataSourceConnectionOperations around the stack-trace lines, then trace ConnectionOperations.executeRead. Done means the generated read-only finder completes without PostgreSQL rejecting the transaction read-only setting.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, postgresql
Domain
backend, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.