I am extending a 3rd party class and overriding a method that I have made "recursive" like so:
public class SubFoo extends Foo {
....
#Override
public void bar(...) {
recursiveSpecificSet.add(...);
if(recursiveSpecificSet.contains(...)){
...
methodCallThatCallsBar(...);
...
}
}
}
Since this method is overrided, I have no control in the method signature. I would like to pass information from the parent recursive call to its child through the recursiveSpecificSet, but I would like that information to be specific to that recursive chain. For instance:
SubFoo sf = new SubFoo();
sf.methodCallThatCallsBar(...); // first call calls bar recursively 3 times
sf.methodCallThatCallsBar(...); // second call calls bar recursively 5 times
In the above code, the first call's recursiveSpecificSet variable should not interfere with the second call's recursiveSpecificSet.
Is this even possible? I know you can usually pass info between recursive iterations through method parameters, but I do not have control on the method signature. Multiple calls to the bar method can also occur in the same thread, so a thread local variable will not work.
Use a threadlocal that stores recursion depth and the payload data. If upon entering bar() the threadlocal is null, initialize it with depth 1, otherwise increment depth. Upon leaving bar(), decrement depth and if it goes under 1, delete the threadlocal. You'll probably have to do this in finally so it doesn't break in case of an exception being thrown.
public void bar() {
if (threadLocal == null) {
threadLocal.set(new Context(recursiveSpecificSet));
}
threadLocal.get().increaseDepth();
try {
...
methodCallThatCallsBar(...);
...
}
finally {
threadLocal.get().decreaseDepth();
if (threadLocal.get().isExitRecursion()) {
threadLocal.remove();
}
}
}
If I understand your question correctly, the answer is not to make bar recursive, but to make bar call a private helper method that is recursive.
#Override
public void bar() {
helper(new HashSet<>());
}
private void helper(Set<String> recursiveSpecificSet) {
...
helper(recursiveSpecificSet);
...
}
Related
I am trying to use Byte Buddy to execute some additional logic when a method is done. Here is the sample code:
T proxyClient = JAXRSClientFactory.fromClient(client, classType, true);
this.configureHttpConduit(conduit, invocationTimeout);
Class buddy = new ByteBuddy()
.subclass(classType)
.method(ElementMatchers.isAnnotatedWith(Path.class))
.intercept(MethodDelegation.to(proxyClient)
.andThen(MethodCall.run(new CloseConnection())))
.make()
.load(this.getClass().getClassLoader(),
Default.INJECTION)
.getLoaded();
return (T) buddy.newInstance();
static class CloseConnection implements Runnable {
void close() {
System.out.println("close connection called");
}
#Override
public void run() {
close();
}
}
When I chain the delegation with the .andThen call, the original caller to this instance loses the return values that was from the "proxyClient" object which it used to invoke a method call on it earlier. Am I using Byte Buddy wrong?
Basically I want to add some additional logic to the end of a method (inside the original method or adding another method call does not matter), but at the same time preserving the return value of the original method call.
This is by design. For every Implementation that you chain via andThen, Byte Buddy expects an empty stack for the next block. Thus, the last implementation is responsible for the return.
The idea of Byte Buddy is to put as much logic as possible into the interceptor. I would suggest to you to write your own interceptor that invokes the delegate and then invokes the close connection. This gives you also full control over the call conditions like closing in a finally block:
public class MyInterceptor<T> {
final T proxyClient;
#RuntimeType
public Object intercept(#Origin Method method,
#AllArguments Object[] args) throws Throwable {
try {
return method.invoke(proxyClient, args);
} finally {
// do your completion logic here
}
}
}
This can of course be improved in terms of performance. Have a look at the #Pipe annotation for that.
I want to return some value depend on some value in inner class:
public boolean rename(File file) {
new OnResultListener() {
#Override
public void onResult(AsyncResult<CharSequence> result) {
// some codes
// Here is what I want to do
if (succeed) {
// rename return true
} else {
// rename return false
}
}
}
}
You can't and it does not make sense. These are two distinct functions that may very well be called on different threads. What you have to do, if you insist on returning something, is that the "rename" function itself should receive a callback as a parameter that gets called upon success. That is, if the downstream call is asynchronous then the ones calling it should be too.
An alternative would be to have a the calling function ("rename" in this case assuming it calls the function that notifies the OnResultListener) to wait on some mutex. Then, in the nested method upon receiving a result, you set some flag and then call notify() which would wake the thread held by the wait.
I have a class that normally runs in a thread that processes data forever until another thread invokes stop() on it. The problem I have is that the unit test gets stuck in the main loop since the test is single threaded and I want to keep it that way. How can I unit test this without polluting the code? this class is part of a critical system and needs to be as simple and efficient as possible so I want to avoid unit testing hacks in the code
public class MyClass implements Runnable {
boolean running;
public void run() {
//foo is injected from the outside
foo.start();
work();
foo.end();
}
public void work() {
running = true;
while(running) { //main loop
bar.process(); //bar is injected from the outside
}
}
public void stop() {
running = false;
}
}
Basically what I'm doing in the test is mocking out foo and bar and I call run() from the unit test, where later I verify in the bar mock whether process was actually called. I also verify that in the foo mock start() and end() got called. The problem is that because I really want to keep the test single threaded, the test thread gets stuck forever in the while(running) loop.
Some things I have tried and don't like
add some VM property to trigger a break at the end of the iteration of the main loop. The problem with this is that as mentioned, this code is very critical and I want to keep the code clear of unit-testing clutter. I don't want production code evaluating in every iteration some VM property that I only use at development time
use the bar mock to invoke stop() on its call of process(). Mockito doesn't like the fact that I call another class' method and throws an exception
externalize the control of the mainloop. so instead of checking a boolean in the while, I call a method that returns whether to continue or not. And this loop-control object can be injected from the outside, that way in the unit test i can make the control method return true and then false to get a single iteration out of the loop. This complexifies the code quite a bit and makes it unnatural and harder to read plus it only would make any sense in a unit test context
Are there any other suggestions or common patterns to test Runnables, or maybe a better way to write my code so that testing it is easier?
I suggest making a change which would both make your code more by-the-book and allow breaking out in a single thread:
while (!Thread.currentThread().isInterrupted() && running) {
bar.process();
}
You can call Thread.currentThread().interrupt() before you run this code; the thread's interrupted flag will be set and the method isInterrupted() will return true.
This is more by-the-book because it makes your main loop participate in Java's interruption mechanism.
Create an interface for the class of bar that only contains the method process. Your MyClass seems generic enough so that this would be OK. Then, instead of mocking bar, create your own implementation dummy (or mock, whatever you like to call it). This will then call the stop method and your process method is only called once. You can check whether BarMock.process was called with an assertion using its isCalled method. Also, I would suggest an isRunning method for your MyClass so that you can check whether it was stopped.
public interface Processable {
public void process();
}
public class BarMock implements Processable {
private MyClass clazz;
private boolean called;
public BarMock(MyClass clazz) {
this.clazz = clazz;
called = false;
}
#Override
public void process() {
// you can assertTrue(clazz.isRunning()) here, if required
called = true;
clazz.stop();
}
public boolean isCalled() {
return called;
}
}
public class MyClass implements Runnable {
boolean running;
public void run() {
// foo is injected from the outside
foo.start();
work();
foo.end();
}
public void work() {
running = true;
while (running) { // main loop
bar.process(); // bar is injected from the outside
}
}
public void stop() {
running = false;
}
public boolean isRunning() {
return running;
}
}
I think this method has three advantages over the one suggested by William F. Jameson, but also disadvantages:
Advantages:
You can test whether your process method was actually called
You don't have to add code that you never use during the actual program run
You can test whether the stop method really stops
Disadvantages:
You have to introduce an interface
Need to test BarMock class, too
That said, I'd still prefer introducting the interface, since it doesn't pollute your code too much and therefore is a small price to pay.
I have a class.
I initialize a variable in the constructor of that class.
I call a method that contains a while loop and increments the variable each time through.
I wrote a test to check the value of the variable after the method has been called (and goes through the while loop one time).
public class ThreadGenerator implements Runnable {
private int requests;
private int limit;
public ThreadGenerator() {
requests = 0;
}
public void setRequestLimit(int anyLimit) {
this.limit = anyLimit;
}
public void generateThread() {
new Thread(this).start();
}
public void run() {
while(requests < limit) {
try {
// do some stuff
requests++;
// close some stuff
} catch (IOException e) {
e.printStackTrace();
}
}
}
public int getRequests() {
return requests; // calling this method from my tests always returns 0
}
In my test, when I create a new instance of this class, then call this method on that class, it runs correctly and it increments the request counter correctly. I've tried several print statements to make sure of that. But if I call getRequests on my ThreadGenerator object in my test, it will return 0, the amount it was initialized with.
My test code:
ThreadGenerator threadGenerator = new ThreadGenerator();
threadGenerator.setRequestLimit(1);
threadGenerator.generateThread();
assertEquals(threadGenerator.getRequests(), 1);
How can I modify this variable I initialized in the constructor and gain access to it in my test suite?
Bear in mind that just because you ask Java to create a new thread with a Runnable, doesn't mean that the run() method will be called immediately. It's likely the case that the assertEquals is happening before the run happens the first time.
You may want to return the thread and call join in the test on the generated thread, which will ensure that the Thread runs until it dies, possibly with a short timeout.
/* in the system under test */
#VisibleForTesting Thread generateAndReturnThread() {
Thread thread = new Thread(this);
thread.start();
return thread;
}
public void generateThread() {
generateAndReturnThread();
}
/* in the test */
#Test public void yourTest() {
ThreadGenerator threadGenerator = new ThreadGenerator();
threadGenerator.setRequestLimit(1);
// wait up to a second for thread to complete
threadGenerator.generateThreadAndReturn().join(1000);
assertEquals(threadGenerator.getRequests(), 1);
}
Side note: Consider AtomicInteger for your requests class, if multiple threads might modify requests. This will help prevent two different threads from both modifying requests and overwriting one another.
In addition to above answer, consider declaring the variable as volatile, so that you can actually get the latest value after another thread incremented the variable.
I hope this is going to be enough information, so here it goes. If you need more info, lemme know in the comments.
I have a class that has two inner classes. The inner classes each have two methods that call a method in the outer class. So, it looks like this:
public OuterClass {
private boolean outerMethodHasBeenCalled = false;
private void outerMethod() {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
private FirstInnerClass {
public void someMethod() {
outerMethod();
}
}
private SecondInnerClass {
public void someOtherMethod() {
outerMethod();
}
}
}
It's important to note that:
This is for an Android app. Instances of FirstInnerClass and SecondInnerClass are passed to a WebView as a JavaScript interface, so someMethod and someOtherMethod can be called at any time, in no particular order.
I currently have a problem with the existing code (without the synchronized keyword) where outerMethod is called pretty much at the exact same time (I print out a log message, and they're timestamped to the 1000th of a second) by different objects. My app then 'does stuff' twice because outerMethodHasBeenCalled is still false when outerMethod was called. This is not okay, and it is exactly what I'm trying to prevent. My app should only 'do stuff' once and only once: the first time outerMethod is called.
It might sound like I have multiple instances of OuterClass, but rest assured that it's only one instance of OuterClass.
It's important that my app 'does stuff' only the first time outerMethod gets called (I hope that's evident by now). All subsequent calls are essentially ignored. Whichever inner class calls outerMethod first -- doesn't matter.
So, is it appropriate to use the synchronized keyword in this case?
Yup, given what you've laid out above, I'd go with:
private synchronized void outerMethod() {
...
}
Note, this will have the side-effect of blocking one of the callers until the outerMethod() completes. If that is acceptable, cool. If the intent is merely that the code in outerMethod() is run once, and it is OK for the second caller not to be delayed if the first caller is running outerMethod(), you might consider:
public OuterClass {
private AtomicBoolean outerMethodHasBeenCalled = new AtomicBoolean();
private void outerMethod() {
if (outerMethodHasBeenCalled.compareAndSet(false, true)) {
// do stuff
}
}
...
See the JavaDoc for AtomicBoolean to grok what is going on there (assuming it is available in Android's Java).
Wrap everything in outerMethod that you want to run only once in a synchronized block:
private void outerMethod() {
synchronized (this) {
if(!outerMethodHasBeenCalled) {
// do stuff
}
outerMethodHasBeenCalled = true;
}
}
That way, the first time the method is called, only one thread will be allowed into the synchronized block at a time. The first one will execute the code in the if statement, then set outerMethodHasBeenCalled to true. The other threads will see that it is true, and skip the if code.