is it possible to change the value of an attribute of a class using reflection.
below is my class :-
public class LoggerManager {
private static LoggerManager _instance = new LoggerManager();
private LoggerManager() {
}
public static LoggerManager getInstance() {
return _instance;
}
public Logger getLogger(String FQCN) {
Logger logger = Logger.getLogger(FQCN);
logger.setLevel(Level.INFO);
return logger;
}
}
i want to change the value of _instance variable using reflection..
basically i want to change the value of the same to _instance = new NewLoggerManager();,
provided that NewLoggerManager extends LoggerManager
is it possible to do so, as i know how to invoke methods, but how to do this one.. ???
Field field = LoggerManager.class.getDeclaredField("_instance");
field.setAccessible(true);
field.set(null, new NewLoggerManager());
the first line obtains the Field definition for the _instance field. Using the "declared" method, because it is able to obtain private fields as well
setting the field to be accessible for reflective operations even if this would not be possible due to its visibility.
setting a new object. Passing null as target object, because the field is static
I have no idea why you need to do this in that way, and basically #Bozho have provided you with correct answer, but I would like to suggest avoiding such traps. You'd better use dependency injection in this case, so it became much more clear and nice and will do the job for you. Try to read about GUICE.
Related
I would like to use a value from application.properties file in order to pass it in the method in another class. The problem is that the value returns always NULL. What could be the problem? Thanks in advance.
application.properties
filesystem.directory=temp
FileSystem.java
#Value("${filesystem.directory}")
private static String directory;
You can't use #Value on static variables. You'll have to either mark it as non static or have a look here at a way to inject values into static variables:
https://www.mkyong.com/spring/spring-inject-a-value-into-static-variables/
EDIT: Just in case the link breaks in the future. You can do this by making a non static setter for your static variable:
#Component
public class MyComponent {
private static String directory;
#Value("${filesystem.directory}")
public void setDirectory(String value) {
this.directory = value;
}
}
The class needs to be a Spring bean though or else it won't be instantiated and the setter will be not be accessible by Spring.
For the ones still facing the issue after all the preceding suggestions, make sure you are not accessing that variable before the bean has been constructed.
That is:
Instead of doing this:
#Component
public MyBean {
#Value("${properties.my-var}")
private String myVar;
private String anotherVar = foo(myVar); // <-- myVar here is still null!!!
}
do this:
#Component
public MyBean {
#Value("${properties.my-var}")
private String myVar;
private String anotherVar;
#PostConstruct
public void postConstruct(){
anotherVar = foo(myVar); // <-- using myVar after the bean construction
}
}
Hope this will help someone avoid wasting hours.
Few things for you to cross check apart from #Plog's answer.
static variables can't be injected with value. Check #Plog's answer.
Make sure the class is annotated with #Component or #Service
The component scan should scan the enclosing package for registering the beans. Check your XML if xml enabled configuration.
Check if the property file's path is correct or in classpath.
The other answers are probably correct for the OP.
However, I ran into the same symptoms (#Value-annotated fields being null) but with a different underlying issue:
import com.google.api.client.util.Value;
Ensure that you are importing the correct #Value annotation class! Especially with the convenience of IDEs nowadays, this is a VERY easy mistake to make (I am using IntelliJ, and if you auto-import too quickly without reading WHAT you are auto-importing, you might waste a few hours like I did).
Of course, the correct class to import is:
import org.springframework.beans.factory.annotation.Value;
Spring uses dependency injection to populate the specific value when it finds the #Value annotation. However, instead of handing the value to the instance variable, it's handed to the implicit setter instead. This setter then handles the population of our NAME_STATIC value.
#RestController
//or if you want to declare some specific use of the properties file then use
//#Configuration
//#PropertySource({"classpath:application-${youeEnvironment}.properties"})
public class PropertyController {
#Value("${name}")//not necessary
private String name;//not necessary
private static String NAME_STATIC;
#Value("${name}")
public void setNameStatic(String name){
PropertyController.NAME_STATIC = name;
}
}
You can make use of this. reference to assess the value of (private String myVar)
this.myVar
Add the #Autowired annotation to the variable declaration of your class.
#Autowired
private FileSystem myFileSystem;
I have a private static inner class that I need to inject a value into and I am having no luck.
My code's pattern is as follows:
#Component
public final class someClassUtil {
#Component
private static class innerClass {
private transient boolean myVar;
#Value("${my.value.to.inject}")
public void setMyVar(final boolean myVar) {
this.myVar = myVar;
}
}
}
I have a feeling that it may have something to do with the access modifiers, but I have tried many variants with no success. Any thoughts?
Since your nested class is private, I fear that Spring's DI mechanism is not able to invoke the setter thus rendering the annotation on it useless.
According to the #Value docs, you need to use #Value("#{my.value.to.inject}"). Note the "#" instead of "$".
I know this would seem to be something blasphemic and it (may) break the singleton nature so, please, don't hurt me! I'm just asking.
Assuming that the example below is just a random situation (and actually MY SITUATION, coincidence? I don't think so...) my question is generic.
I've got a singleton class like this:
public class SingleSessionFactory {
private SingleSessionFactory() {
}
private static class SingleSessionHelper {
private static final SessionFactory SESSION_FACTORY = getSingleSession();
private static SessionFactory getSingleSession() {
if (SESSION_FACTORY == null) {
Configuration hConf = new Configuration();
//hibernate configuration I wish to set by an object or sth dynamic not hard-coded!
try {
return hConf.buildSessionFactory();
} catch (ExceptionInInitializerError ex) {
System.out.println(ex.getMessage());
}
}
return SESSION_FACTORY;
}
}
public static SessionFactory getInstance() {
return SingleSessionHelper.SESSION_FACTORY;
}
}
which instead of the line //hibernate config...bla bla bla & bla... i used to call the setProperty(..) and addAnnotatedClass(..) hard-coded.
I wish to know if it's good to use a custom property object (by instance: MyHibernateConfiguration class) to use inside my getSingleSession(), which inside some attribute to store Hibernate properties (as "hibernate.dialect", "org.hibernate.dialect.PostgreSQLDialect") and annotated class. Injecting or passing or...whatever... in this way "all that things" could be passed dynamically and that would be veeeeeryveryvery cool, isn't it right?
Anyway:
Q: Is it possible?
A1: Yeah of course! And the bestt way to do that is...
A2: NO! This is madness! I'm gonna underrate this question and send you to hell! Muha-ha-ha-haaaa... (yeah, evil laugh...)
That's all folk!
I'm trying to mock a class that looks like below
public class MessageContainer {
private final MessageChain[] messages;
MessageContainer(final int numOfMessages, final MessageManagerImpl manager, final Object someOtherStuff) {
messages = new MessageChain[numOfMessages]
// do other stuff
}
public void foo(final int index) {
// do something
messages[index] = getActiveMessage();
}
}
My test code would be as followed:
#Test
public void testFoo() {
MessageContainer messageContainer = Mockito.mock(MessageContainer.class);
Mockito.doCallRealMethod().when(messageContainer).foo(anyIndex);
}
I got a NullPointerException since 'messages' is null. I tried to inject the mock by using #InjectMocks, however this case is not supported since not every parameters of the constructor are declared as members.
I also tried to set the 'messages' field by using WhiteBox
Whitebox.setInternalState(messageContainer, MessageChain[].class, PowerMockito.mock(MessageChain[].class));
but I got a compile error since setInternalState only supports (Object, Object, Object) and not Object[].
Is there any possible way to mock a private final field?
Thank you guys in advance.
Based on your edits and comments, I would say mocking this class and verifying the method was invoked is sufficient.
If it is third-party code, you should rely only on its method signature, which comprises the class's public API. Otherwise you are coupling your tests too tightly to something you have no control over. What do you do when they decide to use a Collection instead of an array?
Simply write:
MessageContainer container = mock(MessageContainer.class);
//Your code here...
verify(container).foo(obj);
I've been playing with annotations, and I'm wondering how to go about doing this. What I'd like to do is to be able to have a field declared in a class and annotated such that the field will be initialized with a static instance of the class.
Given an annotation like this:
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME) //or would this be RetentionPolicy.CLASS?
public #interface SetThisField {
}
Something like this:
public class Foo {
#SetThisField
private Bar bar;
}
I've played around with using a parser and setting this at runtime, which works but isn't as elegant as I'd like.
I can't find any really good examples of RetentionPolicy.CLASS but the documentation seems to indicate that I could somehow make the declaration of "bar" get compiled into this:
private Bar bar = Bar.getInstance();
It wouldn't look that way in the source code of course, but it would in the byte code and it would behave like that at runtime.
So am I off base here? Is this possible? Or is the parser the way to go with it?
UPDATE: This is the guts of the parser I'm using
public static void parse(Object instance) throws Exception {
Field[] fields = instance.getClass().getDeclaredFields();
for (Field field : fields) {
//"Property" annotated fields get set to an application.properties value
//using the value of the annotation as the key into the properties
if (field.isAnnotationPresent(Property.class)) {
Property property = field.getAnnotation(Property.class);
String value = property.value();
if (!"".equals(value)) {
setFieldValue(instance, field, properties.getProperty(value));
}
}
//"Resource" annotated fields get static instances of the class allocated
//based upon the type of the field.
if (field.isAnnotationPresent(Resource.class)) {
String name = field.getType().getName();
setFieldValue(instance, field, MyApplication.getResources().get(name));
}
}
}
private static void setFieldValue(Object instance, Field field, Object value) throws IllegalAccessException {
boolean accessibleState = field.isAccessible();
field.setAccessible(true);
field.set(instance, value);
field.setAccessible(accessibleState);
}
I would suggest doing the replacement at run time. This is much simpler to implement and test. Changing the byte code at build time is relatively error prone and tricky to get right. For example you would need to understand how byte code is structured and in this case how to add the code to all the constructors in the right place in the code.
If you make the retention RUNTIME, you can have a library which examines the annotation and sets the value after the object is created.