I am using struts2-spring-hibernate in my project.
I am handling the DB connection through spring, so I dont need of hibernate.cfg.xml
I need to execute my query and I need the result
I am successfully getting the result, by using these methods
Mannually open and close the session:
1. Session session = sessionFactory.openSession();
2. Session newSession = HibernateUtil.getSessionFactory().openSession();
Not handling the session mannually
1. getHibernateTemplate().find();
2. getSession().createSQLQuery();
I dont know which method is best one, please suggest me, which one is best for session
when the session will open and close by getHibernateTemplate() and getSession().
I will show the way I use these frameworks together. I avoid the need of HibernateTemplate, I reckon this class is too limited, I prefer to use the Session directly.
Once you have Spring in your project, it should inject the Hibernate SessionFactory in your Daos, so you can handle the Session. First of all, you need to configure the SessionFactory in your applicationContext.xml:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
</bean>
Now you can inject the SessionFactory with the #Autowired annotation:
#Repository
public class HibernateProductDao implements ProductDao {
private final SessionFactory factory;
#Autowired
public HibernateProductDao(final SessionFactory factory) {
this.factory = factory;
}
public List<Product> findAll() {
return factory.getCurrentSession().createCriteria(Product.class).list();
}
public void add(final Product product) {
factory.getCurrentSession().save(product);
}
}
There are here some important thing, you should use the method getCurrentSession() because this way you allow Spring to control the Session lifecycle. If you use getSession() instead, it become your responsability, for instance, close the Session.
Now, let's configure Struts 2. In your web.xml:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
You need the file struts.xml too, to say that Spring will fabricate the objects:
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.objectFactory" value="spring" />
</struts>
Finally, you can inject the Dao in your action:
public class ProductAction {
private ProductDao dao;
#Autowired
public ProductAction(ProductDao dao) {
this.dao = dao;
}
}
Of course, since you're using Spring annotations, you need to scan the packages with component-scan.
That's the best way I found to integrate this frameworks, I hope it's helpful.
Related
How do you limit the accessible scope of a spring bean?
Is this even possible, or recommended?
I ask, as I have a case where I would like a ConnectionManager class to #Autowired #Resource each of its specific IExternalConnections (in case I later need separate ConnectionManager classes).
However, I don't want other classes using those connections directly. It would make sense to me to have some way of making the IExternalConnection beans package private.
Most questions about Spring Bean scope relate to the lifetime of the Bean, which is specifically not what this question is about
Edit:
Here's some code snippets to clarify what I mean
public class ConnectionFactory {
#Resource(name = "defaultConnectionManager")
private IExternalConnectionManager defaultConnectionManager;
#Resource(name = "someOtherConnectionManager")
private IExternalConnectionManager someOtherConnectionManager;
}
The configuration class:
#Configuration
public class Connections {
#Bean
public ConnectionFactory defaultConnectionFactory() {
return new ConnectionFactory();
}
#Bean
public IExternalConnectionManager defaultConnectionManager() {
return new defaultConnectionManager();
}
#Bean
public IExternalConnectionManager someOtherConnectionManager() {
return new someOtherConnectionManager();
}
}
The goal being making Connections only provide the defaultConnectionFactory Bean, and not defaultConnectionManager or someOtherConnectionManager
Would something like this work for you ?
Define the second bean with in the scope of first bean
<bean class="connectionFactory" >
<property name="defaultConnectionManager">
<bean class="com.xyz.Connectionmanager" >
<property name="connection">
<bean class="com.xyz.Connection" ></bean>
</property>
</bean>
</property>
</bean>
My webapp (Spring3 + Hibernate3) always worked with services class-annotated with #Transactional and this configuration:
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
Now... I'm on Google AppEngine. For some nasty reason I don't know yet, #Transactional does not work. It uses some class in javax.naming, which is not whitelisted. It ends up with:
Error creating bean with name 'mySessionFactory': Post-processing of
the FactoryBean's object failed; nested exception is
java.lang.SecurityException: Unable to get members for class
org.hibernate.impl.SessionFactoryImpl
Please don't ask me why.... :-\
Using Spring's HibernateTemplate instead of my dao (which uses raw session factory) solved the problem, but I know it's a little obsolete.
So, I want to try using manual old style transactions. Questions:
where? I'd like to keep the transactions in the service layer.
how?
SessionFactoryImpl dependency is not in Google App Engine whitelist. There is a number of Google hits discussing it.
As far as "what to do", you have options:
Depend on on another JPA provider
Don't use ORM at all, and go native with Spring's JdbcTemplate (my favorite)
I am not sure why you need to use a programmatic transaction management since Hibernate is the root of your problem, but if you just like to know how, here is a draft:
public class SomeService implements SomeInterface {
private SomeDao thisDaoWrapsJdbcTemplate;
private PlatformTransactionManager transactionManager;
public void setTransactionManager( PlatformTransactionManager transactionManager ) {
this.transactionManager = transactionManager;
}
public void doBusiness( Business: business ) {
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = transactionManager.getTransaction( def );
try {
// do business here
Money money = Money.LOTS_OF
...
// wire the money in..
thisDaoWrapsJdbcTemplate.depositLotsOfMoney( money )
transactionManager.commit( status );
} catch ( DataAccessException dae ) {
transactionManager.rollback( status );
throw dae;
}
return;
}
Using Spring 3.1,Mojarra ,Hibernate
applicationContext.xml
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<context:component-scan base-package="mypackage"/>
TestBean.java
#Component
#Scope("session")
public class TestBean {
#Autowired private #Getter #Setter HibernateTemplate hibernateTemplate=null;
public String submit(){
try{
this.test();
}catch (RuntimeException ex) {
FacesUtil.addWarn("Error");
}
return null;
}
#Transactional
public String test() {
Device d1=new Device();
hibernateTemplate.persist(d1);
if(1==1)
throw new RuntimeException("Testing");
Device d2=new Device();
hibernateTemplate.persist(d2);
return null;
}
}
This works(rolled back) ,but shows exception in browser
<h:commandButton value="Submit" action="#{testBean.test}"/>
Tried to show faces message ,but this commits d1
<h:commandButton value="Submit" action="#{testBean.submit}"/>
Calling some other bean's(DAO) transactional method too works,but I would like to have the code in managed bean itself.How should I handle transaction in JSF?
Either move transactional methods to yet another layer or use TransactionTemplate if you wish to avoid it for some reason:
public String test() {
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
try {
txTemplate.execute(new TransactionCallbackWithoutResult() {
#Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// your transactional code here;
}
});
} catch (Exception e) {
// handle exception here
}
return null;
}
Better go for layered architecture Service and DAO layer, directly handling transactions in managed bean defeats the purpose of Single Responsibility Principle of a class.
Managed Bean soul purpose should be for navigation handling and gateway for data from view layer to service layer where you can perform main business logic or use case and delegate data persistence to DAO layer.
As far as messages to UI are concerned you can catch exceptions from service layer and populate required message accordingly.
This way things are more manageable and maintainable and testable. Mock your service layer, test DAO for data persistence and Managed Bean for view layer.
Spring uses proxy/AOP for magical #Transactional to take place and its better you code to interface as it has its own issues if you dont code to interface i.e direct proxy to an interface or CGLIB subclass for injection. Look in docs for tag for proxy setting for better understanding what I mean by code to interface.
Note: HibernateTemplate is considered an Anti Pattern and removed from Hibernate 4 support just a pointer so you can act accordingly if on Hibernate 3.
Hope this helps !!!!!
I'm using Spring + JSF + JPA configuration hosted on Glassfish v3.1.
I'm experiencing some strange (at least for me) behavior of #Transactional annotation. Here is my simplified example:
#Transactional
public void associateGroupToRole(String role, String group) throws MyServiceException {
GroupEntity groupEntity = userDao.getGroupByName(group);
RoleEntity roleEntity = userDao.getRoleByName(role);
//some stuff
if(!roleEntity.getGroups().contains(groupEntity)) {
roleEntity.getGroups().add(groupEntity);
}
}
#Transactional
public void associateGroupToRole(RoleEntity roleEntity, GroupEntity groupEntity) throws MyServiceException {
//some stuff
if(!roleEntity.getGroups().contains(groupEntity)) {
roleEntity.getGroups().add(groupEntity);
}
}
It turns out that "associateGroupToRole" with Entities as arguments works correctly and the one with String - does not. After small modification and coping code from one method to another:
#Transactional
public void associateGroupToRole(String role, String group) throws MyServiceException {
GroupEntity groupEntity = userDao.getGroupByName(group);
RoleEntity roleEntity = userDao.getRoleByName(role);
if(!roleEntity.getGroups().contains(groupEntity)) {
roleEntity.getGroups().add(groupEntity);
}
}
The code runs without any problems and everything is committed to database. My question is: What might be wrong in above example, what is happening to transaction context (when accessing from one annotated method to another), and why my entities are no longer in managed state?
Here is my Spring configuration:
<context:annotation-config />
<context:component-scan base-package="com.mypackage"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
<tx:jta-transaction-manager/>
<tx:annotation-driven/>
As you can see I'm using persistence.xml file and my EntityManager uses JNDI to connect to DB.
Unfortunately there was a bug in some other piece of DAO code. Please vote for close this question.
I have a set of classes with a complex initialization scheme. Basically, I start with the interface I need to get a hold of, and then make a bunch of calls, and I end up with an object that implements that interface.
In order to handle this, I made a factory class that can, given an interface, produce the final object. I made this factory into a bean, and in XML I specified my various service beans as being instantiated via this factory object with a parameter of the interface that they will implement.
This works great, and I totally get exactly the beans I need. Unfortunately, I would like to access them from my controller classes, which are discovered via component scanning. I use #Autowired here, and it appears that Spring has no idea what type of object these are, and since #Autowired works by type, I'm SOL.
Using #Resource(name="beanName") here would work perfectly, however it seems odd to use #Resource for some beans and #Autowired for others.
Is there a way to get Spring to know what interface the factory will be creating for each of these beans without having a different factory method for each type?
I'm using Spring 2.5.6, by the way, otherwise I'd just JavaConfig the whole thing and forget about it.
Factory class:
<T extends Client> T buildService(Class<T> clientClass) {
//Do lots of stuff with client class and return an object of clientClass.
}
app context:
<bean id="serviceFactoryBean" class="com.captainAwesomePants.FancyFactory" />
<bean id="userService" factory-bean="serviceFactoryBean" factory-method="buildService">
<constructor-arg value="com.captain.services.UserServiceInterface" />
</bean>
<bean id="scoreService" factory-bean="serviceFactoryBean" factory-method="buildService">
<constructor-arg value="com.captain.services.ScoreServiceInterface" />
</bean>
my controller:
public class HomepageController {
//This doesn't work
#Autowired #Qualifier("userService") UserServiceInterface userService;
//This does
#Resource(name="scoreService") ScoreServiceInterface scoreService;
}
I suggest you take the factory pattern one step further and implement your factories as Spring FactoryBean classes. The FactoryBean interface has a getObjectType() method which the contain calls to discover what type the factory will return. This gives your autowiring something to get its teeth into, as long as your factory returns a sensible value.
I had a similar problem, but for me I wanted to use a single factory for creating mocked-out implementations of my auto-wired dependencies using JMockit (the testing framework that I am required to use).
After finding no satisfactory solution on the interwebs, I threw together a simple solution that is working really well for me.
My solution uses a Spring FactoryBean as well, but it only uses a single factory bean for creating all my beans (which the original asker seems to have wished to do).
My solution was to implement a factory-of-factories meta-factory that serves-up FactoryBean wrappers around the real, single factory.
Here is the Java for my JMockit mock bean factory:
public class MockBeanFactory<C> implements FactoryBean<C> {
private Class<C> mockBeanType;
protected MockBeanFactory(){}
protected <C> C create(Class<C> mockClass) {
return Mockit.newEmptyProxy(mockClass);
}
#Override
public C getObject() throws Exception {
return create(mockBeanType);
}
#Override
public Class<C> getObjectType() {
return mockBeanType;
}
#Override
public boolean isSingleton() {
return true;
}
public static class MetaFactory {
public <C> MockBeanFactory<C> createFactory(Class<C> mockBeanType) {
MockBeanFactory<C> factory = new MockBeanFactory<C>();
factory.mockBeanType = mockBeanType;
return factory;
}
}
}
And then in the Spring context XML file, you just can simply create the meta factory that creates the specific bean-type factories:
<bean id="metaFactory" class="com.stackoverflow.MockBeanFactory$MetaFactory"/>
<bean factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="mockBeanType" value="com.stackoverflow.YourService"/>
</bean>
To make this work for the original asker's situation, it could be tweaked to make the FactoryBeans into wrappers/adapter for the serviceFactoryBean:
public class FancyFactoryAdapter<C> implements FactoryBean<C> {
private Class<C> clientClass;
private FancyFactory serviceFactoryBean;
protected FancyFactoryAdapter(){}
#Override
public C getObject() throws Exception {
return serviceFactoryBean.buildService(clientClass);
}
#Override
public Class<C> getObjectType() {
return clientClass;
}
#Override
public boolean isSingleton() {
return true;
}
public static class MetaFactory {
#Autowired FancyFactory serviceFactoryBean;
public <C> FancyFactoryAdapter<C> createFactory(Class<C> clientClass) {
FancyFactoryAdapter<C> factory = new FancyFactoryAdapter<C>();
factory.clientClass = clientClass;
factory.serviceFactoryBean = serviceFactoryBean;
return factory;
}
}
}
Then in the XML (notice the userServiceFactory id and the userService bean id are necessary only to work with the #Qualifier annotation):
<bean id="metaFactory" class="com.stackoverflow.FancyFactoryAdapter$MetaFactory"/>
<bean id="userServiceFactory" factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="clientClass" value="com.captain.services.UserServiceInterface"/>
</bean>
<bean id="userService" factory-bean="userServiceFactory"/>
<bean id="scoreServiceFactory" factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="clientClass" value="com.captain.services.ScoreServiceInterface"/>
</bean>
<bean id="scoreService" factory-bean="scoreServiceFactory"/>
And that's it, just one little Java class and a smidge of boiler-plate configuration and your custom bean factory can create all of your beans and have Spring resolve them successfully.
You should be able to achieve this using:
<bean id="myCreatedObjectBean" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass">
<value>com.mycompany.MyFactoryClass</value>
</property>
<property name="targetMethod">
<value>myFactoryMethod</value>
</property>
</bean>
Then you can use either #Resource or #Autowired + #Qualifier to inject into your object directly.