Spring WS and HTTPS? - spring

I use Spring WS to send a request to web service (DentalXChange).
private static final String MESSAGE = <xml request/>
private final WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
public void customSendAndReceive() {
StreamSource source = new StreamSource(new StringReader(MESSAGE));
StreamResult result = new StreamResult(System.out);
webServiceTemplate.sendSourceAndReceiveToResult("https://prelive2.dentalxchange.com/dws/DwsService",
source, result);
}
And here is error
Exception in thread "main" org.springframework.ws.client.WebServiceIOException: I/O error: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext); nested exception is java.net.SocketException: java.security.NoSuchAlgorithmException: Error constructing implementation (algorithm: Default, provider: SunJSSE, class: sun.security.ssl.SSLContextImpl$DefaultSSLContext)
How to solve it. Thanks

Related

Could not convert socket to TLS Spring Mail

I am getting the errors:
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate). Failed messages: javax.mail.MessagingException: Could not convert socket to TLS;
Email sender service class:
#Service
public class EmailSenderService {
#Autowired
private JavaMailSender mailSender;
public void sendEmail(String toEmail,
String subject,
String body){
SimpleMailMessage message=new SimpleMailMessage();
message.setFrom("group18proj#gmail.com");
message.setTo(toEmail);
message.setText(body);
message.setSubject(subject);
mailSender.send(message);
System.out.println("Mail Sent Successfully...");
}
Mail Controller:
#Autowired
EmailSenderService emailSenderService;
#RequestMapping("/mail")
public String sendMail(HttpSession session, Model model){
emailSenderService.sendEmail("mrleftgamer#gmail.com","Test","This is the body of the test email");
session.setAttribute("mailMessage", "Check your email");
return "redirect:/dashboard";
}
I experienced the same problem today. My antivirus was at fault. After temporarily disabling Avast the mail sender worked as expected.

Hystrix Feign Retry for Timeout not working

I have a Feign Configuration and Hystrix Commands in my project.
below is Feign Config
#Configuration
public class FeignRetryConfig {
#Primary
#Bean
public Feign.Builder feignBuilder(Retryer nephosFeignRetryer) {
return HystrixFeign.builder()
.errorDecoder(new FeignErrorDecoder())
.retryer(nephosFeignRetryer);
}
// retry set to 3 times
#Bean
public Retryer nephosFeignRetryer() {
return new Retryer.Default(10, SECONDS.toMillis(5), 5);
}
#Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
and below is my ErrorDecoder:
public class FeignErrorDecoder implements ErrorDecoder {
private final ErrorDecoder defaultErrorDecoder = new Default();
#Override
public Exception decode(String methodKey, Response response) {
Exception exception = defaultErrorDecoder.decode(methodKey, response);
if (response.status() == 500) {
log.error(String.format("##### Got %s response from %s #######", response.status(),
methodKey));
return new RetryableException(
exception.getMessage(),
exception,
null
);
}
return exception;
}
}
and below is my client:
#FeignClient(name = "TEST-CONFIG", configuration = FeignRetryConfig.class, fallbackFactory =
XYZClientFallbackFactory.class)
public interface TestClient {
#RequestMapping(value = "/test", method = RequestMethod.GET, consumes =
MediaType.APPLICATION_JSON_VALUE)
Observable<String> test();
}
SO from TEST-CONFIG I am throwing IOException ( 500 Error ) to Test, but it does not make any retry. below is my error:
com.netflix.hystrix.exception.HystrixRuntimeException: TestClient#test() failed and fallback failed.
at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:815)
at com.netflix.hystrix.AbstractCommand$22.call(AbstractCommand.java:790)
at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at com.netflix.hystrix.AbstractCommand$DeprecatedOnFallbackHookApplication$1.onError(AbstractCommand.java:1451)
at com.netflix.hystrix.AbstractCommand$FallbackHookApplication$1.onError(AbstractCommand.java:1376)
at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: feign.RetryableException: status 500 reading TestClient#test(); content:
{"status":500,"erroritems":[{"code":"RuntimeException","message":"org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection"}]}
at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:108)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:301)
at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:297)
at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
... 30 common frames omitted
Caused by: feign.FeignException: status 500 reading TestClient#test(); content:
{"status":500,"erroritems":[{"code":"RuntimeException","message":"org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection"}]}
at feign.FeignException.errorStatus(FeignException.java:62)
at feign.codec.ErrorDecoder$Default.decode(ErrorDecoder.java:91)
Can Somebody Help Please, What am I Missing ?
I guess you have hystrix enabled. Try setting
feign.hystrix.enabled: false
and see if it works then; if so it would prove your configuration to be ok. There is a post on hystrix and retrying that suggests that this does not go well together. If you want to keep hystrix enabled (and why should you not), perhaps it is worth looking at spring-retry to circumvent the problem.

keystore.jks and truststore.jks can't be found in Spring Boot App

I wrote a 2-way authetication restful service cleint to consume a secured restful web service on port 8443 over https. Here are parts of application.properties:
trust.store=classpath:truststore.jks
trust.store.password=xyz123
key.store=classpath:keystore.jks
key.store.password=xyz123
Below are two ways to configure RestTemplate
#Configuration
public class SSLTemplate {
#Value("${key.store}")
private String keyStore;
#Value("${key.store.password}")
private String keyStorePassword;
#Value("${trust.store}")
private String trustStore;
#Value("${trust.store.password}")
private String trustStorePassword;
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
SSLContext sslContext = SSLContextBuilder.create()
.loadKeyMaterial(ResourceUtils.getFile(keyStore), keyStorePassword.toCharArray(), keyStorePassword.toCharArray())
.loadTrustMaterial(ResourceUtils.getFile(trustStoreF), trustStorePassword.toCharArray())
.build();
...
}
#Configuration
public class SSLTemplate {
#Value("${key.store}")
private Resource keyStoreR;
#Value("${key.store.password}")
private String keyStorePassword;
#Value("${trust.store}")
private Resource trustStoreR;
#Value("${trust.store.password}")
private String trustStorePassword;
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
SSLContext sslContext = SSLContextBuilder.create()
.loadKeyMaterial(keyStoreR.getURL(), keyStorePassword.toCharArray(), keyStorePassword.toCharArray())
.loadTrustMaterial(trustStoreR.getURL(), trustStorePassword.toCharArray())
.build();
...
}
When I run the app via bootRun or within Eclipse, both of them work.
But when I use jar launcer
java -jar app.jar
I got below exception.
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiation
Exception: Failed to instantiate [org.springframework.web.client.RestTemplate]: Factory method 'restTemplate' threw exception;
nested exception is java.io.FileNotFoundException: URL cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/C:/build/libs/app.jar!/BOOT-INF/classes!/truststore.jks
I have also tried
java -Djavax.net.ssl.trustStore=truststore.jks -Djavax.net.ssl.trustStorePassword=xyz123 -Djavax.net.ssl.keyStore=keystore.jks -Djavax.net.ssl.keyStorePassword=xyz123 -jar app.jar
and got the same exception. Any help will be really appreciated.
Try using resource.getInputStream() instead of resource.getFile() as, resource.getFile() in Spring tries to access a file system path but it can not access a path in your JAR
This link has a rich content and do take a look at Andy's answer here
Sample example:
Resource resource = resourceLoader.getResource("classpath:GeoLite2-Country.mmdb");
InputStream dbAsStream = resource.getInputStream();
and do you have use full path
-Djavax.net.ssl.trustStore=something/like/this/truststore.jks

Getting I/O error while executing JUnit test case for Spring Controller

I am executing a test case to call spring controller (GET method). However, It throws below I/O error.
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:8039": Connect to localhost:8039 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect; nested exception is org.apache.http.conn.HttpHostConnectException: Connect to localhost:8039 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:674)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:636)
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
Below is the test case class that i am executing which throws the above error.
public class GetRuleSetsTests extends PreferencesAdminClientTestApplicationTests<GetRuleSetsResponse>{
#Test
public void testSuccess() throws Exception
{
final String mockedResponseJson = rawJsonFromFile("com/cnanational/preferences/client/rule-sets/getRuleSetsResponse.json");
MockRestServiceServer mockServer = mockServer();
mockServer.expect(requestTo(dummyUri()))
.andExpect(method(HttpMethod.GET))
.andExpect(queryParam("ruleSetDescription", "TestRuleDescription"))
.andRespond(withSuccess(
mockedResponseJson,
MediaType.APPLICATION_JSON));
ServiceClientResponse<GetRuleSetsResponse> response = executeDummyRequest();
mockServer.verify();
assertThat(response.isSuccessful(), equalTo(true));
GetRuleSetsResponse programResponse = response.getParsedResponseObject();
assertThat(programResponse.getRuleSets().size(), equalTo(2));
}
#Override
public URI dummyUri() {
return UriComponentsBuilder.fromUri(baseUri())
.path(this.endpointProperties.getRuleSets())
.build()
.toUri();
}
}
What am i missing? Any inputs appreciated.
If you have configured your test environment properly to run MockRestServiceServer
(by that, I mean #RunWith(SpringRunner.class) and #RestClientTest(ClassUnderTestThatCallsTheMockServer.class)), make sure that you are not instantiating your mock server with = new MockServer(), instead just use an instance that is #Autowired from the spring context (because that instance is configured out of the box).
I see that you have a lot of inheritance and overridden methods in your tests, calling things with this.returnSomething..., so make sure that you are not instantiating things outside of the spring context.
Here is a simple example of a mock server to get some posts:
#RunWith(SpringRunner.class)
#RestClientTest(PostClient.class)
public class PostClientMockTest {
// class under test
#Autowired
private PostClient postClient;
// autowired mock server from the spring context
#Autowired
private MockRestServiceServer mockRestServiceServer;
#Test
public void readPosts() throws Exception {
String mockJsonResponse = "My response";
mockRestServiceServer.expect(requestTo("https://myurl.com/posts?userId=1"))
.andRespond(withSuccess(mockJsonResponse, MediaType.APPLICATION_JSON_UTF8));
List<Post> posts = postClient.readPosts(1);
assertEquals(9, posts.size());
mockRestServiceServer.verify();
}
}
Hope this helps

Camel MQTT Configuration options DSL route URL parameter with bean value not working

I ma trying to test pub/sub from an external broker ( AWs IoT ); started off of the camel-example-spring-boot example project and added thecamel-mqtt-starter. Everything seems to work fine until I try to define the mqtt routes. I am having issues with configuring the sslContext url parameter :
#Configuration
public class AppConfig {
#Bean(name="awsiotsslcontext")
SSLContext awsiotsslcontext(){
SSLContext sslContext = null;
try{
ClassLoader cl = this.getClass().getClassLoader();
InputStream is = cl.getResourceAsStream("/cert/myApp.cert.pem");
// You could get a resource as a stream instead.
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate caCert = (X509Certificate)cf.generateCertificate(is);
TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null); // You don't need the KeyStore instance to come from a file.
ks.setCertificateEntry("caCert", caCert);
tmf.init(ks);
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
} catch (Exception e){
}
return sslContext;
}
}
And then in my route builder :
#Component
public class SampleCamelRouter extends RouteBuilder {
#Autowired
SSLContext awsiotsslcontext;
#Override
public void configure() throws Exception {
from("timer://foo?repeatCount=0&delay=5000&fixedRate=true&period=10s")
.setBody(simple("TEST MESSAGE"))
.to("mqtt:awsiot?host=ssl://{{aws.iot.host}}:8883&publishTopicName={{aws.iot.sub.topic}}&sslContext=#awsiotsslcontext").log("Sent :"+body().convertToString().toString());
from("mqtt:awsiot?host=ssl://{{aws.iot.host}}:8883&subscribeTopicName={{aws.iot.sub.topic}}&sslContext=#awsiotsslcontext").log("Recieved : "+body().convertToString().toString());
}
}
getting the following error :
java.lang.IllegalArgumentException: Could not find a suitable setter
for property: sslContext as there isn't a setter method with same
type: java.lang.String nor type conversion possible: No type converter
available to convert from type: java.lang.String to the required type:
javax.net.ssl.SSLContext with value #awsiotsslcontext
I believe this is a simple endpoint configuration issue, but tried various things and nothing seems to work. Having the # with the bean name should have camel to look up in the registry for the bean but here it recognizes it as String ? Any workaround here ?
This was an issue on camel route configuration; when I configured my route under a #Configuration instead of having under #Component as suggested by the documentation, it doesn't complain about bean definition with '#' in the URI; I would expect in a Spring Boot Application the beans would load before the routes by default:
#Bean
RouteBuilder awsIoTRoute() {
return new RouteBuilder() {
#Override
public void configure() throws Exception {
from("timer://foo?repeatCount=0&delay=5000&fixedRate=true&period=17s")
.setBody(simple("TEST MESSAGE"))
.to("mqtt:awsIoTPublisher?host=ssl://{{aws.iot.host}}:8883&publishTopicName={{aws.iot.pub.topic}}&clientId={{aws.iot.pub.clientId}}&sslContext=#sslContext")
.log("Sent :"+body().convertToString().toString());
from("mqtt:awsIoTReciever?host=ssl://{{aws.iot.host}}:8883&subscribeTopicName={{aws.iot.sub.topic}}&clientId={{aws.iot.sub.clientId}}&sslContext=#sslContext").log("Recieved : "+body().convertToString());
}
};
}

Resources