Spring @Transactional funktioniert nicht
Hatte ich vorher einen Beitrag über dieses Problem, das gelöst wurde. Allerdings seit dem Umbau das Projekt mit auto-WLAN-Bohnen und weniger XML-Konfiguration, die ich finde, ich bin ein Wiederaufgreifen dieses Problem. Ich habe den Weg meiner vorherigen Projekt umgesetzt, aber es funktioniert nicht. Kann mir jemand helfen, warum oder was ich ändern sollte damit es funktioniert?
Bin ich absichtlich eine nicht existente Tabelle name einfügen Benutzer-details-Methode, um bewusst eine Ausnahme. Aber die Aussagen für legen Sie Benutzer und legen Sie Benutzerrollen, werden nicht zurückgenommen. Bitte helfen Sie.
Meine aktuelle Entwurf für die Eintragung ist, wie dieses.
Teil 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"/>
Teil Anwendungskontext:
<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>
Anmeldung controller:
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";
}
}
Anmeldung service:
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);
}
}
Anmeldung DAO:
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;
}
}
InformationsquelleAutor der Frage Chris Doyle | 2012-04-04
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dem Grund, dass das verschieben der
context:component-scan
- tags, um die Anwendung, die Kontext-xml-fest das transaktionale Verhalten ist:<tx:annotation-driven />
ist ein post-Prozessor, wraps@Transactional
annotiert bean-Methoden mit einem AOP interceptor-Methode mit Transaktions-Verhalten. Frühjahr post-Prozessoren arbeiten nur auf die spezifische Anwendung Kontext Sie definiert sind.In Ihrem Fall, Sie haben den
<tx:annotation-driven />
post-Prozessor in der Anwendungs-Kontext, während die Bohnen kommentiert mit@Transactional
sind in der servlet-Anwendung Kontext. So, die<tx:annotation-driven />
post-Prozessor betrieben, die auf den Anwendungskontext Bohnen, nicht die servlet-Kontext Bohnen. Wenn diecontext:component-scan
tags verschoben wurden, um den Anwendungskontext, dann die<tx:annotation-driven />
post-Prozessor legten Ihre Transaktions-Methoden entsprechend.Hoffe, dass macht Sinn.
[Bearbeiten]
Was ist der Unterschied zwischen dem Anwendungskontext und ein Servlet-Kontext?
Was ist ein Feder-post-Prozessor und wie funktioniert es?
Was ist AOP in Spring?
InformationsquelleAutor der Antwort MarkOfHall