Skip to content

Commit 46046b5

Browse files
strangeweaverjricher
authored andcommitted
Implemented paged operations and used for database cleanup tasks.
1 parent 0992115 commit 46046b5

File tree

13 files changed

+540
-64
lines changed

13 files changed

+540
-64
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package org.mitre.data;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
import java.util.Collection;
7+
import java.util.HashSet;
8+
import java.util.Set;
9+
10+
/**
11+
* Abstract class for performing an operation on a potentially large
12+
* number of items by paging through the items in discreet chunks.
13+
*
14+
* @param <T> the type parameter
15+
* @author Colm Smyth.
16+
*/
17+
public abstract class AbstractPageOperationTemplate<T> {
18+
19+
private static final Logger logger = LoggerFactory.getLogger(AbstractPageOperationTemplate.class);
20+
21+
private static int DEFAULT_MAX_PAGES = 1000;
22+
private static long DEFAULT_MAX_TIME_MILLIS = 600000L; //10 Minutes
23+
24+
/**
25+
* int specifying the maximum number of
26+
* pages which should be fetched before
27+
* execution should terminate
28+
*/
29+
private int maxPages;
30+
31+
/**
32+
* long specifying the maximum execution time
33+
* in milliseconds
34+
*/
35+
private long maxTime;
36+
37+
/**
38+
* boolean specifying whether or not Exceptions
39+
* incurred performing the operation should be
40+
* swallowed during execution default true.
41+
*/
42+
private boolean swallowExceptions = true;
43+
44+
45+
/**
46+
* default constructor which sets the value of
47+
* maxPages and maxTime to DEFAULT_MAX_PAGES and
48+
* DEFAULT_MAX_TIME_MILLIS respectively
49+
*/
50+
public AbstractPageOperationTemplate(){
51+
this(DEFAULT_MAX_PAGES, DEFAULT_MAX_TIME_MILLIS);
52+
}
53+
54+
55+
/**
56+
* Instantiates a new AbstractPageOperationTemplate with the
57+
* given maxPages and maxTime
58+
*
59+
* @param maxPages the maximum number of pages to fetch.
60+
* @param maxTime the maximum execution time.
61+
*/
62+
public AbstractPageOperationTemplate(int maxPages, long maxTime){
63+
this.maxPages = maxPages;
64+
this.maxTime = maxTime;
65+
}
66+
67+
68+
/**
69+
* Execute the operation on each member of a page of results
70+
* retrieved through the fetch method. the method will execute
71+
* until either the maxPages or maxTime limit is reached or until
72+
* the fetch method returns no more results. Exceptions thrown
73+
* performing the operation on the item will be swallowed if the
74+
* swallowException (default true) field is set true.
75+
*/
76+
public void execute(){
77+
logger.info("Starting execution of paged operation. maximum time: " + maxTime
78+
+ " maximum pages: " + maxPages);
79+
80+
long startTime = System.currentTimeMillis();
81+
long executionTime = 0;
82+
int i = 0;
83+
84+
int exceptionsSwallowedCount = 0;
85+
int operationsCompleted = 0;
86+
Set<String> exceptionsSwallowedClasses = new HashSet<String>();
87+
88+
89+
while (i< maxPages && executionTime < maxTime){
90+
Collection<T> page = fetchPage();
91+
if(page == null || page.size() == 0){
92+
break;
93+
}
94+
95+
for (T item : page) {
96+
try {
97+
doOperation(item);
98+
operationsCompleted++;
99+
} catch (Exception e){
100+
if(swallowExceptions){
101+
exceptionsSwallowedCount++;
102+
exceptionsSwallowedClasses.add(e.getClass().getName());
103+
logger.debug("Swallowing exception " + e.getMessage(), e);
104+
} else {
105+
logger.debug("Rethrowing exception " + e.getMessage());
106+
throw e;
107+
}
108+
}
109+
}
110+
111+
i++;
112+
executionTime = System.currentTimeMillis() - startTime;
113+
}
114+
115+
logger.info("Paged operation run completed " + operationsCompleted + " swallowed " + exceptionsSwallowedCount + " exceptions");
116+
for(String className: exceptionsSwallowedClasses) {
117+
logger.warn("Paged operation swallowed at least one exception of type " + className);
118+
}
119+
}
120+
121+
/**
122+
* method responsible for fetching
123+
* a page of items.
124+
*
125+
* @return the collection of items
126+
*/
127+
public abstract Collection<T> fetchPage();
128+
129+
/**
130+
* method responsible for performing desired
131+
* operation on a fetched page item.
132+
*
133+
* @param item the item
134+
*/
135+
protected abstract void doOperation(T item);
136+
137+
public int getMaxPages() {
138+
return maxPages;
139+
}
140+
141+
public void setMaxPages(int maxPages) {
142+
this.maxPages = maxPages;
143+
}
144+
145+
public long getMaxTime() {
146+
return maxTime;
147+
}
148+
149+
public void setMaxTime(long maxTime) {
150+
this.maxTime = maxTime;
151+
}
152+
153+
public boolean isSwallowExceptions() {
154+
return swallowExceptions;
155+
}
156+
157+
public void setSwallowExceptions(boolean swallowExceptions) {
158+
this.swallowExceptions = swallowExceptions;
159+
}
160+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package org.mitre.data;
2+
3+
/**
4+
* Default implementation of PageCriteria which specifies
5+
* both page to be retrieved and page size in the constructor.
6+
*
7+
* @author Colm Smyth
8+
*/
9+
public class DefaultPageCriteria implements PageCriteria {
10+
11+
private static final int DEFAULT_PAGE_NUMBER = 0;
12+
private static final int DEFAULT_PAGE_SIZE = 100;
13+
14+
private int pageNumber;
15+
private int pageSize;
16+
17+
public DefaultPageCriteria(){
18+
this(DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE);
19+
}
20+
21+
public DefaultPageCriteria(int pageNumber, int pageSize) {
22+
this.pageNumber = pageNumber;
23+
this.pageSize = pageSize;
24+
}
25+
26+
@Override
27+
public int getPageNumber() {
28+
return pageNumber;
29+
}
30+
31+
@Override
32+
public int getPageSize() {
33+
return pageSize;
34+
}
35+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.mitre.data;
2+
3+
/**
4+
* Interface which defines page criteria for use in
5+
* a repository operation.
6+
*
7+
* @author Colm Smyth
8+
*/
9+
public interface PageCriteria {
10+
11+
public int getPageNumber();
12+
public int getPageSize();
13+
}

openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthenticationHolderRepository.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.List;
2020

21+
import org.mitre.data.PageCriteria;
2122
import org.mitre.oauth2.model.AuthenticationHolderEntity;
2223

2324
public interface AuthenticationHolderRepository {
@@ -31,5 +32,5 @@ public interface AuthenticationHolderRepository {
3132

3233
public List<AuthenticationHolderEntity> getOrphanedAuthenticationHolders();
3334

34-
35+
public List<AuthenticationHolderEntity> getOrphanedAuthenticationHolders(PageCriteria pageCriteria);
3536
}

openid-connect-common/src/main/java/org/mitre/oauth2/repository/AuthorizationCodeRepository.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import java.util.Collection;
2020

21+
import org.mitre.data.PageCriteria;
2122
import org.mitre.oauth2.model.AuthorizationCodeEntity;
2223

2324
/**
@@ -56,4 +57,10 @@ public interface AuthorizationCodeRepository {
5657
*/
5758
public Collection<AuthorizationCodeEntity> getExpiredCodes();
5859

60+
/**
61+
* @return A collection of all expired codes, limited by the given
62+
* PageCriteria.
63+
*/
64+
public Collection<AuthorizationCodeEntity> getExpiredCodes(PageCriteria pageCriteria);
65+
5966
}

openid-connect-common/src/main/java/org/mitre/oauth2/repository/OAuth2TokenRepository.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.util.List;
2020
import java.util.Set;
2121

22+
import org.mitre.data.PageCriteria;
2223
import org.mitre.oauth2.model.ClientDetailsEntity;
2324
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
2425
import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
@@ -57,8 +58,12 @@ public interface OAuth2TokenRepository {
5758

5859
public Set<OAuth2AccessTokenEntity> getAllExpiredAccessTokens();
5960

61+
public Set<OAuth2AccessTokenEntity> getAllExpiredAccessTokens(PageCriteria pageCriteria);
62+
6063
public Set<OAuth2RefreshTokenEntity> getAllExpiredRefreshTokens();
6164

65+
public Set<OAuth2RefreshTokenEntity> getAllExpiredRefreshTokens(PageCriteria pageCriteria);
66+
6267
public Set<OAuth2AccessTokenEntity> getAccessTokensForResourceSet(ResourceSet rs);
6368

6469
/**

openid-connect-common/src/main/java/org/mitre/util/jpa/JpaUtil.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616
*******************************************************************************/
1717
package org.mitre.util.jpa;
1818

19+
import org.mitre.data.PageCriteria;
20+
1921
import java.util.List;
2022

2123
import javax.persistence.EntityManager;
24+
import javax.persistence.TypedQuery;
2225

2326
/**
2427
* @author mfranklin
2528
* Date: 4/28/11
2629
* Time: 2:13 PM
2730
*/
2831
public class JpaUtil {
29-
public static <T> T getSingleResult(List<T> list) {
32+
public static <T> T getSingleResult(List<T> list) {
3033
switch(list.size()) {
3134
case 0:
3235
return null;
@@ -37,6 +40,25 @@ public static <T> T getSingleResult(List<T> list) {
3740
}
3841
}
3942

43+
44+
/**
45+
* Get a page of results from the specified TypedQuery
46+
* by using the given PageCriteria to limit the query
47+
* results. The PageCriteria will override any size or
48+
* offset already specified on the query.
49+
*
50+
* @param <T> the type parameter
51+
* @param query the query
52+
* @param pageCriteria the page criteria
53+
* @return the list
54+
*/
55+
public static <T> List<T> getResultPage(TypedQuery<T> query, PageCriteria pageCriteria){
56+
query.setMaxResults(pageCriteria.getPageSize());
57+
query.setFirstResult(pageCriteria.getPageNumber()*pageCriteria.getPageSize());
58+
59+
return query.getResultList();
60+
}
61+
4062
public static <T, I> T saveOrUpdate(I id, EntityManager entityManager, T entity) {
4163
T tmp = entityManager.merge(entity);
4264
entityManager.flush();

0 commit comments

Comments
 (0)