DataFlowTemplate response does not return body - spring-cloud

Considering the test07 stream is already created the following code snippet won't get response body in the exception stack trace.
try {
URI dataFlowUri = URI.create("http://localhost:9393");
DataFlowOperations dataFlowOperations = new DataFlowTemplate(dataFlowUri);
StreamDefinition streamDefinition = Stream.builder(dataFlowOperations)
.name("test07")
.definition("time|log")
.create();
}
catch (Exception ex){
ex.printStackTrace();
}
org.springframework.web.client.HttpClientErrorException$Conflict: 409 : [no body]
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:125)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:184)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:125)
at org.springframework.cloud.dataflow.rest.client.VndErrorResponseErrorHandler.handleError(VndErrorResponseErrorHandler.java:62)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:782)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:740)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:418)
at org.springframework.cloud.dataflow.rest.client.StreamTemplate.createStream(StreamTemplate.java:121)
at org.springframework.cloud.dataflow.rest.client.dsl.StreamDefinition.(StreamDefinition.java:60)
at org.springframework.cloud.dataflow.rest.client.dsl.Stream$StreamDefinitionBuilder.create(Stream.java:400)
on other hand when Post request this directly
http://localhost:9393/streams/definitions?name=test07&definition=time%20%7C%20log&description=test07
the response as follow with status code 409
[
{
"logref": "DuplicateStreamDefinitionException",
"message": "Cannot create stream test07 because another one has already been created with the same name"
}
]
I want to get response body when exception occur
so anyone can help if I'm missing something here?

I had to override the default rest template to get the response body as desired.
ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
RestTemplate restTemplate = new RestTemplate(factory);
URI dataFlowUri = URI.create("http://localhost:9393");
DataFlowOperations dataFlowOperations = new DataFlowTemplate(dataFlowUri, restTemplate);
StreamDefinition streamDefinition = Stream.builder(dataFlowOperations)
.name("test07")
.definition("time|log")
.create();
thanks

Related

Karate ApacheHttpClient Response is failing with error com.intuit.karate - Runtimejava.io.IOException: Attempted read from closed stream

Reference: java.io.IOException: Attempted read from closed stream
Reference: https://github.com/karatelabs/karate/blob/master/karate-core/src/main/java/com/intuit/karate/http/ApacheHttpClient.java
KarateCore - class file: ApacheHttpClient.java is unable to process the Response its failing at the code line
CloseableHttpClient client = clientBuilder.build();
CloseableHttpResponse httpResponse;
byte [] bytes;
try {
httpResponse = client.execute(requestBuilder.build());
HttpEntity responseEntity = httpResponse.getEntity();
if (responseEntity == null || responseEntity.getContent() == null) {
bytes = Constants.ZERO_BYTES;
} else {
**InputStream is = responseEntity.getContent();**
bytes = FileUtils.toBytes(is);
}
request.setEndTimeMillis(System.currentTimeMillis());
} catch (Exception e) {
if (e instanceof ClientProtocolException && e.getCause() != null) { // better error message
throw new RuntimeException(e.getCause());
} else {
throw new RuntimeException(e);
}
}
The Code is failing at line InputStream is = responseEntity.getContent(); when trying to read from a closed stream. The exception message displayed
Error com.intuit.karate - Runtimejava.io.IOException: Attempted read from closed stream.
May be the InputStream need to updated.
I am able read the Http Response content using below code
BufferedReader br = new BufferedReader(
new InputStreamReader((httpResponse.getEntity().getContent())));
String output;
while ((output = br.readLine()) != null){
output = br,readLine();
System.out.println(output);
}
Also the able to read the response using EntityUtils as a string content
String content = EntityUtils.toString(responseEntity);
System.out.println(content);
Not sure if i am missing something in the feature:scenario file response or the ApacheHttpClient.java file need to updated to read InputStream and then convert to bytes.
Feature: Hello
Scenario: Rest API Post
Given url 'some url path'
And header Content-Type = 'application/json'
And request { username: 'abc', password: 'pwd' }
When method POST
Then status 200
And print 'Response is:', response
The expected Response is a JSON format as:
{
"accessToken": "akjdoioikf",
"expires":"2020-01-29T01:09:48Z"
}
Any suggestions, appreciated!

ErrorDecoder not catching SocketTimeoutException

With feign builder I am making call to external URL. I have set readTimeout as 2seconds, I am getting the SocketTimeoutException but it's not going to ErrorDecoder.
Feign Builder Configuration:
Options options = new Options(10000, TimeUnit.MILLISECONDS, 2000,
TimeUnit.MILLISECONDS, false);
return Feign.builder()
.logLevel(level)
.client(client)
.retryer(Retryer.NEVER_RETRY)
.options(options)
.errorDecoder(feignErrorDecoder())
.exceptionPropagationPolicy(UNWRAP);
private ErrorDecoder feignErrorDecoder() {
return (methodKey, response) -> {
return new MyCustomException("ERROR_TIMEOUT",
"Timeout Occurred: " + response.status());
};
}
When I call service exception is not going to ErrorDecoder. java.lang.reflect.UndeclaredThrowableException coming.
ErrorDecoder is not called when an IOException (SocketTimeoutException) is thrown. See SynchronousMethodHandler#executeAndDecode(...). In general decoders are only called when a response is returend by the api-call. The ErrorCoder is only called when the http error code is not 2xx and 4xx.

http client failing to call service with jearsey multipart as an argument

Trying to hit Jersey multipart service with httpclient, and seeing some issues. Could you please share your insights to resolve this issue. Below I posted client code, service, stack trace.
Thanks for your support.
It works good when I use below client and register classes. Not finding any facility to register these classes for http client.
javax.ws.rs.client.Client
client.register(JacksonJsonProvider.class);
client.register(MultiPartFeature.class);
CLIENT CODE:
final String CONTENT_TYPE_MULTIPART = "multipart/related";
final String CONTENT_TYPE = "application/octet-stream";
final String BOUNDARY = "--upload_boundary--";
String responseStr = "";
MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
multipartEntityBuilder.addBinaryBody("file_upload", inputStream, ContentType.create(CONTENT_TYPE), "filename");
HttpPost httpPost = new HttpPost(finalURL);
httpPost.setHeader(HttpHeaders.CONTENT_TYPE, CONTENT_TYPE_MULTIPART);//+";type="+CONTENT_TYPE+";boundary="+BOUNDARY);
httpPost.setEntity(multipartEntityBuilder.build());
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpPost);
HttpEntity entity = response.getEntity();
responseStr = entity.toString();
RestHelper.verifyResponse(response, responseStr);
} catch (ClientProtocolException e) {
LOGGER.error("ClientProtocolException during upload",e);
} catch (IOException e) {
LOGGER.error("IOException during upload",e);
} finally {
response.close();
httpclient.close();
}
REST SERVICE:
#Consumes(MULTIPART_RELATED)
public String addDocument(MultiPart multipart)
STACKTRACE:
httpResponse :::::::::::::::::::: HttpResponseProxy{HTTP/1.1 400 Bad Request [Content-Type: text/html;charset=ISO-8859-1, $WSEP: , Content-Language: en-US, Transfer-Encoding: chunked, X-Cnection: Close, Date: Mon, 10 May 2021 11:50:32 GMT, Set-Cookie: dev-issapps.us=2036276652.6195.0000; path=/; Httponly] ResponseEntityProxy{[Content-Type: text/html;charset=ISO-8859-1,Chunked: true]}}
17:20:32.220 [main] ERROR us.dc.httpproxy.RestHelper - Response Error: RestException{us.dc.httpproxy.RestException
: HTTP/1.1 400 Bad Request', statusCode=400, detail='ResponseEntityProxy{[Content-Type: text/html;charset=ISO-8859-1,Chunked: true]}'}
17:20:32.221 [main] ERROR us.dc.httpproxy.RestClient - Exception in executeMultiPartRequest http://XXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXX/api/applications/GWEW/documents
RestException{ us.dc.httpproxy.RestException: HTTP/1.1 400 Bad Request', statusCode=400, detail='ResponseEntityProxy{[Content-Type: text/html;charset=ISO-8859-1,Chunked: true]}'}
Here is the solution, hope it helps somebody:
compile group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.5.13'
compile group: 'org.apache.httpcomponents', name: 'httpmime', version: '4.5.3'
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
File file = new File("src/main/resources/48-1.jpg");
MultipartEntityBuilder entitybuilder = MultipartEntityBuilder.create();
entitybuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
entitybuilder.addBinaryBody("image", new FileInputStream(file), ContentType.APPLICATION_OCTET_STREAM, file.getName());
entitybuilder.setContentType(ContentType.create("multipart/related"));
HttpEntity mutiPartHttpEntity = entitybuilder.build();
RequestBuilder reqbuilder = RequestBuilder.post(url);
reqbuilder.setEntity(mutiPartHttpEntity);
HttpUriRequest multipartRequest = reqbuilder.build();
HttpResponse httpresponse = httpclient.execute(multipartRequest);
System.out.println("response status = " + httpresponse.getStatusLine().getStatusCode());
System.out.println("filenet id = " + EntityUtils.toString(httpresponse.getEntity()));
}catch(Exception e) {
e.printStackTrace();
}

RESTful client in Unity - validation error

I have a RESTful server created with ASP.Net and am trying to connect to it with the use of a RESTful client from Unity. GET works perfectly, however I am getting a validation error when sending a POST request. At the same time both GET and POST work when sending requests from Postman.
My Server:
[HttpPost]
public IActionResult Create(User user){
Console.WriteLine("***POST***");
Console.WriteLine(user.Id+", "+user.sex+", "+user.age);
if(!ModelState.IsValid)
return BadRequest(ModelState);
_context.Users.Add(user);
_context.SaveChanges();
return CreatedAtRoute("GetUser", new { id = user.Id }, user);
}
My client:
IEnumerator PostRequest(string uri, User user){
string u = JsonUtility.ToJson(user);
Debug.Log(u);
using (UnityWebRequest webRequest = UnityWebRequest.Post(uri, u)){
webRequest.SetRequestHeader("Content-Type","application/json");
yield return webRequest.SendWebRequest();
string[] pages = uri.Split('/');
int page = pages.Length - 1;
if (webRequest.isNetworkError || webRequest.isHttpError){
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
}
else{
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
}
}
}
I was trying both with the Json conversion and writing the string on my own, also with the WWWForm, but the error stays.
The error says that it's an unknown HTTP error. When printing the returned text it says:
"One or more validation errors occurred.","status":400,"traceId":"|b95d39b7-4b773429a8f72b3c.","errors":{"$":["'%' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0."]}}
On the server side it recognizes the correct method and controller, however, it doesn't even get to the first line of the method (Console.WriteLine). Then it says: "Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'".
Here're all of the server side messages:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5001/user application/json 53
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "Create", controller = "User"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Create(TheNewestDbConnect.Data.Entities.User) on controller TheNewestDbConnect.Controllers.UserController (TheNewestDbConnect).
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed action TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect) in 6.680400000000001ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 11.3971ms 400 application/problem+json; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
I have no idea what is happening and how to solve it. Any help will be strongly appreciated!
Turned out I was just missing an upload handler. Adding this line solved it: webRequest.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(JsonObject));

Groovy script for Jenkins: execute HTTP request without 3rd party libraries

I need to create a Groovy post build script in Jenkins and I need to make a request without using any 3rd party libraries as those can't be referenced from Jenkins.
I tried something like this:
def connection = new URL( "https://query.yahooapis.com/v1/public/yql?q=" +
URLEncoder.encode(
"select wind from weather.forecast where woeid in " + "(select woeid from geo.places(1) where text='chicago, il')",
'UTF-8' ) )
.openConnection() as HttpURLConnection
// set some headers
connection.setRequestProperty( 'User-Agent', 'groovy-2.4.4' )
connection.setRequestProperty( 'Accept', 'application/json' )
// get the response code - automatically sends the request
println connection.responseCode + ": " + connection.inputStream.text
but I also need to pass a JSON in the POST request and I'm not sure how I can do that. Any suggestion appreciated.
Executing POST request is pretty similar to a GET one, for example:
import groovy.json.JsonSlurper
// POST example
try {
def body = '{"id": 120}'
def http = new URL("http://localhost:8080/your/target/url").openConnection() as HttpURLConnection
http.setRequestMethod('POST')
http.setDoOutput(true)
http.setRequestProperty("Accept", 'application/json')
http.setRequestProperty("Content-Type", 'application/json')
http.outputStream.write(body.getBytes("UTF-8"))
http.connect()
def response = [:]
if (http.responseCode == 200) {
response = new JsonSlurper().parseText(http.inputStream.getText('UTF-8'))
} else {
response = new JsonSlurper().parseText(http.errorStream.getText('UTF-8'))
}
println "response: ${response}"
} catch (Exception e) {
// handle exception, e.g. Host unreachable, timeout etc.
}
There are two main differences comparing to GET request example:
You have to set HTTP method to POST
http.setRequestMethod('POST')
You write your POST body to outputStream:
http.outputStream.write(body.getBytes("UTF-8"))
where body might be a JSON represented as string:
def body = '{"id": 120}'
Eventually it's good practice to check what HTTP status code returned: in case of e.g. HTTP 200 OK you will get your response from inputStream while in case of any error like 404, 500 etc. you will get your error response body from errorStream.