2

I have spent three days trying to find the solution to this problem to no avail. I am desperate to figure this out. I have a simple spring app, running in servlet 2.5 with jstl tags 1.2, running in tomcat with spring 3.1, using hibernate and the hibernate jpa implementation.

I can list data from a page, but I cannot complete an insert. The record goes back, it appears to fire through with no problems. Yet no insert takes place. I know there are other posts similar but I have looked through them all and have not been able to find a solution anywhere.

If I run the exact same code via a MAIN class, the insert works fine. It just does not work when running as a web-app in tomcat.

I have tried running this via the main which works, inside the controller I have skipped calling the service layer, trying to go directly to the interface, when that didnt work, I tried going directly to the implementing DAO class, and that didnt work. It appears via the spring logs, that the entity manager is getting created, and shut down before a transaction takes place.

Please help me.

Here is my App-context

            <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:aop="http://www.springframework.org/schema/aop" 
                    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.0.xsd 
                    http://www.springframework.org/schema/context 
                    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                    http://www.springframework.org/schema/tx 
                    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
                    http://www.springframework.org/schema/aop 
                    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" 
                    default-autowire="byName">

                <context:component-scan base-package="com.naturalbornliar.site"/>
                <tx:annotation-driven />
                <!-- Bean declarations go here-->

                <bean id="duke" class="com.naturalbornliar.site.entity.Admin">
                    <constructor-arg name="admin_id" type="Long" value="15" />
                    <constructor-arg name="admin_login" type="String" value="testUser" />
                    <constructor-arg name="admin_pwd" type="String" value="testPwd" />
                    <constructor-arg name="email_id" type="int" value="15" />
                    <constructor-arg name="quote" type="String" value="Something to say here" />    
                </bean>

            <!--    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> -->
            <!--        <property name="driverClassName" value="com.mysql.jdbc.Driver"/> -->
            <!--        <property name="url" value="jdbc:mysql://localhost:3306/nbl_db"/> -->
            <!--        <property name="username" value="web_user"/> -->
            <!--        <property name="password" value="web_pwd"/> -->
            <!--        <property name="initialSize" value="5"/> -->
            <!--        <property name="maxActive" value="10"/> -->
            <!--    </bean> -->

                <bean id="simpledataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/nbl_db"/>
                    <property name="username" value="web_user"/>
                    <property name="password" value="web_pwd"/>
                </bean>

                <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                    <constructor-arg ref="simpledataSource"/>
                </bean>

                <bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
                    <property name="persistenceUnitName" value="nblPersistenceUnit"/>
                    <property name="dataSource" ref="simpledataSource"/>
                    <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
                </bean>

            <!--    <bean id="emf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> -->
            <!--        <property name="persistenceUnitName" value="nblPersistenceUnit"/> -->
            <!--        <property name="dataSource" ref="simpledataSource"/>-->
            <!--        <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/> -->
            <!--    </bean> -->

                <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
                    <property name="entityManagerFactory" ref="emf"/>
                    <property name="jpaDialect" ref="jpaDialect"/>
                </bean>

                <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>

                <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                    <property name="database" value="MYSQL"/>
                    <property name="showSql" value="true"/>
                    <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect"/>
                </bean>

                <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

                <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

                <tx:advice id="txAdvice">
                    <tx:attributes>
                        <tx:method name="add*" propagation="REQUIRED"/>
                        <tx:method name="delete*" propagation="REQUIRED"/>
                        <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
                    </tx:attributes>
                </tx:advice>

                <aop:config>

                    <aop:advisor pointcut="execution(* *..CategoryDaoImpl.*(..))" advice-ref="txAdvice"/>

                </aop:config>

                </beans>

Here is my controller:

            package com.naturalbornliar.site.mvc;

            import javax.inject.Inject;

            import org.apache.log4j.Logger;
            import org.springframework.stereotype.Controller;
            import org.springframework.ui.Model;
            import org.springframework.validation.BindingResult;
            import org.springframework.web.bind.annotation.RequestMapping;
            import org.springframework.web.bind.annotation.RequestMethod;

            import com.naturalbornliar.site.entity.Category;
            import com.naturalbornliar.site.entity.Link;
            import com.naturalbornliar.site.service.CategoryService;


            @Controller
            @RequestMapping("/categories")
            public class CategoryController {


                protected final Logger logger = Logger.getLogger(CategoryController.class);

                private final CategoryService categoryService;

                @Inject
                public CategoryController(CategoryService categoryService){
                    this.categoryService = categoryService;
                }

                @RequestMapping(value="/listCategories")
                public String listLinks(Model model){

                    model.addAttribute("categories", categoryService.getAllCategories());

                    return "categories";
                }

                @RequestMapping(method=RequestMethod.GET, params="new")
                public String showCreateCategoryForm(Model model){
                    model.addAttribute(new Category());
                    return "addcategory";
                }

                @RequestMapping(method=RequestMethod.POST)
                public String addCategoryFromForm(Category category, BindingResult bindingResult){
                    if(bindingResult.hasErrors()){
                        return"addcategory";
                        }
                    categoryService.addCategory(category);
                    return "redirect:/categories/listCategories";
                }
            }

Here is my service called from the controller:

            package com.naturalbornliar.site.service;

            import java.util.Collection;

            import javax.inject.Inject;

            import org.springframework.stereotype.Service;

            import com.naturalbornliar.site.entity.Category;
            import com.naturalbornliar.site.i.ICategoryDao;

            @Service
            public class CategoryService {

                private ICategoryDao iCategoryDao;

                @Inject
                public CategoryService(ICategoryDao iCategoryDao){
                    this.iCategoryDao = iCategoryDao;
                }

                public Collection<Category> getAllCategories(){
                    return iCategoryDao.getAllCategories();
                }

                public Collection<Category> getCategoriesByType(String type) {
                    return iCategoryDao.getCategoriesByType(type);
                }

                public Category getCategoryById(Long id) {
                    throw new UnsupportedOperationException();
                }

                public void deleteCategory(Category category) {
                    throw new UnsupportedOperationException();
                }

                public void updateCategory(Category category) {
                    throw new UnsupportedOperationException();
                }

                public void inactivateCategory(Category category){
                    throw new UnsupportedOperationException();
                }

                public void addCategory(Category category){
                    iCategoryDao.addCategory(category);
                }
            }

Here is my implementing DAO:

            package com.naturalbornliar.site.dao;

            import java.util.Collection;
            import java.util.List;

            import javax.persistence.EntityManager;
            import javax.persistence.PersistenceContext;

            import org.apache.log4j.Logger;
            import org.springframework.stereotype.Repository;
            import org.springframework.transaction.annotation.Transactional;

            import com.naturalbornliar.site.entity.Content;
            import com.naturalbornliar.site.i.IContentDao;

            @Transactional
            @Repository
            public class ContentDaoImpl implements IContentDao {

                protected final Logger logger = Logger.getLogger(ContentDaoImpl.class);

                @PersistenceContext
                private EntityManager em;

                public EntityManager getEm() {
                    return em;
                }


                public void setEm(EntityManager em) {
                    this.em = em;
                }

                @Override
                public void addContent(Content content) {
                    // TODO Auto-generated method stub
                    em.persist(content);
                }

                @Override
                public void deleteContent(Content content) {
                    // TODO Auto-generated method stub
                    em.remove(content);

                }

                @Override
                public void inactivateContent(Content content) {
                    // TODO Auto-generated method stub

                }

                @Override
                public Content getContentById(Long id) {
                    // TODO Auto-generated method stub
                    return null;
                }

                @Override
                public Content getContentByName(String name) {
                    // TODO Auto-generated method stub
                    return null;
                }

                @Override
                public Collection<Content> getAllObjects() {
                    List<Content> resultList = em.createQuery("FROM Content", Content.class).getResultList();
                    return resultList;
                }

            }

Here is the interface (just in case)

            package com.naturalbornliar.site.i;

            import java.util.Collection;

            import com.naturalbornliar.site.entity.Content;

            public interface IContentDao {

                public void addContent(Content content);
                public void deleteContent(Content content);
                public void inactivateContent(Content content);
                public Content getContentById(Long id);
                public Content getContentByName(String name);
                public Collection<Content> getAllObjects();

            }
jeremy
  • 111
  • 2
  • 6

4 Answers4

2

Jeremy, thay may be many problems with that and I had similar problem.

In my case I used tomcat and I needed to add spring weaver to tomcat (this problem is described here: http://asrijaffar.blogspot.com/2007/02/spring-jpa-tomcat.html).

In my case I needed to have:

<tx:annotation-driven proxy-target-class="true" />

In DispatcherServlet config.

Additionally in db-context config:

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="jpatest" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
Michal Borek
  • 4,584
  • 2
  • 30
  • 40
  • Michal, I guess I dont understand why I would need spring weaver? I have added the proxy-target you mentioned (though I had had it in the past, and it still didnt work). But since re-adding, it didnt work, though I havent setup spring weaver per that link yet. Why do I need spring weaver, what does it do? – jeremy Feb 27 '12 at 01:56
  • Well I actually solved the problem. Here is the solution, there was another stackoverflow issue that solved it: http://stackoverflow.com/questions/7561360/spring-transaction-not-starting-transactions Basically all that was needed for transactions to fire correctly was for me to add: to my servlet xml. I guess if you just have it in the application config.xml it only works when running under the main class (like in a standalone) if you need to run it in a container you have to declare transaction annotations in the servlet as well. – jeremy Feb 27 '12 at 19:45
2

Well I actually solved the problem. Here is the solution, there was another stackoverflow issue that solved it:

Spring @Transaction not starting transactions

Basically all that was needed for transactions to fire correctly was for me to add:

<tx:annotation-driven proxy-target-class="true"/>

to my servlet xml. I guess if you just have it in the application config.xml it only works when running under the main class (like in a standalone) if you need to run it in a container you have to declare transaction annotations in the servlet as well.

Community
  • 1
  • 1
jeremy
  • 111
  • 2
  • 6
1

I also spent several hours trying to figure out where the problem is although my previous application with the same stack is working fine and I wasn't able to understand the difference.

And.... the error was in tag in spring-servlet.xml - it was defined to scan the root package with all the web controller, repository classes, etc.

After changing it to make scanning of the package with web controllers only, the problem was gone..

Just for you (and for me) in case you might meet the same problem, just an additional hint

alex
  • 90
  • 4
1

I also had this same problem, spent couple nights searching - alex solutions saved me - in servlet xml I changed context:component-scan to scan only package with web controller. Example from this page should look like

<context:component-scan base-package="com.naturalbornliar.site.mvc"/>