Instantiating an Object using Java Reflection - java

I am testing a private method using JUnit and I am invoking it using Reflection. The error I am getting is java.lang.InstantiationException. I know it is not creating an instance of Class but I am not sure what I am doing wrong. Object object = clazz.newInstance(); is the line that throws Exception.
Method under test
private int _getType(String type) {
if ("DATE".equalsIgnoreCase(type)) return Types.DATE;
if ("STRING".equalsIgnoreCase(type)) return Types.VARCHAR;
if ("INT".equalsIgnoreCase(type)) return Types.INTEGER;
if ("TIMESTAMP".equalsIgnoreCase(type)) return Types.TIMESTAMP;
return Types.NULL;
}
JUnit test
#Test
public void testGetType() throws Exception {
String type1 = "DATE";
String type2 = "STRING";
String type3 = "INT";
String type4 = "TIMESTAMP";
Class clazz = SpringStoredProcImpl.class;
Object object = clazz.newInstance();
Method method = object.getClass().getDeclaredMethod("getType", String.class);
method.setAccessible(true);
method.invoke(object, type1);
I don't have my asserts yet so please ignore it.
Thanks in advance.

You try to create an instance with a no argument constructor which does exist in your case.
As the constructors are public you should first create your object normally using the new keyword, then execute the rest of your code starting from Method method...
FYI, if you wanted to create your object by reflection it would be something like clazz.getConstructor(DataSource.class, String.class, ArrayList.class).newInstance(dataSource, sprocName, params) instead of simply clazz.newInstance()

Different answer: don't do that.
Why do you think you need to make this method private? It looks like the responsibility of this method is to "lookup" an enum type, based on string input. I think it would make much more sense to simply make this method package protected and avoid the reflection overhead/hassle.

Related

How to refer a private method for a Supplier or Consumer in java

I want to reuse a piece of code written in Private method of another class A. Like
class A
{
private String method(String data){
return "abcd";
}
}
List myList= getListFromSomeSource();
myList.stream()
.map(A::method)
.collect()....etc
The only way to access a private method of a class, if the class implementation does not provide such an option and if that implementation cannot be modified, is via reflection.
Assuming that the method function of class A has a String return type, a simple way to do so is
public static String invokeMethod(A object, String data) throws Exception {
Method method = A.class.getDeclaredMethod(“method”, String.class);
method.setAccessible(true);
return (String) method.invoke(object, data);
}
Since the Class A method in question is not static, an object reference would need to be used to access it, with or without reflection, e.g.
A object = new A(); // Create object of type A
String data = “...”; // Specify data input
String result = invokeMethod(object, data); // Call method
If such an object of type A cannot be created, or if the caller does not want to pass to invokeMethod a reference to such an object, the only other option left is actually rewriting the method function, outside Class A.

How to pass a method as an argument to a different method?

I have a method let's say in ClassA. I want to pass a method from ClassB as an argument to that method in ClassA. In this case I want to pass the getCode method from ClassB. I don't have any instance of ClassB and I'd like to achieve this without having to create one.
I've tried using simple method reference, but it does not work this way.
I don't want to make getCode a static method either.
public class ClassA {
public void validate() {
Validation validation = new Validation(ClassB::getCode, code);
//...
}
}
My final goal is to have a RequestValidator class to which add validations, each validation will be created with a specific method and a string in its constructor, in this case getCode from classB and code. Please note I only want one instance of RequestValidator. Something like this:
RequestValidator validator = new RequestValidator<>()
.addValidation(new Validation(ClassB::getCode, code))
.addValidation(new Validation(ClassB::getName, name));
getCode needs to be a static function, and the syntax would be ClassB.getCode. You would need ClassB to be imported into ClassA.
See:
Calling static method from another java class
Your use of a method reference will work just fine as long as you define the method arguments properly. You haven't given a lot of information, so I'm going to make some assumptions here. Please correct me if this isn't what you had in mind:
public class B {
public static String getCode() {
return "foobar"; // Replace with your own functionality
}
}
public class Validation {
Validation(Supplier<String> supplier, String code) {
String suppliedCode = supplier.get();
// Do your validation logic
}
}
public static void validate() {
Validation validation = new Validation(ClassB::getCode, code);
}
But this frankly feels like overkill. Why can't you just make your Validation constructor take two String arguments (or whatever types you happen to be using), and then do this?
public static void validate() {
Validation validation = new Validation(ClassB.getCode(), code);
}
Do you have a legitimate need to pass in a method reference instead of simply passing in the return value from the method call?

Invoke method on a argument with a cast using Byte Buddy

I'm very new to Byte Buddy, and I'm trying to use it to create implementations of an interface that execute getter methods on objects. My interface looks like this:
public interface Executor {
Object execute(final Object target);
}
And the idea is that if I have a class such as:
public class User {
...
public String getName() { return this.name; }
public String getSurname() { return this.surname; }
}
I need to be able to create one implementation of the Executor interface which execute(obj) method assumes obj is a User and calls its getName(), then another implementation which does the same for getSurname(), etc. Equivalent java code would therefore be:
public class MyHypotheticalByteBuddyExecutorImpl implements Executor {
#Override
Object execute(final Object target) {
return ((User) target).getName();
}
}
So the idea is to be able to create classes like the above for any combination of class + getter, like in this case User + getName().
I (think I) know how to make Byte Buddy create a class that almost does that:
final Method nameMethod = User.class.getMethod("getName", null);
final Class<?> myHypotheticalByteBuddyExecutorImpl =
new ByteBuddy()
.subclass(Object.class)
.implement(Executor.class)
.method(ElementMatchers.named("execute"))
.intercept(MethodCall.invoke(nameMethod).onArgument(0))
.make()
.load(ByteBuddyTest.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
.getLoaded();
...but then Byte Buddy rightly throws an Exception saying that I cannot execute method getName() on an Object. I'm assuming therefore that I'm lacking the ((User) target) cast:
Exception in thread "main" java.lang.IllegalStateException: Cannot invoke public java.lang.String com.example.User.getName() on class java.lang.Object
at net.bytebuddy.implementation.MethodCall$TargetHandler$ForMethodParameter$Resolved.toStackManipulation(MethodCall.java:2527)
at net.bytebuddy.implementation.MethodCall$Appender.toStackManipulation(MethodCall.java:3541)
at net.bytebuddy.implementation.MethodCall$Appender.apply(MethodCall.java:3502)
...
I believe this could be defined as a StackManipulation (I might be totally wrong), something like:
final StackManipulation typeCasting =
TypeCasting.to(TypeDescription.ForLoadedType.of(User.class));
But I cannot find anywhere in the Byte Buddy API how I can apply this cast (or any other code I might need for casting) to the argument of the execute(Object) method before executing the getter.
How can I implement this?
This should work by using dynamic typing which you can configure by:
MethodCall.invoke(nameMethod)
.onArgument(0)
.withAssigner(Assigner.DEFAULT, Assigner.Typing.DYNAMIC);
The stack manipulation is used for creating custom byte code, I do not think that this is what you want to do here.

How to mock methods in dynamically loaded jars

I have a class called Price with constructor, which I am dynamically loading via reflection:
public Price(Context context, String pair) {
this.context = context;
this.value1 = pair.substring(0, 3);
this.value2 = pair.substring(3, 6);
this.dps = context.getService().getm1(value1, value2).getm2();
}
However I want to mock the Context object
and I want
context.getService().getm1(value1, value2).getm2()
to return 5.
Here is what I have tried
//mocking the Context class
Class<?> contextClass = urlClassLoader.loadClass("com.algo.Context");
constructor =contextClass.getConstructor();
Object context = Mockito.mock(contextClass);
//trying to instantiate the Price class
Class<?> priceClass = urlClassLoader.loadClass("com.algo.Price");
constructor = priceClass.getConstructor(contextClass,String.class);
Mockito.when(context.getService().getm1(value1, value2).getm2().thenReturn(5));
Object price = constructor.newInstance(context,"PRICES");
However I have a red line under
context.getService()
The error says
The method getService() is undefined for the type Object
How can I get around this, my end goal is to create the Price object with the variable
dps
being an int 5, that is why I want to mock the Context object.
For me the only way is to implement your whole test using reflection which is really laborious especially in your case as you will need to do the same thing for each method call as you cannot mock directly context.getService().getm1(value1, value2).getm2().
Assuming that I have a class Context as below
public class Context {
public int getm1(String value1, String value2) {
return -1;
}
}
A normal test case would be:
#Test
public void normal() throws Exception {
Context context = Mockito.mock(Context.class);
Mockito.when(context.getm1(Mockito.anyString(), Mockito.anyString())).thenReturn(5);
Assert.assertEquals(5, context.getm1("foo", "bar"));
}
The same test using reflection would be:
#Test
public void reflection() throws Exception {
... // Here I get the classloader
// Get the class by reflection
Class<?> contextClass = urlClassLoader.loadClass("com.algo.Context");
// Mock the class
Object context = Mockito.mock(contextClass);
// Get the method by reflection
Method method = contextClass.getMethod("getm1", String.class, String.class);
// Invoke the method with Mockito.anyString() as parameter
// to get the corresponding methodCall object
Object methodCall = method.invoke(context, Mockito.anyString(), Mockito.anyString());
// Mock the method call to get what we expect
Mockito.when(methodCall).thenReturn(5);
// Test the method with some random values by reflection
Assert.assertEquals(5, method.invoke(context, "foo", "bar"));
}
Cannot really understand this issue. If you are working with an unknown type it cannot be typed as Context within the construtor.
But independently, an approach would be to create interfaces representing the expected structure of context and then mock the interfaces to return the value.
It is not necessary to really load the dynamic class within the test if it is mocked either way.

How to Avoid Constructor calling During Object Creation?

I want to avoid the constructor calling during object creation in java (either default constructor or user defined constructor) . Is it possible to avoid constructor calling during object creation???
Thanks in advance......
Simply extract the intialization logic that you want to avoid into another method called init. You can not avoid calling exactly one constructor.
No matter what pattern or strategy you use, at some point your will need to call a constructor if you want to create an object.
Actually, its possible under some circumstances by using classes from the JVM implementation (which do not belong to the JRE API and are implemenation specific).
One example here http://www.javaspecialists.eu/archive/Issue175.html
It should also be possible using sun.misc.Unsafe.allocateInstance() (Java7)
Also, the constructor is apparently bypassed when using the clone()-method to create a copy of an object (and the class doesn't override clone to implement it different from the Object.clone() method).
All of these possibilities come with strings attached and should be used carefully, if at all.
You can mock the constructors of a class. They will still be called, but not executed. For example, the following JUnit+JMockit test does that:
static class CodeUnderTest
{
private final SomeDependency someDep = new SomeDependency(123, "abc");
int doSomething(String s)
{
someDep.doSomethingElse(s);
return someDep.getValue();
}
}
static final class SomeDependency
{
SomeDependency(int i, String s) { throw new RuntimeException("won't run"); }
int getValue() { return -1; }
}
#Test
public void mockEntireClassIncludingItsConstructors()
{
new NonStrictExpectations() {
#Mocked SomeDependency mockDep;
{ mockDep.getValue(); result = 123; }
};
int result = new CodeUnderTest().doSomething("testing");
assertEquals(123, result);
}

Categories

Resources