I have developed a webapp using Spring MVC + Hibernate, and using three layers, Controller layer, Service layer and Dao layer.
Now I want to provide a REST api for my webapp.
Since I have a GenericDao which provides generic methods like find(id), findAll(), findByProperty() I thought I could skip the Service Layer in the Api Controller and inject the daos into the Controller itself, otherwise I would have to create class-specific methods for each of my domain objects for these generic find, findAll methods, which is a pain in the ass when I want to presetn just raw data.
My first, more generic question is regarding this architecture decision. Is this a good solution?
My second (and main) question is that I am having trouble when annotating my Controller method with @Transactional
so a hibernate session is opened. It seems that it's not working at all.
I even creted an interface as said in this question.
IApiController
@Controller
public interface IApiController {
@ResponseBody
public String getStation(Long id);
@ResponseBody
public String getStations();
}
ApiController
@Controller
@RequestMapping("/api")
public class ApiController extends BaseApiController implements IApiController {
@Autowired
private IStationDao stationDao;
@RequestMapping(value = "stations/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Transactional(readOnly=true)
public String getStation(@PathVariable Long id){
Station station = stationDao.findById(id);
return pack(station);
}
@Override
@RequestMapping(value = "stations", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
@Transactional(readOnly=true)
public String getStations() {
List<Station> stations = stationDao.findAll();
return pack(stations);
}
}
When I call api/stations
I get a HibernateException: No Session found for current thread
Context config
<context:component-scan base-package="my controller package" />
<mvc:annotation-driven />
<context:annotation-config />
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
<bean id="SessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="mappingLocations">
<list>
<value>classpath*:/hbm/*.hbm.xml</value>
</list>
</property>
</bean>