Question on @In and Bijection
fsat.f_satyaputra.yahoo.co.uk Mar 28, 2008 2:38 PMHi All,
I'd like to understand more about how bijection works in Seam, as some of the objects which I have annotated with @In does not get injected under certain circumstances.
I have a link as such:
<s:link id="bjtest" 
view="/bjtest/start.xhtml" action="#{pageBean.prepare()}" 
value="Start Element Test"/>
Here's my page bean:
@Name("pageBean")
@Scope(ScopeType.CONVERSATION)
@AutoCreate
public class PageBean implements Serializable {
     
     @In
     protected FormElementSet formElementSet;
     @Begin(join=true)
     @RaiseEvent("pageBean.prepare")
     public String prepare() {
          this.formElementSet.initialize();
          return "prepare";
     }
     
     public String save() {
          this.formElementSet.validateSave();
          this.formElementSet.save();
          return "prepare";
     }
     public String submit() {
          this.formElementSet.validateSubmit();
          this.formElementSet.save();          
          return "prepare";
     }
     
     // snip...The PageBean instance have runtime dependencies to the following 4 classes:
@Name("formElementSet")
@Scope(ScopeType.CONVERSATION)
@AutoCreate
public class FormElementSet implements Serializable {
     private Set<FormElement> formElements = new TreeSet<FormElement>();
     
     public void initialize() {
          this.formElements.clear();
     }
     
     public void registerFormElement(FormElement... formElementsInput) {
          for (FormElement elem: formElementsInput) {
               this.formElements.add(elem);
          }
     }
     
     public boolean validateSave() {
          boolean result = true;
          for (FormElement elem: this.getFormElements()) {
               result = result & elem.validateSave();
          }          
          return result;
     }
     
     // snip...     
     
public abstract class BaseFormElement implements FormElement, 
Serializable, Comparable<FormElement> {
     @In
     protected FormElementSet formElementSet;
     @Observer("pageBean.prepare")
     public abstract void register();
}     
     
@Name("includeFormElementOne")
@Scope(ScopeType.CONVERSATION)
@AutoCreate
public class IncludeFormElementOne extends BaseFormElement {
     
     @Override
     public void register() {
          System.out.println("@@@@@@@@@@@@@@@ [" + this + ".register()]");
          this.formElementSet.registerFormElement(this);
     }
     public void save() {
          System.out.println("@@@@@@@@@@@@@@@ [" + this + ".save()]");          
     }
     public boolean validateSave() {
          System.out.println("@@@@@@@@@@@@@@@ [" + this + ".validateSave()]");
          return true;
     }
     
    // snip....    
@Name("includeFormElementTwo")
@Scope(ScopeType.CONVERSATION)
@AutoCreate
public class IncludeFormElementTwo extends BaseFormElement {
     
     @In
     protected IncludeFormElementOne includeFormElementOne;
     
     @Override
     public void register() {
          System.out.println("@@@@@@@@@@@@@@@ [" + this + ".register()] w/ dependency [" + 
this.includeFormElementOne + "]");
          this.formElementSet.registerFormElement(this);
     }
     public void save() {
          System.out.println("@@@@@@@@@@@@@@@ [" + this + ".save()] w/ dependency [" +
 this.includeFormElementOne + "]");          
     }
     public boolean validateSave() {
          System.out.println("@@@@@@@@@@@@@@@ [" + this + ".validateSave() w/ dependency [" + 
this.includeFormElementOne + "]");
          return true;
     }
     // snip....              
After clicking this s:link:
<s:link id="bjtest" 
view="/bjtest/start.xhtml" action="#{pageBean.prepare()}" 
value="Start Element Test"/>
The #{pageBean.prepare()} method is executed, which in turn raises the event and the event observer kicks in to register #{includeFormElementOne} and #{includeFormElementTwo}. This generates the following System.out, which shows the dependency between #{includeFormElementTwo} towards #{includeFormElementOne}:
@@@@@@@@@@@@@@@ [com.juggle.seam.bjtest.IncludeFormElementOne@60feaf.register()] @@@@@@@@@@@@@@@ [com.juggle.seam.bjtest.IncludeFormElementTwo@613422.register()] w/ dependency [com.juggle.seam.bjtest.IncludeFormElementOne@60feaf]
On the subsequent page, I have the button which prompts the save method:
<h:commandButton id="btnSave" 
action="#{pageBean.save()}" value="Save">
</h:commandButton>
This is the resulting System.out:
@@@@@@@@@@@@@@@ [com.juggle.seam.bjtest.IncludeFormElementOne@60feaf.validateSave()] @@@@@@@@@@@@@@@ [com.juggle.seam.bjtest.IncludeFormElementTwo@613422.validateSave() w/ dependency [null] @@@@@@@@@@@@@@@ [com.juggle.seam.bjtest.IncludeFormElementOne@60feaf.save()] @@@@@@@@@@@@@@@ [com.juggle.seam.bjtest.IncludeFormElementTwo@613422.save()] w/ dependency [null]
For some reason the reference from #{includeFormElementTwo} to #{includeFormElementOne} shows null, which indicates that the @In annotation fails to be picked up by the BijectionInterceptor.
My questions are as following:
- Is this an expected behaviour?
 - Is #{includeFormElementTwo} intercepted by the BijectionInterceptor in when the #{pageBean.save()} method is called?
 - Why would the reference #{includeFormElementTwo} to #{includeFormElementOne} becomes null?
 
Apologies if this letter becomes a mouthful, but I really want to understand how bijection works in Seam.
Thank you very much for your time and your help.
Regards,
Felix