SledgeHammer
SledgeHammer

Reputation: 7736

r2dbc ReactiveCrudRepository keeps crashing

My pom.xml has the following dependencies:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-r2dbc</artifactId>
  <version>2.3.3.RELEASE</version><!--$NO-MVN-MAN-VER$-->
</dependency>       

<dependency>
            <groupId>io.r2dbc</groupId>
            <artifactId>r2dbc-mssql</artifactId>
            <scope>runtime</scope>
</dependency>

My properties looks like:

spring.r2dbc.url=r2dbc:mssql://localhost:1433/Admin
spring.r2dbc.username=xxx
spring.r2dbc.password=xxx

Repo looks like:

@Repository
public interface UserRepository extends ReactiveCrudRepository<MyUser, String> {
    @Query("SELECT u.Username AS username, u.Password as password FROM Users u INNER JOIN Roles r ON u.RoleId=r.Roleid WHERE u.Username=@username") 
    public Mono<UserDetails> findByUsername(String username);
}

MyUser looks like:

@SuppressWarnings("serial")
public class MyUser implements UserDetails {

    @Id
    private String username;
    private String password;

    public MyUser(String username, String password) {
        this.username = username;
        this.password = password;
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return null;
    }

    @Override
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        return false;
    }

    @Override
    public boolean isAccountNonLocked() {
        return false;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return false;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

I turned on the SQL profiler and caught the query coming in, and it is 100% correct and returns the correct data, but it seems to be crashing on the deserialization. I set a breakpoint and it never calls the MyUser contructor. If I manually create one with Mono.just(), the app works as expected.

I am getting the following exception:

java.lang.NullPointerException: null
    at org.springframework.data.r2dbc.core.DefaultDatabaseClient$DefaultTypedExecuteSpec.lambda$new$0(DefaultDatabaseClient.java:590) ~[spring-data-r2dbc-1.1.3.RELEASE.jar:1.1.3.RELEASE]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
    |_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
    |_ checkpoint ⇢ HTTP POST "/login?error" [ExceptionHandlingWebHandler]
Stack trace:
        at org.springframework.data.r2dbc.core.DefaultDatabaseClient$DefaultTypedExecuteSpec.lambda$new$0(DefaultDatabaseClient.java:590) ~[spring-data-r2dbc-1.1.3.RELEASE.jar:1.1.3.RELEASE]
        at java.base/java.util.function.BiFunction.lambda$andThen$0(BiFunction.java:70) ~[na:na]
        at io.r2dbc.mssql.MssqlResult.lambda$map$2(MssqlResult.java:169) ~[r2dbc-mssql-0.8.4.RELEASE.jar:0.8.4.RELEASE]

Any ideas on the what the issue is? The exception is on this block of code:

    if (typeToRead.isInterface()) {
        this.mappingFunction = ColumnMapRowMapper.INSTANCE
                .andThen(map -> projectionFactory.createProjection(typeToRead, map));
    } else {
        this.mappingFunction = dataAccessStrategy.getRowMapper(typeToRead);
    }

Upvotes: 2

Views: 1219

Answers (2)

Hantsy
Hantsy

Reputation: 9321

  1. If you are using the Repository, in your codes, MyUser is not annotated with @Table, eg here

  2. You could try to use DatabaseClient to handle the query manually if you do not use the OR Mapping provided in Spring Data R2dbc, it is more flexible if you are stick on writing custom SQL scripts. eg. here.

Upvotes: 1

Igor Kanshyn
Igor Kanshyn

Reputation: 912

Try adding a default constructor (a constructor with no parameters) to your MyUser class.

Upvotes: 0

Related Questions