Interceptor method not called with interceptor binding - java

I'm using Java EE 6 & Jboss AS7.1 and try to use interceptor binding (Example from jboss site).
I have an InterceptorBinding annotation:
#InterceptorBinding
#Target({ ElementType.METHOD, ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
public #interface GeoRestrictedEquipment {
}
The interceptor:
#GeoRestrictedEquipment
#Interceptor
public class GeoRestrictedEquipmentInterceptor {
#EJB EquipmentDao equipmenttDao;
#EJB SecurityService securityService;
#AroundInvoke
public Object checker(InvocationContext ctx) throws Exception {
Integer id = (Integer) ctx.getParameters()[0];
Equipment equipment = equipmenttDao.findById(id);
GeoChecker.check(equipment.getSite(), securityService.getUser());
return ctx.proceed();
}
}
And a bean:
#Stateless
#LocalBean
#SecurityDomain(Realm.NAME)
#RolesAllowed({ Roles.REGISTERED })
public class PumpService implements PumpServiceLocal {
#Override
#GeoRestrictedEquipment
public PumpInfos getPumpInfos(Integer pumpId) {
/* ... */
}
}
But the interceptor is not called... What do I miss from the example ?
The interceptor is called when I write this:
#Override
#Interceptors({GeoRestrictedEquipmentInterceptor.class})
public PumpInfos getPumpInfos(Integer pumpId) {
/* ... */
}
Thanks for your help.

According to the documentation there is another way rather than using beans.xml:
You do not need to specify the interceptor in the beans.xml file when
you use the #Priority annotation.
#Logged
#Interceptor
#Priority(Interceptor.Priority.APPLICATION)
public class LoggedInterceptor implements Serializable { ... }
And it works.

Did you enable your interceptor as described in the referenced example?
By default, a bean archive has no enabled interceptors bound via
interceptor bindings. An interceptor must be explicitly enabled by
listing its class under the element of the beans.xml
file of the bean archive.

You can use any priority value = Priority.Application is 2000 by default.
For example =
#Interceptor
#Loggable
#Priority(100)
public class FileLogger {}
Priority type:
PLATFORM_BEFORE [0-999] - interceptors start at the first. They are started by the platform.
LIBRARY_BEFORE [1000-1999] - by the libraries.
APPLICATION [2000-2999]- by the application
LIBRARY_AFTER,PLATFORM_AFTER [3000-4000]
You manage primary loading for interceptors.

Related

Injecting a CDI interceptor into a beans does not work

I have created a CDI (WELD) interceptor that works and intercept what it is supposed to intercept.
#MyInterceptorBinding
#Interceptor
#Dependent
public class MyInterceptor implements Serializable {
private int myIntegerField;
#AroundInvoke
public Object interceptMethod(InvocationContext ctx) throws Exception {
// Do some operations and side effects on myIntegerField;
try {
Object result = ctx.proceed();
return result;
} catch (Exception e) {
throw e;
}
}
public List<Class<?>> getMyIntegerField() {
return myIntegerField;
}
}
Where MyInterceptorBinding is an interceptor binding:
#Inherited
#InterceptorBinding
#Target({TYPE, METHOD, PARAMETER, FIELD})
#Retention(RetentionPolicy.RUNTIME)
public #interface MyInterceptorBinding {}
I would like to inject my interceptor into a bean class like this:
#ApplicationScoped
public class MyBean implements Serializable {
#Inject
private MyInterceptor interceptor;
public void aMethod(){
int var = interceptor.getMyIntegerField();
// use var in some way...
}
}
but this injection brings to an error:
Unsatisfied dependencies for type MyInterceptor with qualifiers #Default
at injection point [BackedAnnotatedField] #Inject private trials.MyBean.interceptor
How can i overcome this issue? Is a problem related to the fact that is an interceptor?
Should i use the CDI portable extension facility? And, if so, how?
You can't inject interceptors because they aren't beans. What you probably can do is create a helper bean and inject that in both the interceptor and the application scoped bean. That helper bean can then contain the value, the interceptor can set it and the other bean can read it.
A warning about scopes: your MyBean is application scoped, which means that there will be only once instance. If the interceptor is used in request scoped beans, what should the value of the interceptor value be? For this to work, the helper bean should most likely also be application scoped, and you should take care of thread safety.

Spring register beans using custom annotation

I need to register some configuration beans from another module. Here is what I have:
#Configuration
public class MyConfiguration {
#Bean
public FirstConfig(CustomManager manager, CustomContext context) {
return manager.get(FirstConfig.class, context);
}
#Bean
public SecondConfig(CustomManager manager, CustomContext context) {
return manager.get(SecondConfig.class, context);
}
#Bean
public ThirdConfig(CustomManager manager, CustomContext context) {
return manager.get(ThirdConfig.class, context);
}
// some other beans
}
The above code works just fine, but as you can see, there are a lot of boilerplate code. So I'm thinking about creating a custom annotation to simplify this. Something like:
#Configuration
#EnableConfigBeans({FirstConfig.class, SecondConfig.class, ThirdConfig.class})
public class MyConfiguration {
// some other beans
}
The approach I took was to use #Import and implement interface ImportBeanDefinitionRegistrar
public class CustomBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar
and define my annotation like this:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Import({CustomBeanDefinitionRegistrar.class})
public #interface EnableConfigBeans {
Class<?>[] value();
}
However, I'm not able to autowire CustomManager or CustomContext in CustomBeanDefinitionRegistrar since those beans are not ready to use at that phase.
Can someone please give me some suggestions on how to implement this feature? Thanks

How #Repository and #Autowired work in spring boot Dao and Service Layer?

Below is a my sample Dao and Service Layer.
All are in different Packages.
I am using spring-boot 1.4.
How an autowired Dao interface call DaoImpl methods directly?
In java, an interface can refer to child object but iterface.childMethod() is not possible.
What i am thinking is , since i am doing dependency injection, somehow i am receiving an object of daoImpl in service layer.
Can anyone explain the whole concept of what is happening?
ISocietyAccountMasterDao
public interface ISocietyAccountMasterDao extends IGenericRepository<SocietyAccountMaster> {
List<SocietyAccountMaster> getAllSocietyAccounts(String societyId, Long accountTypeId);
}
SocietyAccountMasterDaoImpl
public class SocietyAccountMasterDaoImpl extends AbstractDao<String, SocietyAccountMaster>
implements ISocietyAccountMasterDao {
private final Logger logger = LogManager.getLogger(LoggingAspect.MANUAL);
#Override
public List<SocietyAccountMaster> getAllSocietyAccounts(String societyId, Long accountTypeId) {
Criteria cr = getEntityCriteria();
try {
cr.add(Restrictions.eq("societyId", societyId));
if (!StringUtils.isEmpty(accountTypeId)) {
cr.add(Restrictions.eq("accountType.id", accountTypeId));
}
return cr.list();
} catch (Exception e) {
logger.error("Error While Society Accounts", e);
throw new BindException(BindStatus.FAILURE, BindStatus.FAILURE_MSG);
}
}
ISocietyAccountingService
public interface ISocietyAccountingService {
List<SocietyAccountMasterDto> getAllSocietyAccounts(String societyId);
}
SocietyAccountingServiceImpl
#Service("societyAccountingService")
#Transactional
public class SocietyAccountingServiceImpl implements ISocietyAccountingService {
#Override
public List<SocietyAccountMasterDto> getAllSocietyAccounts(String societyId) {
List<SocietyAccountMasterDto> responses = new ArrayList<SocietyAccountMasterDto>();
List<SocietyAccountMaster> dbSocietyAccountMasters = societyAccountMasterDao.getAllSocietyAccounts(societyId,
null);
for (SocietyAccountMaster dbSocietyAccountMaster : dbSocietyAccountMasters) {
SocietyAccountMasterDto response = new SocietyAccountMasterDto();
response.setNickName(dbSocietyAccountMaster.getNickName());
response.setBankName(dbSocietyAccountMaster.getBankName());
response.setBalance(dbSocietyAccountMaster.getBalance());
responses.add(response);
}
return responses;
}
}
#Component - Indicates a bean is an auto scan component. It means spring will search for bean with beanName, when it is injected as autowire.
#Repository - Indicates DAO component in the persistence layer available as auto-scan component.
If see implements of #Repository annonation as shown below:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface Repository {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* #return the suggested component name, if any
*/
String value() default "";
}
This annotation class is annotated with #Component, which makes it available for auto-wiring. this is reason with DAO impl is available to Service via auto-wiring since Spring auto-detecting it.

Spring AOP: Advice not executing for method with custom annotation

I have created a custom annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.METHOD)
public #interface ValidateBeforeBuild {
}
And an aspect as:
#Aspect
#Component
public class AspectForBuildInBuilders {
private static final Logger LOGGER = LoggerFactory.getLogger(AspectForBuildInBuilders.class);
#Before("#annotation(validateBeforeBuild )")
public void validateBusinessModelAdvice(JoinPoint jp, ValidateBeforeBuild validateBeforeBuild ) throws Throwable {
LOGGER.info("Executing class: {}", jp);
}
}
I have a build() that is marked with above annotation. When I am trying to call the build(), I am not getting the log message from the validateBusinessModelAdvice(). I also have #EnableAspectJAutoProxy in one of the configuration classes. Am I missing something? Is there any more information required?
You defined your annotation as ValidateBeforeBuild and in your aspect you specified validateBeforeBuild (notice the upper V in your annotation)
Try changing
#Before("#annotation(validateBeforeBuild)")
for
#Before("#annotation(ValidateBeforeBuild)")

Spring Bean Alias in JavaConfig

I have a #Service annotated class which provides core functionality which I can use in all my projects:
#Service
public class MyService {}
and another one which extends it to implement project specific stuff:
#Service
public class ExtendedMyService extends MyService {}
Now I would like to configure a bean alias to be able to use #Qualifier("MyServiceAlias") when autowiring it using a property:
# MyService qualifier (default: myService)
myService.qualifier=extendedMyService
In XML it would look like:
<alias name="${myService.qualifier}" alias="MyServiceAlias" />
It is also discussed here, but I need to do it w/o XML, JavaConfig only.
Is it possible and how to realize?
There is an open Jira for this: https://jira.spring.io/browse/SPR-6736
The workaround is to use #Bean in #Configuration class:
#Configuration
public class AppConfig {
#Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
public MyService myService() {}
}
If you want to use the placeholder, another workaround is to use #Bean in a #Configuration class using #Value and the Spring applicationContext.
#Configuration
public class AppConfig {
#Autowired
private ApplicationContext context;
#Bean
public MyService myService(#Value("${myService.qualifier}") String qualifier) {
return (MyService) context.getBean(qualifier);
}
}
NB : special consideration must be taken for the placeholder bean which must be loaded at the beginning (cf javadoc)
With small amount of configuration and one ImportBeanDefinitionRegistrar you can configure bean aliases via Java configuration. You can check bean-alias library project for reference - developed for the needs of my projects. Feel free to modify and/or copy the source into your own project in case the spring version used in it does not work with your setup.
Once you have the library on your path, you declare an alias through the annotation:
#Configuration
#BeanAlias(name = "fromName", alias = "toName")
public class ExampleConfiguration {
}
That's it.
How it works is that with the annotation we import a ImportBeanDefinitionRegistrar implementation
#Import(BeanAliasBeanRegistrar.class)
public #interface BeanAlias {
}
which registers the alias in the BeanDefinitionRegistry
class BeanAliasBeanRegistrar implements ImportBeanDefinitionRegistrar, PriorityOrdered {
#Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
...
registerAlias(registry, metadata.getAnnotationAttributes(BeanAlias.class.getName()));
}
private void registerAlias(BeanDefinitionRegistry registry, Map<String, Object> attributes) {
...
registry.registerAlias(name, alias);
}
}

Categories

Resources