Как исправить java.lang.NoClassDefFoundError для javax/xml/bind/DatatypeConverter
Я использую Java 17 и Spring boot 3.
Я получаю эту ошибку:
Отправка обработчика не удалась: java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
Эту проблему я получаю при получении токена Jet.
Это зависимость, которую я использую.
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
Теперь, когда я получаю ответ от входа в систему, я хочу, чтобы авторизация передавалась во внешний интерфейс, чтобы ее можно было использовать для дальнейших вызовов.
Итак, в моей службе входа в систему я звоню типа
@Override
public LoginResponseDTO authenticateUser(LoginRequestDTO loginRequestDTO) {
Optional<Users> userOptional = repository.findByEmail(loginRequestDTO.getEmail());
Users user = userOptional.get();
String token = generateToken(user.getEmail());
………………..
Это мой класс jwtUtil:
@Component
public class JwtUtil {
private String secret = "your_secret_key";
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public Claims extractAllClaims(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
public boolean validateToken(String token, String username) {
return (username.equals(extractUsername(token)) && !isTokenExpired(token));
}
public String extractUsername(String token) {
return extractAllClaims(token).getSubject();
}
public boolean isTokenExpired(String token) {
return extractAllClaims(token).getExpiration().before(new Date());
}
}
Это моя конфигурация безопасности
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeRequests(authorizeRequests ->
authorizeRequests
.requestMatchers("/api/user/validate").permitAll()
.anyRequest().authenticated()
)
.sessionManagement(sessionManagement ->
sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean(name = "customJwtAuthenticationFilter")
public JwtAuthenticationFilter jwtAuthenticationFilter() {
return new JwtAuthenticationFilter();
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:3000"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
А еще это мой JwtAuthenticationFilter
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtUtil jwtUtil;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails.getUsername())) {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
Может кто-нибудь, пожалуйста, скажите мне, чего мне здесь не хватает и что вам нужно сделать, чтобы решить эту проблему.
Вам необходимо добавить библиотеку jaxb-api
, поскольку библиотека jjwt
по-прежнему использует старую библиотеку JAXB.
Добавьте указанную выше зависимость библиотеки в build.gradle:
dependencies {
.....
implementation 'javax.xml.bind:jaxb-api:2.3.1'
}
Это сработает.
Spring Boot 3 использует
jakarta
вместо старыхjavax
классов, поэтому кажется, что одна из используемых вами зависимостей устарела и все еще ищет старыеjavax.xml.bind.*
классы.