2012-04-04 9 views
17

私はこれまでにこの問題に関する投稿があったが解決した。しかし、自動有線豆とXML構成の少ないプロジェクトを再構築して以来、私はこの問題を再検討しています。以前のプロジェクトでこれを実装した方法に従ってきましたが、うまくいきません。なぜ誰かが私にそれを働かせるために何を変えなければならないのかを助けることができますか?春@取引が効かない

意図的に例外をスローするために、ユーザーの詳細の挿入メソッドに存在しないテーブル名を使用しています。ただし、insert userおよびinsert userロールの文はロールバックされません。助けてください。


私の現在の登録デザインは、このようなものです。

servlet.xmlの一部:アプリケーション・コンテキスト

<context:component-scan base-package="com.doyleisgod.golfer.controllers"/> 
<context:component-scan base-package="com.doyleisgod.golfer.dao"/> 
<context:component-scan base-package="com.doyleisgod.golfer.services"/> 
<context:component-scan base-package="com.doyleisgod.golfer.validators"/> 


パート:

<context:annotation-config /> 
<tx:annotation-driven />  

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
<property name="driverClassName" value="${jdbc.driverClassName}"/> 
<property name="url" value="${jdbc.url}"/> 
<property name="username" value="${jdbc.username}"/> 
<property name="password" value="${jdbc.password}"/> 
</bean> 

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 


登録コントローラ

package com.doyleisgod.golfer.controllers; 

import javax.validation.Valid; 

import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.ui.Model; 
import org.springframework.validation.BindingResult; 
import org.springframework.web.bind.WebDataBinder; 
import org.springframework.web.bind.annotation.InitBinder; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RequestMethod; 
import com.doyleisgod.golfer.formdata.RegistrationForm; 
import com.doyleisgod.golfer.services.IRegistrationService; 
import com.doyleisgod.golfer.validators.RegistrationFormValidator; 

/** 
* Description: Registration controller provides and processes the registration form. 
* @author Chris Doyle 
*/ 
@Controller 
@RequestMapping("/registration.htm") 
public class RegistrationController { 
    protected final Log logger = LogFactory.getLog(getClass()); 
    @Autowired private IRegistrationService iRegistrationService; 
    @Autowired private RegistrationFormValidator registrationFormValidator; 

    // sets a customer validator for the registration form 
    @InitBinder 
    protected void initBinder(WebDataBinder binder) { 
     binder.setValidator(registrationFormValidator); 
    } 

    // Description: Method called by a get request to the registration controller. Returns the 
    @RequestMapping(method=RequestMethod.GET) 
    public String registration (Model model){ 
     model.addAttribute(new RegistrationForm()); 
     return "registration"; 
    } 

    // Description: Method called by a post request to the registration controller. Method calls validation on the registration form using custom validator and returning 
    // any errors back to the user. 
    @RequestMapping(method=RequestMethod.POST) 
    public String processRegistration (@Valid RegistrationForm registrationForm, BindingResult bindingResult, Model model){ 
     logger.info("Received the following registration form details"); 
     logger.info(registrationForm.toString()); 

     if (bindingResult.hasErrors()) { 
      logger.warn("Registration Validation Failed"); 
      model.addAttribute("validationError", "Please correct the fields marked with errors"); 
      return "registration"; 
     } 

     try { 
      iRegistrationService.registerUser(registrationForm); 
     } catch (Exception e) { 
      logger.error("An Exception has occured processing the registration form"); 
      model.addAttribute("exceptionError", "An exception has occured, please try again."); 
      e.printStackTrace(); 
      return "registration"; 
     } 

     return "redirect:login.htm?registration=sucessful"; 
    } 
} 


登録サービス

package com.doyleisgod.golfer.services; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.authentication.encoding.ShaPasswordEncoder; 
import org.springframework.stereotype.Service; 
import org.springframework.transaction.annotation.Transactional; 
import org.springframework.transaction.support.TransactionSynchronizationManager; 

import com.doyleisgod.golfer.dao.IRegistrationDAO; 
import com.doyleisgod.golfer.formdata.RegistrationForm; 

@Service("IRegistrationService") 
public class RegistrationService implements IRegistrationService { 
    @Autowired private IRegistrationDAO iRegistrationDAO; 
    private final boolean enabled = true; 
    private final String roles = "ROLE_USER"; 


    @Override 
    @Transactional (rollbackFor = Exception.class) 
    public void registerUser(RegistrationForm registrationForm) throws Exception { 
     System.out.println("inside the registerUser method. is wrapped in transaction: "+TransactionSynchronizationManager.isActualTransactionActive()); 

     String username = registrationForm.getUsername(); 
     String password = registrationForm.getPassword(); 
     String firstname = registrationForm.getFirstname(); 
     String lastname = registrationForm.getLastname(); 
     String email = registrationForm.getEmail(); 
     int handicap = Integer.parseInt(registrationForm.getHandicap()); 
     String encryptedPassword = ((new ShaPasswordEncoder()).encodePassword(password, username)); 

     iRegistrationDAO.insertUser(username, encryptedPassword, enabled); 
     iRegistrationDAO.insertRoles(username, roles); 
     iRegistrationDAO.insertUserDetails(username, firstname, lastname, email, handicap); 
    } 

    @Override 
    public boolean checkUser(String username) { 
     return iRegistrationDAO.checkUserName(username); 
    } 
} 


登録DAO:アプリケーション・コンテキストXMLへcontext:component-scanタグを移動すると、トランザクションの振る舞いがある一定のことを

package com.doyleisgod.golfer.dao; 

import javax.annotation.Resource; 
import org.apache.commons.dbcp.BasicDataSource; 
import org.springframework.jdbc.core.JdbcTemplate; 
import org.springframework.stereotype.Repository; 
import org.springframework.transaction.support.TransactionSynchronizationManager; 

@Repository("iRegistrationDAO") 
public class RegistrationDAO extends JdbcTemplate implements IRegistrationDAO { 

    @Resource private BasicDataSource dataSource; 

    @Override 
    public boolean checkUserName(String username) { 
     int db_user = queryForInt("select count(username) from users where username = ?", username); 

     if (db_user == 1){ 
      return true; 
     } 

     return false; 
    } 

    @Override 
    public void insertUser(String username, String password, boolean enabled) throws Exception { 
     System.out.println("inside the insertuser method. is wrapped in transaction: "+TransactionSynchronizationManager.isActualTransactionActive()); 

     update("insert into users (username, password, enabled) VALUES (?,?,?)", username, password, enabled); 
    } 

    @Override 
    public void insertRoles(String username, String roles) throws Exception { 
     update("insert into user_roles (username, authority) VALUES (?,?)", username, roles); 
    } 

    @Override 
    public void insertUserDetails(String username, String firstname, String lastname, String email, int handicap) throws Exception { 
     update("insert into user_detailss (username, first_name, last_name, email_address, handicap)" + 
       "VALUES (?,?,?,?,?)", username, firstname, lastname, email, handicap); 

    } 

    public void setDataSource(BasicDataSource dataSource) { 
     this.dataSource = dataSource; 
    } 

    public BasicDataSource getDataSource() { 
     return dataSource; 
    } 
} 
+0

問題は、サーブレット、XMLのコントローラ以外のコンポーネントのコンポーネントスキャンを有するように見えました。私は ' '問題を解決したと思われるアプリケーションコンテキストxmlになぜ私はなぜこのような作品が投稿されたのかという理由の裏に理由を提供したいのかどうかわかりません –

答えて

39

理由:<tx:annotation-driven />は、@Transactional注釈付きBeanメソッドをトランザクション動作を処理するAOPメソッドインターセプタでラップするポストプロセッサです。

アプリケーションコンテキストで<tx:annotation-driven />ポストプロセッサを定義しましたが、@Transactionalで注釈付けされたBeanはサーブレットアプリケーションコンテキストにあります。したがって、<tx:annotation-driven />ポストプロセッサーは、サーブレットコンテキストBeanではなくアプリケーションコンテキストBeanでのみ動作しました。 context:component-scanタグがアプリケーションコンテキストに移動されると、<tx:annotation-driven />ポストプロセッサはトランザクションメソッドを適切にラップしました。

希望はある意味があります。

[編集]

What is the difference between the Application Context and a Servlet Context?

What is a Spring post-processor and how does it work?

What is AOP in Spring?

+0

私はSpring MVC * @ ContextLoaderListenerコンテキストではなくDispatcherServletコンテキストからスキャンする必要があるため、@Controllerのアプリケーションコンテキストへのスキャンも '@ RequestMapping'を動作させることに驚いています(実際には、 )@Controller'クラスの中で '@ Transactional'を使用することです;副作用については疑問に思っています) – Arjan

+0

(DispatcherServletのコンテキストから@Controllerのスキャンを削除し、実際にはすべての '@ RequestMapping'が無視されますが、したがって、失敗します。 – Arjan

+2

彼がDAOとサービスコンポーネントを移動したというコメントのOP状態は、トランザクションの問題を修正したアプリコンテキストにスキャンされます。コメントの質問はなぜだ、私は答えた。 オペレーションは、MVCコントローラのコンポーネントスキャンをサーブレットコンテキストから移動しませんでした。したがって、私は@Arjanからのこれらのコメントがすべてであるかどうか分かりません。 – MarkOfHall