I am writing some kind of integration test on my REST controller using MockRestServiceServer to mock backend behaviour.
What I am trying to achieve now is to simulate very slow response from backend which would finally lead to timeout in my application. It seems that it can be implemented with WireMock but at the moment I would like to stick to MockRestServiceServer.
I am creating server like this:
myMock = MockRestServiceServer.createServer(asyncRestTemplate);
And then I'm mocking my backend behaviour like:
myMock.expect(requestTo("http://myfakeurl.blabla"))
.andExpect(method(HttpMethod.GET))
.andRespond(withSuccess(myJsonResponse, MediaType.APPLICATION_JSON));
Is it possible to add some kind of a delay or timeout or other kind of latency to the response (or maybe whole mocked server or even my asyncRestTemplate)? Or should I just switch to WireMock or maybe Restito?
You can implement this test functionality this way (Java 8):
myMock
.expect(requestTo("http://myfakeurl.blabla"))
.andExpect(method(HttpMethod.GET))
.andRespond(request -> {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(1));
} catch (InterruptedException ignored) {}
return new MockClientHttpResponse(myJsonResponse, HttpStatus.OK);
});
But, I should warn you, that since MockRestServiceServer simply replaces RestTemplate requestFactory any requestFactory settings you'd make will be lost in test environment.
If you control timeout in your http client and use for example 1 seconds you can use mock server delay
new MockServerClient("localhost", 1080)
.when(
request()
.withPath("/some/path")
)
.respond(
response()
.withBody("some_response_body")
.withDelay(TimeUnit.SECONDS, 10)
);
If you want to drop connection in Mock Server use mock server error action
new MockServerClient("localhost", 1080)
.when(
request()
.withPath("/some/path")
)
.error(
error()
.withDropConnection(true)
);
Approach that you can go for:
Specifying the responsebody either with Class Path resource or normal string content. More detailed version of what Skeeve suggested above
.andRespond(request -> {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(5)); // Delay
} catch (InterruptedException ignored) {}
return withStatus(OK).body(responseBody).contentType(MediaType.APPLICATION_JSON).createResponse(request);
});
In Restito, there is a buil-in function to simulate timeout:
import static com.xebialabs.restito.semantics.Action.delay
whenHttp(server).
match(get("/something")).
then(delay(201), stringContent("{}"))
In general, you can define your custom request handler, and do a nasty Thread.sleep() there.
This would be possible in Restito with something like this.
Action waitSomeTime = Action.custom(input -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return input;
});
whenHttp(server).match(get("/asd"))
.then(waitSomeTime, ok(), stringContent("Hello World"))
Not sure about Spring, however. You can easily try. Check DefaultResponseCreator for inspiration.
Related
My current Lambda function is calling a 3rd party web service Synchronously.This function occasionally times out (current timeout set to 25s and cannot be increased further)
My code is something like:
handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
try{
response = calling 3rd party REST service
}catch(Exception e){
//handle exceptions
}
}
1)I want to custom handle the timeout (tracking the time and handling few milli seconds before actual timeout) within my Lambda function by sending a custom error message back to the client.
How can I effectively use the
context.getRemainingTimeInMillis()
method to track the time remaining while my synchronous call is running? Planning to call the context.getRemainingTimeInMillis() asynchronously.Is that the right approach?
2)What is a good way to test the timeout custom functionality ?
I solved my problem by increasing the Lambda timeout and invoking my process in a new thread and timing out the Thread after n seconds.
ExecutorService service = Executors.newSingleThreadExecutor();
try {
Runnable r = () ->{
try {
myFunction();
} catch (Exception e) {
e.printStackTrace();
}
};
f = service.submit(r);
f.get(n, TimeUnit.MILLISECONDS);// attempt the task for n milliseconds
}catch(TimeoutException toe){
//custom logic
}
Another option is to use the
readTimeOut
property of the RestClient(in my case Jersey) to set the timeout.But I see that this property is not working consistently within the Lambda code.Not sure if it's and issue with the Jersey client or the Lambda.
You can try with cancellation token to return custom exceptions with lambda before timeout.
try
{
var tokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(1)); // set timeout value
var taskResult = ApiCall(); // call web service method
while (!taskResult.IsCompleted)
{
if (tokenSource.IsCancellationRequested)
{
throw new OperationCanceledException("time out for lambda"); // throw custom exceptions eg : OperationCanceledException
}
}
return taskResult.Result;
}
catch (OperationCanceledException ex)
{
// handle exception
}
I am trying to connect to a message queue running on a docker container using Reactor Netty. I am doing this as standalone, not using SpringFlux because of dependency issues.
From the examples in the Reactor Netty documentation I saw there is a way to connect to the Server and get a response:
public static void main(String[] args) {
String response =
HttpClient.create()
.headers(h -> h.add("my header", my_header)
.get()
.uri(my_uri)
.responseContent()
.aggregate()
.asString()
.block();
}
but when I try afterwards to display the output via System.out.println() nothing happens.
I also tried to understand how to use:
Flux<V> response(BiFunction<HttpClientResponse,ByteBufFlux,Publisher<V>> receiver)
But I am not sure exactly what to do.
I saw in the documentation there is a class called Connection, which uses a TCPClient and has a method subscribe.
I am kind of lost, can you possibly point me in the right direction of implementing this in Reactor Netty without the use of spring-flux?
Thank you
EDIT:
After some experimentation i got this:
private Disposable subscribe() {
return HttpClient.create()
.headers(h -> h.add("my header", my_header)
.get()
.uri(my_uri)
.response((res, bytes) - > {
System.out.println(bytes.asString());
return bytes.asString();})
.subscribe();
}
This gives me a FluxHandle, how can I use that to actually read the body of the response?
So I figured out how to subscibe and read the data recieved from the Server and even transform the data to JSON, using the jackson library, to be more easily read by my code.
private Disposable subscribe() {
return HttpClient.create()
.headers(h -> h.add("my header", my_header)
.get()
.uri(my_uri)
.response((resp, bytes) -> {
return bytes.asString();
})
.subscribe(response -> {
try {
consumeData(new ObjectMapper()
.readValue(response, MyData.class));
} catch (IOException ex) {
System.out.println("ERROR converting to json: " + ex);
}
});
}
it seems that when using the subscribe() method i can listen to incoming responses and do something with them. I still need to add a way for the connection to close when the server stops, or the message queue is shut down, so the client doesn't hang on non-existent message queue.
I am trying to get a document from Couchbase using the below code:
public synchronized void initialize() {
CouchbaseEnvironment env =
DefaultCouchbaseEnvironment
.builder()
.connectTimeout(10000)
.build();
setBucket(proper
.getCluster()
.openBucket(proper.getBucket(),proper.getBucketPassword())
}
public JsonDocument findByDocumentId(String id) {
try {
return getBucket.get(id);
} catch (Exception e) {
e.printStackTrace(System.out);
}
}
I am able to retrieve 3 or 4 documents successfully, but then I receive a TimeoutException:
java.lang.RuntimeException: java.util.concurrent.TimeoutException
at com.couchbase.client.java.util.Blocking.blockForSingle(Blocking.java:93)
at com.couchbase.client.java.CouchbaseBucket.get(CouchbaseBucket.java:100)
at com.couchbase.client.java.CouchbaseBucket.get(CouchbaseBucket.java:95)
Why am I getting a timeout and how can I avoid it?
You can increase the Key / Value operation timeout using the kvTimeout(long) parameter when configuring your environment.
EG
CouchbaseEnvironment env =
DefaultCouchbaseEnvironment
.builder()
.kvTimeout(5000) //in ms
.build();
But I'd be concerned if you need to increase this and you're not stressing your system. This might point to poorly configured setup somewhere.
For a list of configurable options see http://developer.couchbase.com/documentation/server/4.0/sdks/java-2.2/env-config.html
Thread.sleep would help to avoid this issue.
We have to implement the wait time to next document read. This is not an solution but a work around.
As per my understanding, I want to follow the best practice for releasing the resources at the end to prevent any connection leaks. Here is my code in HelperClass.
public static DynamoDB getDynamoDBConnection()
{
try
{
dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
}
catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
dynamoDB.shutdown();
}
return dynamoDB;
}
My doubt is, since the finally block will be executed no matter what, will the dynamoDB returns empty connection because it will be closed in finally block and then execute the return statement? TIA.
Your understanding is correct. dynamoBD.shutdown() will always execute before return dynamoDB.
I'm not familiar with the framework you're working with, but I would probably organize the code as follows:
public static DynamoDB getDynamoDBConnection()
throws ApplicationSpecificException {
try {
return new DynamoDB(new AmazonDynamoDBClient(
new ProfileCredentialsProvider()));
} catch(AmazonServiceException ase) {
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
throw new ApplicationSpecificException("some good message", ase);
}
}
and use it as
DynamoDB con = null;
try {
con = getDynamoDBConnection();
// Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
// deal with it gracefully
} finally {
if (con != null)
con.shutdown();
}
You could also create an AutoCloseable wrapper for your dynamoDB connection (that calls shutdown inside close) and do
try (DynamoDB con = getDynamoDBConnection()) {
// Do whatever you need to do with con
} catch (ApplicationSpecificException e) {
// deal with it gracefully
}
Yes,dynamoDB will return an empty connection as dynamoBD.shutdow() will be executed before return statement, Always.
Although I am not answering your question about the finally block being executed always (there are several answers to that question already), I would like to share some information about how DynamoDB clients are expected to be used.
The DynamoDB client is a thread-safe object and is intended to be shared between multiple threads - you can create a global one for your application and re-use the object where ever you need it. Generally, the client creation is managed by some sort of IoC container (Spring IoC container for example) and then provided by the container to whatever code needs it through dependency injection.
Underneath the hood, the DynamoDB client maintains a pool of HTTP connections for communicating the DynamoDB endpoint and uses connections from within this pool. The various parameters of the pool can be configured by passing an instance of the ClientConfiguration object when constructing the client. For example, one of the parameters is the maximum number of open HTTP connections allowed.
With the above understanding, I would say that since the DynamoDB client manages the lifecycle of HTTP connections, resource leaks shouldn't really be concern of code that uses the DynamoDB client.
How about we "imitate" the error and see what happens ? This is what I mean:
___Case 1___
try{
// dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
throw new AmazonServiceException("Whatever parameters required to instantiate this exception");
} catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
//dynamoDB.shutdown();
slf4jLogger.info("Database gracefully shutdowned");
}
___Case 2___
try{
// dynamoDB = new DynamoDB(new AmazonDynamoDBClient(new ProfileCredentialsProvider()));
throw new Exception("Whatever parameters required to instantiate this exception");
} catch(AmazonServiceException ase)
{
//ase.printStackTrace();
slf4jLogger.error(ase.getMessage());
slf4jLogger.error(ase.getStackTrace());
slf4jLogger.error(ase);
}
catch (Exception e)
{
slf4jLogger.error(e);
slf4jLogger.error(e.getStackTrace());
slf4jLogger.error(e.getMessage());
}
finally
{
//dynamoDB.shutdown();
slf4jLogger.info("Database gracefully shutdowned");
}
These exercise could be a perfect place to use unit tests and more specifically mock tests. I suggest you to take a close look at JMockit, which will help you write such tests much more easily.
In my servlet, I am executing the following code:
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(3000).build();
CloseableHttpAsyncClient client = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();
try
{
client.start();
for (String request : preparedURLs)
{
client.execute(new HttpGet(request), new FutureCallback<HttpResponse>()
{
public void failed(Exception ex)
{
System.out.println("\n\nRequest Failed Due to : " + ex.getMessage());
}
public void completed(HttpResponse response)
{
System.out.println("\n\nRequest COMPLETED");
}
public void cancelled()
{
System.out.println("\n\nRequest CANCELLED");
}
});
System.out.println("\n\n" + request);
}
}
finally
{
System.out.println("\n*** Finally called ***\n\n");
client.close();
}
But I don't get any response at all. Following is printed in my catalina.out:
http://localhost:8080/servlet/?ps=true
http://localhost:8080/servlet/?ps=true
http://localhost:8080/servlet/?ps=false
*** Finally called ***
I have wrote this code, taking this as example from apache's official site.
I have only omitted the latch part. Is this some thing to do with latch?
If possible please explain the reason of failure too.
This latch that you have removed is actually the synchronization part of the example.
The idea of async client is to make some requests and wait for the responses on other thread. By removing the synchronization the execution directly passes to the finally block instead of waiting the responses and closes the HttpAsyncClient.
In order to get it back working add the latch code from the example.
This is the correct behaviour. You are creating a socket with a conditional Future, and then you proceed to close it without waiting for it.
The example code you linked use a "latch" variable to do so.
You may move the close code inside future callback, but probably this will confuse your waring.
Or you can use the same system of the example, with a shared synchronised counter (maybe just a final AtomicBoolean triggered by an aswer) and wait for it before continuing with your program flow, but that destroy the idea of using async call