Spring aspects across multiple threads - java

Trying to wrap service class with two aspects to get this call chain:
javanica..HystrixCommandAspect -> MyCustomAroundAspect -> MyService
met two problems:
HystrixCommandAspect does not call joinPoint.proceed(). Instead it calls method directly on target class, which effectively skips any other proxies created after javanica's aspect
Hystrix aspect makes subsequent calls running in deferent thread. It leads to message:
"No MethodInvocation found: Check that an AOP invocation is in progress, and that the ExposeInvocationInterceptor is upfront in the interceptor..."
which is reasonable because this interceptor keeps its stuff in thread local.
Questions:
1. Why is Spring APO implemented this way? Is it conceptually wrong to run different aspects in different threads? Are there workarounds except changing the aspects' order?
Why does HystrixCommandAspect call target class directly, but not through joinPoint.proceed()? Doesn't it break the contract (if one even exists)?
regards

Disclaimer: I am not a Spring or Hystrix user, just an AOP guy.
Why does HystrixCommandAspect call target class directly, but not through joinPoint.proceed()? Doesn't it break the contract (if one even exists)?
Actually, you have to ask the Hystrix maintainer. It is a good question, actually. the assumption that Hystrix aspects are the only ones in this universe is certainly a bold one because there actually is an AspectJ or Spring AOP contract for #Around advices:
Either the aspect calls the original method. If it does so, it ought to use proceed(). If it proceeds with the original method arguments or with a modified set, is up to the aspect. Also if it proceeds before, after or in between doing other things.
Or the aspect returns a result (for non-void methods) calculated without proceeding to the original method.
Or the aspect throws an exception, not returning any result.
Having said that, I think it is a design flaw in Hystrix not to pass on the ProceedingJoinPoint and eventually call proceed() on it in case the original method is to be called eventually. If I was a Hystrix user, I would open a bug ticket for that.
Besides, it is in principle no problem to call proceed() asynchronously from another thread in which you inject the joinpoint instance upon creation. Then you can put that thread (or a runnable) into a queue and execute it whenever convenient. Technically you can even call proceed() on the same joinpoint instance multiple times, but if the target method is no pure function without side effects you might want to be careful with that and usually won't do it unless your aspect implements some kind of retry scheme (with or without exponential back-off). So Hystrix could to that too. If they do not then they must be doing something ugly instead, such as use reflection to call the original method. I did not check.

Related

Asynchronously calling synchronized methods?

I want to benefit from asynchronously calling one of my methods. Since I use spring framework, this task is quite trivial, so I just marked the method with #Async annotation.
However my method is using a global variable that is not intended to be used concurrently by multiple threads( you may think of it as javax.jms.Session).
First thing that comes to mind to mark the method with synchronized keyword in order to make sure that method is thread safe.
But on the other hand it will be completely nonsense to use #Async annotation on synchronized method, right?
Is there any benefit to use #Async annotation on method that contains synchronized block ?
The purpose of making something asynchronous is that it will do things in the future, that will take relatively much time, for example file or database operation, and during that time, you can make other useful operations.
In your case, if you do synchronous block inside and async operation, you will lose async functionality making that part of your code block in certain cases. Of course, if you access a shared resource concurrently, you should defend it, the real question here, is that you really need async functionality inside that function? Maybe you can refactor your code to deal with the synchronous resource somewhere else.
Also if you are really into async functionality, and spring, you should check out Spring 5, and what it has to offer, when it's released.
Spring 5.x

PowerMock method intermittently invoking real method

I'm having a very strange problem with PowerMock, and I'm hoping somebody more familiar with its internals can suggest a next direction to chase.
The class under test is a Jersey Resource class. The method being tested has a wait() statement in it, and it subsequently invokes 2 static methods on a Helper class. When the first static method on the Helper class is invoked, the real method is executed, not mocked.
Nuances:
if I invoke the static method before the wait, the Mocked response is returned.
if I invoke the static method twice after the wait, the first time will execute the real method, and the second time will return the Mocked response.
if I invoke the static method once before and 5 times after the wait, the invocation before the wait will return the mock response, the first invocation after the wait will execute the real method, and all subsequent invocations will return the Mocked response.
if I debug it in my IDE debugger and put a break point on the method invocation, the mocked response is returned.
if I comment out the wait(), everything is mocked as expected.
all other mocking and stubbing and spying seems to be fine
I tried writing a test stub to demonstrate my problem to post here, but even I can't reproduce it on anything except the original class. Unfortunately, I cannot post that class so I'm putting out this request for blind advice.
Why might a wait() cause a side-effect in PowerMock like this?
Not sure if this is relevant, but the wait() is due to a method invocation that would normally set up a callback. I don't need the callback (not the point of my test), so I am simply mocking this method and no callback is set up. Since there's no notify, the wait() is simply returning after the specified time limit.
In my test framework, I am using JerseyTest 2.14 (with Grizzly container), RestAssured 2.8.0, and PowerMock 1.5.5.
Not the answer you are looking for but I have seen more than once that this is the better answer to any PowerMock problem: don't use PowerMock.
Even the folks developing it recommend to not use it.
When your production codes forces you to turn to PowerMock; then consider changing your production code. In other words: if you think you need PowerMock to test your code; then most of the time, that means you are dealing with bad design & implementation.
Seriously: PowerMock and its byte code manipulations can open a can of worms of problems. In the long run, you might better spend your time to redesign your "system under test" in order to make it testable using reasonable frameworks. For example, PowerMock breaks most frameworks for measuring code coverage. Something that might not hurt you today, but maybe will later on.

Spring async method called from another async method

I'm using Spring 4 and I've noticed an odd behaviour... if I'm calling an async method multiple times from a normal instance method then they are all called in different threads and finish at random times. But if I call multiple times an async method from another async method then they finish in order. I have something like this:
#Async
public void nonAsyncMethod() {
for (int i = 0; i < 30; i++) {
asyncMethod();
}
}
#Async
public void asyncMethod() {
... something here
}
I'm using the default async executor. Should I use a different one? However this executor do not reuse any threads and starts another one every time so it should be fine... Can it be just a coincidence? But I've tried like more than 10 times and if I revert back to non-async for the first method then they finish randomly
What you are describing is a classic pitfall of Spring AOP.
In short, for Spring to be able to provide the async behavior it needs to create a proxy for your class at runtime. The proxy then does whatever it needs to do before and/or after calling your code. But in your case, the proxy mechanism is not being applied for the second method.
When a bean of your class is injected via Spring into some other component, Spring really injects the proxy instead. Therefor the relevant method of the proxy is called. However, when you are calling a method from inside the class, the limitations of Spring AOP mean the proxy never comes into play, but instead the regular method is called - with no extra features.
That is why asyncMethod is always executing on the same thread as the other method in the same class that called it.
Check out this excellent blog post as well as this part of Spring documentation.
There are some ways around the problem (check out this) that don't require you to refactor your code, but if you want async to work on both methods no matter what, the simplest thing to do is refactor the second method into another class.

Unit testing a nonblocking method (asynchronous testing)

I have a very simple Checkclass which has a blocking waitForCondition() method. This method is blocking. I want to create some unit tests for this method. First, the method should return when the condition is met. Second, the method should return when it is interrupted.
Internally the Check class has an ArrayBlockingQueue and calls its take() method, so my test is really about having coded the logic for the condition correctly (as it should be).
In the application, data for the Check class is fed by another thread via an InputData method. The InputData method executes the logic on incoming data and places a dummy object in the ArrayBlockingQueue when the condition is met. This should cause waitForCondition() to return.
So my first thought is I can test the InputData by mocking and check to see the dummy object is added to the queue when the condition is met. This would require changing the design of the class, since the queue is a private data member (unless it is possible to mock private data). Instead of InputData adding directly to the queue when the condition is met, it would have to call something which could be mocked.
But then there is the problem of checking the waitForCondition() methods themselves, given that InputData is functioning correctly. It's really simply code:
try {
myArrayBlockingQueue.take();
return true;
} catch (InterruptedException ex) {
return false;
}
So I'm wondering if it's worth the imagined trouble: a test which creates another thread with a Check, calls its waitForCondition(), then returns something when it's done. Perhaps, using an Executor service. The fuzzy part is how to synchronize the assertTrue(...). I found this article on asynchronous testing which looks like it might do the trick.
Summary of question:
Should I change the design to test the logic in InputData() and if so, how?
Should I leave out the test of waitForCondition() as long as InputData() is tested?
Or is it better to just do what needs to be done (a somewhat complicated unit test) and test waitForCondition() directly?
If you inject the instance of ArrayBlockingQueue in the constructor of the Check class, then your test can inject the appropriate value in the middle of the test.
Then you can run the unit test with a timeout, and fail if it doesn't return within 100ms or so.
Thanks for the nice link! I faced some similar problems, and maybe that link is a better way to go than what I did. (I'm also interested to see what other answers appear to this question - it's a good question)
If you don't mind changing (at least temporarily) your actual code (yes, this is not a usual unit-test practice!) you can do something I called "Error Injection".
In my implementation, you create a class that reads from properties (or a Map) to "do something funny" at a specific unique point. e.g. your properties might say
myClass.myMethod.blockingQueueTake = interrupt:
myClass.myLongCalculation = throw: java.lang.ArithmeticException(Failed to converge)
In your code, you add testing lines, e.g. right before your queue.take(), add
TestSimulator.doCommand("myClass.myMethod.blockingQueueTake");
The advantage is that everything is happening in real-real code, not some Mock, which can get really hairy. (In my case, the SW was older, not written/designed for unit-testing, so making a Mock was very difficult) The disadvantage is that you will probably want to remove or comment out the code afterwards. So it really isn't a continuous-integration type unit test, it's more of a one-time really serious reality debug. So, I admit, it's far far from ideal, but, it did find a bunch of bugs for me!
You could also use a "test runner" class to run the asserts in a loop. The loop would run the asserts in a try/catch. The exception handler would simply try to run the asserts again until a timeout has expired. I recently wrote a blog post about this technique. The example is written in groovy, but the concept should be easily adaptable for Java.
http://www.greenmoonsoftware.com/2013/08/asynchronous-functional-testing/

Poor JUnit test using springframework has fragile Thread.sleep() calls. How to fix?

I have recently joined a group with some severe JUnit testing issues. One problem is an 8 minute long test! The test has several sections; each makes calls to org.springframework.context.ApplicationEventPublisher.publishEvent()
followed by Thread.sleep() of various amounts of time, then tests conditions.
There are several obvious problems with this approach, the timing of the Thread.sleep() calls is fragile:
tests occasionally fail on busy machines; and
tests take far too long when they do not fail.
Is the pool upon which these events are handled accessible for testing and is there a call to see if the event cascade has quiesced?
Worth mentioning is that test code that actually calls external services are integration tests and not unit tests. If you're truly unit testing here you should replace those calls with mocks. That way you can better control the values returned to your business logic and test for specific conditions. Also, as you've seen, this all but eliminates false positives due to external (non-code) situations. Obviously these tests aren't failing, the facility they expect to use is.
You can overwrite the default applicationEventMulticaster by adding this bean id to your application context.
Instead of the default SimpleApplicationEventMulticaster, you could set a TaskExecutor on this bean to perform the event publishing asynchronously in multiple threads.
Or you could implement your own multicaster, which prints out which event listener took so long or was blocking, for how long and on which events. That could help you to track down the real problem of the 8-Minute-Testcase.
Interestingly, the JavaDoc of the SimpleApplicationEventMulticaster, which is used by default by Spring when you are using ApplicationContext, states the following:
By default, all listeners are invoked in the calling thread. This allows the danger of a rogue listener blocking the entire application, but adds minimal overhead. Specify an alternative TaskExecutor to have listeners executed in different threads, for example from a thread pool.
I (intentionally) avoid Spring so I'm not sure I can help with the specifics but just looking at the sleep issue, you can use something like WaitFor in tempus-fugit (shameless plug) to poll for a Condition rather than "sleep and hope". It's not ideal and usually a change in the way you test (as suggested before) is preferable but it does mean you get finer grained "waits" which are more likely to avoid race-conditions / flaky tests and generally speed up the test.
See the project's documentation for details and post back if you find it useful!

Categories

Resources