Okhttp on Java 7 arises Connection reset - okhttp

I'm supposed to consume a customized PeopleSoft SOAP service using Java.
The service is tested on Postman like this
and the Okhttp snippet suggested works in Java 8 smoothly.
OkHttpClient client = new OkHttpClient().newBuilder().build();
MediaType mediaType = MediaType.parse("application/xml");
RequestBody body = RequestBody.create(mediaType, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><Some XML>");
Request request = new Request.Builder()
.url("urlToPeopleSoftService")
.method("POST", body)
.addHeader("Content-Type", "application/xml")
.build();
Response response = client.newCall(request).execute();
The problem is when i use a jdk 7 to execute the project, getting an annoying Exception
Connection reset
java.net.SocketException: Connection reset
Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.security.ssl.InputRecord.readFully(InputRecord.java:442)
at sun.security.ssl.InputRecord.read(InputRecord.java:480)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:934)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
at com.squareup.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:192)
at com.squareup.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:149)
at com.squareup.okhttp.internal.io.RealConnection.connect(RealConnection.java:112)
at com.squareup.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:184)
at com.squareup.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)
at com.squareup.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)
at com.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)
at com.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)
at com.squareup.okhttp.Call.getResponse(Call.java:286)
at com.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:243)
at com.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:205)
at com.squareup.okhttp.Call.execute(Call.java:80)
at de.gov.dee.journal.JournalData.postRequest(JournalData.java:372)
at de.gov.dee.journal.JournalData.inquiryJournalStatus(JournalData.java:355)
at de.gov.dee.journal.JournalData.checkJournalStatus(JournalDa
ta.java:131)
at de.gov.dee.journal.JournalData.main(JournalData.java:516)
I've tried with okhttp 3.9.0 and okhttp 2.7.5 with no luck
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<version>2.7.5</version>
</dependency>
The bad news is that it MUST be run on Java 7. How can I solve this?

Related

Access token not propagated in Spring Boot 2.7

We use Spring Boot with an OIDC integration to provide authentication and authorization to our users.
Our application acts as Client in the OIDC code flow, calling downstream Resource servers through Http requests to serve user requests.
To have the Client pass the access token of the authenticated user to Resource servers we use the ServletOAuth2AuthorizedClientExchangeFilterFunction and apply that to the org.springframework.web.reactive.function.client.WebClient handling downstream requests.
We recently upgraded from Spring Boot 2.6.7 to 2.7.3 and discovered that the Authentication header containing the access token is no
longer added to outgoing requests, if those requests are scheduled on a thread other than the one serving the original request:
public class MyController {
public Mono<ProductSearchResult> searchByName(SearchProductsQuery query) {
List<String> sortOrder = new ArrayList<>();
System.out.println("--OUTER: " + Thread.currentThread().getName());
return resourceServere.searchByName(query)
.doOnNext(searchResponse -> sortOrder.addAll(searchResponse.getIds()))
.flatMap(searchResponse -> Mono.zip(
getSomething(searchResponse.getIds()),
getSomethingElse(searchResponse.getIds()),
Mono.just(searchResponse.pagination())))
.map(tuple3 -> SearchResultMapper.map(tuple3.getT1(), tuple3.getT2(), tuple3.getT3()));
}
private Mono<List<String>> getSomething(List<String> ids) {
System.out.println("--INNER: " + Thread.currentThread().getName());
if (ids.isEmpty()) {
return Mono.just(new ArrayList<>());
}
return otherResourceServerClient.getStuff(ids);
}
}
Which prints
--OUTER: http-nio-8080-exec-6
--INNER: reactor-http-nio-3
Debugging ServletOAuth2AuthorizedClientExchangeFilterFunction we discovered that the request in the http-nio-thread has the Authentication:
Debugger stopped in ServletOAuth2AuthorizedClientExchangeFilterFunction
whereas the request in the reactor-http thread does not:
Debugger stopped in ServletOAuth2AuthorizedClientExchangeFilterFunction
I can certainly provide more information about our setup, I'm just a bit uncertain what would be relevant.
For starters though, we depend on both spring-starter-webflux and spring-boot-starter-web, as well as on spring-boot-starter-security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Curious to hear if anyone has experienced the same issue?

elasticsearch java.lang.NoSuchMethodError: org.apache.http.client.utils.URLEncodedUtils.formatSegments

I'm trying this basic elasticsearch example from there guide to use java client API in a spring boot project.
but it gives me the following error when running:
java.lang.NoSuchMethodError: org.apache.http.client.utils.URLEncodedUtils.formatSegments([Ljava/lang/String;)Ljava/lang/String;
here is my POM file.
the code:
public void retrieveAuditMessages() throws IOException {
// Create the low-level client
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200)
).build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper()
);
// Create the API client
ElasticsearchClient client = new ElasticsearchClient(transport);
SearchResponse<String> search = client.search(s -> s
.index("logstash-wildfly*")
.query(q -> q
.term(t -> t
.field("host")
.value(v -> v.stringValue("aboSaadoosh"))
)
),
String.class);
for(Hit<String> hit: search.hits().hits())
{
System.out.println(hit.source());
}
}
I guess it's a problem with dependencies, but I don't know how to solve it.
I'm using Elasticsearch version 8.1.1 java client API and spring boot 1.5.7.RELEASE
I solved this by adding org.apache.httpcomponents:httpclient:4.5.13 explicitly in the POM file (instead of version org.apache.httpcomponents:httpclient:4.5.3 included by co.elastic.clients:elasticsearch-java:8.1.1)
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
I don't know if this is the correct way to solve it but anyway it worked for me.

Configure HTTPS in Spring Boot Apache Camel REST API with keystore having multiple certs using camel-jetty component

I am trying to configure https in my apache camel Spring Boot REST application (using apache-camel v3.11.1, springboot v2.5.3) with keystore having multiple certificates.
Problem:
Application run failed
org.apache.camel.RuntimeCamelException: java.lang.IllegalStateException: KeyStores with multiple certificates are not supported on the base class org.eclipse.jetty.util.ssl.SslContextFactory. (Use org.eclipse.jetty.util.ssl.SslContextFactory$Server or org.eclipse.jetty.util.ssl.SslContextFactory$Client instead)
at org.apache.camel.RuntimeCamelException.wrapRuntimeCamelException(RuntimeCamelException.java:51) ~[camel-api-3.11.1.jar:3.11.1]
Project setup:
pom.xml: (dependencies only, to show that I am not using spring-boot-web-starter)
..
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jetty-starter</artifactId>
</dependency>
..
..<!-- all other required dependencies are in place-->
..
</dependencies>
..
application.properties
#camel.component.jetty.keystore=keystore-with-one-certificate.jks # WORKS
camel.component.jetty.keystore=keystore-with-multiple-certificates.jks # DOESN'T WORK
camel.component.jetty.ssl-key-password=password
camel.component.jetty.ssl-password=password
Rest Route:
restConfiguration()
.component("jetty")
.scheme("https")
.port("8080");
rest()
.path("/api")
.get("/{name}")
..
..
.to("direct:x");
Looked at answers in the below posts, but still not able to resolve the exception that I get,
https://stackoverflow.com/a/60598953/6363894,
https://stackoverflow.com/a/55499113/6363894
I know that exception clearly states to use org.eclipse.jetty.util.ssl.SslContextFactory$Server, but I don't understand how/where to use SslContextFactory.Server object.
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStoreResource(findKeyStorePath());
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setKeyManagerPassword("password");
sslContextFactory.setNeedClientAuth(true);
Also I've created a bean for sslContextParameters and added that to restConfiguration as below, this time application runs successfully but then when I test, SSL handshake fails.
restConfiguration()
.component("jetty")
.endpointProperty("sslContextParameters", "#sslContextParameters")
.scheme("https")
.port("8080");
#Bean(name = "sslContextParameters")
public SSLContextParameters setSSLContextParameters() {
KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("keystore-with-multiple-certificates.jks");
ksp.setPassword("password");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("password");
SSLContextServerParameters scsp = new SSLContextServerParameters();
scsp.setClientAuthentication("REQUIRE");
SSLContextParameters scp = new SSLContextParameters();
scp.setServerParameters(scsp);
scp.setKeyManagers(kmp);
return scp;
}
Any help on how to configure SslContextFactory.Server object with the restConfigurations() or any other way I can achieve this? I'll update the post, if any more details are required.

How do I configure JedisConnectionFactory to use SSL so that I don't get the error: "JedisDataException: ERR unencrypted connection is prohibited"?

I have a Redis database with an RLEC (RedisLabs Enterprise Cluster) UI which has been set up for SSL connections.
I have a java app which is able to connect to the redis database using Jedis.
This works:
Jedis jedis = new Jedis(redisInfo.getHost(), redisInfo.getPort(), useSsl);
// make the connection
jedis.connect();
// authorize with our password
jedis.auth(redisInfo.getPassword());
Env vars:
"-Djavax.net.ssl.keyStoreType=PKCS12 -Djavax.net.ssl.keyStorePassword=iloveredis -Djavax.net.ssl.keyStore=$PWD/META-INF/clientKeyStore.p12 -Djavax.net.ssl.trustStoreType=JKS -Djavax.net.ssl.trustStorePassword=iloveredis -Djavax.net.ssl.trustStore=$PWD/META-INF/clientTrustStore.jks"
I also have a Spring Boot app in which I'm trying to connect to the Redis db using JedisConnectionFactory, and I'm not able to. (Using the same app, I am able to connect to a Redis db which does not have SSL enabled).
In my pom.xml:
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>2.1.4.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
In my redis configuration file:
#Configuration
#EnableRedisRepositories
public class RedisConfig {
#Bean
JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration redisConfig = new RedisStandaloneConfiguration();
redisConfig.setHostName(redisInfo.getHost());
redisConfig.setPort(redisInfo.getPort());
redisConfig.setPassword(RedisPassword.of(redisInfo.getPassword()));
boolean useSsl = env.getProperty("spring.redis.ssl", Boolean.class);
JedisClientConfiguration jedisConfig;
if (useSsl) {
jedisConfig = JedisClientConfiguration
.builder()
.useSsl()
.build();
} else {
jedisConfig = JedisClientConfiguration
.builder()
.build();
}
JedisConnectionFactory jcf = new JedisConnectionFactory(redisConfig, jedisConfig);
return jcf;
}
#Bean
public RedisTemplate<?, ?> redisTemplateJedis() {
final RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
template.setConnectionFactory(jedisConnectionFactory());
template.setValueSerializer(new Jackson2JsonRedisSerializer<Object>(Object.class));
return template;
}
This is the error I’m getting:
org.springframework.data.redis.RedisConnectionFailureException: Cannot get Jedis connection; nested exception is redis.clients.jedis.exceptions.JedisDataException: ERR unencrypted connection is prohibited
One other point is that for testing purposes, both the server and app are using self-signed certificates (which work with Jedis).
I do not know how to configure JedisConfigurationFactory so that I don't get this error.
Edited.
To recap, I could connect to Redis with SSL enabled with Jedis the library, but not the Spring library JedisConnectionFactory.
I was trying this in Pivotal Cloud Foundry (PCF).
I wrote to Mark Paluch, author of spring-data-redis, and he suggested I turn off auto-reconfiguration to get it to work in PCF.
I found this page on turning off auto-reconfiguration:
https://docs.cloudfoundry.org/buildpacks/java/configuring-service-connections/spring-service-bindings.html#manual
Cloud Foundry will automatically create a RedisConnectionFactory bean for you, so my JedisConnectionFactory was not getting used.
I had to turn off auto-reconfiguration. Or rather turn on manual configuration.
My JedisConnectionFactory bean (with SSL enabled) then started getting instantiated (along with the cloud service connector’s RedisConnectionFactory bean).
And I had to set my JedisConnectionFactory bean to Primary as there were now two connection factory beans.
I was also getting exceptions about unexpected end of stream.
I had to turn on usePoolingin JedisClientConfiguration.
This is where I posted to jira about the issue (now moved to github):
https://github.com/spring-projects/spring-data-redis/issues/1542

Elasticsearch RestHighLevelClient (6.0.0) -- TimeoutException on runtime

Our application encoutner timeout exception while indexing(store) document in elasticsearch server. It do not frequently happen but approximately once a day. Here are details.
pom.xml
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.0.0</version>
</dependency>
initialization
#Bean
public RestHighLevelClient buildHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(httplist.toArray(new HttpHost[]{})));
return client;
}
exception information
java.lang.RuntimeException: error while performing request
at org.elasticsearch.client.RestClient$SyncResponseListener.get(RestClient.java:682)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:220)
at org.elasticsearch.client.RestClient.performRequest(RestClient.java:192)
at org.elasticsearch.client.RestHighLevelClient.performRequest(RestHighLevelClient.java:428)
at org.elasticsearch.client.RestHighLevelClient.performRequestAndParseEntity(RestHighLevelClient.java:414)
at org.elasticsearch.client.RestHighLevelClient.bulk(RestHighLevelClient.java:229)
......
Caused by: java.util.concurrent.TimeoutException
at org.apache.http.nio.pool.AbstractNIOConnPool.processPendingRequest(AbstractNIOConnPool.java:364)
at org.apache.http.nio.pool.AbstractNIOConnPool.processNextPendingRequest(AbstractNIOConnPool.java:344)
at org.apache.http.nio.pool.AbstractNIOConnPool.release(AbstractNIOConnPool.java:318)
at org.apache.http.impl.nio.conn.PoolingNHttpClientConnectionManager.releaseConnection(PoolingNHttpClientConnectionManager.java:303)
at org.apache.http.impl.nio.client.AbstractClientExchangeHandler.releaseConnection(AbstractClientExchangeHandler.java:239)
I worked around the issue with the following setting:
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "http")); builder.setRequestConfigCallback(
new RestClientBuilder.RequestConfigCallback() {
#Override
public RequestConfig.Builder customizeRequestConfig(
RequestConfig.Builder requestConfigBuilder) {
return requestConfigBuilder.setConnectionRequestTimeout(-1);
}
});
The underlying Apache RestClient has a limitation of AFAIK 10 concurrent connections in its connection pool. So if there are more then 10 concurrent requests, additional requests get queued and might hit the default DEFAULT_CONNECTION_REQUEST_TIMEOUT_MILLIS = 500; set in org.elasticsearch.client.RestClientBuilder

Resources