JSF ManagedBean - injected properties not working correctly on STATE_SAVING_METHOD=client
Asked Answered
G

1

0

I am into a problem from two days and I can not get out from this.

The problem I am having is using a MangedBean property after the deserialization (I guess).
The property (purchaseManager) is set up with Spring, and use a DAO which extends MyBatis as data mapper to interact with the DB.
In fact, on the first access to the page, purchaseManager.getAll() inside init() method works fine.
When i try to call refreshList() as an action from a button, I have a NullPointerException on the getSqlSession() inside the DAO.

Letting only the relevant code the situation is as follow:

@ManagedBean(name = "purchaseController")
@ViewScoped
public class PurchaseController implements Serializable{

    @ManagedProperty(value = "#{purchaseManager}")
    private PurchaseManager purchaseManager;

    @PostConstruct
    public void init(){
        purchaseManager.getAll();
    }

    public void refreshList(){
        purchaseManager.getAll();
    }
}

public class PurchaseManagerImpl implements PurchaseManager, Serializable {
    PurchaseDAO purchaseDAO;

    public void getAll() {
        purchaseDAO.getAll()
    }
}

public class PurchaseDAOImpl extends SqlSessionDaoSupport implements PurchaseDAO, Serializable {

    public void getAll() {
        SqlSession session = getSqlSession();  // when the call comes from refreshList(), session is null
        session.selectList("PAYMENT.getAll", null);
    }
}

in web.xml
<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>server</param-value>
</context-param>

If I change the STATE_SAVING_METHOD to server the application works fine but is not what I want. Same thing if I make the ManageBean as RequestScope but this too will penalize my requirements.

Thank you in advance to anyone for any kind of help! Ermal

Grendel answered 3/4, 2012 at 2:2 Comment(5)
I don't do Spring, so I may be completely wrong, but why are you attempting to inject a Spring managed bean as a JSF managed property? I have never seen this. Spring has its own annotations for this.Acyclic
In Spring infrastructure I have the logic (DAOs and Services) which is an own project BL used by two other web applications, Front-End and Admin-Tool. A lot of references shows this way of injecting ManagedBeans as property of other managed bean. Here an example: mkyong.com/jsf2/injecting-managed-beans-in-jsf-2-0Grendel
Yes, I know how injecting JSF managed beans work, but you're treating a Spring managed bean as a JSF managed bean. If it were an EJB (which Spring is supposed to supplant), you would have used @EJB instead of @ManagedProperty which will basically inject a fully serializable proxy instance. Does Spring really not have some annotation for that? @Autowired or so?Acyclic
@Autowired seems to be the solution to inject correctly the spring beans. Although, I have the error com.sun.faces.mgbean.ManagedBeanCreationException: An error occurred performing resource injection on managed bean purchaseController in the PurchaseController.init() method. My applications seems stabile only when using @ManagedProperty. From your experience, what may cause an eventual issue in PRD environment with only @ManagedProperty?Grendel
Thanks for the comment @BalusC. Starting from your observation I solved the problem adding <aop:scoped-proxy proxy-target-class="false" /> in the Spring bean definition. Now that my manager/service object is defined as I said, thing are working fine. So my DB (MyBatis) reference is not null anymore.Grendel
G
0

Solved the error adding <aop:scoped-proxy proxy-target-class="false" /> to the definition of the service/manager declared through Spring. This makes possible the injection of a fully serializable proxy instance.

<bean id="purchaseManager" class="al.ozone.bl.manager.impl.PurchaseManagerImpl">    
    <property name="purchaseDAO" ref="purchaseDAO" />   
    <aop:scoped-proxy proxy-target-class="false" />
</bean> 

proxy-target-class="false" is for telling that PurchaseManagerImpl implements already an interface. If setted to true or omitted, CGLIB2 library must be used.

In this way JSF is correctly taking data from DB using Spring+MyBatis.

The mistery (for me) on this point (more theorical) is :

  • Is MyBatis object (PurchaseDAOImpl) and the dataSource, correctly handled behind the scenes?
  • Are they recreated or restored on each HTTP request?

Remember that I have STATE_SAVING_METHOD=client and BackingBean as ViewScope.
My Goal is to have the server lighter possible because I expect an hight number of user interactions.

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="poolPreparedStatements" value="true" />
    <property name="defaultAutoCommit" value="false" />
</bean>

Thank you very much to anyone for some light on this matter!

Consulted links:

Spring session-scoped beans (controllers) and references to services, in terms of serialization

http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes-other-injection

http://www.infoq.com/presentations/Whats-New-in-Spring-3.0

Grendel answered 4/4, 2012 at 0:52 Comment(1)
<aop:scoped-proxy proxy-target-class="false" /> solved this error. Setting this question as accepted, maybe helping other people with same issue.Grendel

© 2022 - 2024 — McMap. All rights reserved.