12

I have a String that I'm autowiring as a bean. The value for the String is set via a properties file, and is loaded at runtime. That much I can verify. Here's my XML:

<context:property-placeholder location="classpath:my-app.properties" />

<bean id="loadedProp" class="java.lang.String">
   <constructor-arg>
      <value>${loaded-prop}</value>
   </constructor-arg>
</bean>

And in my application, I autowire in the bean:

@Component
public class Foo {

  @Autowired
  private String loadedProp;
}

Everything works dandy. I have multiple components that autowire in this bean. What I'm trying to do is, while the application is running, update the value of the bean to be something else, so that everywhere the bean is autowired in, it uses the most up to date value. Is it possible to do this, or do I just need to restart everytime I want to change the value?

Pat
  • 2,228
  • 3
  • 24
  • 33

3 Answers3

5

After reading a few of the other answers and comments, I was able to figure out a solution. I ended up creating a simple class:

public class LPropBean {

   private String loadedProp;

   public LPropBean(String loadedProp) {
       this.loadedProp = loadedProp;
   }

   // getters and setters...
}

I updated my XML file:

<bean id="lPropBean" class="LPropBean">
  <constructor-arg>
    <value>${loaded-prop}</value>
  </constructor-arg>
</bean>

And updated all of the @Components that autowire in the bean:

@Autowire
private LPropBean lPropBean;

// ... later ...
lPropBean.setLoadedProp(newProp);

// ... later ...
lPropBean.getLoadedProp();

I'm sure there is a more elegant way, but this worked exactly how I needed it to.

Pat
  • 2,228
  • 3
  • 24
  • 33
3

Since String is immutable, you cannot just change its underlying value and have everyone that has a reference to it be updated.

You can change the reference of the String that an instance of Foo is holding onto to point to a different String, but it will only be realized by objects that are working with the specific Foo you updated. If Foo is a Spring singleton, this shouldn't be an issue though...

nicholas.hauschild
  • 42,483
  • 9
  • 127
  • 120
  • Drat. So would I be able to get around this by autowiring a class that has a a String as a property, and updating that property? Or would I still fall into the same trap? – Pat Feb 09 '12 at 15:53
  • you can use a MutableObject of apache.commons for example and use getter/setter there perhaps? – Sergey Benner Feb 09 '12 at 16:03
  • This sounds plausible, but I would also take a look at some of the suggestions that have come from the comments. Again, it depends on who you have given this `String` to and whether or not things are Spring managed. – nicholas.hauschild Feb 09 '12 at 16:15
  • 1
    Actually, you *can* change the value of a String using reflection, but it's never a good idea, since Strings are interned and you don't know where else the changed value is used. I recently (during debugging) mistakenly changed the internal value of `Boolean.TRUE` to `false`. I guess you can imagine that a lot of unexpected things started happening after that :-) So basically: there is no such thing as an immutable Object in Java (if reflection is available), but some things *should* not be changed – Sean Patrick Floyd Feb 09 '12 at 17:04
0

Every time you want to change your spring injected values through changing the configuration, you are going to have to restart your container, which usually involves restarting your server.

Alberto Gutierrez
  • 1,588
  • 7
  • 9