tx:annotation-driven nie działa w applicationContext.xml

0

Cześć, próbuję ustawić by w applicationContext.xml za pomocą <tx:annotation-driven /> skanowało pakiet w poszukiwaniu adnotacji @Transactional. Wszystko działa kiedy <tx:annotation-driven /> jest w pliku dispatcher-servlet.xml, natomiast nie kiedy jest w applicationContext.xml.

Znalazłem tylko taką wskazówkę w dokumentacji, ale nie za bardzo rozumiem:

@EnableTransactionManagement and <tx:annotation-driven/> only looks for @Transactional on beans in the same application context they are defined in. This means that, if you put annotation driven configuration in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services. See Section 22.2, “The DispatcherServlet” for more information.

Może IntelliJ coś psuje?
https://prnt.sc/kgmlj6

Dodaje jeszcze kod:

Działa dispatcher-servlet.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:mvc="http://www.springframework.org/schema/mvc"
       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.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <mvc:annotation-driven/>
    <context:component-scan base-package="com.company.project1.webapp.*"/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <tx:annotation-driven/>

    <bean id="myDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.h2.Driver"/>
        <property name="url" value="jdbc:h2:tcp://localhost/~/test"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="packagesToScan">
            <list>
                <value>com.company.project1.webapp</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.H2Dialect
                hibernate.format_sql=true
                hibernate.show_sql=true
            </value>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

</beans>

Nie działa w 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:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="com.company.project1.webapp.*"/>
    <tx:annotation-driven />

    <bean id="myDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="org.h2.Driver"/>
        <property name="url" value="jdbc:h2:tcp://localhost/~/test"/>
        <property name="username" value="sa"/>
        <property name="password" value=""/>
    </bean>

    <bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <property name="dataSource" ref="myDataSource"/>
        <property name="packagesToScan">
            <list>
                <value>com.company.project1.webapp</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <value>
                hibernate.dialect=org.hibernate.dialect.H2Dialect
                hibernate.format_sql=true
                hibernate.show_sql=true
            </value>
        </property>
    </bean>

    <bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>

</beans>

ProfileService.java

@Service
@Transactional
public class ProfileService {

    private ProfileDao profileDao;

    @Autowired
    public ProfileService(ProfileDao profileDao) {
        this.profileDao = profileDao;
    }

    public void createProfile(ProfileDTO profileDTO) {
        Profile profile = profileDTO.getAsProfile();
        profileDao.save(profile);
    }
}

ProfileDao.java

@Repository
public class ProfileDao {

    private SessionFactory sessionFactory;

    @Autowired
    public ProfileDao(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void save(Profile profile) {
        Session session = sessionFactory.getCurrentSession();
        session.save(profile);
    }
}
1

A czy w web.xml w ogóle mówisz że powinno ładować kontekst z tego pliku applicationContext? Pewnie nie, więc ten plik jest ignorowany. Przecież to nie jest jakaś magia że spring sobie przegląda wszystkie xmle w projekcie w poszukiwaniu kontekstów...

0

@Shalom: mam coś takiego

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>
1

A nie powinno być czasem:

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

?

1

Pokaż gdzieś ten kod w repo bo tak to możemy zgadywać do jutra. Szczególnie że dopiero teraz zauważyłem że chcesz mieć w ogóle 2 konteksty tutaj.

1

Tak na szybko to pierwszy błąd polega na tym, że skanujesz pakiety z obu kontekstów, a tylko w jednym masz te transakcje. Wywal skanowanie pakietów z tego kontekstu mvc i zostaw tam tylko skanowanie pakietu .controllers. Zgaduje że ładowanie kontekstu dispatchera już ci tworzy te wszystkie beany, ale nie robi im proxy dla transactional.

1 użytkowników online, w tym zalogowanych: 0, gości: 1