001 package de.deepamehta.core.impl;
002
003 import de.deepamehta.core.service.DeepaMehtaService;
004 import de.deepamehta.core.service.Transactional;
005 import de.deepamehta.core.storage.spi.DeepaMehtaTransaction;
006
007 import com.sun.jersey.api.model.AbstractMethod;
008 import com.sun.jersey.spi.container.ContainerRequest;
009 import com.sun.jersey.spi.container.ContainerRequestFilter;
010 import com.sun.jersey.spi.container.ContainerResponse;
011 import com.sun.jersey.spi.container.ContainerResponseFilter;
012 import com.sun.jersey.spi.container.ResourceFilter;
013 import com.sun.jersey.spi.container.ResourceFilterFactory;
014
015 import java.util.ArrayList;
016 import java.util.List;
017 import java.util.logging.Logger;
018
019
020
021 class TransactionFactory implements ResourceFilterFactory {
022
023 // ---------------------------------------------------------------------------------------------- Instance Variables
024
025 private DeepaMehtaService dms;
026
027 private Logger logger = Logger.getLogger(getClass().getName());
028
029 // ------------------------------------------------------------------------------------------------- Class Variables
030
031 private static final ThreadLocal<DeepaMehtaTransaction> threadLocalTransaction = new ThreadLocal();
032
033 // ---------------------------------------------------------------------------------------------------- Constructors
034
035 TransactionFactory(DeepaMehtaService dms) {
036 this.dms = dms;
037 }
038
039 // -------------------------------------------------------------------------------------------------- Public Methods
040
041 @Override
042 public List<ResourceFilter> create(AbstractMethod method) {
043 if (!method.isAnnotationPresent(Transactional.class)) {
044 return null;
045 }
046 //
047 logger.fine("### Adding transaction support to " + method);
048 List<ResourceFilter> filters = new ArrayList();
049 filters.add(new TransactionResourceFilter(method));
050 return filters;
051 }
052
053 // ------------------------------------------------------------------------------------------------- Private Classes
054
055 private class TransactionResourceFilter implements ResourceFilter {
056
057 private AbstractMethod method;
058
059 private TransactionResourceFilter(AbstractMethod method) {
060 this.method = method;
061 }
062
063 @Override
064 public ContainerRequestFilter getRequestFilter() {
065 return new ContainerRequestFilter() {
066
067 @Override
068 public ContainerRequest filter(ContainerRequest request) {
069 logger.fine("### Begining transaction of " + method);
070 DeepaMehtaTransaction tx = dms.beginTx();
071 threadLocalTransaction.set(tx);
072 return request;
073 }
074 };
075 }
076
077 @Override
078 public ContainerResponseFilter getResponseFilter() {
079 return new ContainerResponseFilter() {
080
081 @Override
082 public ContainerResponse filter(ContainerRequest request, ContainerResponse response) {
083 boolean success = response.getMappedThrowable() == null; // ### TODO: is this criteria concise?
084 DeepaMehtaTransaction tx = threadLocalTransaction.get();
085 if (success) {
086 logger.fine("### Comitting transaction of " + method);
087 tx.success();
088 } else {
089 logger.warning("### Rollback transaction of " + method);
090 }
091 tx.finish();
092 return response;
093 }
094 };
095 }
096 }
097 }