No transaction in progress exception with Spring 3.1 and JPA 2

Old Man Programmer picture Old Man Programmer · Jul 18, 2012 · Viewed 14.6k times · Source

I have been at this for weeks. I have tried eclipselink and now just plain JPA. I keep getting the same issue. Everytime I try to flush my entity manager I get 'javax.persistence.TransactionRequiredException: no transaction is in progress' exception. I know its something to do with how I have everything wired but I can't figure it out.

I have tried writing JUnit tests to test, but since I am new to spring that has a entirely different set of issue.

Some things to note: I am not using a persistence.xml since I am using spring 3.1 *App Server: WebSphere 8.5 (Liberty Profile)*

exception

[ERROR   ] SRVE0777E: Exception thrown by application class 'org.springframework.web.servlet.FrameworkServlet.processRequest():894'
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
  at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
  at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
  at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
  at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1221)
  at [internal classes]
[ERROR   ] SRVE0315E: An execption occurred: com.ibm.ws.webcontainer.webapp.WebAppErrorReport: org.springframework.web.util.NestedServletException: Request processing failed&#59; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
    at com.ibm.ws.webcontainer.webapp.WebAppErrorReport.constructErrorReport(WebAppErrorReport.java:153)
    at com.ibm.ws.webcontainer.webapp.WebAppErrorReport.constructErrorReport(WebAppErrorReport.java:194)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1078)
    at com.ibm.ws.webcontainer.webapp.WebApp.handleRequest(WebApp.java:4173)
    at com.ibm.ws.webcontainer.webapp.WebGroup.handleRequest(WebGroup.java:302)
    at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost.handleRequest(DynamicVirtualHost.java:296)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:1006)
    at com.ibm.ws.webcontainer.osgi.DynamicVirtualHost$1.run(DynamicVirtualHost.java:253)
    at com.ibm.ws.http.dispatcher.internal.channel.HttpDispatcherLink$TaskWrapper.run(HttpDispatcherLink.java:457)
    at com.ibm.ws.threading.internal.Worker.executeWork(Worker.java:398)
    at com.ibm.ws.threading.internal.Worker.run(Worker.java:380)
    at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:894)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:595)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:668)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1221)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:757)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:440)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.invokeTarget(WebAppFilterChain.java:125)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:92)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:192)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:89)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:322)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:184)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:155)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
    at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:192)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:89)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:939)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.invokeFilters(WebAppFilterManager.java:1036)
    ... 9 more
Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress
    at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:983)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
    at $Proxy120.flush(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
    at $Proxy120.flush(Unknown Source)
    at com.smartpharm.dao.AbstractGenericDao.save(AbstractGenericDao.java:22)
    at com.smartpharm.account.dao.impl.AccountDaoJpaImpl.createUser(AccountDaoJpaImpl.java:27)
    at com.smartpharm.account.service.impl.AccountServiceImpl.createUser(AccountServiceImpl.java:21)
    at com.smartpharm.account.controller.AccountController.createAccount(AccountController.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    ... 49 more

pom.xml dependencies

    <properties>
        <org.springframework.version>3.1.1.RELEASE</org.springframework.version>
    </properties>
<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.3</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.19</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>commons-pool</groupId>
            <artifactId>commons-pool</artifactId>
            <version>1.6</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
            <version>1.3</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>com.lexi.lexidata</groupId>
            <artifactId>LexiData</artifactId>
            <version>1.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-asl</artifactId>
            <version>1.9.6</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-taglibs</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${org.springframework.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${org.springframework.version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate.javax.persistence</groupId>
            <artifactId>hibernate-jpa-2.0-api</artifactId>
            <version>1.0.1.Final</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-core-lgpl</artifactId>
            <version>1.9.7</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>1.9.7</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.1.4.Final</version>
            <type>jar</type>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2.2</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <type>jar</type>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>3.1.1.RELEASE</version>
            <type>jar</type>
            <scope>test</scope>
        </dependency>
    </dependencies>

app-config.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"
    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-3.1.xsd">


     <context:annotation-config/>
     <context:component-scan base-package="com.smartpharm"/>   

     <import resource="db-config.xml"/>
     <import resource="security-config.xml"/>

</beans>

db-config.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:jee="http://www.springframework.org/schema/jee"
     xmlns:tx="http://www.springframework.org/schema/tx"
     xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
        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-3.0.xsd">


     <jee:jndi-lookup id="lexiDataSource" jndi-name="jdbc/lexiDb" expected-type="javax.sql.DataSource"/> 
     <jee:jndi-lookup id="smartDataSource" jndi-name="jdbc/smartDb" expected-type="javax.sql.DataSource"/>

     <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="smartDataSource" />
        <property name="packagesToScan" value="com.smartPharm" />
        <property name="jpaVendorAdapter">
           <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
              <property name="showSql" value="true" />
              <property name="generateDdl" value="true" />
              <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect" />
           </bean>
        </property>
     </bean>

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

     <tx:annotation-driven transaction-manager="txManager" proxy-target-class="false" />


</beans>

AbstractGenericDao

package com.smartpharm.dao;

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

import org.springframework.transaction.annotation.Transactional;


public abstract class AbstractGenericDao<K,PK> implements GenericDao<K,PK> {

    @PersistenceContext
    public EntityManager em;

    public EntityManager getEntityManager() {
        return em;
    }

    @Transactional
    public K save(K toAdd) {
        em.persist(toAdd);
        em.flush();
        return toAdd;
    }

    abstract public K find(PK pk);

    public void deleteByPrimaryKey(PK pk) {
        em.remove(find(pk));
        em.flush();
    }

    public void delete(K toDelete) {
        em.remove(toDelete);
        em.flush();
    }

}

AccountDaoJpaImpl package com.smartpharm.account.dao.impl;

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

import com.smartpharm.account.dao.AccountDao;
import com.smartpharm.account.entities.User;
import com.smartpharm.account.model.CreateUserRequest;
import com.smartpharm.dao.AbstractGenericDao;

@Repository
@Transactional
public class AccountDaoJpaImpl extends AbstractGenericDao<User, Integer> implements AccountDao{

    private static Logger log = Logger.getLogger(AccountDaoJpaImpl.class);

    @Transactional
    public void createUser(CreateUserRequest createUserRequest){
        log.info("creating User for " + createUserRequest.getEmailAddress());

        User user = new User();
        user.setUserName(createUserRequest.getEmailAddress());
        user.setPassword("password");

        user = save(user);

        log.debug("user " + user.getUserId() + " created");
    }


    @Override
    public User find(Integer pk) {
        // TODO Auto-generated method stub
        return null;
    }
}

AccountServiceImpl

package com.smartpharm.account.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.smartpharm.account.dao.AccountDao;
import com.smartpharm.account.model.CreateUserRequest;
import com.smartpharm.account.service.AccountService;


@Service
@Transactional
public class AccountServiceImpl implements AccountService {

    @Autowired
    AccountDao accountDao;

    @Transactional
    public void createUser(CreateUserRequest request){
        accountDao.createUser(request);
    }
}

AccountController

package com.smartpharm.account.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.smartpharm.account.model.CreateUserRequest;
import com.smartpharm.account.model.CreateUserResponse;
import com.smartpharm.account.service.AccountService;

@Controller
public class AccountController {

    private static Logger log = Logger.getLogger(AccountController.class);

    @Autowired
    AccountService accountService;

    public AccountController(){
    }

    @RequestMapping(value="/admin/createUser", method=RequestMethod.POST)
    public @ResponseBody CreateUserResponse createAccount(@RequestBody CreateUserRequest createUserRequest, HttpServletRequest request, HttpServletResponse response){
        log.debug(createUserRequest);

        accountService.createUser(createUserRequest);

        return new CreateUserResponse("userCreated", "no error");
    }

}

Also in the log right before it tries to commit at the DB layer I see log that it created then destroyed an EntityManager twice

DEBUG AccountController - CreateUserRequest 
firstName = test
middleInit = test
lastName = tset
emailAddress = test
dob = 
address1 = 
address2 = 
city = 
state = 
zip = 


INFO  AccountDaoJpaImpl - creating User for test

DEBUG SharedEntityManagerCreator$SharedEntityManagerInvocationHandler - Creating new EntityManager for shared EntityManager invocation

DEBUG SessionImpl - Opened session at timestamp: 13426274946

DEBUG EntityManagerFactoryUtils - Closing JPA EntityManager

DEBUG SharedEntityManagerCreator$SharedEntityManagerInvocationHandler - Creating new EntityManager for shared EntityManager invocation

DEBUG SessionImpl - Opened session at timestamp: 13426274950

DEBUG EntityManagerFactoryUtils - Closing JPA EntityManager

Answer

Tomasz Nurkiewicz picture Tomasz Nurkiewicz · Jul 18, 2012
@Transactional(propagation=Propagation.MANDATORY)

Quoting Spring JavaDoc on MANDATORY:

Support a current transaction, throw an exception if none exists. Analogous to EJB transaction attribute of the same name.

Just change it to:

@Transactional

to use default (REQUIRED) propagation. Alternatively call AccountDaoJpaImpl.createUser() from external transaction, e.g. wrap AccountServiceImpl.createUser() with @Transactional (with default propagation).