Spring / @Transactional с AspectJ полностью игнорируется

Я использую Spring-Data Neo4j 2.2.0-RELEASE. (моя следующая проблема будет применима к любому другому типу сопоставления объектов, почему бы и нет JPA)

В моем проекте у меня есть общедоступный метод, аннотированный аннотацией @Transactional Spring, так как я хочу обновить/сохранить объект внутри него:

public class MeetingServices {

    private UserRepository userRepository;

    private MeetingRepository meetingRepository;

    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void setMeetingRepository(MeetingRepository meetingRepository) {
        this.meetingRepository = meetingRepository;
    }

    @Transactional("neo4jTransactionManager")
    public void save(Meeting meeting) {
        User creator = userRepository.getUserByEmail("[email protected]");
        creator.participateIn(meeting); // this line leads to a NotInTransactionException since it signals that no transaction context is associated.
        meeting.setCreator(creator);
    }

Мой application-context.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:neo4j="http://www.springframework.org/schema/data/neo4j"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/neo4j
       http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase">
        <constructor-arg value="target/neo4jgraph" />
    </bean>

    <neo4j:config graphDatabaseService="graphDatabaseService" />

    <bean id="meetingServices" class="services.MeetingServices">
        <property name="userRepository"><ref bean="userRepository"/></property>
        <property name="meetingRepository"><ref bean="meetingRepository"/></property>
    </bean>

    <bean id="userServices" class="services.UserServices">
        <property name="userRepository"><ref bean="userRepository"/></property>
    </bean>

    <bean id="neo4jTransactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager">
            <bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
                <constructor-arg ref="graphDatabaseService" />
            </bean>
        </property>
        <property name="userTransaction">
            <bean class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
                <constructor-arg ref="graphDatabaseService" />
            </bean>
        </property>
    </bean>

    <tx:annotation-driven mode="aspectj"
        transaction-manager="neo4jTransactionManager" />

    <!-- auto-generated repositories for Neo4j storage -->
    <neo4j:repositories base-package="repositories"/> 

    <context:spring-configured/>

    <context:annotation-config/>

</beans>

Как мы видим в этой конфигурации, для транзакций используется аспект J.

Итак, я попытался протестировать другой способ, изменив свой application-context.xml, чтобы использовать функцию proxy вместо функции aspectJ:

<?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:neo4j="http://www.springframework.org/schema/data/neo4j"
       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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/neo4j
       http://www.springframework.org/schema/data/neo4j/spring-neo4j.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase">
        <constructor-arg value="target/neo4jgraph" />
    </bean>

    <neo4j:config graphDatabaseService="graphDatabaseService" />

    <bean id="meetingServices" class="services.MeetingServices">
        <property name="userRepository"><ref bean="userRepository"/></property>
        <property name="meetingRepository"><ref bean="meetingRepository"/></property>
    </bean>

    <bean id="userServices" class="services.UserServices">
        <property name="userRepository"><ref bean="userRepository"/></property>
    </bean>

    <tx:annotation-driven mode="proxy" />


    <neo4j:repositories base-package="repositories"/>

    <context:spring-configured/>

    <context:annotation-config/>

</beans>

Эта конфигурация работает довольно хорошо, поскольку аннотация @Transactional (чей параметр neo4jTransactionManager, конечно, был удален) теперь учитывается для метода моего сервиса.

Мой вопрос (независимо от того, будет ли мой проект работать с простым методом proxy):

Что я пропустил или неправильно настроил в своей первой конфигурации Spring, из-за чего функции транзакций аспекта J не работают?

В настоящее время я совершенствую свои технические навыки с помощью Spring и прочитал несколько статей о "ткачестве во время загрузки" для аспектаJ. Может ли это быть связано с моей проблемой?


person Mik378    schedule 25.03.2013    source источник


Ответы (1)


Попробуйте добавить <context:load-time-weaver/>, чтобы включить переплетение времени загрузки, и добавьте spring-aspects.jar в путь к классам.

См. http://static.springsource.org/spring/docs/current/spring-framework-reference/html/aop.html#aop-aj-ltw-spring для получения дополнительной информации.

Изменить

Для общих Java-приложений, т. е. не работающих в веб-контейнере или контейнере приложений, необходимо включить инструментарий Java с помощью параметра javaagent:

java -javaagent:path/to/spring-instrument.jar your.Main

Если вы хотите сплести свои собственные аспекты, вам необходимо предоставить файл META-INF/aop.xml с объявлениями аспектов. (Не требуется только для весенних аспектов, он уже предоставлен на spring-aspect.jar).

Наконец, вместо этого вы можете использовать переплетение во время компиляции, используя подключаемый модуль maven aspectj, например:

<plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>aspectj-maven-plugin</artifactId>
            <configuration>
                <complianceLevel>1.6</complianceLevel>
                <aspectLibraries>
                    <aspectLibrary>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring-aspects</artifactId>
                    </aspectLibrary>
                </aspectLibraries>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
person Jose Luis Martin    schedule 25.03.2013
comment
Я уже пробовал это, но в итоге получил вот это: Caused by: java.lang.IllegalStateException: ClassLoader [sun.misc.Launcher$AppClassLoader] does NOT provide an 'addTransformer(ClassFileTransformer)' method. Specify a custom LoadTimeWeaver or start your Java virtual machine with Spring's agent: -javaagent:org.springframework.instrument.jar - person Mik378; 25.03.2013
comment
Добавьте параметр для основного средства запуска: java -javaagent:C:/projects/foo/lib/global/spring-instrument.jar foo.Main, как в справочном примере. - person Jose Luis Martin; 25.03.2013
comment
Я просто последовал твоему совету :) но это приводит к следующему: Вызвано: java.lang.VerifyError: (class: services/MeetingServices$$EnhancerByCGLIB$$73b088b5, method: setMeetingRepository signature: (Lrepositories/MeetingRepository;)V) Inconsistent stack height 1 != 0. Похоже на известную ошибку (stackoverflow.com/questions/9027009/aspectj-verifyerror). Я использую Java 7. Я только что попробовал совет: добавление параметров -XX:-UseSplitVerifierto VM, но ошибка все еще возникает. - person Mik378; 25.03.2013
comment
Попробуйте с maven и скомпилируйте время плетения. Я просто публикую пример. удалите тег ltw и параметр javaagent. они не требуются при использовании плетения во время компиляции. - person Jose Luis Martin; 25.03.2013
comment
Спасибо, я попробую это (метод maven), как только вернусь к своему компьютеру, я сообщу вам :) - person Mik378; 25.03.2013
comment
Плагин не работает в eclipse. Следуя указаниям в stackoverflow.com/questions/6522540/ ...AJDT m2e Configurator не работает во время установки. ... удалить m2eclipse .. установить AJDT m2e Configurator по-прежнему не удается ... установить инструменты разработки aspectJ (Juno) .. установить AJDT m2e Configurator с m2e ... и, наконец, работать с этой конфигурацией stackoverflow.com/questions /6844603/. Какая ПИТА! Теперь аспект J сплетается во время компиляции, но транзакций по-прежнему нет. - person s_t_e_v_e; 05.08.2013