After reading the article of Chiral Software about @Factory and @Unwrap Seam annotations, I found it could be useful to add some information on Seam bijection from my experience on the subject.
One common mistake with Seam is to be too confident in its “magic”.
One of the first traps you can fall in when you start with Seam is about outjection.
See this code for instance :
@Name("registerHdl")
@Scope(ScopeType.CONVERSATION)
public class RegisterHandler implements Serializable{
@Out
private Registrant registrant=new Registrant();
@Create
public void create()
{
}
}
...
@Entity
public class Registrant {
private Long id;
private String firstName;
private String lastName;
private String email;
private String origine;
(getters and setters skiped)
}
It defines a component in the conversation scope with a private field containing an entity which is outjected with “registrant” name.
Later we’ll want to use this variable in a view :
pages.xml :
...
<page view-id="/register.xhtml">
<begin-conversation join="true" />
<navigation>
<rule if-outcome="ok">
<end-conversation />
<redirect view-id="/thanks.xhtml"></redirect>
</rule>
</navigation>
</page>
...
register.xhtml :
...
<span class="inputLabel">Your name : </span><br/>
<h:inputText id="Name" styleClass="inputShort" required="true"
value="#{registrant.lastName}"/>
...
But it doesn’t work (an exception occurs when the form is submitted). We started a conversation in pages.xml and called the outjected “registrant” variable from registerHdl without any success.
So what went wrong ?
The problem is that the “registerHdl” component is never created and the call we made to “registrant” didn’t trigger this creation.
To trigger this creation we could have called a method of registerHdl. We could have mapped the fields with #{registerHdl.registrant} in the view after having defined getter and setter for registrant in the component. But ther’s a better way.
That’s here that @Factory start to be useful.
@Name("registerHdl")
@Scope(ScopeType.CONVERSATION)
public class RegisterHandler implements Serializable{
private Registrant registrant=new Registrant();
@Factory
public Registrant getRegistrant() {
return registrant;
}
public void setRegistrant(Registrant registrant) {
this.registrant = registrant;
}
@Create
public void create()
{
}
}
We deleted the @Out annotation and added a getter with the @Factory annotation. This new configuration triggers the creation of registerHdl component when we call #{registrant…} in our view.
To summarize @Out outjects a field as a context variable after the creation of the component and @Factory triggers if necessary the creation of the component to outject the return value of a method. @Out is only visible in the component life cycle and @Factory is visible in the whole application.
But that’s not the only difference between @Factory and @Out as we’ll see in part 2 of this article.



