Dependency Injection Issue in Spring MVC [version Spring 3.1.0.RELEASE] - spring

I am creating a Spring MVC application.
The Controller depends on one of the services [name: TestExecutionOrchestratorService.java] in the Service layer.
The TestExecutionOrchestratorService depends on a couple of other services
[names: JUnitTestExecutorService, QTPTestExecutorService].The configuration is set up to inject these services in a Map.
The Controller and the TestExecutionOrchestratorService are autowired using annotations.
The TestExecutionOrchestratorService and its dependencies are wired using XML configuration.
Dependency Issue I am trying to solve:
The Controller is getting an object of TestExecutionOrchestratorService. The TestExecutionOrchestratorService is getting
the Map of dependency services injected [I can tell by the log messages printed out]. I save this Map as an instance
variable in the TestExecutionOrchestratorService. However, the instance of the TestExecutionOrchestratorService object in the
Controller does not seem to have the Map set during dependency injection. In other words:
Controller---DEPENDS ON--->TestExecutionOrchestratorService---DEPENDS ON--->Map[of JUnitTestExecutorService, QTPTestExecutorService]
The Map is empty in the instance of the TestExecutionOrchestratorService set in the Controller. I know from log messages that the
Map is being injected during server startup.
The code and XML files are below:
Listing 1 - Controller
/**
* Handles requests for the application home page.
*/
#Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
#Autowired
private TestExecutionOrchestratorService testExecutionOrchestratorService;
/**
* Simply selects the home view to render by returning its name.
*/
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Locale locale, Model model) {
logger.info("Welcome home! the client locale is "+ locale.toString());
Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
String formattedDate = dateFormat.format(date);
model.addAttribute("serverTime", formattedDate );
//ISSUE: Call to the service layer. The Map in the service is empty even though dependency injection is happening
//there.
if (testExecutionOrchestratorService != null) {
logger.info("testExecutionOrchestratorService is not null. Executing it...");
testExecutionOrchestratorService.runTests();
}
else {
logger.info("testExecutionOrchestratorService is null. Why Why Why??");
}
return "home";
}
}
Listing 2 - TestExecutionOrchestratorService
/*
* This class is the entry point into test execution. It takes the request to execute tests
* and calls the appropriate test executors.
*/
#Service("testExecutionOrchestratorService")
public class TestExecutionOrchestratorService implements TestResultsReporter {
/* List of executor services */
private Map<String, TestExecutorService> testExecutors = new HashMap<String, TestExecutorService>();
private static final Logger logger = LoggerFactory.getLogger(TestExecutionOrchestratorService.class);
/*
* For Spring's dependency injection - to inject all the test executors.
*/
public void setExecutormap(Map<String, TestExecutorService> exMap) {
if (exMap != null) {
Set<Entry<String, TestExecutorService>> mapEntrySet = exMap.entrySet();
logger.error("TestExecutionOrchestratorService [setExecutorMap]: Got a map of test executors. The entries are:");
for (Entry<String, TestExecutorService> mapE: mapEntrySet) {
logger.error("Key: " + mapE.getKey() + ", Value: " + mapE.getValue().getExecutorName());
}
//ISSUE: testExecutors is showing as null in the "runTests" method that is called by the Controller. Why??
testExecutors.putAll(exMap);
}
else {
logger.error("TestExecutionOrchestratorService [setExecutorMap]: Got a null executors map");
}
}
/* runTests - Calls upon the various executors to run the tests.
* ISSUE: The Controller is calling this method but the Map set in 'setExecutorMap' is not being found. */
public void runTests() {
logger.error("TestExecutionOrchestratorService [runTests]: Entering the method");
/* Create a unique test run ID. This will be the current time stamp. */
String testRunTimestamp = new Timestamp(new Date().getTime()).toString();
logger.error("TestExecutionOrchestratorService [runTests]: Will execute executors with test run ID: " + testRunTimestamp);
/* Call each executor and ask them to run their default tests. */
if ((testExecutors != null) && (!testExecutors.isEmpty())) {
logger.error("TestExecutionOrchestratorService [runTests]: test executors are available. Will execute them.");
Collection<TestExecutorService> teServices = testExecutors.values();
for (TestExecutorService teService: teServices) {
teService.runTests(testRunTimestamp, null, this);
}
}
else {
/* ISSUE: THIS IS WHERE EXECUTION IS ALWAYS COMING */
logger.error("TestExecutionOrchestratorService [runTests]: There are no test executors available.");
}
}
}
Listing 3 - Spring's Web context XML file (root-context.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="..">
<!-- Root Context: defines shared resources visible to all other web components -->
<!-- Defining services -->
<!-- The following services are defined here: TestExecutionOrchestratorService,
JUnitTestExecutorService, QTPTestExecutorService -->
<!-- Definition of the JUnitTestExecutorService -->
<bean id="junitexecutor" name="junitexecutor" class="com.testing.autofwk.execution.JUnitTestExecutorService" />
<!-- Definition of the QTPTestExecutorService -->
<bean id="qtpexecutor" name="qtpexecutor" class="com.testing.autofwk.execution.QTPTestExecutorService" />
<!-- Definition of the TestExecutionOrchestratorService -->
<bean id="testexecutororchestrator" name="testexecutororchestrator" class="com.testing.autofwk.execution.TestExecutionOrchestratorService">
<property name="executormap">
<map>
<entry key="junit">
<ref local="junitexecutor"/>
</entry>
<entry key="qtp">
<ref local="qtpexecutor"/>
</entry>
</map>
</property>
</bean>
<context:component-scan base-package="com.testing.autofwk.execution" />
</beans>
Listing 4 - The MVC application dispatcher's context XML file (servlet-context.xml)
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="..">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.testing.autofwk" />
</beans:beans>

It seem that you are creating more than one TestExecutionOrchestratorService and the wrong one is injected in your controller. One object is created when the root-context.xml is loaded and since the TestExecutionOrchestratorService has the #Service annotation other beans will be create when the class will be scan.
On top of that, some package will be scan twice because of the dispatcher's context XML file.
It is a good practice to use something like this in the dispatcher's context XML file to avoid scanning the same class multiple times :
<context:component-scan base-package="com.testing.autofwk" use-default-filters="false">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation" />
</context:component-scan>
And in the root context :
<context:component-scan base-package="com.testing.autofwk">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>

Related

Spring id-reference not working as expected

I'm working my way through the Spring Framework reference documentation with some very basic application code. So far, I've created an ApplicationContext from an XML file and loaded some beans. I believe I understand this process pretty well. I've loaded some basic beans with attributes based on fundamental types and found that straight-forward.
I'm now working on a composite bean with other beans as its attributes. So far, I've been able to set these attributes using a direct reference to a bean and an inner bean. However, when I try to get the idref element to work (see http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/beans.html#beans-idref-element) I get the following exception:
java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.example.BasicBean] for property 'idRef': no matching editors or conversion strategy found
Code snippets below:
Application Context XML
<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
<bean id="id-bean" class="com.example.BasicBean" scope="singleton">
<property name="value" value="31"/>
</bean>
<bean id="ref-bean" class="com.example.BasicBean" scope="singleton">
<property name="value" value="37"/>
</bean>
<bean id="cb" class="com.example.CompositeBean" scope="singleton">
<property name="id" ref="id-bean"/> <!-- works -->
<property name="inner"> <!-- works -->
<bean class="com.example.BasicBean">
<property name="value" value="43"/>
</bean>
</property>
<property name="idRef"> <!-- exception thrown -->
<idref bean="ref-bean"/>
</property>
</bean>
</beans>
Java App Code
public void main()
{
context = new ClassPathXmlApplicationContext("beans.xml");
CompositeBean cb = context.getBean("cb", CompositeBean.class);
}
Java Bean Code
public class CompositeBean
{
private BasicBean id;
private BasicBean idRef;
private BasicBean inner;
// Default constructor exists
// Setters, getters for each attribute exist
...
}
public class BasicBean
{
private int value;
// Default constructor exists
// Setters, getters for each attribute exist
...
}
Version info: I'm using Eclipse IDE (Kepler), Maven 3.1, Java 7 (1.7.45), Spring 3.2.4
Any thoughts on what I'm doing wrong?
Thanks #Farid for pointing out that I was mis-using the idref attribute in this instance. As the Spring doco points out (which I'd read several times and still missed this) it's designed for passing the id of a bean around a container and not the actual bean. So, stick to the first two means above (ref and inner bean) for passing a bean around.

Initialize an Java Object in Spring xml

How to Initialize an Java Object in Spring xml
if you have a class and you want to create an object from this class, but without Initialization, so the Initialization will be done in XML. so how
in xml . logger = Logger.getRootLogger();
import org.apache.log4j.*;
public class App {
public void setLogger(Logger logger){
this.logger = logger;
}
}
In app.xml
<bean id="log" class="org.apache.log4j.Logger" factory-method="getRootLogger"/>
<bean id="app" class="com.comptel.mc.App" >
<property name="logger" ref="log"/>
</bean>
Then you can get the initialized bean in your code
App bean = new ClassPathXmlApplicationContext("app.xml").getBean(App.class);

How to execute SQL script only once at startup in Spring?

I have a web application based on Spring JDBC and Jersey RESTful web service. I'm using the following Spring JDBC template class to initiate the dataSource and execute an SQL script (update_condition_table.sql):
public class CustomerJDBCTemplate implements CustomerDAO {
private DataSource dataSource;
private JdbcTemplate jdbcTemplateObject;
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
this.jdbcTemplateObject = new JdbcTemplate(dataSource);
Resource rc = new ClassPathResource("update_condition_table.sql");
JdbcTestUtils.executeSqlScript(jdbcTemplateObject, rc, false);
}
// ......other methods
}
The bean configuration file is beans.xml:
<!-- Initialization for data source -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/customer" />
<property name="username" value="root" />
<property name="password" value="mypassword" />
</bean>
<!-- Definition for customerJDBCTemplate bean -->
<bean id="customerJDBCTemplate" class="com.example.db.CustomerJDBCTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
The Jersey controller class contains the instantiation of class CustomerJDBCTemplate and serves as the REST web service:
#Path("/customer")
public class CustomerService {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
CustomerJDBCTemplate dbController = (CustomerJDBCTemplate) context.getBean("customerJDBCTemplate");
// ... some GET/POST methods
}
When I launched my web app by entering the index URL in the browser, the SQL script gets executed by the customerJDBCTemplate bean. However, when I clicked to navigate to other pages, it crashed and reported that the SQL script cannot be executed again. So obviously the SQL script was executed again after initialization of dataSource and initial launch of the index web page. How to avoid this by just running the SQL script only once upon initial startup of the web app?
Looks like I need to move the bean instantiate code out of CustomerService class, but where should I put that code?
I figured it out that I should set the bean application context to be static within CustomerService class and do it in the static initialization block as follows:
#Path("/customer")
public class CustomerService {
private static ApplicationContext context;
private static CustomerJDBCTemplate dbController;
static {
context = new ClassPathXmlApplicationContext("beans.xml");
dbController = (CustomerJDBCTemplate) context.getBean("customerJDBCTemplate");
}
//... other methods
}
I guess the reason is Jersey creates a different instance of CustomerService for each HTTP session (correct me if I'm wrong). So if I set the bean context as instance variable, it will do the initialization for every HTTP request.
Have your CustomerJDBCTemplate implement InitializingBean. afterPropertiesSet will get called once, right after all properties have been set by Spring's BeanFactory.
For example:
public class CustomerJDBCTemplate implements CustomerDAO, InitializingBean {
...
// ......other methods
public void afterPropertiesSet() throws Exception {
//do your initializing, or call your initializing methods
}
}

#ExceptionHandler not working with Spring MVC 3.1 unit test

I'm able to do nearly all of the unit test on my Spring MVC controller by instantiating the object outside of the normal servlet context. But I would like to be able to run some tests to insure that my object serialization is working properly, headers are being generated, etc.
To run a test inside the servlet context, I create a modified context file so that various beans are NOT constructed, then I create mocked versions of those beans in my test case using EasyMock. I then invoke my handler with code like this, and get most of what I need from the MockHttpServletResponse.
I think this gets the essence of it:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "file:root-context.xml",
"file:junit-servlet-context.xml" } )
public class HomeControllerConfigHandlerHttp {
#Autowired
private RequestMappingHandlerAdapter handlerAdapter;
#Autowired
private RequestMappingHandlerMapping handlerMapping;
... //miscellaneous setup
public void someTest() throws Exception
{
MockHttpServletRequest request = new MockHttpServletRequest();
request.setMethod("GET");
request.setRequestURI("/config");
request.addParameter("foo", "bar");
request.addParameter("device", "oakmont");
MockHttpServletResponse response = new MockHttpServletResponse();
Object handler = handlerMapping.getHandler(request).getHandler();
replay(dblient);
expect(serviceClient.checkDevice("oakmont")).andReturn( true );
serviceClient.destroy();
replay(serviceClient);
ModelAndView modelAndView = handlerAdapter.handle(request, response, handler);
String content = new String( response.getContentAsByteArray() );
Assert.assertEquals(content, "Expected configuration");
String content_type = response.getHeader("Content-type");
Assert.assertEquals( content_type, "text/plain");
int status = response.getStatus();
Assert.assertEquals(status, 200 );
This does what I expect it to do, but there is one catch. I do a lot of error handling in my controller with an #ExceptionHandler. It is an easy way to back out of an error case in any handler, and it gives me a consistent way of exposing errors.
The #ExceptionHandler works fine in normal servlet deployment, but in this unit test mockup it does not get invoked when I throw an exception. Stepping into the Spring code is a bit of a challenge for me, I'm new to it and so I get lost pretty quickly. However, it looks like in the normal servlet environment, there is an exception handler that looks for an annotated handler. When running under SpringJUnit4ClassRunner, the exception isn't processed the same way.
If there is a way to fix this, I'd like to do it. I've avoided spring-test-mvc because of a lack of pioneer spirit, but if someone tells me that it can manage this just fine, I'll try that instead.
The contents of my junit-servlet-context.xml file are nearly identical to the servlet-context.xml file created by the Spring Template MVC wizard. The only difference is the addition of an exclude-filter that is used to prevent instantiation of a #Component that creates a few singletons used by my controller.
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC #Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by #Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.cisco.onplus.home.dmz" >
<context:exclude-filter type="regex" expression=".*InitDatabase.*"/>
</context:component-scan>
</beans:beans>
Add following class for loading Dispatcher servlet in context:
public class MockWebApplicationContext extends AbstractContextLoader {
#Override
public ApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) throws Exception {
String[] locations = mergedContextConfiguration.getLocations();
return loadContext(locations);
}
#Override
public ApplicationContext loadContext(String... locations) throws Exception {
XmlWebApplicationContext webApplicationContext = new XmlWebApplicationContext();
webApplicationContext.setConfigLocations(locations);
webApplicationContext.setServletContext(new MockServletContext(new FileSystemResourceLoader() ) );
ServletConfig config = new MockServletConfig();
config.getServletContext().setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, webApplicationContext);
final DispatcherServlet servlet = new DispatcherServlet(webApplicationContext);
webApplicationContext.addBeanFactoryPostProcessor(new BeanFactoryPostProcessor() {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.registerResolvableDependency(DispatcherServlet.class, servlet);
}
});
webApplicationContext.refresh();
servlet.init(config);
return webApplicationContext;
}
#Override
protected String getResourceSuffix() {
return ".xml";
}
}
Once you are done with that use
#ContextConfiguration(locations = {"classpath:app-config.xml",loader = MockWebApplicationContext.class)
to load DispatcherServlet using Autowired annotation on test class. Process it using
servlet.service(request,response);
Now it should handle exception flow also.
It probably requires 3.1.2 though.
I am afraid you will have to look at spring-test-mvc, the reason is the handling of exception from the controllers and using ExceptionResolver to call the appropriate #ExceptionHandler is done at the level of DispatcherServlet, not HandlerAdapter. The test that you have starts at the level of HandlerAdapter.
I highly recommend spring-test-mvc though, I have been using it for a while and have not seen any issues for my scenarios - http://biju-allandsundry.blogspot.com/2012/07/spring-mvc-integration-tests.html.
A test for an exception flow would look like this with spring-test-mvc:
xmlConfigSetup("classpath:/META-INF/spring/web/webmvc-config.xml")
.configureWebAppRootDir("src/main/webapp", false).build()
.perform(get("/contexts/exception"))
.andExpect(status().isOk())
.andExpect(view().name("exceptionPage"));

Injection of autowired dependencies failed while using #Transactional

I testing my DAO, but it didn't work. The following error occurs:
Tests in error:
testAccountOperations(com.tsekhan.rssreader.dao.HibernateControllerTest): Error creating bean with name 'com.tsekhan.rssreader.dao.HibernateControllerTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: com.tsekhan.rssreader.dao.HibernateController com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController; nested exception is java.lang.IllegalArgumentException: Can not set com.tsekhan.rssreader.dao.HibernateController field com.tsekhan.rssreader.dao.HibernateControllerTest.hibernateController to $Proxy25
My DAO:
#Service
#Scope("singleton")
public class HibernateController extends HibernateDaoSupport {
#Autowired
public SessionFactory sessionFactory;
#Transactional
public void addAcount(Account account) {
sessionFactory.getCurrentSession().saveOrUpdate(account);
}
}
My test for this DAO:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:/applicationContext.xml")
public class HibernateControllerTest {
#Autowired
HibernateController hibernateController;
private Set<Channel> getTestChannelList(String channelLink) {
Channel testChannel = new Channel();
testChannel.setSourceLink(channelLink);
Set<Channel> testChannelList = new HashSet<Channel>();
testChannelList.add(testChannel);
return testChannelList;
}
private Account getTestAccount(String accountLogin, String channelLink) {
Account testAccount = new Account();
testAccount.setAccountLogin(accountLogin);
testAccount.setChannelList(getTestChannelList(channelLink));
return testAccount;
}
#Test
public void testAccountOperations() {
hibernateController
.addAcount(getTestAccount("test_login", "test_link"));
}
}
My applicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd"
default-autowire="byName">
<!-- Enabling spring-transaction annotations -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Enabling annotation-driven configurating -->
<context:annotation-config />
<!-- Creation of transaction manager -->
<bean id="transactionManager" scope="singleton"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="sessionFactory" scope="singleton"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="configLocation" value="classpath:/hibernate.cfg.xml"/>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
<!--
A Spring interceptor that takes care of Hibernate session lifecycle.
-->
<bean id="hibernateInterceptor"
class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean name="employeeDAO" scope="prototype"
class="com.tsekhan.rssreader.dao.HibernateController" />
<!-- Searching for hibernate POJO files in package com.tsekhan.rssreader.web -->
<context:component-scan base-package="com.tsekhan.rssreader.web" />
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
</beans>
I note, that if you comment #Transactional in DAO, bean is created correctly. What happens?
First of all its realy bad to give name ending in Controller to a DAO its very confusing, Controller and DAO have all together different purpose.
When you add #Transactional to a service or dao class, for spring to make it work in a transaction needs to create a proxy of that class, its a kind of wrapper where in before the execution of proxied class(class in consideration which is proxied) method spring starts the transaction and after the execution in case no exceptions completes the transaction, this can be done in spring via AOP and Annotations. To describe in code.
public class OriginalDaoImpl implements OriginalDao extends DaoSupport {
public void save(Object o){
manager.save(o);
}
}
public class ProxyDaoImpl implements OriginalDao {
private OriginalDao originalDaoImpl; //instance of OriginalDaoImpl
public void save(Object o){
try{
transaction.start();
originalDaoImpl.save(o);
transaction.commit();
}catch(Exception e){
transaction.rollback();
}finally{
//clean up code
}
}
}
As you see this is not an exact implementation but a foundation code, how transaction magically works for you. The key point is there interface OriginalDao which makes this injection easy as OriginalDaoImpl and ProxyDaoImpl both implement same interface. Hence they can be swapped i.e. proxy taking place of original. This dynamic proxy can be created in java by Java dynamic proxy. Now, the question what if your class is not implementing an interface, it gets harder for the replacement to happen.
One of the libraries CGLIB as far as I know, helps in such a scenario, whereby it generates a dynamic subclass for the class in consideration and in overriden method performs the magic as described above, by calling super.save(o) to delegate to original code.
Now to the problem of injection.
Create interface and make your dao implement that and spring will default to JDK proxy as it is behaving now.
Add proxy-target-class="true" attribute to <tx:annotation-driven transaction-manager="transactionManager"/>
As far as exception is concerned it is throwing as it is expecting injected bean to be of type 'HibernateController' but its not.
For you reference you can refer links below.
10.5.6 Using #Transactional
Spring AOP Doc
Hope this helps !!!!!.
If your are using Spring MVC make sure to scan specific controller classes alone in servlet context file. Otherwise it will scan 2 times and transaction is not available on the application context.

Resources