2011-08-03 4 views
0

J'espère vraiment que vous pouvez m'aider. J'ai regardé partout sur Internet pour des réponses et aucun d'entre eux ne fonctionne. J'utilise Spring 3 + JTA + EclipseLink mais j'obtiens une exception TransactionRequiredException lors du vidage d'une transaction. Maintenant, je suis très habitué à simplement définir mon contexte de persistance et injecter l'EntityManager et la transaction est gérée par le serveur de l'application.Spring + Eclipselink + JtaTransactionManager = javax.persistence.TransactionRequiredException

Alors voici ce que j'ai.

persistence.xml

<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="CartouchanPU" transaction-type="JTA"> 
     <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> 
     <jta-data-source>java:app/jdbc/CartouchanDS</jta-data-source> 
     <class>com.cartouchan.locator.database.models.Authority</class> 
     <class>com.cartouchan.locator.database.models.AuthorityPK</class> 
     <class>com.cartouchan.locator.database.models.User</class> 
     <class>com.cartouchan.locator.database.models.UserPK</class> 
     <exclude-unlisted-classes>false</exclude-unlisted-classes> 
     <properties> 
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> 
      <property name="eclipselink.ddl-generation" value="none"/> 
      <property name="eclipselink.target-database" value="MySQL"/> 
      <property name="eclipselink.jdbc.native-sql" value="true"/> 
      <property name="eclipselink.jdbc.cache-statements" value="true"/> 
     </properties>   
    </persistence-unit> 
</persistence> 

printemps-config.xml

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

<jee:jndi-lookup jndi-name="java:app/jdbc/CartouchanDS" id="CartouchanDS" /> 

    <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> 
    <property name="autodetectUserTransaction" value="true" /> 
    <property name="autodetectTransactionManager" value="true" /> 
    <property name="transactionManagerName" value="java:appserver/TransactionManager"/> 
</bean> 

<context:annotation-config /> 

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
    <property name="persistenceUnitName" value="CartouchanPU" /> 
    <property name="persistenceUnitManager"> 
     <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"/> 
    </property> 
    <property name="loadTimeWeaver"> 
     <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" /> 
    </property> 
    <property name="jpaVendorAdapter"> 
     <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"> 
      <property name="showSql" value="true" /> 
     </bean> 
    </property> 
    <property name="jpaDialect"> 
     <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" /> 
    </property> 
</bean> 

CreateAccount.class

import java.text.MessageFormat; 

import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 

import org.apache.log4j.Logger; 
import org.springframework.transaction.annotation.Propagation; 
import org.springframework.transaction.annotation.Transactional; 
import org.springframework.web.bind.ServletRequestBindingException; 
import org.springframework.web.bind.ServletRequestUtils; 
import org.springframework.web.servlet.ModelAndView; 
import org.springframework.web.servlet.mvc.Controller; 

public class CreateAccount implements Controller { 
    private static final Logger logger = Logger.getLogger(CreateAccount.class); 

    // @Autowired 
    // private JtaTransactionManager transactionManager; 

    @PersistenceContext 
    private EntityManager  entityManager; 

    @Transactional(propagation = Propagation.REQUIRES_NEW) 
    @Override 
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { 
     logger.info(MessageFormat.format("Called handle request", "")); 
     String username = ServletRequestUtils.getRequiredStringParameter(request, "username"); 
     logger.info(MessageFormat.format("username {0}", username)); 
     String password = ServletRequestUtils.getRequiredStringParameter(request, "password"); 
     logger.info(MessageFormat.format("password {0}", password)); 
     String passwordConfirm = ServletRequestUtils.getRequiredStringParameter(request, "passwordConfirm"); 
     logger.info(MessageFormat.format("passwordConfirm {0}", passwordConfirm)); 

     if (!password.equals(passwordConfirm)) { 
      throw new ServletRequestBindingException("Passwords don't match"); 
     } 

     //transactionManager.getUserTransaction().begin(); 
     User user = new User(); 
     //try { 
     UserPK userPK = new UserPK(); 
     userPK.setUsername(username); 
     user.setId(userPK); 
     user.setPassword(passwordConfirm); 
     user.setEnabled((byte) 1); 

     logger.info(MessageFormat.format("persist the user {0}", username)); 
     entityManager.persist(user); 
     entityManager.flush(); 
     //  logger.info(MessageFormat.format("Before Refresh user {0}", username)); 
     //  entityManager.refresh(user); 
     //   transactionManager.getUserTransaction().commit(); 
     //  } catch (Exception e) { 
     //   logger.error(MessageFormat.format("Got an exception {0}", e.getMessage()), e); 
     //   transactionManager.getUserTransaction().rollback(); 
     //  } 

     //  transactionManager.getUserTransaction().begin(); 

     //  AuthorityPK authorityPK = new AuthorityPK(); 
     //  //try { 
     //  logger.info(MessageFormat.format("Refreshed user {0} = {1}", username, user.getId())); 
     // 
     //  authorityPK.setUserId(user.getId().getId()); 
     //  authorityPK.setAuthority(com.cartouchan.locator.models.Authority.ROLE_USER.toString()); 
     //  Authority authority = new Authority(); 
     //  authority.setId(authorityPK); 
     // 
     //  logger.info(MessageFormat.format("Save the authority {0}", com.cartouchan.locator.models.Authority.ROLE_USER.toString())); 
     //  entityManager.persist(authority); 

     //   transactionManager.getUserTransaction().commit(); 
     //  } catch (Exception e) { 
     //   logger.error(MessageFormat.format("Got an exception {0}", e.getMessage()), e); 
     //   transactionManager.getUserTransaction().rollback(); 
     //  } 

     logger.info(MessageFormat.format("Go to /index.zul", "")); 
     ModelAndView modelAndView = new ModelAndView("index"); 

     logger.info(MessageFormat.format("Return ", "")); 
     return modelAndView; 
    } 
} 

Alors, voici l'affaire, quand je décommenter les pièces TransactionManager, le programme fonctionne comme prévu, ce qui est je peux voir les instructions d'insertion. Cependant, lorsque vous utilisez le code ci-dessus, je reçois le stacktrace suivant:

INFO: Starting ZK 5.0.7.1 CE (build: 2011051910) 
INFO: Parsing jndi:/server/Cartouchan/WEB-INF/zk.xml 
INFO: WEB0671: Loading application [Cartouchan-Web] at [/Cartouchan] 
INFO: Cartouchan-Web was successfully deployed in 1,537 milliseconds. 

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] Called handle request 

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] username blah 

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] password test 

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] passwordConfirm test 

INFO: 2011-08-04 01:09:52 CreateAccount [INFO] persist the user blah 

INFO: Instantiated an instance of org.hibernate.validator.engine.resolver.JPATraversableResolver. 
INFO: EclipseLink, version: Eclipse Persistence Services - 2.2.0.v20110202-r8913 
CONFIG: connecting(DatabaseLogin(
    platform=>MySQLPlatform 
    user name=> "" 
    connector=>JNDIConnector datasource name=>null 
)) 
CONFIG: Connected: jdbc:mysql://localhost:3306/Cartouchan 
    User: [email protected] 
    Database: MySQL Version: 5.1.51 
    Driver: MySQL-AB JDBC Driver Version: mysql-connector-java-5.1.11 (Revision: ${svn.Revision}) 
CONFIG: connecting(DatabaseLogin(
    platform=>MySQLPlatform 
    user name=> "" 
    connector=>JNDIConnector datasource name=>null 
)) 
CONFIG: Connected: jdbc:mysql://localhost:3306/Cartouchan 
    User: [email protected] 
    Database: MySQL Version: 5.1.51 
    Driver: MySQL-AB JDBC Driver Version: mysql-connector-java-5.1.11 (Revision: ${svn.Revision}) 
INFO: file:/Applications/NetBeans/glassfish-3.1/glassfish/domains/domain1/eclipseApps/Cartouchan-Web/WEB-INF/classes/_CartouchanPU login successful 
WARNING: StandardWrapperValve[cartouchan]: PWC1406: Servlet.service() for servlet cartouchan threw exception 
javax.persistence.TransactionRequiredException: 
Exception Description: No externally managed transaction is currently active for this thread 
    at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.throwCheckTransactionFailedException(JTATransactionWrapper.java:86) 
    at org.eclipse.persistence.internal.jpa.transaction.JTATransactionWrapper.checkForTransaction(JTATransactionWrapper.java:46) 
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.checkForTransaction(EntityManagerImpl.java:1666) 
    at org.eclipse.persistence.internal.jpa.EntityManagerImpl.flush(EntityManagerImpl.java:744) 
    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 $Proxy151.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 $Proxy151.flush(Unknown Source) 
    at com.cartouchan.locator.controllers.CreateAccount.handleRequest(CreateAccount.java:56) 
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644) 
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:560) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:755) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848) 
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1534) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:343) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:112) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:256) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:215) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655) 
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595) 
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98) 
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162) 
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:326) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:227) 
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:170) 
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:822) 
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:719) 
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1013) 
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) 
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) 
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) 
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) 
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) 
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) 
    at java.lang.Thread.run(Thread.java:680) 

Comme vous pouvez le voir, il se connecte correctement à la base de données, et il « persiste » les données, mais jamais exécuter l'instruction d'insertion. Ensuite, lors du rinçage du EM, il jette l'exception.

Votre aide sera grandement appréciée.

Cordialement.

Répondre

1

Ok, donc je compris comment obtenir ce travail à 100%. Tout d'abord, je n'ai pas besoin de définir de persistance (contexte/unité) dans web.xml. Ensuite, j'ai supprimé le gestionnaire de transactions et les beans entityManagerFactory. Supprime également le contexte: ligne pilotée. J'ai aussi fait mes haricots "sans fèves". Je l'instancie ensuite à travers le printemps grâce à des recherches de contexte jndi. Cela autowires le entitymanager exactement comme je le veux. Plus soucieux des transactions, le serveur d'applications gère cela.

donc ma config finale est:

printemps-config.xml:

<jee:jndi-lookup jndi-name="java:global/Cartouchan-Web/CategoryController" id="categoryController"/> 
<jee:jndi-lookup jndi-name="java:global/Cartouchan-Web/UserController" id="userController"/> 

<bean id="applicationContextProvider" class="com.cartouchan.locator.beans.CustomApplicationContext"></bean> 

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

échantillon de haricot:

import java.text.MessageFormat; 
import java.util.List; 

import javax.ejb.Stateless; 
import javax.persistence.EntityManager; 
import javax.persistence.PersistenceContext; 

import org.apache.log4j.Logger; 

@Stateless 
public class CategoryController { 
    private static final Logger logger = Logger.getLogger(CategoryController.class); 

    @PersistenceContext 
    private EntityManager  entityManager; 

    public CategoryController() { 
     // TODO Auto-generated constructor stub 
    } 

    public boolean createCategory(final String name) { 
     boolean result = false; 
     try { 
      com.cartouchan.locator.database.models.Category category = new com.cartouchan.locator.database.models.Category(); 
      category.setName(name); 
      entityManager.persist(category); 
      entityManager.flush(); 
      result = true; 
     } catch (Exception ex) { 
      logger.error(MessageFormat.format("Could not create the category {0}", name), ex); 
     } 

     return result; 
    } 

    public boolean updateCategory(final int id, final String name) { 
     boolean result = false; 
     try { 
      com.cartouchan.locator.database.models.Category category = getCategory(id); 
      category.setName(name); 
      entityManager.merge(category); 
      entityManager.flush(); 
      result = true; 
     } catch (Exception ex) { 
      logger.error(MessageFormat.format("Could not update for the category {0} -{1}", id, name), ex); 
     } 

    return result; 
    } 

    public boolean deleteCategory(final int id) { 
     boolean result = false; 
     try { 
      com.cartouchan.locator.database.models.Category category = getCategory(id); 
      entityManager.remove(entityManager.merge(category)); 
      entityManager.flush(); 
      result = true; 
     } catch (Exception ex) { 
      logger.error(MessageFormat.format("Could not delete for the category {0}", id), ex); 
     } 

     return result; 
    } 

    public com.cartouchan.locator.database.models.Category getCategory(final int id) { 
     return (com.cartouchan.locator.database.models.Category) entityManager.createQuery("select p from Category p where p.id=:id").setParameter("id", id).getSingleResult(); 
    } 

    public List<com.cartouchan.locator.database.models.Category> getAllCategories() { 
     return (List<com.cartouchan.locator.database.models.Category>) entityManager.createQuery("select p from Category p").getResultList(); 
    } 
} 

ensuite d'utiliser la fève, juste faire une recherche standard printemps de la fève. C'est de la tarte.

1

Pour utiliser les transactions JTA gérées par le serveur d'applications, vous devez utiliser EntityManagerFactroy créé par le serveur d'applications lui-même.

à savoir vous devez supprimer votre déclaration LocalContainerEntityManagerFactoryBean et obtenir EntityManagerFactory à partir du serveur d'applications via <jee:jndi-lookup>. Vous devez également configurer le serveur d'applications pour créer EntityManagerFactory - voir la documentation de votre serveur d'applications.

Voir aussi:

+0

c'est génial merci beaucoup !!! Le lien ne marche pas tout à fait ;-) – user876923

+0

@axtavt mais comment exécuter ce même exemple sans utiliser un conteneur J2EE, c'est-à-dire en utilisant un gestionnaire de transactions tierce comme BTM ou JOTM? – joarderm

Questions connexes