Spring Injected Models
nealhaggard Apr 23, 2008 5:55 PMSpring Injected Models and Seam
I'm trying to use a Spring-defined service and framework/model layer that I have created and jarred up from a separate project to be reused in the Web layer of my application. Using my service objects have worked flawlessly, I was able to retrieve objects from my service layer and show them in a table without an issue.  Now I'm trying to use Seam to create a new account for a user on the web layer by injecting an 'Account' model object from my Spring definition of a JPA/Hibernate POJO.  
The problem I'm seeing is that Seam appears to be injecting a fresh account into my RegisterBean with every request.  How do I set up the RegisterBean with one Account object that'll stick around until I'm done registering the user?  (Note that I'm using a4j's support to re-validate the Account object with every onblur, so it'll need to stick through that).
Am I going about this completely wrong?  I'm new to Seam, but not JSF, so I have enough knowledge to be dangerous, but really am still grasping to understand the state/stateless nature of doing this with POJOs instead of EJBs. I really don't want to have to rewrite my Model objects as EJBs as the JPA/Hibernate POJO is working great in the rest of the app.  
I'm including what I feel are the relevant code pieces to help you guys answer my question.  If you need more info, please let me know and I'll post more of my config.
components.xml
<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
            xmlns:core="http://jboss.com/products/seam/core"
            xmlns:persistence="http://jboss.com/products/seam/persistence"
            xmlns:drools="http://jboss.com/products/seam/drools"
            xmlns:bpm="http://jboss.com/products/seam/bpm"
            xmlns:security="http://jboss.com/products/seam/security"
            xmlns:mail="http://jboss.com/products/seam/mail"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:spring="http://jboss.com/products/seam/spring"
            xsi:schemaLocation=
                "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.0.xsd 
                 http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.0.xsd 
                 http://jboss.com/products/seam/drools http://jboss.com/products/seam/drools-2.0.xsd
                 http://jboss.com/products/seam/bpm http://jboss.com/products/seam/bpm-2.0.xsd
                 http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.0.xsd
                 http://jboss.com/products/seam/mail http://jboss.com/products/seam/mail-2.0.xsd
                 http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd
                 http://jboss.com/products/seam/spring
                 http://jboss.com/products/seam/spring-2.0.xsd">
   <core:init debug="@debug@" jndi-pattern="@jndiPattern@"/>
     
   <core:manager concurrent-request-timeout="500" 
                 conversation-timeout="120000" 
                 conversation-id-parameter="cid"/>
    
   <persistence:managed-persistence-context name="entityManager"
                                     auto-create="true"
                          entity-manager-factory="#{MyAppEntityManagerFactory}"/>
   <persistence:entity-manager-factory name="MyAppEntityManagerFactory" 
                      persistence-unit-name="MyApp"/>
   
   <drools:rule-base name="securityRules">
       <drools:rule-files><value>/security.drl</value></drools:rule-files>
   </drools:rule-base>
   <security:identity authenticate-method="#{authenticator.authenticate}"
                           security-rules="#{securityRules}"
                              remember-me="true"/>
                              
   <event type="org.jboss.seam.security.notLoggedIn">
       <action execute="#{redirect.captureCurrentView}"/>
   </event>
   <event type="org.jboss.seam.security.loginSuccessful">
       <action execute="#{redirect.returnToCapturedView}"/>
   </event>
   
   <spring:context-loader>
     <spring:config-locations>
       <value>classpath:coreResourceContext.xml</value>
       <value>classpath:daoContext.xml</value>
       <value>classpath:modelContext.xml</value>
     </spring:config-locations>
   </spring:context-loader>
      
</components>
menu.xhtml
<rich:toolBar
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:s="http://jboss.com/products/seam/taglib"
    xmlns:rich="http://richfaces.org/rich">
    <rich:toolBarGroup>
        <h:outputText value="#{projectName}:"/>
        <s:link view="/home.xhtml" value="Home"/>
        <s:link view="/accountList.xhtml" value="Accounts" rendered="#{identity.loggedIn}" />
    </rich:toolBarGroup>
    <!-- @newMenuItem@ -->
    <rich:toolBarGroup location="right">
        <h:outputText value="Welcome, #{identity.username}!" rendered="#{identity.loggedIn}"/>
        <s:link view="/login.xhtml" value="Login" rendered="#{not identity.loggedIn}"/>
        <s:link view="/register.xhtml" value="Register" rendered="#{not identity.loggedIn}" conversationScope="begin" />
        <s:link view="/home.xhtml" action="#{identity.logout}" value="Logout" rendered="#{identity.loggedIn}"/>
    </rich:toolBarGroup>
</rich:toolBar>
RegisterBean.java
@Name("registerAccount")
@Scope(ScopeType.CONVERSATION)
public class RegisterBean {
     @In("#{accountService}")
     private AccountService accountService;
     @In("#{account}")
     @Out
     private Account account;
     @In
     private FacesMessages facesMessages;
     private boolean registered = false;
     /**
      * Do the work of creating an account.
      * 
      * @return
      */
     @End
     public void register() {
          LogicMessages messages = new LogicMessages();
          try {
               messages = accountService.create(account);
               registered = true;
          } catch (LogicException e) {
               messages.addAll(e.getMessages());
          }
          WebUtil.addLogicMessages(messages, facesMessages);
     }
     /**
      * @return the registered
      */
     public boolean isRegistered() {
          return registered;
     }
}
register.xhtml
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
     xmlns:s="http://jboss.com/products/seam/taglib"
     xmlns:ui="http://java.sun.com/jsf/facelets"
     xmlns:f="http://java.sun.com/jsf/core"
     xmlns:h="http://java.sun.com/jsf/html"
     xmlns:rich="http://richfaces.org/rich"
     xmlns:a4j="http://richfaces.org/a4j"
     template="layout/template.xhtml">
     <ui:define name="body">
          <h:form id="registerForm">
               <h:messages globalOnly="true" />
               <rich:panel>
                    <f:facet name="header">Register a new Account</f:facet>
                    <fieldset>
                         <s:decorate id="nameDecoration"     template="layout/edit.xhtml">
                              <ui:define name="label">Name:</ui:define>
                              <h:inputText value="#{account.name}" required="true">
                                   <a4j:support event="onblur" reRender="nameDecoration" />
                              </h:inputText>
                         </s:decorate>
                         <s:decorate id="emailDecoration" template="../layout/edit.xhtml">
                              <ui:define name="label">Email:</ui:define>
                              <h:inputText value="#{account.email}" required="true">
                                   <a4j:support event="onblur" reRender="emailDecoration" />
                              </h:inputText>
                         </s:decorate>
                         <s:decorate id="securityQuestionDecoration"     template="layout/edit.xhtml">
                              <ui:define name="label">SecurityQuestion:</ui:define>
                              <h:inputText value="#{account.securityQuestion}" required="true">
                                   <a4j:support event="onblur" reRender="securityQuestionDecoration" />
                              </h:inputText>
                         </s:decorate>
                         <s:decorate id="securityAnswerDecoration" template="layout/edit.xhtml">
                              <ui:define name="label">Security Answer:</ui:define>
                              <h:inputText value="#{account.securityAnswer}" required="true">
                                   <a4j:support event="onblur" reRender="securityAnswerDecoration" />
                              </h:inputText>
                         </s:decorate>
                    </fieldset>
               </rich:panel>
               <div class="actionButtons">
                    <h:commandButton value="Register!" action="#{registerAccount.register}" />
               </div>
          </h:form>
     </ui:define>
</ui:composition>
daoContext.xml (relevant bit)
<bean id="accountDao" class="myapp.AccountJpaDaoImpl"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean> <bean id="accountService" class="myapp.AccountServiceImpl"> <constructor-arg> <ref bean="accountDao" /> </constructor-arg> </bean>
modelContext.xml (relevant bit)
<bean id="account" class="myapp.AccountImpl" scope="prototype" />
 
    