/
UnitOfWorkApplicationListener.java
110 lines (94 loc) · 4.38 KB
/
UnitOfWorkApplicationListener.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
package io.dropwizard.hibernate;
import org.glassfish.jersey.server.internal.process.MappableException;
import org.glassfish.jersey.server.model.ResourceMethod;
import org.glassfish.jersey.server.monitoring.ApplicationEvent;
import org.glassfish.jersey.server.monitoring.ApplicationEventListener;
import org.glassfish.jersey.server.monitoring.RequestEvent;
import org.glassfish.jersey.server.monitoring.RequestEventListener;
import org.hibernate.SessionFactory;
import javax.ws.rs.ext.Provider;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* An application event listener that listens for Jersey application initialization to
* be finished, then creates a map of resource method that have metrics annotations.
*
* Finally, it listens for method start events, and returns a {@link RequestEventListener}
* that updates the relevant metric for suitably annotated methods when it gets the
* request events indicating that the method is about to be invoked, or just got done
* being invoked.
*/
@Provider
public class UnitOfWorkApplicationListener implements ApplicationEventListener {
private ConcurrentMap<ResourceMethod, Optional<UnitOfWork>> methodMap = new ConcurrentHashMap<>();
private Map<String, SessionFactory> sessionFactories = new HashMap<>();
public UnitOfWorkApplicationListener() {
}
/**
* Construct an application event listener using the given name and session factory.
*
* <p/>
* When using this constructor, the {@link UnitOfWorkApplicationListener}
* should be added to a Jersey {@code ResourceConfig} as a singleton.
*
* @param name a name of a Hibernate bundle
* @param sessionFactory a {@link SessionFactory}
*/
public UnitOfWorkApplicationListener(String name, SessionFactory sessionFactory) {
registerSessionFactory(name, sessionFactory);
}
/**
* Register a session factory with the given name.
*
* @param name a name of a Hibernate bundle
* @param sessionFactory a {@link SessionFactory}
*/
public void registerSessionFactory(String name, SessionFactory sessionFactory) {
sessionFactories.put(name, sessionFactory);
}
private static class UnitOfWorkEventListener implements RequestEventListener {
private ConcurrentMap<ResourceMethod, Optional<UnitOfWork>> methodMap;
private final UnitOfWorkAspect unitOfWorkAspect;
UnitOfWorkEventListener(ConcurrentMap<ResourceMethod, Optional<UnitOfWork>> methodMap,
Map<String, SessionFactory> sessionFactories) {
this.methodMap = methodMap;
unitOfWorkAspect = new UnitOfWorkAspect(sessionFactories);
}
@Override
public void onEvent(RequestEvent event) {
final RequestEvent.Type eventType = event.getType();
if (eventType == RequestEvent.Type.RESOURCE_METHOD_START) {
Optional<UnitOfWork> unitOfWork = methodMap.computeIfAbsent(event.getUriInfo()
.getMatchedResourceMethod(), UnitOfWorkEventListener::registerUnitOfWorkAnnotations);
unitOfWorkAspect.beforeStart(unitOfWork.orElse(null));
} else if (eventType == RequestEvent.Type.RESP_FILTERS_START) {
try {
unitOfWorkAspect.afterEnd();
} catch (Exception e) {
throw new MappableException(e);
}
} else if (eventType == RequestEvent.Type.ON_EXCEPTION) {
unitOfWorkAspect.onError();
} else if (eventType == RequestEvent.Type.FINISHED) {
unitOfWorkAspect.onFinish();
}
}
private static Optional<UnitOfWork> registerUnitOfWorkAnnotations(ResourceMethod method) {
UnitOfWork annotation = method.getInvocable().getDefinitionMethod().getAnnotation(UnitOfWork.class);
if (annotation == null) {
annotation = method.getInvocable().getHandlingMethod().getAnnotation(UnitOfWork.class);
}
return Optional.ofNullable(annotation);
}
}
@Override
public void onEvent(ApplicationEvent event) {
}
@Override
public RequestEventListener onRequest(RequestEvent event) {
return new UnitOfWorkEventListener(methodMap, sessionFactories);
}
}