/*
* Copyright 2002-2004 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.springframework.autobuilds.ejbtest.hibernate.tx.ejb;
import java.sql.SQLException;
import javax.ejb.CreateException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.autobuilds.ejbtest.Constants;
import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.ejb.support.AbstractStatelessSessionBean;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
/**
* <p>EJB used just to test proper Hibernate Session binding and unbinding in
* a CMT (Container Managed Transaction) environment with JTA, but no Spring
* TransactionManager involved. The methods here are not an example of what your
* own EJB methods should do; they are just meant to test that Spring internals
* are working ok. However the config of this bean _is_ a general example of how
* you would set up an EJB to work with CMT without Spring transaction environment</p>
*
* <p>In a CMT without Spring transactions environment, as long as the Hibernate
* Configuration is set up with a TransactionManagerLookup so Hibernate (and Spring)
* can find the JTA TransactionManager, Spring is still able to bind the Hibernate
* Session to the current transaction, and ensure that all Hibernate work in a
* transaction happens within the same session (when using
* HibernateTemplate/SessionFactoryUtils.</p>
*
* <p>This is not an example of how you would ideally write an EJB in a Spring
* environment. Ideally the EJB just obtains a POJO service object (wrapped with
* TransactionInterceptor and possibly HibernateInterceptor) from an
* ApplicationContext, and delegates all method calls to it. The technique used
* here though is useful when there is a need to keep actual business code in the
* EJB, and have this code work with Hibernate/Spring Mappers/DAOs.
* </p>
*
* @author colin sampaleanu
*/
public class CmtJtaNoSpringTxEJB extends AbstractStatelessSessionBean
implements
SessionBean,
CmtJtaNoSpringTx {
// --- statics
public static final String SESSION_FACTORY_ID = "hibSessionFactory";
protected static final Log logger = LogFactory
.getLog(CmtJtaNoSpringTxEJB.class);
// --- attributes
SessionFactory sessionFactory;
/*
* (non-Javadoc)
*
* @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
*/
public void setSessionContext(SessionContext sessionContext) {
super.setSessionContext(sessionContext);
setBeanFactoryLocator(ContextSingletonBeanFactoryLocator.getInstance());
setBeanFactoryLocatorKey(Constants.SERVICE_LAYER_CONTEXT_ID);
}
/*
* arghhh! stupid method needed just to make XDoclet happy, otherwise it will
* create one in the subclass it generates, killing the one in the superclass
* @ejb.create-method
*/
public void ejbCreate() throws CreateException {
super.ejbCreate();
}
// javadoc in superclass
protected void onEjbCreate() throws CreateException {
sessionFactory = (SessionFactory) getBeanFactory().getBean(
SESSION_FACTORY_ID);
}
// javadoc in superclass
public String echo(String input) {
return "hello " + input;
}
// javadoc in superclass
public void testSameSessionReceivedInTwoRequests() throws TestFailureException {
Session sess1 = SessionFactoryUtils.getSession(sessionFactory, true);
Session sess2 = SessionFactoryUtils.getSession(sessionFactory, true);
if (sess1 != sess2)
throw new TestFailureException(
"Should have received the same Session in each execute call since we are in one JTA transaction, but they were different.");
sess1.close();
}
public void throwExceptionSoSessionUnbindCanBeVerified()
throws DataAccessException {
HibernateTemplate h = new HibernateTemplate(sessionFactory, true);
h.execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
return session;
}
});
h.execute(new HibernateCallback() {
public Object doInHibernate(Session session)
throws HibernateException, SQLException {
throw new DataRetrievalFailureException(
"This Exception is being thrown just to verify proper unbinding of Hibernate Session from JTA transaction");
}
});
}
}