NoSuchFieldException on getClass().getField() - java

java.lang.NoSuchFieldException: id
The below line is creating the exception.
String fieldValue =String.valueOf(studyplanCategory.getClass().getField(filterProperty).get(studyplanCategory));
studyplanCategory is a valid object and has got actual values. Beacuse of this exception the load method and the search function in the LazyLoading DataTable of my JSF webapp is not working.

From the Javadoc for Class.getField(...):
Returns a Field object that reflects the specified public member field
of the class or interface represented by this Class object. The name
parameter is a String specifying the simple name of the desired field.
The field to be reflected is determined by the algorithm that follows.
Let C be the class represented by this object:
If C declares a public field with the name specified, that is the
field to be reflected. If no field was found in step 1 above, this
algorithm is applied recursively to each direct superinterface of C.
The direct superinterfaces are searched in the order they were
declared. If no field was found in steps 1 and 2 above, and C has a
superclass S, then this algorithm is invoked recursively upon S. If C
has no superclass, then a NoSuchFieldException is thrown. See The Java
Language Specification, sections 8.2 and 8.3.
If the field you are trying to retrieve via:
studyplanCategory.getClass().getField(filterProperty)
is private, then you will get a NoSuchFieldException. For private fields, try this instead:
studyplanCategory.getClass().getDeclaredField(filterProperty)
And to get around potential illegal access exceptions when setting values via a field this way:
Field field = studyplanCategory.getClass().getDeclaredField(filterProperty);
field.setAccessible(true);
field.get(studyplanCategory);

App fires up this exception because its doesn't see attribudes your want to give back.
Method getField() return non-private attribudes so if your attribudes are private, method doesn't see them. You can check http://docs.oracle.com/javase/tutorial/reflect/member/fieldTrouble.html
So you can do that your attribudes will change on protected or public and then should work it right. But this way (its same like example on primefaces) simulate real database.
public List<Car> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,String> filters) {
List<Car> data = new ArrayList<Car>();
//filter
for(Car car : datasource) {
boolean match = true;
for(Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
String filterValue = filters.get(filterProperty);
String fieldValue = String.valueOf(car.getClass().getField(filterProperty).get(car));
...
So this list simulate real database only for example. If you want to use it. so you shoud do it on backing bean class and there do it. You open connection already with some filter or don't and then return data from database.
//EDIT: Man wrote that you should use getDeclaredField() but i did try this and it didn't work well, and throws up IlegalAccessException. When a pretype attribudes to protected, it works fine. I don't know why.

Best solutions for getClass().getField() problem are:
Use getDeclaredField() instead of getField()
1)
String propertyName = "test";<br/>
Class.forName(this.getClass().getName()).getDeclaredField(propertyName);
2)
String propertyName = "name";<br/>
Replace **"HelloWorld"** with your class name<br/>
HelloWorld.class.getDeclaredField(propertyName)

I had faced the same problem. My issue was my variables are not public . Make sure your class variables are public
private Object getVariableValue(Object clazz, String variableName) {
try {
Field field = clazz.getClass().getField(variableName);
return field.get(clazz);
} catch (NoSuchFieldException e) {
return "";
} catch (IllegalAccessException e) {
return "";
}
}

I agree that we should Use getDeclaredField() instead of getField()
private Field getOwnProperty(Object clazz, String propertyName) {
try {
return clazz.getClass().getDeclaredField(propertyName);
} catch (NoSuchFieldException e) {
log.warn( "Object has no property : " + propertyName );
return null;
}
}

Related

retrieving POJO objects programmatically?

Let, say for instance i have a POJO class employee with three attributes
1.Name (String)
2.Location (String)
3.Date of Birth (Date)
then i fired a query into database which retrieve first row of table and populate this POJO
with table data as follows:-
Name - john
location - USA
Date of Birth - 27/09/2014
To retrieve the values from this POJO i have to call getName(),getLocation() and getDOB().
But is there any method by which i can get all the values which is store in the POJO, in an Object type array without using getter method
for example:
Object[0] has the value "John".
Object[1] has the value "USA".
Object[2] has the value "27/09/2014".
(In my case, there are around 80 attributes in a class and number of these attributes increases because of client requirements and i am fetching each and every value by getter method and every time a single attribute is added i have to write a getter method in the code to fetch values. I basically want a more dynamic solution to this problem.)
you can try this:
String[] getObjectsPublicMethods(Object o)
{
Class clazz = o.getClass();
Method[] methods = clazz.getDeclaredMethods();
String[] result = new String[methods.length];
for (int i=0; i<methods.length; ++i)
{
try
{
result[i] = (String) methods[i].invoke(o, new Object[] {})
} catch (IllegalAccessException e)
{
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
} catch (InvocationTargetException e)
{
}
}
return result;
}
This method uses reflection to get the information you want, BUT
it assumes that the getter methods are declared public in this class AND
that all of the public methods return String.
I think what you are looking for is called reflection.
i hope this link helps http://docs.oracle.com/javase/tutorial/reflect/index.html
or this answer:
Is it possible to use Java Reflection to print out attributes of the parent class?

can annotation get context object?

Maybe title "can annotation get context object?" is not correct, but I don't know how to give it a right and clear one.
I use Spring AOP + Java Annotation to save log, here is my code:
CategoryAction.java :
#ServiceTracker(methodDesp="save category, category name:"+this.category.getName())
public String save() throws Exception
{
this.categoryService.save(this.category);
this.setJsonDataSimply(null);
return "save";
}
TrackAdvice.java :
public Object trackAround(ProceedingJoinPoint point) throws Throwable
{
String log = "success";
ServiceTracker tracker = null;
Method method = null;
AbstractAction action = null;
try
{
Object result = point.proceed();
action = (AbstractAction) point.getTarget();
MethodSignature signature = (MethodSignature) point.getSignature();
method = signature.getMethod();
tracker = method.getAnnotation(ServiceTracker.class);
return result;
}
catch (Exception e)
{
log = e.getMessage();
throw e;
}
finally
{
if (tracker != null)
{
String userId = (String) ActionContext.getContext().getSession().get(Constant.USERID);
if (userId == null)
{
userId = "unknown";
}
TrackLog t = new TrackLog();
t.setWhen(new Date());
t.setUserId(userId);
t.setResult(log);
t.setMethodName(action.getClass().getCanonicalName() + "." + method.getName());
t.setMethodDesp(tracker.methodDesp());
this.trackService.save(t);
}
}
}
ServiceTracker is my own annotation, in my TrackAdvice class, I get the current executing method, if the method has a ServiceTracker annotation, then save the methodDesp in annotation to database.
Now the question is the methodDesp in annotation is dynamic, I want to get this object and retrieve its category property.
It seems that Java Annotation doesn't support this, maybe it supports but I don't know how.
What you can do is use some sort of expression language in the annotation value and then run some interpreter in your advice code. One example using SPEL could look like this:
#ServiceTracker(methodDesp="save category, category name: #{category.name}")
And in your advice code, you can then extract the expression token, make use of a SpelExpression and pass it the target reference as root object (you may want to check what's available out of the box in the SPEL API for supporting your use-case(s)).
It seems that Java Annotation doesn't support this
You are correct - there is no way to do this in pure java.
The reason is that because annotations are static metadata that is wired into classes and defined at compile-time (this start to exist only at run-time, not compile-time).
In other words there is no straightforward way to make methodDesp of some annotated method of some class dynamic, since it's value has to be resolved statically, at compile-time.
However, technically there is a way to do something like you want. What I talk about is using javassist to either manipulate or create your classes (and annotations applied to them) at runtime. But be warned that this is rather hacky way and I generally would not recommend to go there.

Convert an attribute to its name

It is possible to access a class attribute by its name using the following code:
MyClass.class.getDeclaredField("myAtt");
is it possible to create a function which do reverse? i.e. a function which convert an attribute to its name?
EDIT: I'm adding this edit to make this more clear:
consider the following class:
class MyClass {
Integer myAttribute;
}
I am looking for a function which accepts myAttribute (itself, or a reference to it. idk!) and returns "myAttribute" string.
Try java.lang.reflect.Field.getName();
You can use Field#getName method : -
Field[] fields = MyClass.class.getDeclaredFields();
for (Field field: fields) {
System.out.println(field.getName());
}
PS: - You should name your classes starting with uppercase letters.
UPDATE: - Ok, if you have your name of the attribute: - private String attrName;, you can get the corresponding field my using: -
Field field = MyClass.class.getDeclaredField("attrName");
// Then do this. Which is meaningless. But I don't know why you want to do this
// Your fieldName will contain "attrName" which you know already
String fieldName = field.getName();
But fetching the name from the above field doesn't make sense. I would be surprised if you were looking for this only. But you can be more clear with your question.
If I understand your question you want to get the name of the Field thats current value matches the value of a variable.
private String getAttributeName(Object myInstance, Object myValue) throws IllegalAccessException
{
Field[] fields = MyClass.class.getDeclaredFields();
for (Field each : fields)
{
if (each.get(myInstance).equals(myValue))
return each.getName();
}
return null;
}
Then you can call it,
getAttributeName(myInstance, myValue);

How to know whether a property exists or not in a property file?

How to know whether a property exists or not in a property file in java?
According to http://java.sun.com/javase/6/docs/api/java/util/Properties.html, getProperty() returns null if the property was not found. You could also call propertyNames() or stringPropertyNames() and look to see whether the property name of interest is in the returned set.
Yet another alternative is to exploit the fact the Properties extends Hashtable<Object,Object> and use containsKey.
Just load the properties file and then try to get the desired property.
public String getProperty(String key)
Searches for the property with the specified key in this property list. If the key is not found in this property list, the default property list, and its defaults, recursively, are then checked. The method returns null if the property is not found.
http://java.sun.com/j2se/1.5.0/docs/api/java/util/Properties.html#getProperty(java.lang.String)
You can also call getProperty(String key, String defaultValue) and check if the return value is the defaultValue.
See https://docs.oracle.com/javase/8/docs/api/java/util/Properties.html#getProperty-java.lang.String-java.lang.String-
You can use hasProperty
AllValues.hasProperty("childList")
If you want to check that at the start of program you can do the following:
Create a class VerifiedProperties that extends Properties
Add all properties as fields of this class as public final int/String/boolean/etc...
Add private final String propertyNotValid="Property not valid" String to this class
Add private final String propertyNotFound="Property not found" String to this class
Override getProperty() method from Properties class.
You can add #Deprecated tag to suggest usage of the fields. It is impossible to hide this method because it is public in Properties class.
Initialize all fields in the constructor using getProperty() method or dedicated for type (look examples below)
Example methods that takes care of different property types:
#Override
#Deprecated
/*
Deprecated annotation added to suggest usage of the fields.
*/
public final String getProperty(String key)
{
String propertyValue = super.getProperty(key);
if (propertyValue != null)
{
return propertyValue;
}
else
{
throw new NoSuchFieldError(this.propertyNotFound + " " + key);
}
}
private int getIntegerProperty(String key)
{
String propertyValue = this.getProperty(key);
try
{
int propertyIntValue = Integer.parseInt(propertyValue);
return propertyIntValue;
}
catch (NumberFormatException e)
{
throw new NumberFormatException(this.propertyNotValid + " " + key);
}
}
private boolean getBooleanProperty(String key)
{
String propertyValue = this.getProperty(key);
try
{
boolean propertyBooleanValue = Boolean.parseBoolean(propertyValue);
return propertyBooleanValue;
}
catch (NumberFormatException e)
{
throw new NumberFormatException(this.propertyNotValid + " " + key);
}
}
private long getLongProperty(String key)
{
String propertyValue = this.getProperty(key);
try
{
long propertyLongValue = Long.parseLong(propertyValue);
return propertyLongValue;
}
catch (NumberFormatException e)
{
throw new NumberFormatException(this.propertyNotValid + " " + key);
}
}
Then you can create somewhere:
public static VerifiedProperties properties;
and use the properties that you need as properties.myProperty
Advantages:
you have full control over properties which includes exception handling and null checking
If property does not exist or is in incorrect format, you will have the information at the initialization of the program
You don't need to worry about parsing properties to different types than String in your code.
You can add validators to your String properties
You can easily refactor property name
If you are using external property file that can be modified by the user outside of your application, if provided change is incorrect or there are fields missing your program will not start.
Disadvantages:
For each property besides adding value to *.properties file you need to create field and assign value in the constructor. If you have a lot of properties then this file can look unpleasant.
Hints:
it is easier to mantain the file if you keep the same name for the field as in properties file.
(Netbeans) you can Toggle Rectangular Selection to add public final String and similar to many lines at once.
(Netbeans) to keep *.properties file clean you can use this solution.
The answer by crazyscot is now outdated. According to the new javadoc, the property will just get created if it doesn't exist,
"If there is no current set of system properties, a set of system properties is first created and initialized in the same manner as for the getProperties method".
Here is some trick how to find out is some file (not mandatory property file) exists in class path
public class FileUtil {
public static boolean isFileExists(String fileName){
return null != FileUtil.class.getResourceAsStream(fileName);
}
}
Sure it not always works as long it depends on class loading aspects

Pitfalls in getting member variable values in Java with reflection

I have an abstract class as follows. I want to get all the values of member variables.
public abstract class PARAMS {
public static final String NAME1 = "VAL1";
public static final String NAME2 = "VAL2";
public static final String NAME3 = "VAL3";
}
The values are retrieved using reflection as follows.
Field[] fields = PARAMS.class.getFields();
for (Field field : fields) {
String name = field.getName() ;
String value = (String) field.get(name);
}
This is the first time I am experimenting with reflection. Is this a correct way to achieve the goal? I would like to know what are the pitfalls in using reflection in this case.
You code iterates over both static and private fields. So you should check that you iterate over static fields only.
for (Field field : PARAMS.class.getFields()) {
if (Modifiered.isStatic(field.getModifiers())) continue;
String name = field.getName() ;
String value = (String) field.get(PARAMS.class);
}
NB: as Jon mentioned, for static field access the instance parameter is ignored. However, I prefer passing in the class instead of null since this is a better documentation of the indent.
It is however even better practice to annotate your fields with an annotation so that you only get those fields that you really want no other static fields added by other programmers (or even the Java language behind the scenes). If you do so, your code would look like
for (Field field : PARAMS.class.getFields()) {
if (!field.isAnnotationsPresent(YourAnnotation.class)) continue;
String name = field.getName() ;
String value = (String) field.get(PARAMS.class);
}
It's not quite correct - the argument to get should ideally be null for the sake of readability: the point of that argument is to give it a target for when you're retrieving instance fields.
So your code can be just:
Field[] fields = PARAMS.class.getFields();
for (Field field : fields) {
String name = field.getName() ;
String value = (String) field.get(null);
}
Now, this should work... but what are you going to do with these values? Is there any reason why you want to do this rather than creating an immutable Map<String, String> which is exposed directly?
Reflection is fine where it's necessary, but you haven't given enough information to determine whether it's actually necessary in this case.
another problem, getFields return all accessible fields (static or not) of this class and all its superclasses. Not a problem for the specific code you posted, since the only superclass is Object which has no public field.
I would at least test if the field is declared in the correct class - getDeclaringClass() - and if it has the correct return type - getType().
Using an Annotation, as Adrian suggested, is best IMHO.

Categories

Resources