0

I use Spring JPA and GraphQL-Java-Kickstart set of libs with Kotlin. When I send a query to my app it throws this:

2020-02-26 18:51:42.707 ERROR 2672 --- [nio-8080-exec-7] g.k.e.error.DefaultGraphQLErrorHandler   : Error executing query Exception while fetching data (/createUser) : lateinit property userRepository has not been initialized

kotlin.UninitializedPropertyAccessException: lateinit property userRepository has not been initialized
at com.minerepo.minerepo.resolver.mutation.RootMutationResolver.createUser(RootMutationResolver.kt:16) ~[main/:na]

This is my resolver:

@Component
class RootMutationResolver : GraphQLMutationResolver {
    @Autowired
    private lateinit var userRepository: UserRepository

    fun createUser(user: UserInput): User = userRepository.save(User(
            id = UUID.randomUUID().toString(),
            email = user.email,
            nick = user.nick
    ))
}

This is an entity:

@Entity
data class User(
        @Id val id: String,
        @NotNull @Email var email: String,
        @NotBlank @Length(min=4, max=64) var nick: String
) : ProjectOwner // Table-per-class inheritance

This is the input type class:

data class UserInput(
        var email: String,
        var nick: String
)

This is the repository:

@Repository
@Component
interface UserRepository : JpaRepository<User, String>

And this is the main class:

@SpringBootApplication
class MinerepoApplication {
    @Bean
    fun schema() : GraphQLSchema = SchemaParser.newParser()
            .file("schema.graphqls")
            .resolvers(RootQueryResolver(), RootMutationResolver())
            .build()
            .makeExecutableSchema()
}

fun main(args: Array<String>) {
    runApplication<MinerepoApplication>(*args)
}

1 Answers1

0

Can you autowire UserRepository in anothor component (not GraphQL component)?

I think you miss the @EnableJpaRepositories annotation over the MinerepoApplication class. Example:

@SpringBootApplication
@EnableJpaRepositories(basePackageClasses = [MinerepoApplication::class])
class MinerepoApplication {
    @Bean
    fun schema() : GraphQLSchema = SchemaParser.newParser()
            .file("schema.graphqls")
            .resolvers(RootQueryResolver(), RootMutationResolver())
            .build()
            .makeExecutableSchema()
}

This will instruct Spring Data to scan the MinerepoApplication class package (and child packages) for JPA repositories.

You don't need the annotation @Repository and @Component over the JPA repository interface. In addition, @Repository also works like @Component.

I would also like to add that when you inject the necessary dependencies in your components, you should not use @Autowired over the field, you should inject them through the constructor. Example:

@Component
class RootMutationResolver(
   private val userRepository: UserRepository
) : GraphQLMutationResolver {

    fun createUser(user: UserInput): User = userRepository.save(User(
            id = UUID.randomUUID().toString(),
            email = user.email,
            nick = user.nick
    ))
}
mrg
  • 322
  • 1
  • 5
  • It didn't work. I can wire the repository in my main class (I've checked only there), and it is not null even without `@EnableJpaRepositories` – Mikhail Oleynikov Feb 27 '20 at 11:10
  • I made it work this way: 1. I've used a constructor to inject the repository into the resolver 2. I've then injected the resolver into my application class and used the instance instead of creating it I think it didn't work because I've passed my own instance previously which likely Spring couldn't see. The second part with the constructors of your answer have helped :) – Mikhail Oleynikov Feb 27 '20 at 11:35