Method Reflect - Call sequence of methods - java

I am trying to learn Method Reflect so I can apply in my Java application.
I created two POJO classes.
Wishes.java
public class Wishes {
private String greeting;
public String getGreeting() {
this.greeting="Good Afternoon!";
return greeting;
}
public void setGreeting(String greeting) {
this.greeting = greeting;
}
}
Day.java
public class Day {
private Wishes wishes;
public Wishes getWishes() {
return wishes;
}
public void setWishes(Wishes wishes) {
this.wishes = wishes;
}
}
This is what I do in my main method. DemoApp.java
public class DemoApp {
public static void main(String[] args) {
try {
Class cls=Wishes.class;
Method method1=cls.getDeclaredMethod("getGreeting");
String result1=(String) method1.invoke(cls.newInstance());
System.out.println(result1);
Class clazz=Day.class;
Method method=clazz.getDeclaredMethod("getWishes().getGreeting");
String result=(String) method.invoke(clazz.newInstance());
System.out.println(result);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
I run the application. For the first one I am getting exact output as it's straight forward. But for the second I am getting exception. Here is the console output and stacktrace.
Good Afternoon!
java.lang.NoSuchMethodException: com.myapp.demo.Day.getWishes().getGreeting()
at java.lang.Class.getDeclaredMethod(Class.java:2004)
at com.myapp.demo.DemoApp.main(DemoApp.java:17)
How to call the getGreeting method from getWishes from using Day class with Method reflect? Is it possible? Otherwise what is the best way to do that with method reflect?
In my application, the method name I am getting is from one XML file. So it may contain single method or sequence of method calls like the above.

first of all in Day class you should initiate wishes
private Wishes wishes = new Wishes();
second you need to this:
Method method=clazz.getDeclaredMethod("getWishes");
Object result= method.invoke(clazz.newInstance());
Method method2=result.getClass().getDeclaredMethod("getGreeting");
String result2=(String) method2.invoke(cls.newInstance());
System.out.println(result2);

The method Class#getDeclaredMethod takes the name of a method and the types of its parameters. You are handing the string getWishes().getGreeting what is not a valid method name. You want to use
Method method = clazz.getDeclaredMethod("getWishes");
what should work in order to get the instance of Wishes from your Day instance. For the received instance, you can then call the getGreeting method reflectively. Method chaining as you suggest it does not work with reflection. There are however libraries easing the reflection API as for example for bean access of chained properties. For your learning purposes, you however need to chain the reflective calls manually.

Reflective calls are not stacked. So the way you are calling the method getGreeting doesn't work.
You can try this way instead:
Class cls=Wishes.class;
Method method1=cls.getDeclaredMethod("getGreeting");
String result1=(String) method1.invoke(cls.newInstance());
System.out.println(result1);
Class clazz=Day.class;
Object ob = clazz.newInstance();
Method method2=clazz.getDeclaredMethod("setWishes", cls);
method2.invoke(ob, cls.newInstance());
Method method=clazz.getDeclaredMethod("getWishes");
Object day =(Object) method.invoke(ob);
System.out.println(((Wishes)day).getGreeting());
Note: This snippet can further be refactored to suit your requirements

There is no such method "getWishes().getGreeting" on the Day class. what you have to do is.
invoke "Day.getWishes() and get the output
on top of the above output object invoke getGreeting
On sequences you have to execute one by one.
By the way, I think it is worth having a look at JXPath library as an alternative.
you can give a complex object and do a xpath search.

Reflection calls don't stack - there is no method with the name "getWishes().getGreeting()" in class Day.
You need to first call "Day.getWishes()" and then call "getGreeting()" on the returned object.

Related

How to wrap exceptions handling in helper class with lambda expressions

I am having troubles while trying to refactor exception handling logic in an helper class.
My code uses a repository which accesses a database and might throw the custom exception RepositoryException. If such exception is thrown by the repository, I want my code to catch it and set an error label in the graphical user interface (view):
... // more code
try {
existingCourse = repository.findByTitle(course.getTitle()); // <- throws RepositoryException
} catch (RepositoryException e) {
view.showError(e.getMessage(), course);
return;
}
... // some more code
The point is that this code is repeated several times and I would prefer to have it refactored in an helper class.
This is what I came up to after some experiments:
A custom FunctionalInterface called ThrowingSupplier, which represent the code that throws the exception.
A TransactionManager helper class, with a catcher methods that accepts a ThrowingSupplier
This is the related code (BaseEntity is just a base class for entities in my domain, as you might guess):
// ThrowingSupplier.java
#FunctionalInterface
public interface ThrowingSupplier<T extends BaseEntity> {
T get() throws RepositoryException;
}
/* ------------------------------------------------------ */
// ExceptionManager.java
public final class ExceptionManager<T extends BaseEntity> {
private T result;
private String exceptionMessage;
ExceptionManager() {
}
public boolean catcher(ThrowingSupplier<T> supplier) {
try {
clearResult();
clearExceptionMessage();
result = supplier.get();
return true;
} catch (RepositoryException e) {
exceptionMessage = e.getMessage();
}
return false;
}
// public getters and 'clearers' for attributes
...
}
And this is how I am using this now:
...
em = new ExceptionManager();
... // more code
if (!em.catcher(() -> repository.findByTitle(course.getTitle()))) {
view.showError(em.getExceptionMessage(), course);
return;
}
existingCourse = em.getResult();
... // some more code
Now it seems to me that this does not give any advantages with respect to using directly the try catch in every repository invocation. This is mainly because I need both the return value of the repository method and a way to tell the caller if the repository call has been successful. As a variation I tried to add the showError call inside catcher, but then I must pass view and entity in every invocation of catcher, which I do not like very much as it makes the code less readable.
Is there another way to accomplish this in an elegant manner or it is better to leave the try catch in every call to the repository? Also, what is the standard way to deal with this problem?

Is it possible to execute code right before a field is accessed in java?

I am trying to automate the construction of some objects in java.
To do this, I have these sample classes:
class TestInjected extends CommonAncestor {
TestInjected() {
System.out.println("I am Test Injected");
}
void exist() {
System.out.println("Hey there, I exist");
}
}
class CommonAncestor {
CommonAncestor() {
super();
init();
}
void init() {
try {
Field f = this.getClass().getDeclaredField("x");
f.set(this, f.getType().newInstance());
} catch (NoSuchFieldException e) {
} catch (IllegalAccessException e) {
} catch (InstantiationException e) {
}
}
}
public class TestInjection extends CommonAncestor{
TestInjected x;
private TestInjected y;
private TestInjected getY() {
if (y == null) {
y = new TestInjected();
}
return y;
}
public TestInjection() {
super();
}
public void test() {
x.exist();
}
public void test2() {
getY().exist();
}
}
And I also have a testing class:
public class TestInjectionTest {
#Test
public void test1() {
TestInjection t = new TestInjection();
t.test();
t.test2();
}
}
What I am doing here is, on constructor, I check for the Field x, and I initialize it via reflection. This way, I make sure that whenever a method is called, like in this case, test(), Field x has already been initialized, and therefor, it works.
The second approach, is to force programmers to use a getter, in this case, for Field y, where this getter method makes sure to initialize the object.
However, I am wondering, if hava has any way to execute reflection, when a variable is accessed. Let's say, instead of having to execute reflection code on constructor, if somehow, that code could be executed whenever "x" is required.
i.e:
x.exist()
--> check x is getting called, initialize it, and then call exist()
Any reflection method, or any library, that gives me this?
I can't really understand what problem you are trying to solve, but I'm sure there is a better solution. Work with the platform, not against it. Having said that the answer is no in the general case. You could run something that rewrites the byte codes (essentially adding a getter behind the scenes) but you can't intercept field accesses out of the box.
Make the fields private and expose them with methods if you need to initialize them. Or do it in the constructor.
EDIT: based on your comments I think what you are really looking for is dependency injection. Take a look at CDI (https://docs.oracle.com/javaee/6/tutorial/doc/giwhl.html) or Spring (https://spring.io) or Guice (https://github.com/google/guice).

Dynamically loading method from external class

I am trying to load methods Customer.cypher and Customer.cypherCBC method from my class Configuration. Customer class is rendering from different environments so few environmets are having cypherCBC() and cypher() method and few are having only cypher() method.
Now i want to check if cypherCBC if not there in Customer class then load cypher() method. My function is so far;
try {
Class<?> customerClass = Class.forName("com.myapp.impl.service.Customer");
Object obj = customerClass.newInstance();
//here getting "NoSuchMethodException" exception
Method methodCBC = customerClass.getDeclaredMethod("cypherCBC", String.class); //line - 7
if(methodCBC.getName().equals("cypherCBC")){
methodCBC.invoke(obj, new String(dbshPass));
System.out.println("CYPHER_CBC: "
+ methodCBC.invoke(obj, new String(dbshPass)));
}else{
Method method = customerClass.getDeclaredMethod("cypher", String.class);
method.invoke(obj, new String(dbshPass));
System.out.println("CYPHER: " + method.invoke(obj, new String(dbshPass)));
}
}catch (Exception e){
e.printStackTrace();
}
Getting an error at line 7.
NoSuchMethodException:
com.myapp.impl.service.Customer.cypherCBC(java.lang.String)
that means for particular environment class Customer doesn't having cypherCBC() method, but ideally it should come in else part and execute cypher() method.
Class<?> client = null;
Object obj = null;
try{
client = Class.forName("com.myapp.impl.service.Client");
obj = client.newInstance();
}catch (InstantiationException ex) {
System.err.println("Not able to create Instance of Class");
} catch (IllegalAccessException ex) {
System.err.println("Not able to access Class");
} catch (ClassNotFoundException ex) {
System.err.println("Not able to find Class");
}
try {
Method methodCBC = client.getDeclaredMethod("cypherCBC", String.class);
System.out.println("CYPHER_CBC: " + methodCBC.invoke(obj, new String(dbshPass)));
}catch (NoSuchMethodException ex) {
System.err.println("Not able to find Method on class");
ex.printStackTrace();
} catch (Exception e){
e.printStackTrace();
}
That is exactly what is to be expected: getDeclaredMethod() throws that exception when no method exists that meets your specification. And you are wondering that it throws an exception if the required method is missing? Hint: better read the javadoc next time. Don't assume that something does something, but verify your assumptions!
Besides: read your code again. What is it doing? You are asking "give me the method named 'foo'". And then, your next step is to ask that method "is your name 'foo'". So even without reading javadoc, it should become clear that your logic is flawed.
As solution, you can implement a non-throwing lookup yourself, like
private Method lookupCypher(Class<?> client, String methodName) {
for (Method declaredMethod : client.getDeclardMethods()) {
if (declaredMethod.getName().equals(methodName)) {
Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
if (parameterTypes.length == 1 && parameterTypes[0].equals(String.class)) {
// so declaredMethod has the given name, and takes one string as argument!
return declaredMethod;
}
}
// our search didn't reveal any matching method!
return null;
}
Using that helper method, you can rewrite your code to:
Method toInvoke = lookupCypher(client, "cypherCBC");
if (toInvoke == null) {
toInvoke = lookupCypher(client, "cypher");
}
toInvoke(obj, new String ...
Or, with the idea from hunter in mind; a much more "OO like" version:
interface CustomerCypherWrapper {
void cypher(String phrase);
}
class NewCustomerWrapper() implements CustomerCypherWrapper {
#Override
void cypher(String phrase) {
new Customer.cypherCBC(phrase);
}
}
class oldCustomerWrapper() implements CustomerCypherWrapper {
#Override
void cypher(String phrase) {
new Customer.cypher(phrase);
}
}
And your client code boils down to:
CustomerCypherWrapper wrapper =
(lookupCypher(..., "cypherCBC") == null)
? new NewCustomerWrapper()
: new OldCustomerWrapper();
wrapper.cypher();
[ I hope you notice that my version A) is easier to read and B) doesn't contain any duplicated code any more. ]
And yes, an alternative implementation of the lookup method could just go like
private Method lookupCyper(Client<?>, String methodName) {
try {
return client.getDeclaredMethod(methodName, String.class);
} catch ....
and return null;
}
... return your public cypherCBC method
But that is an "uncommon practice" in Java. In Java, we ask for permission; instead of forgiveness. Unlike other languages
if you compile the application with a Customer class which has both method,you can use reflection once to check whether the cypherCBC method available or not at runtime, then you can keep that status, you can call the method without using reflection
if(newVersion)
{
customer.cypherCBC(arg);
}
else
{
customer.cypher(arg);
}
But to write a better application,you should use two version baselines.
even though this is a small code fragment you should setup a another module to hide this Customer class and its interactions,that module should have two versions. but your main module has only single version.Now when you you deliver the application , product should be packaged with right version baseline based on compatibility for the target environment.
Although reflection works (as explained in the other answers). if you have control over the Customer class, you can try a non-reflection approach.
interface CBCCypherable {
public String cypherCBC(String pass);
}
You can now have two versions of Customer class, one that implements CBCCypherable and one that doesn't. And when you call it, it looks like this:
Customer c = new Customer();
if (c instanceof CBCCypherable) {
((CBCCypherable)c).cypherCBC(pass);
} else {
c.cypher(pass);
}
What you get with this solution is much simpler code, and as a bonus the compiler will check that you use the correct method name and parameter types. Unlike with reflection, where that's all your job, and you have to run the code to find out if something's wrong.
P.s.: I don't know if this is just sample code or you are really encrypting/hashing passwords here, but it's generally considered a bad idea to roll your own security code.

Reflector: How to list getters of a class and invoke them in Java?

The following SO post shows very nicely how to use introspector to list the getters associated with a class.
Java Reflection: How can i get the all getter methods of a java class and invoke them
The code I am using from this post is:
for(PropertyDescriptor propertyDescriptor :
Introspector.getBeanInfo(User.class,Object.class).getPropertyDescriptors()){
System.out.println(propertyDescriptor.getReadMethod());
}
This works fine for my 'User' class, with the output being:
public java.lang.String com.SingleEntity.mind_map.User.getName()
public int com.SingleEntity.mind_map.User.getNumber_of_entries()
public java.lang.String com.SingleEntity.mind_map.User.getUser_created_date()
My question now is, how do I now invoke those methods? If this is explained somehow in the linked SO I apologise but I don't understand it and would really appreciate an example.
Naturally I know how to invoke a Class method normally, but the assumption here is that the getters are unknown to the program until the above code discovers them.
PropertyDescriptor.getReadMethod() returns a Method object.
Simply use Method.invoke(Object instance, Object... args).
Something in the lines of...
for(PropertyDescriptor propertyDescriptor :
Introspector.getBeanInfo(User.class,Object.class).getPropertyDescriptors()){
try {
Object value = propertyDescriptor
.getReadMethod()
.invoke(myUserInstance, (Object[])null);
}
catch (IllegalAccessException iae) {
// TODO
}
catch (IllegalArgumentException iaee) {
// TODO
}
catch (InvocationTargetException ite) {
// TODO
}
}

Use of try/catch inside constructor calling another constructor

I m having a problem of calling a constructor with arguments from default constructor.
Class A {
private static Properties properties;
A(Properties property){
// do some checks
try{
load(property, fileName)
} catch(IOException e) {
throw new RuntimeException();
}
}
A(){
this(load(properties));
}
private static Properties load(Properties properties, String fileName ) throws IOException {
try {
properties.load(A.class.getClassLoader()
.getResourceAsStream(fileName));
} catch (IOException ioException) {
throw new IOException("Unable to process the properties File. " + fileName, ioException);
}
return properties;
}
}
My problem is: In Default constructor I wanted to use try/catch block and do the same operation of throwing a run time exception. Can you help me out as what can be done in this?
WRT this post: chaining constructors in Java without throwing exceptions from the default constructor
I have an option of putting try/catch inside another method. But is there any other way?
P.S: I do not want to use 'throws'
Java does not allow chained constructor calls to be enclosed within a try block, since such constructs could if not restricted allow an object whose base object threw an exception to end up being returned to calling code. This makes it difficult to express certain concepts involving resources like files [e.g. it would be helpful to have a constructor open a file before chaining to the parent and close it afterward, but there's no way to safely have a constructor take responsibility for a file which is opened before chaining to the parent]. The best one can do in Java is avoid public constructors which might throw exceptions and instead use factory methods which can be better equipped to handle them.
Option 1: Pass the other constructor a new empty instance of Properties:
class A
{
public A()
{
this(new Properties());
}
// rest of code...
}
Option 2: Pass the other constructor a null instance of Properties. You'll then have to guard against null in load(...), but you probably should be anyway:
class A
{
public A()
{
this(null);
}
// rest of code...
}
Option 3: Pass the other constructor a default instance of Properties:
class A
{
private static final Properties defaultProperties;
static
{
defaultProperties = new Properties();
// populate here however you wish
}
public A()
{
this(defaultProperties);
}
// rest of code...
}

Categories