Request processing failed; nested exception is feign.RetryableException: Read timed out executing POST - spring-cloud-feign

I have made POST call with feignClient with "XYZ" object request message, then I didn't get response within "5" seconds (This is expected), so I sent "ERROR" object request to the same service but I didn't get any response and causing below error.
Request processing failed; nested exception is feign.RetryableException: Read timed out executing POST xyz.com/third-party/abc/1212 with root cause java.net.SocketTimeoutException: Read timed out
Code:
try {
ResponseEntity<Object> successResponseEntity = sapService.callService(XYZ);
} catch (RetryableException e) {
ResponseEntity<Object> errorResponseEntity = sapService.callService(ERROR);
}
// fiegn client
#FeignClient(name = "sapService", url = "${abc.url}", configuration = FeignClientInterceptorConfiguration.class)
public interface SapService {
#PostMapping(path = "${endpoint}")
ResponseEntity<Object> callService(#PathVariable(value = "name") String name, #RequestBody Object request);
}
public class FeignClientInterceptorConfiguration {
#Bean
public Retryer retryer(ApplicationContext applicationContext) {
return Retryer.NEVER_RETRY;
}
}
Application.yaml
feign:
client:
config:
SapService:
readTimeout: 5000
connectTimeout: 5000

Related

WebClientReactiveJwtBearerTokenResponseClient failing to parse successful response

I am assuming that its because of the specified body extractor, just wondering what part of the response is incorrect or if there is a different token response class.
var client = new WebClientReactiveJwtBearerTokenResponseClient();
client.setBodyExtractor(BodyExtractors.toMono(OAuth2AccessTokenResponse.class));
...
LOG.info("Response: {}", client
.getTokenResponse(request)
.onErrorMap(e -> {
LOG.error("Error is {}", e.getMessage());
return e;}
)
.block());
It fails with
Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.security.oauth2.core.OAuth2AccessToken.getScopes()" because the return value of "org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse.getAccessToken()" is null
at org.springframework.security.oauth2.client.endpoint.AbstractWebClientReactiveOAuth2AccessTokenResponseClient.populateTokenResponse(AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java:240) ~[spring-security-oauth2-client-5.7.6.jar:5.7.6]
at org.springframework.security.oauth2.client.endpoint.AbstractWebClientReactiveOAuth2AccessTokenResponseClient.lambda$readTokenResponse$3(AbstractWebClientReactiveOAuth2AccessTokenResponseClient.java:228) ~[spring-security-oauth2-client-5.7.6.jar:5.7.6]
but, the access token is in the response which looks like
{
"access_token":"00D8K0000004cbe!AQgAQGO6yn3qEnI_QJJTsQHT5SyYt75M_o0QW9YdKDoj4L_r3wQir3P4zkCFal.I0oeNciySYsw52VazmZV_5LVy",
"scope":"api full",
"instance_url":"https://example.org",
"id":"00D8K0000004cbeUAA/0055f000008GSREAA4",
"token_type":"Bearer"
}

netty-readtimeout and return customized response to front end

I have a question regarding configuration of timeouts on a netty TCP server.
Currently we have configured readTimeOut as 120s. Set the connect timout like this:
socketChannel.pipeline().addLast(new ReadTimeoutHandler(120, TimeUnit.SECONDS));
But if the read time exceeds 120s, service doesn't response to front end correctly. If tested from postman, got the "Could not get any response" as response.
Following is the netty config we using:
public class EventLoopNettyCustomizer implements NettyServerCustomizer {
#Override
public HttpServer apply(HttpServer httpServer) {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workGroup = new NioEventLoopGroup();
return httpServer.tcpConfiguration(tcpServer -> tcpServer
.bootstrap(serverBootstrap -> serverBootstrap
.group(bossGroup, workGroup)
.option(ChannelOption.SO_BACKLOG, 10000)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000)
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new ReadTimeoutHandler(120, TimeUnit.SECONDS));
socketChannel.pipeline().addLast(new WriteTimeoutHandler(120, TimeUnit.SECONDS));
}
})
.channel(NioServerSocketChannel.class)));
}
}
How can I config the netty so that it is able to return customized response? Including http status and message.

Jenkins Docker container - 403 no valid crumb was included in the request

I'm setting up my Jenkins server, and on simple requests in the web interface, like creating a folder, a pipeline, a job, etc., I periodically get the following error:
HTTP ERROR 403
Problem accessing /job/Mgmt/createItem. Reason:
No valid crumb was included in the request
The server is using the Jenkins/Jenkins container, orchestrated by Kubernetes on a cluster on AWS created with kops. It sits behind a class ELB.
Why might I be experiencing this? I thought the crumb was to combat certain CSRF requests, but all I'm doing is using the Jenkins web interface.
Enabling proxy compatibility may help to solve this issue.
Go to Settings -> Security -> Enable proxy compatibility in CSRF Protection section
Some HTTP proxies filter out information that the default crumb issuer uses to calculate the nonce value. If an HTTP proxy sits between your browser client and your Jenkins server and you receive a 403 response when submitting a form to Jenkins, checking this option may help. Using this option makes the nonce value easier to forge.
After a couple of hours of struggling, I was able to make it work with curl:
export JENKINS_URL=http://localhost
export JENKINS_USER=user
export JENKINS_TOKEN=mytoken
export COOKIE_JAR=/tmp/cookies
JENKINS_CRUMB=$(curl --silent --cookie-jar $COOKIE_JAR $JENKINS_URL'/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)' -u $JENKINS_USER:$JENKINS_TOKEN)
echo $JENKINS_CRUMB
curl --cookie $COOKIE_JAR $JENKINS_URL/createItem?name=yourJob --data-binary #jenkins/config.xml -H $JENKINS_CRUMB -H "Content-Type:text/xml" -u $JENKINS_USER:$JENKINS_TOKEN -v
when calling the http://JENKINS_SERVER:JENKINS_PORT/JENKINS_PREFIX/crumbIssuer/api/json you receive a header ("Set-Cookie") to set a JSESSIONID, so you must supply it in the upcoming requests you issue,
the reason is that jenkins test for valid crumb in this manner: comparing the crumb you send in the request with a crumb it generates on the server side (using your session id),
you can see it in jenkins code: scroll down to method:
public boolean validateCrumb(ServletRequest request, String salt, String crumb)
it means you HAVE to include a session in the next requests (after fetching the crumb)!
so the curl --cookie must be used as ThiagoAlves stated in his solution
i use java so i used this next tester (HTTPClient would be prefered, but i wanted a simple java only example):
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;
public class JobRunner
{
String jenkinsUser = "tester";
String jenkinsPassword = "1234"; // password or API token
String jenkinsServer = "localhost";
String jenkinsPort = "8080";
String jenkinsPrefix = "/jenkins";
String jSession = null;
String crumb = null;
HttpURLConnection connection = null;
String responseBody = "";
public void openConnection(String requestMethod, String relativeURL) throws Exception
{
// prepare the authentication string
String authenticationString = jenkinsUser + ":" + jenkinsPassword;
String encodedAuthenticationString = Base64.getEncoder().encodeToString(authenticationString.getBytes("utf-8"));
// construct the url and open a connection to it
URL url = new URL("http://" + jenkinsServer + ":" + jenkinsPort + jenkinsPrefix + relativeURL);
connection = (HttpURLConnection) url.openConnection();
// set the login info as a http header
connection.setRequestProperty("Authorization", "Basic " + encodedAuthenticationString);
// set the request method
connection.setRequestMethod(requestMethod);
}
public void readResponse() throws Exception
{
// get response body and set it in the body member
int responseCode = connection.getResponseCode();
switch (responseCode)
{
case 401:
System.out.println("server returned 401 response code - make sure your user/password are correct");
break;
case 404:
System.out.println("server returned 404 response code - make sure your url is correct");
break;
case 201:
case 200:
System.out.println("server returned " + responseCode + " response code");
InputStream responseBodyContent = connection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(responseBodyContent));
String currentLine;
while ((currentLine = bufferedReader.readLine()) != null)
{
responseBody = responseBody + currentLine + "\n";
}
break;
default:
System.out.println("server returned error response code: " + responseCode);
break;
}
}
public void setSessionCookie() throws Exception
{
jSession = connection.getHeaderField("Set-Cookie");
System.out.println("jSession: " + jSession);
}
public void disconnect() throws Exception
{
if(connection!=null)
{
connection.disconnect();
connection = null;
responseBody = "";
}
}
public void getCrumb() throws Exception
{
try
{
openConnection("GET", "/crumbIssuer/api/json");
readResponse();
setSessionCookie();
int crumbIndex = responseBody.indexOf("crumb\":\"");
if(crumbIndex!=-1)
{
int crumbIndexEnd = responseBody.indexOf("\",\"", crumbIndex);
crumb = responseBody.substring(crumbIndex + "crumb\":\"".length(), crumbIndexEnd);
System.out.println(crumb);
}
}
finally
{
disconnect();
}
}
public void runJob() throws Exception
{
try
{
openConnection("POST", "/job/test/build");
connection.setDoOutput(true);
connection.setRequestProperty("Cookie", jSession);
connection.setRequestProperty("Jenkins-Crumb", crumb);
readResponse();
System.out.println("Post response: " + responseBody);
}
finally
{
disconnect();
}
}
public static void main(String[] args)
{
JobRunner jobRunner = new JobRunner();
try
{
jobRunner.getCrumb();
jobRunner.runJob();
}
catch (Exception err)
{
err.printStackTrace();
}
}
}

Volley android "javax.net.ssl.SSLHandshakeException: Handshake failed"

Hi I'm rebuilding a API call using volley library
this is my test code to send XML data and receive xml response (I just need to successfully receive response in string format)
String url ="https://prdesb1.singpost.com/ma/FilterOverseasPostalInfo";
final String payload = "<OverseasPostalInfoDetailsRequest xmlns=\"http://singpost.com/paw/ns\"><Country>AFAFG</Country><Weight>100</Weight><DeliveryServiceName></DeliveryServiceName><ItemType></ItemType><PriceRange>999</PriceRange><DeliveryTimeRange>999</DeliveryTimeRange></OverseasPostalInfoDetailsRequest>\n";
RequestQueue mRequestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
// Start the queue
mRequestQueue.start();
// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Do something with the response
Log.v("tesResponse","testResponseS");
Log.v("response",response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Handle error
Log.v("tesResponse","testResponseF");
Log.v("error",error.toString());
}
}
){
#Override
public String getBodyContentType() {
return "application/xml; charset=" +
getParamsEncoding();
}
#Override
public byte[] getBody() throws AuthFailureError {
String postData = payload;
try {
return postData == null ? null :
postData.getBytes(getParamsEncoding());
} catch (UnsupportedEncodingException uee) {
// TODO consider if some other action should be taken
return null;
}
}
};
// stringRequest.setRetryPolicy(new DefaultRetryPolicy(5*DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0));
stringRequest.setRetryPolicy(new DefaultRetryPolicy(0, 0, 0));
// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
I have test the String url and the payload on POSTMAN and give successful result. But don't know why my android app give this error
08-22 19:44:24.335 16319-16518/com.example.victory1908.test1 D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 08-22 19:44:24.355 16319:16319 D/ ]
HostConnection::get() New Host Connection established 0x7f67de64eac0, tid 16319
[ 08-22 19:44:24.399 16319:16518 D/ ]
HostConnection::get() New Host Connection established 0x7f67de64edc0, tid 16518
08-22 19:44:24.410 16319-16518/com.example.victory1908.test1 I/OpenGLRenderer: Initialized EGL, version 1.4
08-22 19:44:24.662 16319-16319/com.example.victory1908.test1 V/tesResponse: testResponseF
08-22 19:44:24.662 16319-16319/com.example.victory1908.test1 V/error: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Handshake failed
Just notice problem only with API 23+ (android 6.0 and above) API 22 is working fine!
I have tried set the retry policy but does not work. Anyone know what wrong with the code. Thanks in advance

Spring not allowing RequestMethod.DELETE

I have this endpoint that invoke my service method which in turn call my repo class to Delete a user, but when i call this endpoint through postman i get a request Method not supported" printed in the console,any help would be greatly appreciated
#RequestMapping(value = "/{useId}/delete-user", method = RequestMethod.DELETE)
public ResponseEntity<String> deleteUser(#PathVariable("userId") String userId){
ResponseEntity<String> response = null;
try {
validate(userId);
userService.deleteUser(Long.parseLong(userId));
response = new ResponseEntity<String>(HttpStatus.NO_CONTENT);
}catch (InputMismatchException e){
response = new ResponseEntity<String>(HttpStatus.BAD_REQUEST);
} catch (UserNotFoundException e) {
response = new ResponseEntity<String>(HttpStatus.NOT_FOUND);
} catch (AccessDeniedException e) {
response = new ResponseEntity<String>(HttpStatus.FORBIDDEN);
}
return response;
}
The message received is Request method 'DELETE' not supported
There is a typo in the #RequestMapping. userid is misspelled. That is why Spring is not mapping the DELETE to deleteUser method

Resources