I have a functor object:
private static Func1<MyEvent, Observable<Data>> getDataOnEvent = new Func1<MyEvent, Observable<Data>>() {
#Override
public Observable<Data> call(MyEvent event) {
return ApiFactory.get().getData()
}
};
For its invoking I need to do this:
result = getDataOnEvent.call(someEvent)
Is it possible to do this instead:
result = getDataOnEvent(someEvent)
Like it is done with Python and Javascript? Maybe a new version of java OR some library like Lombok?
Just use,
private static Observable<Data> getDataOnEvent(MyEvent event) {
return ApiFactory.get().getData()
}
and you can call result = getDataOnEvent(someEvent); whenever you need it. As you can see, writing it this way, will save even more boiler code than the five letters .call on the invocation side.
If Func1 is a functional interface, you can use ContainingClass::getDataOnEvent wherever a Func1<MyEvent, Observable<Data>> is expected. You can also store it into a static variable, if you prefer using the simple identifier getDataOnEvent as function:
private static Func1<MyEvent, Observable<Data>> getDataOnEvent
= ContainingClass::getDataOnEvent;
Then you can use getDataOnEvent(event) to call it or getDataOnEvent to refer to it as a Func1 instance whenever you need it.
If Func1 is not a functional interface, then you can’t create the function in this compact form, but on the other hand, in that case it wouldn’t be reasonable to ask for a support for calling an arbitrary method without naming it explicitly, either.
I know what you mean, groovy code call a closure like this:
def code = { 123 };
//can be called like any other method if the variable is a closure.
assert code() == 123;
//can be call explicitly by using `call` method
assert code.call() == 123;
javascript code call a function like this:
let code = () => 123;
//can be called like any other function if the variable is a function.
assert code() == 123;
//can be call explicitly by using `call` method
assert code.call() == 123;
But I can tell you java gammar not support this feature for fields/variables, maybe in the next jdk will be enable this feature which a field/variable refer to Callable.
Fortunately, Single-Static-Import Declarations supports calling a method directly if the static member is a method, for example:
import static java.lang.Math.abs;
assert abs(-1) == 1;
If you really want to make an identifier called like a method call, you can fake something like this:
class ApiFactory {
public static Func1<MyEvent, Observable<Data>> getDataOnEvent = new Func1<MyEvent, Observable<Data>>() {
public Observable<Data> call(MyEvent event) {
return ApiFactory.get().getData();
}
};
public static Observable<Data> getDataOnEvent(MyEvent event) {
return getDataOnEvent.call(event);
}
}
then you can call like this:
import static ${package}.ApiFactory.getDataOnEvent;
// which is calling a static method
result = getDataOnEvent(event);
// which is calling a static field
result = getDataOnEvent.call(event);
Related
I have several methods in a class that require a boolean to be set to true in order to execute correctly.
I could write the if statement in each method, but it is not convenient if I or someone else wants to ad another method. I or he could forget about the check.
Is there a way in java to execute a method before each other methods (exactly like JUnit does with #BeforeEach ) in a class ?
Edit: Lots of very interesting techniques/answers/concepts proposed. I'll be in touch when I've understood them. Thanks.
Lets make a method turnBooleanTrue() where effectively the boolean is set to true in order for the method to be execute correctly.
Then, you can write up your very own InvocationHandler that would intercept calls to your objects, and then reflectively (using reflection API) invoke first the turnBooleanTrue() method followed by the method to which the call was made.
Will look something like this
public class MyClassInvocationHandler implements InvocationHandler {
// initiate an instance of the class
MyClass myClass = new MyClassImpl();
#Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// look up turnBooleanTrue() method
Method turnBooleanTrue = myClass.getClass().getMethod("turnBooleanTrue");
// invoke the method
turnBooleanTrue.invoke(...); // toggle the boolean
// invoke the method to which the call was made
// pass in instance of class
Object returnObj = method.invoke(myClass, args);
return returnObj;
}
EDIT
Added some lines to have an object of MyClass initialized. You need something to invoke the method on and maintain the state. Changed util to myClass in the code example above.
Considering my use case, it was a bit overkill to use AOP or other concepts. So I basically did a check in each functions.
With AOP, this is how what you need would look:
// wraps around all methods in your class that have a boolean parameter
#Around(value = "#target(*..YourClass) && args(yourBool)", argNames = "jp,yourBool")
Object scheduleRequest(ProceedingJoinPoint jp, boolean yourBool) {
if (yourBool) {
jp.proceed(yourBool);
} else {
throw new RuntimeException("cannot execute this method!");
}
}
This would handle the case that the method take the boolean you say needs evaluation as its (only) parameter. If it comes from a different source, you may need to wire it into the aspect somehow, that depends on your overall design.
I suggest a simple solution by dividing your workflow in four components.
You have an interface you use to execute commands.
You have an interface that defines which commands you can use.
You have one wrapper that analyzes your boolean value.
You have an implementation of the work performing class, that implements the second interface.
Your wrapper initialize the worker.
Your wrapper exposes an action performing command that accepts the executing interface.
if the boolean is true, pass the worker to the executing interface work method.
the executing interfaces work method calls the work function on the command instance interface, the worker.
See it online: https://ideone.com/H6lQO8
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
WorkDistributer wd = new WorkDistributer();
wd.enable();
wd.performAction((w) -> {w.printHello();});
wd.disable();
wd.performAction((w) -> {w.printHello();});
wd.enable();
wd.performAction((w) -> {w.printAnswer();});
wd.disable();
wd.performAction((w) -> {w.printAnswer();});
}
}
class WorkDistributer
{
private boolean enabled = false;
private ActionPerformer worker;
public WorkDistributer() {
this.worker = new Worker();
}
public void enable() {
enabled = true;
}
public void disable() {
enabled = false;
}
public void performAction(ActionCommand command) {
if(this.enabled) {
command.run(this.worker);
}
}
}
class Worker implements ActionPerformer {
public void printHello() {
System.out.println("hello");
}
public void printAnswer() {
System.out.println(21 * 2);
}
}
interface ActionPerformer {
public void printHello();
public void printAnswer();
}
interface ActionCommand {
public void run(ActionPerformer worker);
}
Suppose that I have the following method:
void test () {...}
I am getting this method via reflection, but invoking it will be very slow, so I want to get Runnable from it as if I will write
this::test
Is there any way to achieve this?
I need an implementation for method like this: Runnable toRunnable(Method method); So we are getting a Method and we need to return Runnable
This is not exactly equivalent to this::test, since that also uses the this instance to bind to, so you will also have to pass an instance to bind to. But then you can use method handles, which is the underlying implementation for something like this::test.
With a class like this:
public class MyClass {
public void test() {
System.out.println("Test Called");
}
}
You can create this method:
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
public static Runnable toRunnable(Method method, Object instance) throws ReflectiveOperationException {
Lookup lookup = lookup();
MethodHandle test = lookup.unreflect(method);
try {
return (Runnable) LambdaMetafactory.metafactory(
lookup,
"run",
methodType(Runnable.class, instance.getClass()),
methodType(void.class),
test,
methodType(void.class)
).getTarget().invoke(instance);
} catch (Throwable e) {
throw new RuntimeException("Should not occur", e);
}
}
And call it like this:
Object ref = new MyClass(); // get from somewhere
Runnable result = toRunnable(ref.getClass().getMethod("test"), ref);
result.run(); // prints 'Test Called'
The caveat is that the test method has to be accessible from the point at which you're calling lookup(), you can get around this either by passing the Lookup to the method manually, and creating it at a place where you can access the test method. Or if you're in Java 9 you can use privateLookup(Class<?>, Lookup) instead, but the Lookup you pass to that needs to be created in the same module as the method you're trying to access. (in short, method handles has a few more access restrictions to it). But if the method and class you're trying to access are publicly accessible then there's no problem.
I'm trying to override a private method on a Java class using meta programming. The code looks something like this:
// Java class
public class MyClass{
private ClassOfSomeSort property1;
private ClassOfSomeOtherSort property2;
public void init(){
property1 = new ClassOfSomeSort();
property2 = new ClassOfSomeOtherSort();
doSomethingCrazyExpensive();
}
private void doSomethingCrazyExpensive(){
System.out.println("I'm doing something crazy expensive");
}
}
// Groovy class
public class MyClassTest extends Specification{
def "MyClass instance gets initialised correctly"(){
given:
ExpandoMetaClass emc = new ExpandoMetaClass( MyClass, false )
emc.doSomethingCrazyExpensive = { println "Nothing to see here..." }
emc.initialize()
def proxy = new groovy.util.Proxy().wrap( new MyClass() )
proxy.setMetaClass( emc )
when:
proxy.init()
then:
proxy.property1 != null
proxy.property2 != null
}
}
The problem is that the overridden implementation of doSomethingCrazyExpensive isn't called - I think that this is because the private method is called by the init() method internally and not called through the metaClass. If I call myProxy.doSomethingCrazyExpensive() directly, the overridden method is invoked, so the meta-programming does work to some degree.
Is there a way to use meta programming to override a method on a Java class (or instance) in such a way that the overridden implementation is called when it is invoked internally?
Groovy as operator is quite powerful, and can create proxies out of concrete types whose changes are visible in Java. Sadly, seems like it can't override private methods, though i managed to change a public method:
Java class:
public class MyClass{
public void init(){
echo();
doSomethingCrazyExpensive();
}
public void echo() { System.out.println("echo"); }
private void doSomethingCrazyExpensive(){
System.out.println("I'm doing something crazy expensive");
}
}
Groovy test:
class MyClassTest extends GroovyTestCase {
void "test MyClass instance gets initialised correctly"(){
def mock = [
doSomethingCrazyExpensive: { println 'proxy crazy' },
echo: { println 'proxy echo' }
] as MyClass
mock.init()
mock.doSomethingCrazyExpensive()
}
}
It prints:
proxy echo
I'm doing something crazy expensive
proxy crazy
So the public method got intercepted and changed, even when being called from Java, but not the private one.
You cannot override a method called from Java code in Groovy using metaClass.
That's why you won't be able to "mock" the call to this private method in Java: it is being called by the Java class itself, not from Groovy.
This limitation wouldn't apply, of course, if your class was written in Groovy.
I would suggest that you refactor the Java class if you can so that you can use normal means to mock the expensive method call. Or even make the method protected, then override it in a sub-class.
I stumbled on this question and thought I should provide a different answer: Yes you can override an existing method - you just have to change the meta class to ExpandoMetaClass.
This happens automatically when you add your first method, for example.
Here's an example:
println ""
class Bob {
String name
String foo() { "foo" }
void print() { println "$name = ${foo()} ${fum()} metaclass=${Bob.metaClass}"}
def methodMissing(String name, args) { "[No method ${name}]" }
}
new Bob(name:"First ").print()
Bob.metaClass.fum = {-> "fum"}
new Bob(name:"Second").print()
Bob.metaClass.fum = {-> "fum"}
new Bob(name:"Third ").print()
Bob.metaClass.foo = {-> "Overriden Foo"}
new Bob(name:"Fourth").print()
The results are:
First = foo [No method fum] metaclass=org.codehaus.groovy.runtime.HandleMetaClass#642a7222[groovy.lang.MetaClassImpl#642a7222[class Bob]]
Second = foo fum metaclass=groovy.lang.ExpandoMetaClass#21be3395[class Bob]
Third = foo fum metaclass=groovy.lang.ExpandoMetaClass#21be3395[class Bob]
Fourth = Overriden Foo fum metaclass=groovy.lang.ExpandoMetaClass#21be3395[class Bob]
You can see after the fum method was added the meta class changed to an expando. Now when the attempt is made to override the original foo - it works.
It seems you can't use Groovy metaprogramming to replace methods of Java classes - even public methods - try the following in the Groovy console to confirm:
ArrayList.metaClass.remove = { obj ->
throw new Exception('remove')
}
ArrayList.metaClass.remove2 = { obj ->
throw new Exception('remove2')
}
def a = new ArrayList()
a.add('it')
// returns true because the remove method defined by ArrayList is called,
// i.e. our attempt at replacing it above has no effect
assert a.remove('it')
// throws an Exception because ArrayList does not define a method named remove2,
// so the method we add above via the metaClass is invoked
a.remove2('it')
If you can modify the source code of MyClass, I would either make doSomethingCrazyExpensive protected, or preferably, refactor it so that it's more test-friendly
public class MyClass {
private ClassOfSomeSort property1;
private ClassOfSomeOtherSort property2;
private CrazyExpensive crazyExpensive;
public MyClass(CrazyExpensive crazyExpensive) {
this.crazyExpensive = crazyExpensive;
}
public void init(){
property1 = new ClassOfSomeSort();
property2 = new ClassOfSomeOtherSort();
crazyExpensive.doSomethingCrazyExpensive();
}
}
public interface CrazyExpensive {
public void doSomethingCrazyExpensive();
}
After making the changes above, when testing MyClass you can easily instantiate it with a mock/stub implementation of CrazyExpensive.
I am new to Mockito, please help in understanding the basic.
According to me above code is supposed to print 5 when mocked.add(6,7) gets called , but add() method is not getting called and the code prints 0.. why ? any solution for this code ?
import org.mockito.Mockito;
import static org.mockito.Mockito.*;
class Calc{
int add(int a,int b){
System.out.println("add method called");
return a+b;
}
}
class MockTest{
public static void main(String[] args) {
Calc mocked=mock(Calc.class);
when(mocked.add(2,3)).thenReturn(5);
System.out.println(mocked.add(6,7));
}
}
In order to get result of 5, you have to pass the exact params as when you set up the when..then. Otherwise mockito will return a 'default' value (which is 0 for integer:
What values do mocks return by default?
In order to be transparent and unobtrusive all Mockito mocks by
default return 'nice' values. For example: zeros, falseys, empty
collections or nulls. Refer to javadocs about stubbing to see exactly
what values are returned by default.
If you want to return 5 for any integer then use:
when(mocked.add(Mockito.any(Integer.class),Mockito.any(Integer.class))).thenReturn(5);
A "mock" is just an empty dummy object that simulates behaviour of a "real" object. If you define a behaviour such like when(mocked.add(2,3)).thenReturn(5); you specifically tell this mock what to do, when it receives those exact values.
mocked.add(6,7) will return 0 at that point, since you haven't defined its behaviour for those values and therefore uses a default value. So if you want to cover all possible inputs, you can go with the solution #MaciejKowalski posted and use the generic matchers like Mockito.any(Integer.class).
Still I believe it is not clear how to correctly handle mocks. Mocks are a way of providing external dependencies to a system-under-test without the need to set up a whole dependency tree. The real methods inside that class are usually not called. That's what something like when(mocked.add(2,3)).thenReturn(5); means. It tells the mock to behave like the real dependency without actually having it at hand.
An example could look like this:
public class TestClass {
private ExternalDependency dep;
public void setDep(ExternalDependency dep) {
this.dep = dep;
}
public int calculate() {
return 5 + dep.doStuff();
}
}
public class ExternalDependency {
public int doStuff() {
return 3;
}
}
Now in your test code you can use mocks like this:
#Test
public void should_use_external_dependency() {
// Aquire a mocked object of the class
ExternalDependency mockedDep = Mockito.mock(ExternalDependency.class);
// Define its behaviour
Mockito.when(mockedDep.doStuff()).thenReturn(20);
TestClass sut = new TestClass();
sut.setDep(mockedDep);
// should return 25, since we've defined the mocks behaviour to return 20
Assert.assertEquals(25, sut.calculate());
}
If sut.calculate() is invoked, the method in ExternalDependency should not be really called, it delegates to the mocked stub object instead. But if you want to call the real method of the real class, you could use a Spy instead with Mockito.spy(ExternalDependency.class) or you could do that with when(mockedDep.doStuff()).thenCallRealMethod();
I'm trying to override a private method on a Java class using meta programming. The code looks something like this:
// Java class
public class MyClass{
private ClassOfSomeSort property1;
private ClassOfSomeOtherSort property2;
public void init(){
property1 = new ClassOfSomeSort();
property2 = new ClassOfSomeOtherSort();
doSomethingCrazyExpensive();
}
private void doSomethingCrazyExpensive(){
System.out.println("I'm doing something crazy expensive");
}
}
// Groovy class
public class MyClassTest extends Specification{
def "MyClass instance gets initialised correctly"(){
given:
ExpandoMetaClass emc = new ExpandoMetaClass( MyClass, false )
emc.doSomethingCrazyExpensive = { println "Nothing to see here..." }
emc.initialize()
def proxy = new groovy.util.Proxy().wrap( new MyClass() )
proxy.setMetaClass( emc )
when:
proxy.init()
then:
proxy.property1 != null
proxy.property2 != null
}
}
The problem is that the overridden implementation of doSomethingCrazyExpensive isn't called - I think that this is because the private method is called by the init() method internally and not called through the metaClass. If I call myProxy.doSomethingCrazyExpensive() directly, the overridden method is invoked, so the meta-programming does work to some degree.
Is there a way to use meta programming to override a method on a Java class (or instance) in such a way that the overridden implementation is called when it is invoked internally?
Groovy as operator is quite powerful, and can create proxies out of concrete types whose changes are visible in Java. Sadly, seems like it can't override private methods, though i managed to change a public method:
Java class:
public class MyClass{
public void init(){
echo();
doSomethingCrazyExpensive();
}
public void echo() { System.out.println("echo"); }
private void doSomethingCrazyExpensive(){
System.out.println("I'm doing something crazy expensive");
}
}
Groovy test:
class MyClassTest extends GroovyTestCase {
void "test MyClass instance gets initialised correctly"(){
def mock = [
doSomethingCrazyExpensive: { println 'proxy crazy' },
echo: { println 'proxy echo' }
] as MyClass
mock.init()
mock.doSomethingCrazyExpensive()
}
}
It prints:
proxy echo
I'm doing something crazy expensive
proxy crazy
So the public method got intercepted and changed, even when being called from Java, but not the private one.
You cannot override a method called from Java code in Groovy using metaClass.
That's why you won't be able to "mock" the call to this private method in Java: it is being called by the Java class itself, not from Groovy.
This limitation wouldn't apply, of course, if your class was written in Groovy.
I would suggest that you refactor the Java class if you can so that you can use normal means to mock the expensive method call. Or even make the method protected, then override it in a sub-class.
I stumbled on this question and thought I should provide a different answer: Yes you can override an existing method - you just have to change the meta class to ExpandoMetaClass.
This happens automatically when you add your first method, for example.
Here's an example:
println ""
class Bob {
String name
String foo() { "foo" }
void print() { println "$name = ${foo()} ${fum()} metaclass=${Bob.metaClass}"}
def methodMissing(String name, args) { "[No method ${name}]" }
}
new Bob(name:"First ").print()
Bob.metaClass.fum = {-> "fum"}
new Bob(name:"Second").print()
Bob.metaClass.fum = {-> "fum"}
new Bob(name:"Third ").print()
Bob.metaClass.foo = {-> "Overriden Foo"}
new Bob(name:"Fourth").print()
The results are:
First = foo [No method fum] metaclass=org.codehaus.groovy.runtime.HandleMetaClass#642a7222[groovy.lang.MetaClassImpl#642a7222[class Bob]]
Second = foo fum metaclass=groovy.lang.ExpandoMetaClass#21be3395[class Bob]
Third = foo fum metaclass=groovy.lang.ExpandoMetaClass#21be3395[class Bob]
Fourth = Overriden Foo fum metaclass=groovy.lang.ExpandoMetaClass#21be3395[class Bob]
You can see after the fum method was added the meta class changed to an expando. Now when the attempt is made to override the original foo - it works.
It seems you can't use Groovy metaprogramming to replace methods of Java classes - even public methods - try the following in the Groovy console to confirm:
ArrayList.metaClass.remove = { obj ->
throw new Exception('remove')
}
ArrayList.metaClass.remove2 = { obj ->
throw new Exception('remove2')
}
def a = new ArrayList()
a.add('it')
// returns true because the remove method defined by ArrayList is called,
// i.e. our attempt at replacing it above has no effect
assert a.remove('it')
// throws an Exception because ArrayList does not define a method named remove2,
// so the method we add above via the metaClass is invoked
a.remove2('it')
If you can modify the source code of MyClass, I would either make doSomethingCrazyExpensive protected, or preferably, refactor it so that it's more test-friendly
public class MyClass {
private ClassOfSomeSort property1;
private ClassOfSomeOtherSort property2;
private CrazyExpensive crazyExpensive;
public MyClass(CrazyExpensive crazyExpensive) {
this.crazyExpensive = crazyExpensive;
}
public void init(){
property1 = new ClassOfSomeSort();
property2 = new ClassOfSomeOtherSort();
crazyExpensive.doSomethingCrazyExpensive();
}
}
public interface CrazyExpensive {
public void doSomethingCrazyExpensive();
}
After making the changes above, when testing MyClass you can easily instantiate it with a mock/stub implementation of CrazyExpensive.