I've been building a project app and wanted to include JWT security. I followed along with a tutorial and have an issue with this code snippet.
@Configuration
@RequiredArgsConstructor
public class ApplicationConfig {
private final UserRepository repository;
@Bean
public UserDetailsService userDetailsService() {
return username -> repository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I receive this error:
ApplicationConfig.java:21: error: variable userRepository not initialized in the default constructor
private final UserRepository userRepository;
^
From extensive googling/stackoverflow reading I believe that the repository isn't getting instantiated by Spring before Spring loads this configuration class. I've tried auto wiring the repository, among other things.
I've seen no one else post this issue on the GitHub page that I followed and I'm unsure how to fix, advice welcome!
Other relevant code snippets following:
@Repository
public interface UserRepository extends JpaRepository<User, Integer> {
Optional<User> findByUsername(String username);
}
@SpringBootApplication
@EnableConfigurationProperties(ConfigProperties.class)
@EnableJpaRepositories("com.browna.teller_back.repositories")
public class TellerBackApplication {
public static void main(String[] args) {
SpringApplication.run(TellerBackApplication.class, args);
}
}
User entity class
@Builder
@Entity
@Table(name = "users",
uniqueConstraints = {
@UniqueConstraint(columnNames = "username"),
@UniqueConstraint(columnNames = "email")
})
public class User implements UserDetails {
@Getter
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@NotBlank
@Size(max = 20)
private String username;
@NotBlank
@Size(max = 50)
@Email
private String email;
@NotBlank
@Size(max = 120)
private String password;
@Enumerated(EnumType.STRING)
private Role role;
public User() {
}
public User(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
public @NotBlank @Size(max = 20) String getUsername() {
return username;
}
The problem is that you are using Project Lombok at least you have put the @RequiredArgsConstructor
on your configuration class in the hopes to not have to add a constructor.
ApplicationConfig.java:21: error: variable userRepository not initialized in the default constructor
The error you get mentions the default constructor. Which is the default no-args constructor which will get added to Java classes when no other explicit constructor has been added.
This simply means that you have added Lombok as a dependency but haven't setup the compiler plugin in your Maven pom.xml
or Gradle build.gradle
.
If it were me I would ditch Lombok and simply add a single arg constructor to your ApplicationConfig
class. This would make it work without any additional added code generation magic.
@Configuration
public class ApplicationConfig {
private final UserRepository repository;
public ApplicationConfig(UserRepository repository) {
this.repository=repository;
}
// Other code not listed...
}
If you really want make sure you setup the maven-compiler-plugin
correctly.
Dependency declaration
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
Plugin configuration
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
NOTE: You don't need the version
tags as Spring Boot will manage those.
NOTE2: If you get this error in your IDE (like Intellij) make sure that you have enabled annotation processors, else the annotations from Lombok won't do anything.