I want to set the value of a private field using reflection for unit testing.
Problem is, that field is static.
Here's what I'm working from:
/**
* Use to set the value of a field you don't have access to, using reflection, for unit testing.
*
* Returns true/false for success/failure.
*
* #param p_instance an object to set a private field on
* #param p_fieldName the name of the field to set
* #param p_fieldValue the value to set the field to
* #return true/false for success/failure
*/
public static boolean setPrivateField(final Object p_instance, final String p_fieldName, final Object p_fieldValue) {
if (null == p_instance)
throw new NullPointerException("p_instance can't be null!");
if (null == p_fieldName)
throw new NullPointerException("p_fieldName can't be null!");
boolean result = true;
Class<?> klass = p_instance.getClass();
Field field = null;
try {
field = klass.getDeclaredField(p_fieldName);
field.setAccessible(true);
field.set(p_instance, p_fieldValue);
} catch (SecurityException e) {
result = false;
} catch (NoSuchFieldException e) {
result = false;
} catch (IllegalArgumentException e) {
result = false;
} catch (IllegalAccessException e) {
result = false;
}
return result;
}
I realize this has probably already been answered on SO, but my search didn't turn it up...
Basically the problem is your utility method, which assumes you have an instance. It's reasonably easy to set a private static field - it's exactly the same procedure as for an instance field, except you specify null as the instance. Unfortunately your utility method uses the instance to get the class, and requires it to be non-null...
I'd echo Tom's caveat: don't do that. If this is a class you have under your control, I'd create a package level method:
void setFooForTesting(Bar newValue)
{
foo = newValue;
}
However, here's a complete sample if you really, really want to set it with reflection:
import java.lang.reflect.*;
class FieldContainer
{
private static String woot;
public static void showWoot()
{
System.out.println(woot);
}
}
public class Test
{
// Declared to throw Exception just for the sake of brevity here
public static void main(String[] args) throws Exception
{
Field field = FieldContainer.class.getDeclaredField("woot");
field.setAccessible(true);
field.set(null, "New value");
FieldContainer.showWoot();
}
}
Just pass null for the object-instance argument. So:
field.set(null, p_fieldValue);
This will let you set the static field.
Related
I have two questions regarding the static block and Constants with below code.
Constant (or even simple Static variable) cannot be directly referrenced from static block. It gives error saying "Cannot reference a field before it is defined". But it is ok when accessing through a static method.
If I assign a value to a constant in static block's catch as mentioned below it gives error saying "The final field NAME may already have been assigned". But if asigning in catch it gives error saying "The blank final field NAME may not have been initialized".
I want to know why is it bahaving like this?
Code :
public class TestStaticblock {
static{
try {
// NAME = dummyStringValue() + NAME_APPENDER; // Cannot reference a field before it is defined
// NAME = dummyStringValue() + getNameAppender(); // This is OK
NAME = dummyStringValue();
} catch (Exception e) {
NAME = null; // The final field NAME may already have been assigned
}
}
private static String dummyStringValue() throws Exception{
return "dummy";
}
private static String getNameAppender() throws Exception{
return NAME_APPENDER;
}
private static final String NAME; // If I comment Catch it says "The blank final field NAME may not have been initialized"
private static String NAME_APPENDER = "appender";
}
You can only assign to NAME once (because it is final). Assign the result to a temporary variable, and then assign to NAME (and don't silently swallow Exceptions). Something like,
static {
String temp = null;
try {
temp = dummyStringValue();
} catch (Exception e) {
e.printStackTrace();
}
NAME = temp;
}
The reason you can't assign NAME the way your are currently is because the compiler performs static program analysis (specifically, the data-flow analysis) and that detects that there is a possible code path where NAME is not assigned. And because NAME is final, that is a compilation error.
You cannot use a static final field in a static block before it has been assigned, yet you can access it just by calling a method.
For example, this code prints null FOO:
public class Main {
static final String FOO;
static {
foo();
FOO = "FOOFOO".substring(0, 3);
foo();
}
static void foo() {
System.out.println(FOO);
}
public static void main(String[] args) {}
}
This is undeniably odd, but I guess it would have made the language considerably more complicated to make things such as this impossible.
As for your second question, this doesn't compile.
static{
try {
NAME = dummyStringValue();
} catch (Exception e) {
NAME = null; // The final field NAME may already have been assigned
}
}
This is also odd. If an exception is thrown it can only have occurred inside the method dummyStringValue(). Since you can't assign values to final fields inside a method, it is completely impossible for the NAME variable to have already been assigned in the catch block. Therefore there is no possible code path where NAME is not assigned. You'd think it ought to work in the same way as
static{
if (someCondition()) {
NAME = dummyStringValue();
} else {
NAME = null;
}
}
which compiles fine.
I guess the reason is again that it would have made the language much more complicated to allow this. There is no great benefit to allowing it as you can just use a method or a temp variable as indicated in the other answers. Exceptions just are more complicated than if statements - they can act almost like a goto. A good point was made by #ElliottFrisch in the comments. What about something like this:
static{
try {
NAME1 = dummyStringValue1();
NAME2 = dummyStringValue2();
} catch (Exception e) {
// Has NAME1 been assigned here?
}
}
Perhaps this would be of assistance to those looking for something similar.
There is a little-known feature of Java (discussed in JavaSpecialists Throwing Exceptions from Fields that if you wish to initialise a final instance variable (i.e. NOT a static) to the result of a method call that throws an exception then you can avoid the obvious error by adding a constructor that throws the exception.
Note that this solution only works for non-statics (not what you are observing).
public class TestStaticblock {
private final String NAME = dummyStringValue();
// Adding this removes the "unreported Exception" above.
public TestStaticblock() throws Exception {
}
private static String dummyStringValue() throws Exception {
return "dummy";
}
}
My strong personal preference is to use methods instead of static initializer blocks which initializer a single variable:
private static final String NAME = getName();
private static String getName() {
try {
return something();
} catch (Exception e) {
return null;
}
}
You don't get issues like the one you have described.
You can only calculate one field value, so you are not tempted to throw lots of things into the same block.
You can re-invoke a method to test it.
Here is my code.
public class PropertyLoader {
private Properties appProperties;
/**
* The instance.
*/
private static PropertyLoader inst = null;
/**
* Instantiates a new property data loader.
*/
private PropertyLoader() {
try
{
appProperties = new Properties();
appProperties.load(this.getClass().getClassLoader().getResourceAsStream("app.properties"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static PropertyLoader getInstance() {
if (inst == null) {
inst = new PropertyLoader();
}
return inst;
}
}
public String getPropertyAPP(String key) {
return appProperties.getProperty(key);
}
}
Synchronization is needed for the getPropertyAPP method: it is a singleton, so many threads can access the same instance simultaneously and call it.
Can anyone suggest me the right way?
you can use following solution
public class PropertyLoader {
private Properties appProperties;
/** The instance. */
private static PropertyLoader inst = null;
static{
inst = new PropertyLoader();
}
/**
* Instantiates a new property data loader.
*/
private PropertyLoader() {
try
{
appProperties = new Properties();
appProperties.load(this.getClass().getClassLoader().getResourceAsStream("app.properties"));
}
catch(IOException e)
{
e.printStackTrace();
}
}
public static PropertyLoader getInstance() {
return inst;
}
public String getPropertyAPP(String key) {
return appProperties.getProperty(key);
}
}
A simpler solution, which is also thread safe, is to use static initialisation to initialise a static field.
public class AppProperties {
private static final Properties appProperties;
static {
try {
appProperties = new Properties();
appProperties.load(AppProperties.class
.getClassLoader().getResourceAsStream("app.properties"));
} catch(IOException e) {
e.printStackTrace();
}
}
public String get(String key) {
return appProperties.getProperty(key);
}
public String get(String key, String defaultValue) {
return appProperties.getProperty(key, defaultValue);
}
}
You have a massive race condition happening in your getInstance() method. If more than one threads call getInstance() at the same time you will create multiple instances and assign them in turn to the static variable. Considering what you're doing here this won't cause any logic problems, but does mean you're doing more work than necessary.
I recommend you do some reading about the Singleton pattern, why it's bad, and how to implement it in a safe way in Java.
But in short, don't use the Singleton pattern, it's hideously broken and will make any code that uses this object tightly-coupled and will inhibit your ability to do any kind of isolated testing.
Several issues with your code:
(a) Are you sure you need lazy initialisation? The cost of initialisation must be noticeable and the chance that the resource is never used must be non-zero. Also: it may be preferable to fail during program start rather than at some indeterminate moment later when the resource is first accessed. This really depends on your application.
(b) One way of implementing the lazy initialisation is using the correct version of double checked locking (the volatile keyword is essential):
private static volatile PropertyLoader inst;
...
public static PropertyLoader getInstance() {
if (inst == null) {
synchronized(PropertyLoader.class) {
if (inst == null) {
inst = new PropertyLoader();
}
}
}
return inst;
}
This wikipedia article explains why this works (as of Java 5 but nore before): http://en.wikipedia.org/wiki/Double-checked_locking
(c) Catching exceptions and simply logging them is plain wrong under most circumstances. In your case, no property would ever be returned from getPropertyAPP. This may be ok if the presence of the properties is clearly declared to be optional.
I am trying to check if another class has a member variable called "list" in it, and I want a boolean to tell me if that class has it or not.
If the class has "list", the boolean returns true and everything is good. But if the class DOESN'T have "list" in it, it doesn't return false but it causes an error:
public static void main(String[]args) throws NoSuchFieldException, SecurityException{
boolean has = Person.class.getDeclaredField("list")!=null;
System.out.println(has);
}
The error:
Exception in thread "main" java.lang.NoSuchFieldException: list
at java.lang.Class.getDeclaredField(Unknown Source)
at test.main(test.java:21)
Line 21 is where I declared the boolean has.
So I have 2 questions:
How do I return false if there ISNT "list" in class Person?
If the varible exists, how can I make it into an object?
As an answer to the first question, if there isn't such a list, the NoSuchFieldException is thrown, so catch that exception then and return or set a boolean to false in that case.
How do I return false if there ISNT "list" in class Person?
Class.getDeclaredFields() throws a NoSuchFieldExeption if the field does not exist, so you need to catch the NoSuchFieldException:
public static void main(String[]args) {
boolean has = false;
try {
Person.class.getDeclaredField("list");
has = true;
} catch (NoSuchFieldException nsfe) {
// intentionally ignored
}
System.out.println(has);
}
It is usually a bad idea to simply ignore a thrown exception (the catch block should at least contain something like nsfe.printStackTrace()), but in this case it should be fine.
If the varible exists, how can I make it into an object?
I am not 100% sure what you mean by this, but you can get a reference to the desired attribute through the return value of getDeclaredField(), which is a java.lang.reflect.Field - in that case, I would avoid the boolean and restructure the code slightly, e.g.:
// #param Person object which has a "list" member
public void printListField(Object p) throws IllegalArgumentException, IllegalAccessException {
Field listField = null;
try {
listField = Person.class.getDeclaredField("list");
} catch (NoSuchFieldException nsfe) {
// intentionally ignored
}
if (listField != null) {
Object l = listField.get(p);
System.out.println("list is " + l);
} else {
System.out.println("No list member available!");
}
}
Note that you need a reference to an actual object of class Person in order to retrieve a reference to an instance variable.
public static void main(String[]args) throws NoSuchFieldException, SecurityException{
try {
boolean has = Person.class.getDeclaredField("list")!=null;
} catch(NoSuchFieldException e) {
has=false;
}
System.out.println(has);
}
So why not the below ?
try {
has = Person.class.getDeclaredField("list")!=null;
}
catch (NoSuchFieldException e) {
has = false;
}
Although I can't help thinking your design is flawed such that you have to perform this check (if you're inheriting legacy code you may have little choice, perhaps)
According to java-doc:
* #exception NoSuchFieldException if a field with the specified name is
* not found.
So if you want to check that field exists you should intercept exception:
boolean has;
try {
Person.class.getDeclaredField("list");
has = true;
} catch (NoSuchFieldException e) {
has = false;
}
You can get all fields by reflection,then check each field from the field array.
The method getDeclaredField will throw an exception(NoSuchFieldException) if the field does not exist. So you have to put a try/catch block around this method. And if you catch a NoSuchFieldException, then set has to false.
public static void main (String [] args) {
boolean has = false;
try {
Field f = Person.class.getDeclaredField("list");
has = true;
} catch (NoSuchFieldException e) {
has = false;
}
System.out.println(has);
}
See the java documentation at the following link:
http://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getDeclaredField(java.lang.String)
I want to transfer a variable value of type List (variable name is seznamRacunov) from one class to another.
Class 1
public class UvoziRacun
{
private String potRacuna;
private List<String> seznamRacunov = new ArrayList();
public void setRacun(List<String> seznamRacunov)
{
this.seznamRacunov = seznamRacunov;
}
public List<String> getRacun()
{
return seznamRacunov;
}
public String getPotRacuna()
{
return potRacuna;
}
public void showDailog()
{
try
{
JFileChooser racun = new JFileChooser();
racun.setCurrentDirectory(new File(""));
racun.setFileFilter(new javax.swing.filechooser.FileFilter()
{
public boolean accept(File f)
{
return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory();
}
public String getDescription()
{
return "XML Datoteka";
}
});
//racun.setMultiSelectionEnabled(true);
int r = racun.showOpenDialog(new JFrame());
if (r == JFileChooser.APPROVE_OPTION)
{
potRacuna = racun.getSelectedFile().getPath();
seznamRacunov.add(potRacuna); //value is stored
}
//System.out.print("Racuni: " + seznamRacunov);
}
catch(Exception ex){}
}
}
Class 2
public class PrikaziRacune extends javax.swing.JFrame
{
UvoziRacun rac = new UvoziRacun();
public PrikaziRacune()
{
initComponents();
try
{
System.out.print(rac.getRacun()); // value is null, why?
//jLabel2.setText();
}
catch(Exception ex){}
}
Method seznamRacunov.add(potRacuna); store a value into seznamRacunov in Class 1, but the value of list does not pass in class 2 where I called getter. What is wrong?
Method seznamRacunov.add(potRacuna); store a value into seznamRacunov
in Class 1, but the value of list does not pass in class 2 where I
called getter.
Thats because, you are trying to get() your List without even calling the method - showDailog() which in turn invokes your add() method to populate list.
Make sure, you invoke this method - showDailog() to populate the list, before you actually fetch the List with get method
Or, it would be better, if you add a constructor to your class, which does the task of initializing your List. Then you can create an instance using that constructor and thus you won't have any problem.
PS: - You should always have at least a 0-arg constructor to initialize your fields, rather than letting compiler handle this task for you.
And one more thing, you should never, ever engulp your exception by having an empty catch block. Else there is no point in catching them. Add a printStackTrace() call instead.
public PrikaziRacune() {
initComponents();
try
{
rac.showDailog(); // Will populate the list
System.out.print(rac.getRacun()); // You can get the value here.
//jLabel2.setText();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
Also, check your ArrayList declaration in your first class. You are using generic type List on LHS, and a Raw type ArrayList on the RHS. Its something that you should avoid.
Have Generic type on both the sides: -
private List<String> seznamRacunov = new ArrayList<String>();
I'm implementing a method that does something like:
...
try {
myPojo.setProperty("foo");
myService.execute(myPojo);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
...
If some exception is thrown by my service from this try block on pojo property will have the new value. Is there some way to start a kind of transaction for pojo changes and roll it back if something goes wrong?
Something like:
PojoTransaction pt = startPojoTransaction();
transactionedPojo = pt.handleByTransaction(myPojo);
try {
transactionedPojo.setProperty("foo");
myService.execute(transactionedPojo);
pt.commit;
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
Or something similar...
Take a look at the Memento Pattern, it includes a Java example.
http://en.wikipedia.org/wiki/Memento_pattern
I toyed around with the idea, this is far from perfect, just a simple proof of concept. There are pitfalls in this implementation:
It only tries to call a parameterless constructor of the given source
object to create the target-copy, would need some logic to select a correct constructor (or only support Cloneables?)
Only copies fields declared in the class, not from superclasses (this problem can be solved walking through the inheritance tree and copying any superclass fields)
If the fields are complex types, only the references are copied to target-object, so any changes to them will not be transactional, as both the source and target share the same instance (solvable by recursively creating copies of nested objects and copying their values, requires walking through the entire object-graph, starting from source, and then doing it vice-versa on commit-time)
But, improving from here, I believe it could become very usable. Here's the POC:
import java.lang.reflect.Field;
import org.junit.Assert;
import org.junit.Test;
public class PojoTransactionTest
{
public static class PojoTransaction<T>
{
/**
* This is the original (unmodified) object
*/
private T source;
/**
* This is the object modified by within the transaction
*/
private T target;
/**
* Creates a new transaction for the given source object
* #param source Source object to modify transactionally
*/
public PojoTransaction(T source)
{
try
{
this.source = source;
this.target = (T)source.getClass().newInstance(); //Note: this only supports parameterless constructors
copyState(source, target);
}
catch(Exception e)
{
throw new RuntimeException("Failed to create PojoTransaction", e);
}
}
/**
* Copies state (member fields) from object to another
* #param from Object to copy from
* #param to Object to copy to
* #throws IllegalAccessException
*/
private void copyState(T from, T to) throws IllegalAccessException
{
//Copy internal state to target, note that this will NOT copy fields from superclasses
for(Field f : from.getClass().getDeclaredFields())
{
f.setAccessible(true);
f.set(to, f.get(from));
}
}
/**
* Returns the transaction target object, this is the one you should modify during transaction
* #return Target object
*/
public T getTransactionTarget()
{
return target;
}
/**
* Copies the changes from target object back to original object
*/
public void commit()
{
try
{
copyState(target, source);
}
catch(Exception e)
{
throw new RuntimeException("Failed to change state of original object", e);
}
}
}
public static class TestData
{
private String strValue = "TEST";
private int intValue = 1;
private float floatValue = 3.1415f;
public String getStrValue()
{
return strValue;
}
public void setStrValue(String strValue)
{
this.strValue = strValue;
}
public int getIntValue()
{
return intValue;
}
public void setIntValue(int intValue)
{
this.intValue = intValue;
}
public float getFloatValue()
{
return floatValue;
}
public void setFloatValue(float floatValue)
{
this.floatValue = floatValue;
}
}
#Test
public void testTransaction()
{
//Create some test data
TestData orig = new TestData();
//Create transaction for the test data, get the "transaction target"-object from transaction
PojoTransaction<TestData> tx = new PojoTransaction<TestData>(orig);
TestData target = tx.getTransactionTarget();
target.setFloatValue(1.0f);
target.setIntValue(5);
target.setStrValue("Another string");
//Original object is still at the original values
Assert.assertEquals(1, orig.getIntValue());
Assert.assertEquals(3.1415f, orig.getFloatValue(), 0.001f);
Assert.assertEquals("TEST", orig.getStrValue());
//Commit transaction
tx.commit();
//The "orig"-object should now have the changes made to "transaction target"-object
Assert.assertEquals(5, orig.getIntValue());
Assert.assertEquals(1.0f, orig.getFloatValue(), 0.001f);
Assert.assertEquals("Another string", orig.getStrValue());
}
}
The question is a bit vague, but it sounds like you are wrestling with the basic design pattern for transaction management. You would benefit greatly from the experience that has gone into the production of the pattern used here:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html
Perhaps Spring Transaction management would suit you well for your project anyway.