Java commons-httpclient: Testing timeout values - java

Abstract: how do devs Integration TEST timeouts for http requests?
Backstory: My team is having issues related to unusually long lasting HTTP web requests. We use the commons-httpclient version 3 by Apache. The code looks similar to this:
PostMethod post = new PostMethod(endpoint);
post.getParams().setSoTimeout(someInt);
httpClient.executeMethod(post);
The time to complete this request is usually acceptable (2 seconds or so), but occasionally, we will see 50-60 second requests despite having our SO timeout set to 4 seconds. This prompted me to do some research and found that most people are setting Connection Timeouts ANNNNND SO timeouts. It appears that SO timeouts should be set lower (as they simply time the distance between bytes in transit) and the the connection timeout is what we originally planned to use (i.e. initial delay between request and 1st byte returned).
Here is the code we scraped and plan on using:
httpClient.getHttpConnectionManager().getParams()
.setConnectionTimeout(someInt);
httpClient.getHttpConnectionManager().getParams()
.setSoTimeout(someInt);
The main pain here is that we are unable to integration test this change. More precisely, we are confused on how to integration test the delays coming from a socket connection to a foreign server. After digging through the commons-httpclient, I see protected and private classes that we will have to reproduce (because they are unextendable and unusable from outside the class), mock and string together the classes to ultimately get down to the socket class in java (which relies on a java native method -- which we would also need to reproduce and inject via mocks -- something I dont see frequently at that level).
The reason I am reaching out to Stack Overflow is to see how others are testing this/not testing this. I want to avoid testing this functionality in a performance environment at all costs.
Another thought of mine was to set up a mockserver to respond to the httpclient with a programmable delay time. I haven't seen an example of that yet.

First of all, there is no such thing as unit testing http requests - that would be integration testing.
Secondly, you can use a tool like JMeter to send http requests and test whether the response is being received in a certain amount of time as shown here in JMeter.

Taking the mock server route, I managed to set up a small web server with an API endpoint that I could test against. Here is the related code:
Lightweight server setup:
TJWSEmbeddedJaxrsServer server = new TJWSEmbeddedJaxrsServer();
server.setPort(SERVER_PORT);
server.getDeployment().getResources().add(new TestResource());
server.start();
API Endpoint:
/**
* In order to test the timeout, the resource will be injected into an embedded server.
* Each endpoint should have a unique use case.
*/
#Path("tests")
public class TestResource {
#POST
#Produces({MediaType.APPLICATION_XML})
#Path("socket-timeout")
public Response testSocketTimeout() throws InterruptedException {
Thread.sleep(SOCKET_TIMEOUT_SLEEP);
return Response.ok().build();
}
}
Within the api endpoint related class, I can control the sleep timeout which then triggers a socket timeout within the httpclient class. Its a bit hacky, but it works to test the functionality in the way I wanted to (simple, lightweight and effective).

Related

Programmatically created Feign client and Eureka target

I have started a few days ago to learn about fault tolerance solutions in microservices. I have some microservices in my ecosystem and they are now interconnected with Eureka service lookup. I used FeignClient to call from one to another. As I heard and read, that Hystrix is getting into maintenance, I wondered if I could use Resilience4J in Feign instead of Hystrix. Well, at least not from annotation level right now as it seems. I found a great Feign.Builder adapter to add resilience4j fault tolerance features above a FeignClient as a decorator (https://github.com/resilience4j/resilience4j/tree/master/resilience4j-feign) so I wanted to use it.
So I used this, added together the features and added the default encoder, decoder, etc. items into the feign builder. Turns out I have to finish of course my code with a .target call which creates my client proxy and I could not really do this with Eureka in a good way:
The first constructor, which takes the class type and the URL is hardcoded, so if I add an eureka next server query into this parameter, it is just a hardcoded url for one of the instances, this is not load balanced. Some kinda workaround could be that I create prototype-scope or similar short lived scoped beans of this client and always get the "next url" for the call. This adds lots of burden to use the clients in every class I make. At least as I saw it. Maybe I could add some kind of singleton helper bean around the prototyping, but again this is not a good design as I see
I thought maybe I could create an EurekaTarget from the Target interface, but of course none of the methods indicate any "end of lifecycle" things, not even the apply method. I thought maybe that is one point which is called before doing a service call, but I saw multiple calls towards it so I had to change the url for all calls.
Do you know any better solution to do this migration?
I guess you are using Spring Boot?
The next version v1.0.0 of Resilience4j will support the #FeignClient annotation.
There was a PR which added the functionality -> https://github.com/resilience4j/resilience4j/pull/579
You can then use it as follows:
#FeignClient(name = DUMMY_FEIGN_CLIENT_NAME)
#CircuitBreaker(name = DUMMY_FEIGN_CLIENT_NAME)
public interface DummyFeignClient {
String DUMMY_FEIGN_CLIENT_NAME = "dummyFeignClient";
#GetMapping(path = "/api/{param}")
void doSomething(#PathVariable(name = "param") String param);
}

DropwizardAppRule ClassRule does not release connections after test completion

I have some integration tests for a RESTful application written in Java using Dropwizard. The test suite runs fine until eventually it hangs and I get an exception with C3P0PooledConnectionPoolManager: java.sql.SQLNonTransientConnectionException: Too many connections
I identified that the connections are not being cleaned up after each test using C3P0Registry.getPooledDataSources(), but I misdiagnosed the problem as not closing my jersey response entities, as detailed here: https://jersey.github.io/documentation/latest/client.html#d0e5255
Many of the tests are checking for just a status code, so it made sense to me that this would be happening (In the link it states: "If you don't read the entity, then you need to close the response manually by response.close()"). However, after fixing this problem and ensuring that each entity was closed, I'm still getting persistent connections between tests.
I'm using DropwizardAppRule as a Class Rule and after creation at the beginning and end of each test run, I can call to close the client that is associated with the rule, but the connections remain open. My C3P0ConnectionPool gains 3 connections per test class that is run and I can't figure out a way to stop it from growing with each new class that is added.
ClassRule snippet:
#ClassRule
public static final DropwizardAppRule<MicroServiceCoreConfiguration> RULE =
new DropwizardAppRule<>(App.class, ResourceHelpers.resourceFilePath("./config.yml"));
Will update with any information that is requested!

Integration testing with spark server

I'm trying to IT my spark server. My intentions are to test all the controller functions.
I have thought about few options:
1. Set up a server that will start when running the tests, and terminate when the tests are over.
The problem with this solution is that I have to rewrite my whole server logic to the new server (we start server from scratch every time we set the server before the testing).
Initiate a controller from the test class (essential to initiate and not static call, in order to configure the right db to the controller) that will call the controller functions and check their answers.
This is my favorite one, but it means that I have to mock a spark request. I'm trying to build a spark request, and spark response objects, to send to my controller, and haven't found a single way to do that properly (and how to send parameters, set url routes etc..)
#Test
Public void testTry(){
String expectedName = "mark";
myController myCtl = new myController()
Request req = null;
Response res = null;
String childName = myCtl.getChildNameFromDB(req, res);
assertEquals(childName, expectedName);
}
The last one is to do the exact logic of the controller function in the test, and instead of getting the parameters from the request, ill initiate them myself.
For example, instead of:
String username = req.params(""usrName")
It will be:
Strimg username = "mark"
But that solution will demand copying a lot of code, and you might miss a little code line which might make the test succeed when in reality, the controller function fails (or doesn't deliver as wanted).
What do you think about Integratiom testing a spark driven server? I'm open minded to new solutions as well.
If you want to do integration testing, I would suggest to use your first approach, using a randomly chosen free TCP port and a HTTP client library (I often use the excellent HttpRequest library to that effect).
The main issue with this approach is that since Spark API is static, you won't be able to stop/start the server between test cases/suites.

RPC over STOMP using Spring, and correctly handling server side errors propagated to clients

I need to implement RPC over STOMP, where the client runs with javascript in a browser, and the server side is implemented using Spring messaging capabilities.
While using #MessageMapping is fine for normal messaging, I find using #SendToUser quite limitating for implementing RPC because the client has an hard time to understand which reply is associated with which request in a scenario when multiple simultaneous requests are being made from the client.
Of course there is no problem when just only one request is made, and the client waits for its reply, but problems arise when the client has to keep track of multiple "open" rpc calls.
I've managed to make the system mostly fine by associating an ID with every request, i.e.: the client sends an id together with the message, and the server replies with a special message wrapper that contains this id, so the client is able to associate asynchronous replies with requests.
This works fine but has several limitations:
I have to develop code that needs to understand this structure, and that defies the uitlity to have simple annotated methods
when the server side code generates an Exception the Spring #MessageExceptionHandler get called and the correct Exception is returned to the client, but the request id is lost because the handler has no (easy) way to access it.
I know that with rabbitmq we can add "reply-to" header to every request that needs to be associated with a special reply (the rpc response), and this is implemented by creating a special temporary queue that the user is automatically subscribed to, but how may I use this scheme in Spring? Also, that would tie me a specific broker.
How may I elegantly implement a correct RPC call in Spring that correctly handles server side exceptions?
I find this a general problem and I think Spring could benefit greatly to implement it natively.
This not exactly what you demand, but maybe you can attempt something like this :
Path variables in Spring WebSockets #SendTo mapping
You define an ID on your client and send id to the queue /user/queue/{myid}
On the serveur side you will have a class who looks like this :
#MessageMapping("/user/queue/{myid}")
public void simple(#DestinationVariable String id, Object requestDto) {
simpMessagingTemplate.convertAndSendToUser(userId, "/user/queue/" + id, responseDto);
}
This solution can work with the same principle as the rabbit mq solution you mention.
Hope this helps.
If you do not need the exception/reason on the client, but only want to know which message failed you could send ack messages for successful messages. For successful messages you always have easy access to the message id / headers. By the absence of the ack message the client knows which message has failed.
Of course this comes at the costs of sending all the ack messages and knowing the timout of requests. Also additional code is required to keep track on the client side, but this can be done using a middleware and would end up in an ok-ish dev experience for the business logic.

Jersey Client proper way to execute parallel POST requests

I'm looking for the proper way of executing POST requests using jersey client (with apache http client 4.x)
Since Client instance and WebResource instance are thread-safe, the natural way of coding the method will be:
public AuthorizedAccount createAuthTokenFromUserPass(Credentials credentials)
throws AuthenticationServiceClientException {
ClientResponse response = resource.accept("application/x-protobuf").post(
ClientResponse.class, credentials);
return getAuthorizedAccountFromResponse(response);
}
ClientResponse instance is properly released.
When this method is executed from multiple threads, it ends-up by POSTing same credential instance to the server, for each thread.
A solution will be to synchronise the method, but will end-up by executing the POSTs in sequence.
Is there a different way to do it? (avoiding the re-creation of Client instance)
After spending a lot of time trying to figure out what is not working properly, I found out that the issue was not really in jersey client implementation but in my own code. I have used a custom implementation of MessageBodyWriter, where I was not careful enough. I did not read properly the contract of the interface. I have shared an instance variable between call of getSize() and writeTo(), and the MassageBodyWriter is reused.

Categories

Resources