Announcement Announcement Module
Collapse
No announcement yet.
Spring 3.1 Hibernate 4.1 context visibility Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring 3.1 Hibernate 4.1 context visibility

    I'm having trouble understanding issues that seem to be linked to the persistence context difference between the applicationContext and dispatcher-servlet context.

    My applicationContext.xml and dispatcher-servlet.xml is posted in the second post in this thread.

    I have a generic DAO, a service package with and interface called "ServiceService", and an impl package underneath it with "ServiceServiceImpl".

    My class definition looks like this:

    Code:
     @Repository("serviceDao")
        public class ServiceServiceImpl extends GenericDAOWithJPA<Service, Integer> implements ServiceService
    I copied all of this from an example, so I'm started to get confused if that class is really a service or if it's the actual DAO....

    Either way, if I try to create Service objects from within that DAO and persist them, hibernate generates and ID and no errors are thrown, however, through my Spring controller which has this DAO auto-wired, if I do a findAll(), I get no results.

    Then, if I build a service object in my controller, then persist it through the serviceDao object in the controller, a findAll() returns this object with the incremented ID (as if the persist command that I did from inside the DAO actually worked, but it just doesn't show up in the results).

    Every time I make a small change to my .xml files, things go haywire. I've read till my eyes bleed and still can't seem to find a consensus on how to use <context:annotation-config/>, <tx:transaction-driven>, <mvc:annotation-driven>, etc etc.

    To get into the weeds a little more, one of my goals was to hold a map in-memory of Service objects. On the page that displays values, it will make an AJAX call to my controller and retrieve these objects from the map, so it doesn't have to execute queries each time the page is accessed. These values are not likely to change very often at all. There will be an administration page where an admin can persist the services currently in the map to the database, add new services to the map, or rebuild the map from persistence. So when my webapp starts up, I need to query another web service to get my initial list of Services... I created a method annotated with @PostConstruct in my ServiceServiceImpl class to fetch them, then persist them. When I do this, I can't do a findAll() and see any of them from my controller. If I call that method to fetch the Services and persist them from the controller, where all of the logic is in that method in my ServiceServiceImpl class, I still can't see them. But if I separate the logic just a little bit and call a method from my controller to ServiceServieImpl to a) fetch the list from the remote service, b) loop through that list, call get the map from the ServiceServiceImpl class and add them one by one, and finally c) call a method in ServiceServiceImpl to persist that map to the database (loops through the map and calls super.entityManager.persist(Service), it works and from my controller, I can do a findAll() and see those services.

    I'm pretty sure my xml files are properly structured so that all of my annotated beans EXCEPT controllers are loaded in the applicationContext, and only the controllers are loaded in the dispatcher-servlet context. From my understanding, the dispatcher-servlet should have visibility into the application context (not vice versa). So I don't understand why entities that are created/persisted from within one of my service/dao objects seem to be invisible to my dispatcher-servlet context.

    I think I've blurred the lines between the DAO and the service layer -- my ServiceServiceImpl contains quite a bit of logic and various methods to either retrieve objects from the local map or to persist/query via it's parents entityManager. Any advice to help me sort out this mess... create better distinction between service layer and dao layer, and figure out what the heck is going on with contexts/visibility would be greatly appreciated.

  • #2
    applicationContext.xml:
    Code:
     <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans" 
               xmlns:context="http://www.springframework.org/schema/context" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:mvc="http://www.springframework.org/schema/mvc" 
               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/mvc  
                http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.1.xsd 
                http://www.springframework.org/schema/security 
                http://www.springframework.org/schema/security/spring-security-3.1.xsd 
                http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
        
            <context:annotation-config/>
            <context:property-placeholder location="classpath:database.properties" />
            
            <context:component-scan base-package="com.myproj">
                <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
            </context:component-scan>
        
            <bean id="persistenceUnitManager" class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
                <property name="persistenceXmlLocations">
                    <list>
                        <value>classpath:/META-INF/jpa-persistence.xml</value>
                    </list>
                </property>
                <property name="defaultDataSource" ref="dataSource"/>
            </bean>
        
            <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
                <property name="driverClassName" value="${database.driverClassName}" />
                <property name="url" value="${database.url}" />
                <property name="username" value="${database.username}" />
                <property name="password" value="${database.password}" />
            </bean>
        
            <bean id="entityManagerFactory"
                  class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
                <property name="packagesToScan" value="com.myproj" />
                <property name="persistenceUnitName" value="SWTC" />
                <property name="dataSource" ref="dataSource" />
                <property name="persistenceXmlLocation" value="classpath:META-INF/jpa-persistence.xml" />
                <property name="persistenceProvider" ref="persistenceProvider" />
                <!--
                <property name="jpaVendorAdapter">
                    <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                        <property name="databasePlatform" value="${database.platform}" />
                        <property name="showSql" value="${database.showSql}" />
                        <property name="generateDdl" value="${database.generateDdl}" />
                   
                    </bean>
                </property>
                -->
                <property name="jpaProperties">
                    <props>
                        <prop key="hibernate.cache.use_second_level_cache">false</prop>
                        <prop key="hibernate.show_sql">true</prop>
                        <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
                        <prop key="hibernate.ejb.naming_strategy">org.hibernate.cfg.ImprovedNamingStrategy</prop>
                        <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
                        <prop key="javax.persistence.validation.mode">none</prop>
                        <prop key="hibernate.show.sql">true</prop>
                        <prop key="hibernate.format_sql">true</prop>
                    </props>
                </property>
            </bean>
        	
            <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
                <property name="entityManagerFactory" ref="entityManagerFactory" />
            </bean>
        
            <tx:annotation-driven transaction-manager="transactionManager" />
            
            <bean id="persistenceProvider" class="org.hibernate.ejb.HibernatePersistence" />
            <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
            <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="database" value="HSQL" />
            </bean>   
            
            <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
            <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
            
        
            <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
          
        </beans>
    and my dispatcher-servlet.xml:

    Code:
      <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans" 
               xmlns:context="http://www.springframework.org/schema/context" 
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
               xmlns:mvc="http://www.springframework.org/schema/mvc" 
               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/mvc  
                http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd 
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-3.1.xsd 
                http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
        
               
            <mvc:annotation-driven />
           
           <!-- Sets what packages to automatically scan for annotations -->
           
            <context:component-scan base-package="com.myproj.controllers">
                <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
            </context:component-scan>
            
           
            <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
                <property name = "alwaysUseFullPath" value = "true" />
            </bean>
        
            <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
                <property name="alwaysUseFullPath" value="true" />
            </bean>
           <!--
            <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />
            <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
        -->
        </beans>

    Comment


    • #3
      Please use the search as this question has been answered before...

      The error is in your dispatcher-servlet.xml... You should first disable the default filters in your component scan and then tell it to scan for controllers... The fact that you include something doesn't automatically exclude everything else!!! Currently it scans for everything basically duplicating your services and due to the absence of tx:annotation-driven in your dispatcher-servlet.xml it creates a non transactional instance.

      Originally posted by turick
      I'm pretty sure my xml files are properly structured so that all of my annotated beans EXCEPT controllers are loaded in the applicationContext, and only the controllers are loaded in the dispatcher-servlet context.
      As mentioned the fact that you include something doesn't imply you exclude everything else! Also note the comments below, although not related to your problem will cleanup your xml.

      Also your configuration is flawed (overly configured more) remove the AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor, those are implied by the component-scan.

      Also why do you use the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter as those are the older @RequestMapping annotation processing beans. The correct ones are already registered through the mvc:annotation-driven.

      For your applicationContext the same applies and also remove the context:annotation-config (already implied by the component-scan) as well as the PersistenceExceptionTranslationPostProcessor .

      I strongly suggest a read of the reference guide and for more info on Spring MVC this book. (Shameless plug)...
      Last edited by Marten Deinum; Oct 29th, 2012, 09:13 AM. Reason: Fixed typo.

      Comment

      Working...
      X