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 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.
/** * 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.

When using this constructor, the UnitOfWorkApplicationListener should be added to a Jersey ResourceConfig as a singleton.
Params:
  • name – a name of a Hibernate bundle
  • sessionFactory – a SessionFactory
/** * 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.
Params:
  • name – a name of a Hibernate bundle
  • sessionFactory – a 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); } }