After upgrading spring boot from 3.3.5 to 3.4.2 in microservices , Spring Boot JUnits are failing with below error
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.test.web.client.TestRestTemplate': java.io.IOException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
Caused by: java.io.IOException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
... 112 common frames omitted
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
at java.base/java.security.Provider$Service.newInstance(Provider.java:1868) ~[na:na]
at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:236) ~[na:na]
at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:164) ~[na:na]
at java.base/javax.net.ssl.SSLContext.getInstance(SSLContext.java:185) ~[na:na]
at java.base/javax.net.ssl.SSLContext.getDefault(SSLContext.java:110) ~[na:na]
at java.net.http/jdk.internal.net.http.HttpClientImpl.<init>(HttpClientImpl.java:283) ~[java.net.http:na]
... 111 common frames omitted
Caused by: java.security.KeyManagementException: problem accessing trust store
at java.base/sun.security.ssl.SSLContextImpl$DefaultManagersHolder.<clinit>(SSLContextImpl.java:942) ~[na:na]
at java.base/sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(SSLContextImpl.java:1111) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
application-test.properties
spring.ssl.bundle.jks.kafka.truststore.location=classpath:client-truststore.jks
spring.ssl.bundle.jks.kafka.truststore.password=password
spring.ssl.bundle.jks.kafka.keystore.location=classpath:client-keystore.jks
spring.ssl.bundle.jks.kafka.keystore.password=password
Comment From: Niserga
Junit looks something like below
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@TestPropertySource(
value = "classpath:application-test.properties",
properties = {
"commons.kafka.stream.core.system.cert.configuration.enabled=true"
})
public class KafkaSslConfigEnabledTest {
@Inject
private ApplicationContext applicationContext;
@Test
public void kafkaSslConfigBeanShouldExist() {
applicationContext.getBean(KafkaSslConfig.class);
}
}
Bean Class
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "commons.kafka.stream.core.system.cert.configuration", name = "enabled", matchIfMissing = true)
public class KafkaSslConfig {
@Value("${spring.ssl.bundle.jks.kafka.keystore.location}")
private String keystoreLocation;
@Value("${spring.ssl.bundle.jks.kafka.keystore.password}")
private String keystorePassword;
@Value("${spring.ssl.bundle.jks.kafka.truststore.location}")
private String truststoreLocation;
@Value("${spring.ssl.bundle.jks.kafka.truststore.password}")
private String truststorePassword;
@PostConstruct
public void setSslSystemProperty() {
log.info(
"setup kafka ssl-->start for keystore={}, truststore={}",
this.keystoreLocation,
this.truststoreLocation);
System.setProperty("javax.net.ssl.keyStore", this.keystoreLocation);
System.setProperty("javax.net.ssl.keyStorePassword", this.keystorePassword);
System.setProperty("javax.net.ssl.trustStore", this.truststoreLocation);
System.setProperty("javax.net.ssl.trustStorePassword", this.truststorePassword);
}
}
Comment From: philwebb
I've edited your comment to improve the formatting. You might want to check out this Mastering Markdown guide for future reference.
Comment From: philwebb
From the snippets provided, it seems that you have a very unusual setup where you're trying to use @Value
annotations with our spring.ssl.bundle
properties. The stacktrace also don't appear to have any Spring Boot classes in it.
As such, I suspect the problem isn't in Spring Boot but rather something specific to your application. I think you would be better trying asking a question on Stack Overflow. When you do so, I would suggest providing a minimal, reproducible example that recreates the problem.
Comment From: Niserga
Thanks for the reply.
@Value("${spring.ssl.bundle.jks.kafka.keystore.location}")
--> it is just variable name to hold keystore and truststore details set in a application-test.properties
.
I have modified to another name. Still same issue.
Pleas find below modified application-test.properties
commons.kafka.stream.core.system.cert.configuration.enabled=false
spring.cloud.stream.kafka.streams.binder.configuration.ssl.truststore.location=classpath:client-truststore.jks
spring.cloud.stream.kafka.streams.binder.configuration.ssl.truststore.password=password
spring.cloud.stream.kafka.streams.binder.configuration.ssl.keystore.location=classpath:client-keystore.jks
spring.cloud.stream.kafka.streams.binder.configuration.ssl.keystore.password=password
and also bean KafkaSslConfig.java
@Slf4j
@Configuration
@ConditionalOnProperty(prefix = "commons.kafka.stream.core.system.cert.configuration", name = "enabled", matchIfMissing = true)
public class KafkaSslConfig {
@Value("${spring.cloud.stream.kafka.streams.binder.configuration.ssl.keystore.location}")
private String keystoreLocation;
@Value("${spring.cloud.stream.kafka.streams.binder.configuration.ssl.keystore.password}")
private String keystorePassword;
@Value("${spring.cloud.stream.kafka.streams.binder.configuration.ssl.truststore.location}")
private String truststoreLocation;
@Value("${spring.cloud.stream.kafka.streams.binder.configuration.ssl.truststore.password}")
private String truststorePassword;
@PostConstruct
public void setSslSystemProperty() {
log.info(
"setup kafka ssl-->start for keystore={}, truststore={}",
this.keystoreLocation,
this.truststoreLocation);
System.setProperty("javax.net.ssl.keyStore", this.keystoreLocation);
System.setProperty("javax.net.ssl.keyStorePassword", this.keystorePassword);
System.setProperty("javax.net.ssl.trustStore", this.truststoreLocation);
System.setProperty("javax.net.ssl.trustStorePassword", this.truststorePassword);
}
}
Comment From: Niserga
and When i did debug mode error (Caused by: java.security.KeyManagementException: problem accessing trust store) is coming from ,SSLContextImpl->getTrustManagers(). Null being passed for keystore for provider "SunJSSE"
private static TrustManager[] getTrustManagers() throws Exception {
TrustManagerFactory tmf = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
if ("SunJSSE".equals(tmf.getProvider().getName())) {
// The implementation will load the default KeyStore
// automatically. Cached trust materials may be used
// for performance improvement.
tmf.init((KeyStore)null);
} else {
// Use the explicitly specified KeyStore for third party's
// TrustManagerFactory implementation.
KeyStore ks = TrustStoreManager.getTrustedKeyStore();
tmf.init(ks);
}
return tmf.getTrustManagers();
}
But in case of Springboot 3.3.5,we dont have any issue and also in debug mode with Springboot 3.3.5 ,control would not go to SSLContextImpl->getTrustManagers().Test cases runs successfull...
The issue seems to be related to the SSL configuration when the TestRestTemplate
is initialized or @SpringBootTest
could you please guide on this.
Comment From: Niserga
as per the error trace,Error creating bean TestRestTemplate
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.boot.test.web.client.TestRestTemplate': java.io.IOException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
Comment From: Niserga
As per this https://docs.spring.io/spring-boot//api/java/org/springframework/boot/test/web/client/TestRestTemplate.html
If you are using the @SpringBootTest annotation with an embedded server, a TestRestTemplate is automatically available.
may be while initializing TestRestTemplate bean,getting java.security.NoSuchAlgorithmException Caused by: java.security.KeyManagementException: problem accessing trust store
Comment From: philwebb
Each comment that you add to this issue causes a notification for folks watching the repository so it's best if you can consolidate your thoughts before posting. It's still not clear that this is a Spring Boot issue, and we're not going to be able to determine what is causing the exception without a sample application that reproduces the problem.
Comment From: Niserga
Since my junit had @SpringBootTest
, internally it might be trying to create the bean TestRestTemplate
.On that time below error was
Caused by: org.springframework.beans.factory.BeanCreationException: **Error creating bean with name 'org.springframework.boot.test.web.client.TestRestTemplate': java.io.IOException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)**
Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
... 112 common frames omitted
Caused by: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
at java.base/java.security.Provider$Service.newInstance(Provider.java:1868) ~[na:na]
at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:236) ~[na:na]
at java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:164) ~[na:na]
at java.base/javax.net.ssl.SSLContext.getInstance(SSLContext.java:185) ~[na:na]
at java.base/javax.net.ssl.SSLContext.getDefault(SSLContext.java:110) ~[na:na]
at java.net.http/jdk.internal.net.http.HttpClientImpl.<init>(HttpClientImpl.java:283) ~[java.net.http:na]
... 111 common frames omitted
**Caused by: java.security.KeyManagementException: problem accessing trust store**
at java.base/sun.security.ssl.SSLContextImpl$DefaultManagersHolder.<clinit>(SSLContextImpl.java:942) ~[na:na]
at java.base/sun.security.ssl.SSLContextImpl$DefaultSSLContext.<init>(SSLContextImpl.java:1111) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
Keystore was tampered with, or password was incorrect
Comment From: Niserga
Stack trace from spring boot
Comment From: philwebb
@Niserga As I've already asked, please stop adding so many comments to this issue. If you think you've found a bug, you need to provide a sample application as a GitHub project or zip file that we can run. If you're looking for general help then please ask on stackoverflow.com.