Announcement Announcement Module
Collapse
No announcement yet.
Transactions are not rolling back JDBC Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • #16
    Controller
    Code:
    package com.myCompany.net.controller;
    
    import java.util.Map;
    import java.util.concurrent.ConcurrentHashMap;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import javax.validation.Valid;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.propertyeditors.StringTrimmerEditor;
    import org.springframework.stereotype.Controller;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    import org.springframework.ui.Model;
    import org.springframework.validation.BindingResult;
    import org.springframework.validation.Validator;
    import org.springframework.web.bind.WebDataBinder;
    import org.springframework.web.bind.annotation.InitBinder;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.servlet.ModelAndView;
    
    import com.myCompany.net.dao.IRAFService;
    import com.myCompany.net.domain.Customer;
    import com.myCompany.net.domain.Recommendation;
    import com.myCompany.net.domain.ResourceNotFoundException;
    import com.myCompany.net.email.IEmailService;
    
    @Controller
    public class RecommendationController {
    
    	private final IRAFService rafService;
    	private final IEmailService emailService;
    	
    	@Autowired
    	Validator recommendationValidator;
    	
    	@InitBinder
    	protected void initBinder(WebDataBinder binder) {
    		binder.setValidator(recommendationValidator);
    		binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    	}
    	
    	private Map<Long, Recommendation> recommendations = new ConcurrentHashMap<Long, Recommendation>();
    	
    	public RecommendationController(final IRAFService rafService, final IEmailService emailService) {
    		this.rafService = rafService;
    		this.emailService = emailService;
    	}
    	
    	@RequestMapping(value="/", method={RequestMethod.GET,RequestMethod.POST} )
    	public ModelAndView getCreateForm(HttpServletRequest request) {
    		
    		ModelAndView mv = new ModelAndView("index");
    		HttpSession session = request.getSession();
    		
    		if(session.getAttribute("friendsCount") != null ) {
    			mv.addObject("friendsCount", (Integer)session.getAttribute("friendsCount"));
    			session.removeAttribute("friendsCount");
    		} else {
    			mv.addObject("friendsCount", 0);
    		}
    		
    		if(session.getAttribute("recommendation") != null ) {
    			mv.addObject("recommendation", (Recommendation)session.getAttribute("recommendation"));
    			session.removeAttribute("recommendation");
    		} else {
    			mv.addObject("recommendation", new Recommendation());
    		}
    
    		return mv;
    	}
    	
    	@RequestMapping(value="formsubmit", method=RequestMethod.POST)	
    	public ModelAndView create(@Valid Recommendation recommendation, BindingResult result, HttpServletRequest request, 
    							   @RequestParam(value="friendsCount", required=false) Integer friendsCount, 
    							   @RequestParam(value="addFriend", required=false) String addFriend) {
    		
    		if(addFriend != null && !"".equals(addFriend)) {
    			HttpSession session = request.getSession();
    			session.setAttribute("friendsCount", friendsCount + 1);
    			session.setAttribute("recommendation", recommendation);
    			return new ModelAndView("redirect:/");
    		}
    		
    		if (result.hasErrors()) {
    			System.out.println("We have errors in AccountController");
    			ModelAndView mv = new ModelAndView("index");
    			if(friendsCount != null) mv.addObject("friendsCount", friendsCount);
    			mv.addObject("recommendation", recommendation);
    			return mv; //new ModelAndView("redirect:/404");
    		}
    
    	
    
    		final Customer customer = recommendation.getCustomer();
    		System.out.println("DOB == " + customer.getDob());
    		rafService.addFriends(recommendation,customer);			
    		return new ModelAndView("redirect:/thankyou");
    	}
    	
    	@RequestMapping(value="/addFriend/{friendsCount}", method=RequestMethod.GET)
    	public String addFriendNoJavascript(@PathVariable("friendsCount") int friendsCount, HttpServletRequest request) {
    
    		HttpSession session = request.getSession();
    		session.setAttribute("friendsCount", friendsCount + 1);
    		return "redirect:/"; //return mv;
    	}
    	
    	
    	@RequestMapping(value="/thankyou", method=RequestMethod.GET)
    	public ModelAndView showThankyouPage() {
    		System.out.println("Detected: POST Request for Path :/thankyou");
    		ModelAndView mv = new ModelAndView("thankyou");				
    		return mv;
    	}
    	
    	
    	@RequestMapping(value="/socialauthexample", method=RequestMethod.GET)
    	public ModelAndView showSocialAuthPage() {
    		System.out.println("Detected: GET Request for Path :/socialauthexample");
    		ModelAndView mv = new ModelAndView("socialauthexample");
    		return mv;
    	}
    	
    	
    	@RequestMapping(value="{id}", method=RequestMethod.GET)
    	public String getView(@PathVariable("id") Long id, Model model) {
    		System.out.println("Detected: Get Request for query string :id");
    		Recommendation account = this.recommendations.get(id);
    		if (account == null) {
    			throw new ResourceNotFoundException(id);
    		}
    		model.addAttribute(account);
    		return "account/view";
    	}
    }
    So by setting the autocommit to false in Service-context.xml, nothing is commited at all. To keep it simple Im just trying to make the service method addFriends transactional

    Code:
    @Override
    	@Transactional (propagation=Propagation.NESTED, isolation=Isolation.DEFAULT, readOnly=false)
    	public void addFriends(final Recommendation recomendations,Customer customer) {
    		rafDao.addFriends(recomendations, customer);
    Thnaks so much for assisting with this!

    Comment


    • #17
      Originally posted by DJC_Spring View Post
      Check Auto commit from command line:

      Code:
      mysql> select @@autocommit;
      +--------------+
      | @@autocommit |
      +--------------+
      |            1 |
      +--------------+
      1 row in set (0.00 sec)
      So 1 = enabled!!

      I inserted a record from the command line and tried to rollback, The recored was of course still there.

      Can anyone tell me the best way to disable this? Is it better to do this in a mysql.ini file somewhere? Or is there a xml configuaration I can use?
      Hmmm no.... the prompt "mysql>" is a give away that you are testing this with the command line MySQL client. This client is always in autoCommit mode by default (as that make sense for an interactive client). You need to write some JDBC calls in Java to perform the same test from a connection that Spring is actually using.

      Now you have confirmed you are using MySQL and other details... it would be highly unusual to find the spring managed JDBC connection has autoCoimmit enabled. The problem here is your testing method. Since it is more a property of the client than the server.

      You should also while you are at it very your transaction isolation, maybe dump "SHOW VARIABLES" from the spring connection over JDBC.


      What what the result from the Thread.sleep(); test ?

      Comment


      • #18
        Code:
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        		<property name="dataSource" ref="dataSource"/>
        	</bean>
        Call this "txManager" (as per documentation) I believe this is the default name expected by <tx:annotation-driven/> you can configure a different name but you need need to lookup the documentation for the element tx:annocation-driven on how to specify that.

        Set a breakpoint inside your DAO implementation method (rafDao#addFriends(Recommendation account, Customer customer)) looks for transactional stuff and proxies in the stack trace you see. This confirms interception is taking place and annotation (@Transactional) processing is working.

        I don't believe the autoCommit setting in dataSource is required, see my previous reply. Remove it, you have jump to the wrong conclusing based on an invalid test. Also check that @@auto_commit reports the currently active auto-commit mode for the connection (the server default is not important).

        Most of the arguments you supply to some @Transactional attribute use are the defaults anyway, very often you can get away with just 2 forms:

        @Transactional
        @Transactional(readOnly=true)

        Dependant upon the kind of operation being perform on the data model.
        Last edited by dlmiles; Jun 23rd, 2011, 06:08 PM.

        Comment


        • #19
          So by setting the autocommit to false in Service-context.xml, nothing is commited at all. To keep it simple Im just trying to make the service method addFriends transactional

          Code:
          @Override
          	@Transactional (propagation=Propagation.NESTED, isolation=Isolation.DEFAULT, readOnly=false)
          	public void addFriends(final Recommendation recomendations,Customer customer) {
          		rafDao.addFriends(recomendations, customer);
          Thnaks so much for assisting with this!
          Are you sure you mean/want Propagation.NESTED ?

          This has the effect of suspending the current tranaction in progress (if there is one) and starting a new one. Only if you throw an exception from this method #addFriend() will that inner transaction be rolled back.

          Once execution gets back to the "caller" the previous transaction will be un-suspended and continued. Maybe you want REQUIRED which has the effect of making the JDBC work join the existing transaction. The entire set of operations in JDBC takes place inside one transaction and only if you do not throw an exception back to your Controller will the data be committed.

          However if you use NESTED there are 2 boundaries to consider. Change this to REQUIRED until you are fully sure you want 2 JDBC transactions to be taking place, most people do not want this, if you are unsure use REQUIRED which is the default.

          Also... confirm the locations where you need transaction boundaries (those methods with @Transaction in force) are not calling fellow methods on the same instance of "this". since Spring proxying does not work cross local calss method invocations. If you entire application was written using REQUIRED mode only then this fact rarely becomes an issue.

          Comment


          • #20
            Originally posted by dlmiles View Post
            Hmmm no.... the prompt "mysql>" is a give away that you are testing this with the command line MySQL client. This client is always in autoCommit mode by default (as that make sense for an interactive client). You need to write some JDBC calls in Java to perform the same test from a connection that Spring is actually using.

            Now you have confirmed you are using MySQL and other details... it would be highly unusual to find the spring managed JDBC connection has autoCoimmit enabled. The problem here is your testing method. Since it is more a property of the client than the server.

            You should also while you are at it very your transaction isolation, maybe dump "SHOW VARIABLES" from the spring connection over JDBC.


            What what the result from the Thread.sleep(); test ?

            Hi dlmiles,

            Thanks for the advise and help.

            I added thread.sleep() just beore I threw the exception

            Code:
            @Override	
            	@Transactional
            	public void addFriends(final Recommendation recomendations,Customer customer) {
            		
            		// Iterate on each Friend
            		final String customerEmail = recomendations.getCustomer().getEmail();
            		final String recommededCar = recomendations.isRecommededProductCar() ? "Y" : "N";
            		final String recommededHome = recomendations.isRecommededProductHome() ? "Y" : "N";
            		final String recommededPet = recomendations.isRecommededProductPet() ? "Y" : "N";
            		final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
            		
            		getJdbcTemplate().batchUpdate(SQL_INSERT_FREINDS, new BatchPreparedStatementSetter() {
            			@Override
            			public void setValues(PreparedStatement ps, int i) throws SQLException {
            				Recommendee feed = recomendations.getRecommendee().get(i);
            				ps.setString(1, feed.getEmail());
            				ps.setString(2, feed.getFirstName());
            				ps.setString(3, feed.getLastName());
            				ps.setString(4, dateFormat.format(new Date()));
            				ps.setString(5, customerEmail);
            				ps.setString(6, recommededCar);
            				ps.setString(7, recommededHome);
            				ps.setString(8, recommededPet);
            			}
            			
            			@Override
            			public int getBatchSize() {
            				return recomendations.getRecommendee().size();
            			}
            		});
            		
            		
            		try {
            			Thread.currentThread().sleep(1000000000);
            		} catch (InterruptedException e) {
            			// TODO Auto-generated catch block
            			e.printStackTrace();
            		}
            		int i =0;
            		if(i==0) throw new RuntimeException("Throwing exception!");
            		
            		saveOrUpdateCustomer(customer);
            	}
            and then run a select from mySQL query browser. MySql showed the inserted row just as normal - no errors or anything.

            I removed the autocommit setting in my dataSource

            Code:
            <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
            			<property name="driverClassName" value="com.mysql.jdbc.Driver" />
            			<property name="url" value="jdbc:mysql://localhost:3306/raf" />
            			<property name="username" value="root" />
            			<property name="password" value="root" />					
            	</bean>
            How do I dump "SHOW VARIABLES" from the spring connection over JDBC?

            Comment


            • #21
              mysql> show variables like '%iso%';
              +---------------+-----------------+
              | Variable_name | Value |
              +---------------+-----------------+
              | tx_isolation | REPEATABLE-READ |
              +---------------+-----------------+
              1 row in set (0.00 sec)

              mysql>

              Comment


              • #22
                Originally posted by dlmiles View Post
                Code:
                <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                		<property name="dataSource" ref="dataSource"/>
                	</bean>
                Call this "txManager" (as per documentation) I believe this is the default name expected by <tx:annotation-driven/> you can configure a different name but you need need to lookup the documentation for the element tx:annocation-driven on how to specify that.
                Yes I have done this now


                Originally posted by dlmiles View Post
                Set a breakpoint inside your DAO implementation method (rafDao#addFriends(Recommendation account, Customer customer)) looks for transactional stuff and proxies in the stack trace you see. This confirms interception is taking place and annotation (@Transactional) processing is working.
                I have done this and cannot seem to find anything in the stack trace. So maybe the annotation is not working.. ?

                Debug stacktrace is:

                Code:
                Tomcat v7.0 Server at localhost [Apache Tomcat]	
                	org.apache.catalina.startup.Bootstrap at localhost:64089	
                		Thread [main] (Running)	
                		Thread [pool-1-thread-1] (Running)	
                		Daemon Thread [ContainerBackgroundProcessor[StandardEngine[Catalina]]] (Running)	
                		Daemon Thread ["http-bio-8080"-Acceptor-0] (Running)	
                		Daemon Thread ["http-bio-8080"-AsyncTimeout] (Running)	
                		Daemon Thread ["http-bio-8080"-exec-1] (Running)	
                		Daemon Thread ["ajp-bio-8009"-Acceptor-0] (Running)	
                		Daemon Thread ["ajp-bio-8009"-AsyncTimeout] (Running)	
                		Daemon Thread ["http-bio-8080"-exec-2] (Running)	
                		Daemon Thread ["ajp-bio-8009"-exec-1] (Suspended (breakpoint at line 181 in RAFDAOImpl))	
                			RAFDAOImpl.addFriends(Recommendation, Customer) line: 181	
                			RAFServiceImpl.addFriends(Recommendation, Customer) line: 71	
                			RecommendationController.create(Recommendation, BindingResult, HttpServletRequest, Integer, String) line: 105	
                			NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
                			NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
                			DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
                			Method.invoke(Object, Object...) line: 597	
                			AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker(HandlerMethodInvoker).invokeHandlerMethod(Method, Object, NativeWebRequest, ExtendedModelMap) line: 176	
                			AnnotationMethodHandlerAdapter.invokeHandlerMethod(HttpServletRequest, HttpServletResponse, Object) line: 426	
                			AnnotationMethodHandlerAdapter.handle(HttpServletRequest, HttpServletResponse, Object) line: 414	
                			DispatcherServlet.doDispatch(HttpServletRequest, HttpServletResponse) line: 790	
                			DispatcherServlet.doService(HttpServletRequest, HttpServletResponse) line: 719	
                			DispatcherServlet(FrameworkServlet).processRequest(HttpServletRequest, HttpServletResponse) line: 644	
                			DispatcherServlet(FrameworkServlet).doPost(HttpServletRequest, HttpServletResponse) line: 560	
                			DispatcherServlet(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 641	
                			DispatcherServlet(HttpServlet).service(ServletRequest, ServletResponse) line: 722	
                			ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 304	
                			ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210	
                			CharacterEncodingFilter.doFilterInternal(HttpServletRequest, HttpServletResponse, FilterChain) line: 88	
                			CharacterEncodingFilter(OncePerRequestFilter).doFilter(ServletRequest, ServletResponse, FilterChain) line: 76	
                			ApplicationFilterChain.internalDoFilter(ServletRequest, ServletResponse) line: 243	
                			ApplicationFilterChain.doFilter(ServletRequest, ServletResponse) line: 210	
                			StandardWrapperValve.invoke(Request, Response) line: 240	
                			StandardContextValve.invoke(Request, Response) line: 164	
                			NonLoginAuthenticator(AuthenticatorBase).invoke(Request, Response) line: 462	
                			StandardHostValve.invoke(Request, Response) line: 164	
                			ErrorReportValve.invoke(Request, Response) line: 100	
                			AccessLogValve.invoke(Request, Response) line: 563	
                			StandardEngineValve.invoke(Request, Response) line: 118	
                			CoyoteAdapter.service(Request, Response) line: 399	
                			AjpProcessor.process(SocketWrapper<Socket>) line: 303	
                			AjpProtocol$AjpConnectionHandler.process(SocketWrapper<Socket>, SocketStatus) line: 183	
                			AjpProtocol$AjpConnectionHandler.process(SocketWrapper<Socket>) line: 169	
                			JIoEndpoint$SocketProcessor.run() line: 311	
                			ThreadPoolExecutor$Worker.runTask(Runnable) line: 886	
                			ThreadPoolExecutor$Worker.run() line: 908	
                			TaskThread(Thread).run() line: 662	
                	C:\Java\jdk1.6\bin\javaw.exe (24 Jun 2011 12:41:12)
                Originally posted by dlmiles View Post
                I don't believe the autoCommit setting in dataSource is required, see my previous reply. Remove it, you have jump to the wrong conclusing based on an invalid test. Also check that @@auto_commit reports the currently active auto-commit mode for the connection (the server default is not important).
                Yes, I removed autocommit.

                Originally posted by dlmiles View Post
                Most of the arguments you supply to some @Transactional attribute use are the defaults anyway, very often you can get away with just 2 forms:

                @Transactional
                @Transactional(readOnly=true)

                Dependant upon the kind of operation being perform on the data model.
                I changed it to just @Transactional on the service. I have even set
                @Transactional on the dao method to see if I can see any spring transactional stuff in the stack trace (posted above)


                Im so puzzled guys.. This is giving me head ache now

                Comment


                • #23
                  Hmmm.. not sure if this explains.. but found this while doing maven:redeploy

                  Code:
                  13:16:26,065 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'asyncWorker': no URL paths identified
                  13:16:26,065 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'scheduledProcessor': no URL paths identified
                  13:16:26,065 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'recommendationValidator': no URL paths identified
                  13:16:26,065 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor': no URL paths identified
                  13:16:26,065 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor': no URL paths identified
                  13:16:26,065 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.context.annotation.internalRequiredAnnotationProcessor': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.context.annotation.internalCommonAnnotationProcessor': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping#0': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.format.support.FormattingConversionServiceFactoryBean#0': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.validation.beanvalidation.LocalValidatorFactoryBean#0': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#0': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.handler.MappedInterceptor#0': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.scheduling.annotation.internalAsyncAnnotationProcessor': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.scheduling.annotation.internalScheduledAnnotationProcessor': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.config.viewControllerHandlerAdapter': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.config.viewControllerHandlerMapping': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.handler.MappedInterceptor#1': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'validator': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter': no URL paths identified
                  13:16:26,066 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.resource.ResourceHttpRequestHandler#0': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'localeResolver': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'messageSource': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'properties': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.beans.factory.config.PropertyPlaceholderConfigurer#0': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'springApplicationContext': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'emailService': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'org.springframework.web.servlet.handler.SimpleMappingExceptionResolver#0': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'viewResolver': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'socialAuthProperties': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'scopedTarget.socialAuthTemplate': no URL paths identified
                  13:16:26,067 DEBUG [DefaultAnnotationHandlerMapping] Rejected bean name 'socialAuthTemplate': no URL paths identified

                  Comment


                  • #24
                    Originally posted by DJC_Spring View Post
                    Yes I have done this now

                    I have done this and cannot seem to find anything in the stack trace. So maybe the annotation is not working.. ?

                    Debug stacktrace is:
                    Code:
                    		Daemon Thread ["ajp-bio-8009"-exec-1] (Suspended (breakpoint at line 181 in RAFDAOImpl))	
                    			RAFDAOImpl.addFriends(Recommendation, Customer) line: 181	
                    			RAFServiceImpl.addFriends(Recommendation, Customer) line: 71	
                    			RecommendationController.create(Recommendation, BindingResult, HttpServletRequest, Integer, String) line: 105	
                    			NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
                    ...

                    Sorry bad advice from me http://static.springsource.org/sprin...ve-annotations the table in there explains the default bean name should be "transactionManager".

                    The proxying should show up between the Controller and the Service.



                    You can use the getJdbcTemplate() to run a SELECT like query to run @@auto_commit and "SHOW VARIABLES" from inside spring and dump it to log or System.err. Just to confirm these points off. I don't think your problem is there.

                    I shall digest the rest of your info and make another reply.

                    Comment


                    • #25
                      I was on a portable device yesterday so could not easily take in all the config you posted.

                      As I think another poster has said. From what I can make out you as doing a <context:component-scan/> and <tx:annotation-driven/> in WAR global applicationContext.xml.

                      I would for now remove and/or move them to the raf-servlet.xml. So your applicationContext.xml is simply dataSource, transactionManager and have your Service/DAO/Controller in the raf-servlet.xml. I would also not use <context:component-scan/> just yet (for reasons below), I don't think you need it to get past this problem. So just move the <tx:annotation-driven/> into raf-servlet.xml.


                      To clarify what I think were the other posters intentions...

                      1) You have a component-scan happening for the same package space as the Service is in (I would not advise mixing the methods on instating the bean in the BeanFactory for the same package namespace without understanding things more fully). But you also declare the same bean name explicitly the child context (raf-servlet.xml). This can have the effect of having it twice with same name in different contexts. The nearest matching entry is used to @Autowired which means the one in the ApplicationContext.xml is probably never used, but it is also the only one getting transaction support via proxing.



                      2) ... this is because you have not used <tx:annotation-driven/> in the same raf-servlet.xml as the Service/DAO/whatever-bean you want it to process for transaction support. When this is used in raf-servlet.xml your backtrace test should look different, between Controller and Service. Also to note since there is no "transactionManager" bean in the raf-servlet.xml (which is a correct design choice for you IMHO) when the <tx:annotation-driven/> goes to lookup that bean name it won't find it in raf-servlet.xml, it will then go to its parent ApplicationContext.xml and find it and use it. This is completely what you want. There should be no bean called "dataSource" or "transationManager" in raf-servlet.xml these should be resolved via the parent.


                      I would also go around and check / update the XSD scheme version number at the top of all your *.xml files to reflect the same spring version 3.x (there seems to be a mix of versions), while this should not be related to this issue, it may cause you problems trying to use new features present in 3.x.


                      I myself do transaction at the Service layer and do not use @Transactional on any DAO. As I consider all DAO usage to expect to be within an already open transactional context. This makes is clear where the boundary is and does not unncessarly proxy DAOs. That said, using @Transational at both levels will not break your design and it will do what you expect.
                      Last edited by dlmiles; Jun 24th, 2011, 02:29 PM.

                      Comment


                      • #26
                        The problem is your configuration you have basically 2 and sometimes 3 instances of the same beans... I suggest a read of the reference guide on what component-scan does and also how Bean(Factory)PostProcessors work.

                        But in short
                        1) remove your dao, service and controllers from the raf-servlet those duplicate the beans (they are already created by the component scan)
                        2) raf-servlet component-scan only scan for @Controllers
                        3) ContextLoaderListener component-scan scan for everything but controllers

                        Or remove your ContextLoaderListener put the tx:annotation-driven into the raf-servlet.xml and still remove your dao/servlet/controller from that configuration.

                        Single config
                        Code:
                        <?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:aop="http://www.springframework.org/schema/aop" 
                        	   	xmlns:tx="http://www.springframework.org/schema/tx"
                        		xmlns:context="http://www.springframework.org/schema/context"
                        		xmlns:mvc="http://www.springframework.org/schema/mvc" 
                        		xmlns:task="http://www.springframework.org/schema/task"
                        		xsi:schemaLocation="http://www.springframework.org/schema/mvc 
                        							http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                        							http://www.springframework.org/schema/beans 
                        							http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                        							http://www.springframework.org/schema/context 
                        							http://www.springframework.org/schema/context/spring-context-3.0.xsd
                        							http://www.springframework.org/schema/task 
                        							http://www.springframework.org/schema/task/spring-task-3.0.xsd
                        		 					http://www.springframework.org/schema/aop 
                        		 					http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                        		 					http://www.springframework.org/schema/tx
                        		 					http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
                        
                        	
                        	<!-- Scans the Classpath of this application for @Components to deploy as beans -->
                        	<context:component-scan base-package="com.myCompany.net" />
                        	
                        	<!-- Configures the @Controller programming model -->
                        	<mvc:annotation-driven />	
                        	
                        	<task:annotation-driven />
                        	<tx:annotation-driven />
                        	 
                        	<!-- Forwards requests to the "/" resource to the "welcome" view -->
                        	<!-- mvc:view-controller should only be used for the static pages i.e. pages that doesn't contain any inputs. This tag essentially bypasses the controller -->
                        	<mvc:view-controller path="/" view-name="welcome" />	
                        	
                        	<!-- Configures Handler Interceptors -->
                        	<mvc:interceptors>
                        		<!-- Changes the locale when a 'locale' request parameter is sent; e.g.	/?locale=de -->
                        		<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
                        	</mvc:interceptors>
                        
                        	<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />	
                        		
                        	<!-- Handles HTTP GET requests for /resources/** by efficiently serving	up static resources in the ${webappRoot}/resources/ directory -->
                        	<mvc:resources mapping="/resources/**" location="/resources/" />
                        
                        	<!-- Saves a locale change using a cookie -->
                        	<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
                        
                        	<!-- Database -->
                        	 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
                        			<property name="driverClassName" value="com.mysql.jdbc.Driver" />
                        			<property name="url" value="jdbc:mysql://localhost:3306/raf" />
                        			<property name="username" value="root" />
                        			<property name="password" value="root" />		
                        			<property name="defaultAutoCommit" value="false" />		
                        	</bean>
                         
                        	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                        		<property name="dataSource" ref="dataSource"/>
                        	</bean>
                        
                        	<!-- Application Message Bundle -->
                        	<bean id="messageSource"
                        		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
                        		<property name="basename" value="/WEB-INF/messages/messages" />
                        		<property name="cacheSeconds" value="0" />
                        	</bean>
                        
                        	<bean id="properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                        		<property name="locations">
                        			<list>
                        				<value>WEB-INF/raf.properties</value>
                        			</list>
                        		</property>
                        	</bean>
                        	
                        	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                        		<property name="properties" ref="properties" />
                        	</bean>
                        
                        	<bean id="springApplicationContext"	class="com.myCompany.spring.beans.SpringApplicationContextBean" />
                        	
                        <!--	<import resource="classpath:/com/myCompany/net/download/customer-download-context.xml" />-->
                        <!--	<import resource="classpath:/com/myCompany/net/jobs/recommendationEmail/recommend-a-friend-context.xml" />-->
                        <!--	<import resource="classpath:/com/myCompany/net/jobs/recommendationExpired/recommendation-expiry-context.xml" /> -->
                        <!--	<import resource="classpath:/com/myCompany/net/jobs/recommendationApprovedEmail/voucher-approval-context.xml" />-->
                        <!--	<import resource="classpath:/com/myCompany/net/jobs/recommendationList/voucher-list-email-context.xml" />-->
                        	
                        	<import resource="services.xml" />
                        	<import resource="web-mvc-config.xml" />
                        	
                        	<!--  Include properties for SocialAuth -->	
                        	<import resource="properties.xml" />
                        	
                        	
                        	<bean id="socialAuthTemplate" class="org.brickred.socialauth.spring.bean.SocialAuthTemplate" scope="session">
                            	<aop:scoped-proxy/>
                            </bean>
                                
                            <bean id="recommendationController" class="com.myCompany.net.controller.RecommendationController">
                        		<constructor-arg ref="emailService" />
                        		<constructor-arg ref="rafService" />
                        	</bean>
                        	
                            <bean id="socialAuthWebController" class="org.brickred.socialauth.spring.controller.SocialAuthWebController">
                            	<constructor-arg value="http://universalstudios.myCompany.net/RAFWeb/" />
                                <constructor-arg value="authSuccess.do" />
                                <constructor-arg ref="socialAuthProperties" />
                            </bean>
                        
                        </beans>
                        I also suggest removing the constructors from the controller and make it autowired fields (or put @Autowired on the constructor arguments, then you can remove the controller definitions from your xml, cleans up your xml nicely).
                        Last edited by Marten Deinum; Jun 24th, 2011, 02:51 PM.

                        Comment


                        • #27
                          Dear All,

                          thankyou for the advise and apologies for the delay. I was off ill from work with sickness bug and have just returned to try to resolve this.

                          Ok, Marten I have done what you suggested and my trasnactions are still not rolling back..

                          I had to comment out
                          Code:
                           <property name="defaultAutoCommit" value="false" />
                          on the datasource as nothing was being persisted to the database wwhen i removed the exception

                          Please see following posts with updated config.. Im determined to get to the bottom of this!

                          Comment


                          • #28
                            Web.xml

                            Code:
                            <?xml version="1.0" encoding="UTF-8"?>
                            <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
                            	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                            	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
                            
                            	<context-param>
                            		<param-name>log4jConfigLocation</param-name>
                            		<param-value>/WEB-INF/log4j.xml</param-value>
                            	</context-param>
                            
                            	<listener>
                            		<listener-class>org.springframework.web.util.Log4jConfigListener
                            		</listener-class>
                            	</listener>
                            	
                            		
                            	<filter>
                            		<filter-name>characterEncodingFilter</filter-name>
                            		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
                            		<init-param>
                            			<param-name>encoding</param-name>
                            			<param-value>UTF-8</param-value>
                            		</init-param>
                            		<init-param>
                            			<param-name>forceEncoding</param-name>
                            			<param-value>true</param-value>
                            		</init-param>
                            	</filter>
                            
                            	<filter-mapping>
                            		<filter-name>characterEncodingFilter</filter-name>
                            		<url-pattern>/*</url-pattern> 
                            	</filter-mapping>
                            	
                            	<servlet>
                            		<servlet-name>raf</servlet-name>
                            		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>		
                            		<load-on-startup>1</load-on-startup>
                            	</servlet>
                            
                            	<servlet-mapping>
                            		<servlet-name>raf</servlet-name>
                            		<url-pattern>/</url-pattern>
                            	</servlet-mapping>
                            
                            	<servlet-mapping>
                                      <servlet-name>default</servlet-name>
                                      <url-pattern>/static/*</url-pattern>
                                      <url-pattern>*.png</url-pattern>
                                      <url-pattern>*.jpg</url-pattern>
                                      <url-pattern>*.js</url-pattern>
                                      <url-pattern>*.gif</url-pattern>
                                      <url-pattern>*.css</url-pattern>
                                 </servlet-mapping>
                            	
                            
                            
                            </web-app>

                            Comment


                            • #29
                              raf-servlet.xml

                              Code:
                               
                              <?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:aop="http://www.springframework.org/schema/aop" 
                              	   	xmlns:tx="http://www.springframework.org/schema/tx"
                              		xmlns:context="http://www.springframework.org/schema/context"
                              		xmlns:mvc="http://www.springframework.org/schema/mvc" 
                              		xmlns:task="http://www.springframework.org/schema/task"
                              		xsi:schemaLocation="http://www.springframework.org/schema/mvc 
                              							http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
                              							http://www.springframework.org/schema/beans 
                              							http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                              							http://www.springframework.org/schema/context 
                              							http://www.springframework.org/schema/context/spring-context-3.0.xsd
                              							http://www.springframework.org/schema/task 
                              							http://www.springframework.org/schema/task/spring-task-3.0.xsd
                              		 					http://www.springframework.org/schema/aop 
                              		 					http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
                              		 					http://www.springframework.org/schema/tx
                              		 					http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
                              
                              	
                              	<!-- Scans the Classpath of this application for @Components to deploy as beans -->
                              	<context:component-scan base-package="com.myCompany" />
                              	
                              	<!-- Configures the @Controller programming model -->
                              	<mvc:annotation-driven />	
                              	
                              	<task:annotation-driven />
                              	<tx:annotation-driven />
                              	 
                              	<!-- Forwards requests to the "/" resource to the "welcome" view -->
                              	<!-- mvc:view-controller should only be used for the static pages i.e. pages that doesn't contain any inputs. This tag essentially bypasses the controller -->
                              	<mvc:view-controller path="/" view-name="welcome" />	
                              	
                              	<!-- Configures Handler Interceptors -->
                              	<mvc:interceptors>
                              		<!-- Changes the locale when a 'locale' request parameter is sent; e.g.	/?locale=de -->
                              		<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
                              	</mvc:interceptors>
                              
                              	<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />	
                              		
                              	<!-- Handles HTTP GET requests for /resources/** by efficiently serving	up static resources in the ${webappRoot}/resources/ directory -->
                              	<mvc:resources mapping="/resources/**" location="/resources/" />
                              
                              	<!-- Saves a locale change using a cookie -->
                              	<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
                              
                              	<!-- Database -->
                              	 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
                              			<property name="driverClassName" value="com.mysql.jdbc.Driver" />
                              			<property name="url" value="jdbc:mysql://localhost:3306/raf" />
                              			<property name="username" value="root" />
                              			<property name="password" value="root" />		
                              <!--			<property name="defaultAutoCommit" value="false" />		-->
                              	</bean>
                               
                              	<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                              		<property name="dataSource" ref="dataSource"/>
                              	</bean>
                              
                              	<!-- Application Message Bundle -->
                              	<bean id="messageSource"
                              		class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
                              		<property name="basename" value="/WEB-INF/messages/messages" />
                              		<property name="cacheSeconds" value="0" />
                              	</bean>
                              
                              	<bean id="properties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
                              		<property name="locations">
                              			<list>
                              				<value>WEB-INF/raf.properties</value>
                              			</list>
                              		</property>
                              	</bean>
                              	
                              	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
                              		<property name="properties" ref="properties" />
                              	</bean>
                              
                              	<bean id="springApplicationContext"	class="com.myCompany.spring.beans.SpringApplicationContextBean" />
                              	
                              <!--	<import resource="classpath:/com/myCompany/net/download/customer-download-context.xml" />-->
                              <!--	<import resource="classpath:/com/myCompany/net/jobs/recommendationEmail/recommend-a-friend-context.xml" />-->
                              <!--	<import resource="classpath:/com/myCompany/net/jobs/recommendationExpired/recommendation-expiry-context.xml" /> -->
                              <!--	<import resource="classpath:/com/myCompany/net/jobs/recommendationApprovedEmail/voucher-approval-context.xml" />-->
                              <!--	<import resource="classpath:/com/myCompany/net/jobs/recommendationList/voucher-list-email-context.xml" />-->
                              	
                              	<import resource="services.xml" />
                              	<import resource="web-mvc-config.xml" />
                              	
                              	<!--  Include properties for SocialAuth -->	
                              	<import resource="properties.xml" />
                              	
                              	
                              	<bean id="socialAuthTemplate" class="org.brickred.socialauth.spring.bean.SocialAuthTemplate" scope="session">
                                  	<aop:scoped-proxy/>
                                  </bean>
                                      
                              <!--    <bean id="recommendationController" class="com.myCompany.net.mvc.controller.RecommendationController">-->
                              <!--		<constructor-arg ref="emailService" />-->
                              <!--		<constructor-arg ref="rafService" />-->
                              <!--	</bean>-->
                              	
                                  <bean id="socialAuthWebController" class="org.brickred.socialauth.spring.controller.SocialAuthWebController">
                                  	<constructor-arg value="http://universalstudios.myCompany.net/RAFWeb/" />
                                      <constructor-arg value="authSuccess.do" />
                                      <constructor-arg ref="socialAuthProperties" />
                                  </bean>
                              
                              </beans>
                              Last edited by DJC_Spring; Jun 29th, 2011, 10:08 AM.

                              Comment


                              • #30
                                RecommendationController

                                Code:
                                package com.myCompany.net.mvc.controller;
                                
                                import java.util.Map;
                                import java.util.concurrent.ConcurrentHashMap;
                                
                                import javax.servlet.http.HttpServletRequest;
                                import javax.servlet.http.HttpSession;
                                import javax.validation.Valid;
                                
                                import org.springframework.beans.factory.annotation.Autowired;
                                import org.springframework.beans.propertyeditors.StringTrimmerEditor;
                                import org.springframework.stereotype.Controller;
                                import org.springframework.transaction.annotation.Propagation;
                                import org.springframework.transaction.annotation.Transactional;
                                import org.springframework.ui.Model;
                                import org.springframework.validation.BindingResult;
                                import org.springframework.validation.Validator;
                                import org.springframework.web.bind.WebDataBinder;
                                import org.springframework.web.bind.annotation.InitBinder;
                                import org.springframework.web.bind.annotation.PathVariable;
                                import org.springframework.web.bind.annotation.RequestMapping;
                                import org.springframework.web.bind.annotation.RequestMethod;
                                import org.springframework.web.bind.annotation.RequestParam;
                                import org.springframework.web.servlet.ModelAndView;
                                
                                import com.myCompany.net.domain.Customer;
                                import com.myCompany.net.domain.Recommendation;
                                import com.myCompany.net.domain.ResourceNotFoundException;
                                import com.myCompany.net.email.IEmailService;
                                import com.myCompany.service.IRAFService;
                                
                                @Controller
                                public class RecommendationController {
                                
                                	private final IRAFService rafService;
                                	private final IEmailService emailService;
                                	
                                	@Autowired
                                	Validator recommendationValidator;
                                	
                                	@InitBinder
                                	protected void initBinder(WebDataBinder binder) {
                                		binder.setValidator(recommendationValidator);
                                		binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
                                	}
                                	
                                	private Map<Long, Recommendation> recommendations = new ConcurrentHashMap<Long, Recommendation>();
                                	
                                	@Autowired
                                	public RecommendationController(final IRAFService rafService, final IEmailService emailService) {
                                		this.rafService = rafService;
                                		this.emailService = emailService;
                                	}
                                	
                                	@RequestMapping(value="/", method={RequestMethod.GET,RequestMethod.POST} )
                                	public ModelAndView getCreateForm(HttpServletRequest request) {
                                		
                                		ModelAndView mv = new ModelAndView("index");
                                		HttpSession session = request.getSession();
                                		
                                		if(session.getAttribute("friendsCount") != null ) {
                                			mv.addObject("friendsCount", (Integer)session.getAttribute("friendsCount"));
                                			session.removeAttribute("friendsCount");
                                		} else {
                                			mv.addObject("friendsCount", 0);
                                		}
                                		
                                		if(session.getAttribute("recommendation") != null ) {
                                			mv.addObject("recommendation", (Recommendation)session.getAttribute("recommendation"));
                                			session.removeAttribute("recommendation");
                                		} else {
                                			mv.addObject("recommendation", new Recommendation());
                                		}
                                
                                		return mv;
                                	}
                                	
                                	@RequestMapping(value="formsubmit", method=RequestMethod.POST)	
                                	public ModelAndView create(@Valid Recommendation recommendation, BindingResult result, HttpServletRequest request, 
                                							   @RequestParam(value="friendsCount", required=false) Integer friendsCount, 
                                							   @RequestParam(value="addFriend", required=false) String addFriend) {
                                		
                                		if(addFriend != null && !"".equals(addFriend)) {
                                			HttpSession session = request.getSession();
                                			session.setAttribute("friendsCount", friendsCount + 1);
                                			session.setAttribute("recommendation", recommendation);
                                			return new ModelAndView("redirect:/");
                                		}
                                		
                                		if (result.hasErrors()) {
                                			System.out.println("We have errors in AccountController");
                                			ModelAndView mv = new ModelAndView("index");
                                			if(friendsCount != null) mv.addObject("friendsCount", friendsCount);
                                			mv.addObject("recommendation", recommendation);
                                			return mv; //new ModelAndView("redirect:/404");
                                		}
                                
                                	
                                	
                                		final Customer customer = recommendation.getCustomer();
                                		System.out.println("DOB == " + customer.getDob());
                                		rafService.addFriends(recommendation,customer);	
                                		return new ModelAndView("redirect:/thankyou");
                                	}
                                	
                                	@RequestMapping(value="/addFriend/{friendsCount}", method=RequestMethod.GET)
                                	public String addFriendNoJavascript(@PathVariable("friendsCount") int friendsCount, HttpServletRequest request) {
                                
                                		HttpSession session = request.getSession();
                                		session.setAttribute("friendsCount", friendsCount + 1);
                                		return "redirect:/"; //return mv;
                                	}
                                	
                                
                                	@RequestMapping(value="/thankyou", method=RequestMethod.GET)
                                	public ModelAndView showThankyouPage() {
                                		System.out.println("Detected: POST Request for Path :/thankyou");
                                		ModelAndView mv = new ModelAndView("thankyou");		
                                		mv.addObject("customerName", "Darren");
                                		return mv;
                                	}
                                	
                                
                                	@RequestMapping(value="/socialauthexample", method=RequestMethod.GET)
                                	public ModelAndView showSocialAuthPage() {
                                		System.out.println("Detected: GET Request for Path :/socialauthexample");
                                		ModelAndView mv = new ModelAndView("socialauthexample");
                                		return mv;
                                	}
                                	
                                
                                	@RequestMapping(value="{id}", method=RequestMethod.GET)
                                	public String getView(@PathVariable("id") Long id, Model model) {
                                		System.out.println("Detected: Get Request for query string :id");
                                		Recommendation account = this.recommendations.get(id);
                                		if (account == null) {
                                			throw new ResourceNotFoundException(id);
                                		}
                                		model.addAttribute(account);
                                		return "account/view";
                                	}
                                }
                                Last edited by DJC_Spring; Jun 29th, 2011, 10:08 AM.

                                Comment

                                Working...
                                X