Multithreading in the spring project is not working properly - java

I need to run a function on a complete independent thread wile the rest of my function gets executed for example
public void a(){
// do dome work
}
public void b(){
// do dome work
a()
return "hello"
}
I need my code to start ruining function a but returns hello without waiting for function a to end
I have tried task executors with spring and #Async annotation but noting is working
public static String mainMEthod() {
asyncMethodWithReturnType();
return "hello";
}
#Async
public static Future<String> asyncMethodWithReturnType() {
for (int i = 0; i < 10; i++) {
System.out.println("Execute method asynchronously - " +
Thread.currentThread().getName());
}
try {
Thread.sleep(5000);
return new AsyncResult<String>("hello world !!!!");
} catch (InterruptedException e) {
//do anything
}
return null;
}
Here is the output :
Execute method asynchronously - main
Execute method asynchronously - main
Execute method asynchronously - main
Execute method asynchronously - main
Execute method asynchronously - main
Execute method asynchronously - main
Execute method asynchronously - main
Execute method asynchronously - main
Execute method asynchronously - main
Execute method asynchronously - main
but it should not be running on the main thread

#Async has two limitations:
it must be applied to public methods only
self-invocation – calling the async method from within the same class – won’t work.
The reasons are simple – the method needs to be public so that it can be proxied. And self-invocation doesn’t work because it bypasses the proxy and calls the underlying method directly.
Also make sure to configure correctly:
#Configuration
#EnableAsync
public class SpringAsyncConfig { ... }
Read more:
https://www.baeldung.com/spring-async

The way Spring add functionalities like Async (apart from many others like this) is by creating and injecting a proxy which has the logic of providing these functionality.
In your case the call to asyncMethodWithReturnType cannot be intercepted by Spring as this is plain java method call without intermediate spring managed proxy. For more information you can check out here.

The #Async can't be run in a separate thread if the caller is within the same bean.
So option one is to move the a() method to a different bean and call it from b()
Or, consider doing what we did in our spring boot project when we needed something similar:
public void b() {
CompletableFuture.runAsync(() -> a());
return "hello";
}

Related

How to mock handle.useTransaction in JDBI

I have a class with public method name process() which invoked a private method called processAandB().
In the method processAandB() we are using
handle.useTransaction(h -> {
//calling processA and processB private methods
processA(h)
processB(h)
}) [JDBI handle]
In processA we are creating tasks(Callable) which are to be processed via executor service and same applies to processB.
I am writing a JUnit test case where I've mocked the Handle and called the process() method and the problem is control is not going inside handle.useTransaction().
I am not sure how to invoke useTransaction in such a way that it call the processA and processB method too.
I tried mocking transaction too but couldn't.
Not sure what is the approach I should follow here.

Java wait or sleep in my case

Wait or Sleep...which method will be suitable?
void A()
{
//Some Code 1
some_function(); // calling a method and will seek for a response from other device, communicating on bluetooth
//Some code 2
}
I want my program to wait for the process of some_function(). However at the moment it starts executing "Some Code 2" part of function A().
And kindly if someone specify wait method implementation my case.
p.s: Async is not my priority.
Since you dint want to do async task,making the thread sleep may freeze the UI. Even if it didn't, it is still insanely bad practice.
so first thing - you have to do it on a separate thread. and Asynctask is best for it.
some_function() would be executed before //Some code 2 if it is not running on a separate thread(As you said its not Asynctask).But in case it is running on a separate thread(which it should be)-.
you can just simply call "//Some code 2" inside some_function() at the end.
OR
if you do not want to do that,try it like this-
First make an interface -
public static interface On_some_function_complete{
void onComplete(what ever parameters you want);
}
put an instance of this interface in your some_function() as parameter where ever you define it and call the onComplete method in the end of the function ,like-
void some_function(On_some_function_complete arg_on_complere){
//what ever stuff your code dose
arg_on_complere.onComplete(/*with required arguments*/);
}
now make call like -
void A()
{
//Some Code 1
some_function(new On_some_function_complete{
#Override
public void onComplete(Bitmap result) {
//Some code 2
}
});
}
OR
you must have some function that you can override to handle on-Compete action

Using guava AbstractScheduledService

I'm trying to execute some task periodically using guava AbstractScheduledService :
public class MyService extends AbstractScheduledService {
public MyService() {
}
#Override
protected void runOneIteration() {
doStuff();
}
private void doStuff() {
// Do stuff
}
#Override
protected Scheduler scheduler() {
return Scheduler.newFixedRateSchedule(0, 8, TimeUnit.HOURS);
}
}
So this service should execute some task periodically every 8 hours but it never actually does. The inherited isRunning() method returns false and the runOneIteration() method never gets invoked.
I have managed to make it work by calling the startAsync() method (inherited from parent class) from my service constructor but I don't see any reference saying this is the way it should work.
Have I missed something here? Is this the way the AbstractScheduledService works?
AbstractScheduledServiced implements Service. The Service interface describes lifecycle methods including startAsync. The ServiceState enum literals contain documentation on what they mean. A Service in NEW state (just created):
A service in this state is inactive. It does minimal work and consumes minimal resources.
For the Service to do something useful you have to transition it to the state RUNNING
A service in this state is operational.
That's why you have to start the Service before it does anything.
I would also advise against calling startAsync from the constructor and instead calling it from the Code that creates your MyService instance. It is rarely an expected thing to have such heavy side effects (creation of Threads) in the constructor.

How to unit test a method that simply starts a thread with jUnit?

As in the title, I want to test a method like this:
public void startThread()
{
new Thread()
{
public void run()
{
myLongProcess();
}
}.start();
}
EDIT:
Judging by comments I guess it is not very common to test if a thread starts or not. So I've to adjust the question... if my requirement is 100% code coverage do I need to test if that thread starts or not? If so do I really need an external framework?
This can be done elegantly with Mockito. Assuming the class is named ThreadLauncher you can ensure the startThread() method resulted in a call of myLongProcess() with:
public void testStart() throws Exception {
// creates a decorator spying on the method calls of the real instance
ThreadLauncher launcher = Mockito.spy(new ThreadLauncher());
launcher.startThread();
Thread.sleep(500);
// verifies the myLongProcess() method was called
Mockito.verify(launcher).myLongProcess();
}
If you need 100% coverage, you will need to call startThread which will kick off a thread. I recommend doing some sort of verification that the thread was stared (by verifying that something in myLongProcess is happening, then clean up the thread. Then you would probably do the remainder of the testing for myLongProcess by invoking that method directly from your unit test.

How do I write a JUnit test case to test threads and events

I have a java code which works in one (main) thread. From the main thread, i spawn a new thread in which I make a server call. After the server call is done, I am doing some work in the new thread and after that the code joins the main thread.
I am using eclipse Jobs to do the server call.
I want to know, how do I write a JUnit test case for this.
You may need to restructure your code so that it can be easily tested.
I can see several distinct areas for testing:
Thread Management code: the code that launches the thread(s) and perhaps waits for results
The "worker" code run in the thread
The concurrency issues that may result when multiple threads are active
Structure your implementation so that Your Thread Management code is agnostic as to the details of the Worker. Then you can use Mock Workers to enable testing of Thread Management - for example a Mock Worker that fails in certain ways allows you to test certain paths in the management code.
Implement the Worker code so that it can be run in isolation. You can then unit test this independently, using mocks for the server.
For concurrency testing the links provided by Abhijeet Kashnia will help.
This is what I created ConcurrentUnit for. The general usage is:
Spawn some threads
Have the main thread wait or sleep
Perform assertions from within the worker threads (which via ConcurrentUnit, are reported back to the main thread)
Resume the main thread from one of the worker threads once all assertions are complete
See the ConcurrentUnit page for more info.
I'm guessing that you may have done your mocking code and may want a simple integration test to ensure that that your server call works.
One of the difficulties in testing threads comes from their very nature - they're concurrent. This means that you're force into writing JUnit test code that is forced to wait until your thread has finished its job before testing your code's results. This isn't a very good way of testing code, and can be unreliable, but usually means that you have some idea about whether you code is working.
As an example, your code may look something like:
#Test
public void myIntegrationTest() throws Exception {
// Setup your test
// call your threading code
Results result = myServerClient.doThreadedCode();
// Wait for your code to complete
sleep(5);
// Test the results
assertEquals("some value",result.getSomeValue());
}
private void sleep(int seconds) {
try {
TimeUnit.SECONDS.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
I really don't like doing this and prefer mocks and agree with the other answers. But, if you need to test your threads, then this is one approach that I find works.
When your only problem is waiting for the result, use ExecutorService for spawning your threads. It can accept work jobs both as Runnable and Callable. When you use the latter, then you are given a Future object in return, that can be used to wait for the result. You should consider using ExecutorService anyway, as from what I understand, you create many threads, and this is a perfect use case for executor services.
class AnyClass {
private ExecutorService threadPool = Executors.newFixedThreadPool(5);
public List<Future<Integer>> anyMethod() {
List<Future> futures = new ArrayList<>();
futures.add(threadPool.submit(() -> {
// Do your job here
return anyStatusCode;
}));
futures.add(threadPool.submit(() -> {
// Do your other job here
return anyStatusCode;
}));
return futures;
}
}
And the test class:
class TestAnyClass {
#Test
public void testAnyMethod() {
AnyClass anyObject = new AnyClass();
List<Future<Integer>> futures = anyObject.anyMethod();
CompletableFuture[] completable = futures.toArray(new CompletableFuture[futures.size()]);
// Wait for all
CompletableFuture.allOf(completable).join();
}
}
I suggest you use a mocking framework, to confirm that the server call was indeed made. As for the thread unit testing: Unit testing multithreaded applications
The resources provided by Abhijeet Kashnia may help, but I am not sure what you are trying to achieve.
You can do unit testing with mocks to verify your code, that won't test concurrency but will provide coverage.
You can write an integration test to verify that the threads are being created and joined in the fashion you expect.However this will not guarantee against concurrency problems. Most concurrent problems are caused by timing bugs which are not predictable and thus can't be tested for accurately.
Here is my solution to test asynchrone method which used thread.start:
public class MyClass {
public void doSomthingAsynchrone() {
new Thread(() -> {
doSomthing();
}).start();
}
private void doSomthing() {
}
}
#RunWith(PowerMockRunner.class)
#PrepareForTest(MyClass.class)
public class MyClassTest {
ArgumentCaptor<Runnable> runnables = ArgumentCaptor.forClass(Runnable.class);
#InjectMocks
private MyClass myClass;
#Test
public void shouldDoSomthingAsynchrone() throws Exception {
// create a mock for Thread.class
Thread mock = Mockito.mock(Thread.class);
// mock the 'new Thread', return the mock and capture the given runnable
whenNew(Thread.class).withParameterTypes(Runnable.class)
.withArguments(runnables.capture()).thenReturn(mock);
myClass.doSomthingAsynchrone();
runnables.getValue().run();
/**
* instead of 'runnables.getValue().run();' you can use a real thread.start
*
* MockRepository.remove(Thread.class);
* Thread thread = new Thread(runnables.getValue());
* thread.start();
* thread.join();
**/
verify(myClass, times(1)).doSomthing();
}
}

Categories