Friday, April 5, 2013

My ManagedProperty is null!

I've actually been told by a developer or two that I shouldn't use Managed Properties because "they don't work right."

The scenario:
JSF 2.0
Tomcat 6.0.32
Java 1.6

Imagine the following Managed Bean, which requires a value from another Managed Bean:


@ManagedBean(name = "downloadBacking")
@ViewScoped
public class DownloadBacking implements Serializable {

private static final long serialVersionUID = 4778576272893200307L;

@ManagedProperty("#{userModel.username}")
private String userID;

        public DownloadBacking(){

                   System.out.println("UserID is: " + userID;
       }


public String getUserID() {
return userID;
}

public void setUserID(String userID) {
this.userID = userID;
}
}

What would the output be from the above code when the object is instantiated, if the value of userModel.username is "Magnus the Red"?

A) "UserID is: Magnus the Red"
B) Casting error
C) NullPointerError
D) "Ahriman had better watch out..."

The correct answer is C.  This is why I'm told that ManagedProperty doesn't work right.

The truth is that ManagedProperty works just fine, if you understand the order in which things are happening.  The problem here is that JSF used the setUserID() method to inject the value of userModel.username into the object.  Well, that can't happen until the object has been instantiated, right?  Well if the reference to the ManagedProperty is taking place in the constructor, how can it already have the value of the ManagedProperty in it if the object isn't even completely instantiated yet?

The solution here is to NOT put references to a ManagedProperty in your constructor.  Instead, use the @PostConstruct annotation with an initialize() method to run your code AFTER the value has been injected into the newly created bean.


@ManagedBean(name = "downloadBacking")
@ViewScoped
public class DownloadBacking implements Serializable {

private static final long serialVersionUID = 4778576272893200307L;

@ManagedProperty("#{userModel.username}")
private String userID;


@PostConstruct
public void initialize(){


                   System.out.println("UserID is: " + userID;
         }


public String getUserID() {
return userID;
}

public void setUserID(String userID) {
this.userID = userID;
}
}



Now the output will be A).

4 comments:

  1. if username was not an string and an object instead, this example would work?

    ReplyDelete
  2. Yes. Remember, a String in Java is an Object anyway.

    ReplyDelete
  3. Amazing post! I initially found your blog a week or so ago, and I want to subscribe to your RSS feed.

    Graphic Design Rochester NY
    Web Designing Rochester NY
    Web Development Rochester NY

    ReplyDelete
  4. congrats bro .... this was very helpful

    ReplyDelete