org.apache.deltaspike.jpa.impl.transaction.TransactionStrategyHelper Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.deltaspike.jpa.impl.transaction;
import org.apache.deltaspike.core.util.AnnotationUtils;
import org.apache.deltaspike.jpa.api.transaction.Transactional;
import org.apache.deltaspike.jpa.impl.entitymanager.EntityManagerMetadata;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.spi.BeanManager;
import javax.inject.Inject;
import javax.interceptor.InvocationContext;
import javax.persistence.EntityManager;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Helper which provides utility methods for any
* {@link org.apache.deltaspike.jpa.spi.transaction.TransactionStrategy}.
*/
@Dependent
public class TransactionStrategyHelper implements Serializable
{
private static final long serialVersionUID = -6272327391611428125L;
@Inject
private BeanManager beanManager;
/**
* This method uses the InvocationContext to scan the @Transactional
* interceptor for a manually specified Qualifier.
*
* If none is given (defaults to Any.class) then we scan the intercepted
* instance and resolve the Qualifiers of all it's injected EntityManagers.
*
* Please note that we will only pickup the first Qualifier on the
* injected EntityManager. We also do not parse for binding or
* &h#064;NonBinding values. A @Qualifier should not have any parameter at all.
* @param entityManagerMetadata the metadata to locate the entity manager
* @param interceptedTargetClass the Class of the intercepted target
*/
public Set> resolveEntityManagerQualifiers(EntityManagerMetadata entityManagerMetadata,
Class interceptedTargetClass)
{
Set> emQualifiers = new HashSet<>();
Class extends Annotation>[] qualifierClasses = entityManagerMetadata.getQualifiers();
if (qualifierClasses == null || qualifierClasses.length == 1 && Any.class.equals(qualifierClasses[0]) )
{
// this means we have no special EntityManager configured in the interceptor
// thus we should scan all the EntityManagers ourselfs from the intercepted class
collectEntityManagerQualifiersOnClass(emQualifiers, interceptedTargetClass);
}
else
{
// take the qualifierKeys from the qualifierClasses
Collections.addAll(emQualifiers, qualifierClasses);
}
//see DELTASPIKE-320
if (emQualifiers.isEmpty())
{
emQualifiers.add(Default.class);
}
return emQualifiers;
}
/**
* Scan the given class and return all the injected EntityManager fields.
* Attention: we do only pick up EntityManagers which use @Inject!
*/
private void collectEntityManagerQualifiersOnClass(Set> emQualifiers,Class target)
{
// first scan all declared fields
Field[] fields = target.getDeclaredFields();
for (Field field : fields)
{
if (EntityManager.class.equals(field.getType()))
{
// also check if this is an injected EM
if (field.getAnnotation(Inject.class) != null)
{
boolean qualifierFound = false;
Class extends Annotation> qualifier = getFirstQualifierAnnotation(field.getAnnotations());
if (qualifier != null)
{
emQualifiers.add(qualifier);
qualifierFound = true;
}
if (!qualifierFound)
{
// according to the CDI injection rules @Default is assumed
emQualifiers.add(Default.class);
}
}
}
}
// finally recurse into the superclasses
Class superClass = target.getSuperclass();
if (!Object.class.equals(superClass))
{
collectEntityManagerQualifiersOnClass(emQualifiers, superClass);
}
}
/**
* Extract the first CDI-Qualifier Annotation from the given annotations array
*/
private Class extends Annotation> getFirstQualifierAnnotation(Annotation[] annotations)
{
for (Annotation ann : annotations)
{
if (beanManager.isQualifier(ann.annotationType()))
{
return ann.annotationType();
}
}
return null;
}
EntityManagerMetadata createEntityManagerMetadata(InvocationContext context)
{
EntityManagerMetadata metadata = new EntityManagerMetadata();
metadata.readFrom(context.getMethod().getDeclaringClass(), beanManager);
metadata.readFrom(context.getMethod(), beanManager);
return metadata;
}
/**
* @return the @Transactional annotation from either the method or class
* or null
if none present.
*/
protected Transactional extractTransactionalAnnotation(InvocationContext context)
{
Class targetClass = context.getTarget() != null ? context.getTarget().getClass() :
context.getMethod().getDeclaringClass();
return AnnotationUtils
.extractAnnotationFromMethodOrClass(beanManager, context.getMethod(), targetClass, Transactional.class);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy