View Javadoc

1   /*
2    * Copyright 2005-2007 The Kuali Foundation
3    *
4    *
5    * Licensed under the Educational Community License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.opensource.org/licenses/ecl2.php
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.kuali.rice.kew.preferences;
18  
19  import java.util.ArrayList;
20  import java.util.Collection;
21  import java.util.List;
22  
23  import org.junit.Test;
24  import org.kuali.rice.kew.preferences.service.PreferencesService;
25  import org.kuali.rice.kew.service.KEWServiceLocator;
26  import org.kuali.rice.kew.test.KEWTestCase;
27  import org.kuali.rice.kew.useroptions.UserOptions;
28  import org.kuali.rice.kew.useroptions.UserOptionsService;
29  import org.kuali.rice.kim.bo.entity.KimPrincipal;
30  import org.springframework.transaction.TransactionStatus;
31  import org.springframework.transaction.support.TransactionCallback;
32  import org.springframework.transaction.support.TransactionTemplate;
33  
34  
35  public class PreferencesServiceTest extends KEWTestCase {
36  
37      /**
38       * Test that the preferences are saved by default when going through the preferences service.  This
39       * means that the preferences service will persist any user option that was not in the db when it went
40       * to fetch that preference.
41       */
42  	@Test public void testPreferencesDefaultSave() throws Exception {
43         //verify that user doesn't have any preferences in the db.
44  
45         final UserOptionsService userOptionsService = KEWServiceLocator.getUserOptionsService();
46         KimPrincipal principal = KEWServiceLocator.getIdentityHelperService().getPrincipalByPrincipalName("rkirkend");
47         Collection userOptions = userOptionsService.findByWorkflowUser(principal.getPrincipalId());
48         assertTrue("UserOptions should be empty", userOptions.isEmpty());
49  
50         PreferencesService preferencesService = KEWServiceLocator.getPreferencesService();
51         Preferences preferences = preferencesService.getPreferences(principal.getPrincipalId());
52         assertTrue("Preferences should require a save.", preferences.isRequiresSave());
53  
54         userOptions = userOptionsService.findByWorkflowUser(principal.getPrincipalId());
55         assertTrue("UserOptions should not empty", userOptions.isEmpty());
56  
57         preferencesService.savePreferences(principal.getPrincipalId(), preferences);
58         userOptions = userOptionsService.findByWorkflowUser(principal.getPrincipalId());
59         assertTrue("UserOptions should not be empty", !userOptions.isEmpty());
60  
61         preferences = preferencesService.getPreferences(principal.getPrincipalId());
62         assertFalse("Preferences should NOT require a save.", preferences.isRequiresSave());
63  
64         // now delete one of the options
65         final UserOptions refreshRateOption = userOptionsService.findByOptionId("REFRESH_RATE", principal.getPrincipalId());
66         assertNotNull("REFRESH_RATE option should exist.", refreshRateOption);
67         TransactionTemplate template = new TransactionTemplate(KEWServiceLocator.getPlatformTransactionManager());
68         template.execute(new TransactionCallback() {
69             public Object doInTransaction(TransactionStatus status) {
70                 userOptionsService.deleteUserOptions(refreshRateOption);
71                 return null;
72             }
73         });
74         assertNull("REFRESH_RATE option should no longer exist.", userOptionsService.findByOptionId("REFRESH_RATE", principal.getPrincipalId()));
75  
76         preferences = preferencesService.getPreferences(principal.getPrincipalId());
77         assertTrue("Preferences should now require a save again.", preferences.isRequiresSave());
78  
79         // save refresh rate again
80         template.execute(new TransactionCallback() {
81             public Object doInTransaction(TransactionStatus status) {
82                 userOptionsService.save(refreshRateOption);
83                 return null;
84             }
85         });
86         preferences = preferencesService.getPreferences(principal.getPrincipalId());
87         assertFalse("Preferences should no longer require a save.", preferences.isRequiresSave());
88      }
89  
90  
91  	/**
92       * Tests default saving concurrently which can cause a race condition on startup
93       * that leads to constraint violations
94       */
95      @Test public void testPreferencesConcurrentDefaultSave() throws Throwable {
96         //verify that user doesn't have any preferences in the db.
97         final UserOptionsService userOptionsService = KEWServiceLocator.getUserOptionsService();
98         final KimPrincipal principal = KEWServiceLocator.getIdentityHelperService().getPrincipalByPrincipalName("rkirkend");
99         Collection userOptions = userOptionsService.findByWorkflowUser(principal.getPrincipalId());
100        assertTrue("UserOptions should be empty", userOptions.isEmpty());
101 
102        final PreferencesService preferencesService = KEWServiceLocator.getPreferencesService();
103        Runnable getPrefRunnable = new Runnable() {
104            public void run() {
105                Preferences preferences = preferencesService.getPreferences(principal.getPrincipalId());
106                assertTrue("Preferences should require a save.", preferences.isRequiresSave());
107                Collection updatedOptions = userOptionsService.findByWorkflowUser(principal.getPrincipalId());
108                assertTrue("UserOptions should be empty", updatedOptions.isEmpty());
109            }
110        };
111        final List<Throwable> errors = new ArrayList<Throwable>();
112        Thread.UncaughtExceptionHandler ueh = new Thread.UncaughtExceptionHandler() {
113            public void uncaughtException(Thread thread, Throwable error) {
114                errors.add(error);
115            }
116        };
117 
118        // 3 threads should do
119        Thread t1 = new Thread(getPrefRunnable);
120        Thread t2 = new Thread(getPrefRunnable);
121        Thread t3 = new Thread(getPrefRunnable);
122        t1.setUncaughtExceptionHandler(ueh);
123        t2.setUncaughtExceptionHandler(ueh);
124        t3.setUncaughtExceptionHandler(ueh);
125        t1.start();
126        t2.start();
127        t3.start();
128        t1.join();
129        t2.join();
130        t3.join();
131 
132        if (errors.size() > 0) {
133            throw errors.iterator().next();
134        }
135 
136        Preferences preferences = preferencesService.getPreferences(principal.getPrincipalId());
137        assertTrue("Preferences should require a save.", preferences.isRequiresSave());
138        Collection updatedOptions = userOptionsService.findByWorkflowUser(principal.getPrincipalId());
139        assertTrue("UserOptions should be empty", updatedOptions.isEmpty());
140        preferencesService.savePreferences(principal.getPrincipalId(), preferences);
141        updatedOptions = userOptionsService.findByWorkflowUser(principal.getPrincipalId());
142        assertTrue("UserOptions should not be empty", !updatedOptions.isEmpty());
143 
144     }
145 }