Interceptor binding doesn't work - java

I have CDI interceptor class annotated with javax.interceptor.InterceptorBinding #LogBinding, defined as follows:
#InterceptorBinding
#Retention(RUNTIME)
#Target({METHOD, TYPE})
public #interface LogBinding {}
Then I use annotation on EJB bean:
#Alternative
#Stateless
#LogBinding
public class FooService {
#Asynchronous
public fooMethod() {
}
}
I invoke fooMethod from another bean. The problem is that interceptor isn't called. Everything works when I change #LogBinding annotation to #Interceptors({LogInterceptor.class}) on the FooService.
I don't know if it may have impact but FooService is market as #Alternative, because it's injected in other places as EJB bean, below is the producer field:
#Default
#Produces
#EJB
private FooService fooService;
#Interceptor
#LogBinding
#Priority(Interceptor.Priority.APPLICATION)
public class LogInterceptor {
#AroundInvoke
public Object invoke(final InvocationContext invocationContext) throws Exception {
System.out.println("it works");
}
}
Why it doesn't work?

You also have to annotate your interceptor class with that binding in order for it to know which class to use as the interceptor
#LogBinding
#Interceptor
public class LogInterceptor {...}

Related

Exclude a specific method to be invoked by CDI Interceptor

I have an interceptor binding annotation :
#InterceptorBinding
#Target({ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface MyBinding {
}
To this CDI interceptor :
#Interceptor
#MyBinding
public class MyInterceptor {
#AroundInvoke
public Object applyPolicy(InvocationContext ctx) throws Exception {
return blablabla;
}
}
And a class annotated, that mean every methods of this class will invoke MyInterceptor
#MyBinding
public class GlobalController {
public void methodA() {...}
public void methodB() {...}
}
All works fine, but I wish methodB not invoking my interceptor.
I tried both annotations #ExcludeClassInterceptors and #ExcludeDefaultInterceptors on my method but it doesn't works for me. I think these annotations are especially for exclude a method for EJB Interceptor, and not CDI Interceptor with Interceptor binding.
Not sure about these annotations but as a workaround you can add an annotation to the method you want to exclude. Get Method from InvocationContext in the interceptor and check whether the method has the annotation. In this case just delegate to the original method.
Try #MyBinding at method level:
public class GlobalController {
#MyBinding
public void methodA() {...}
public void methodB() {...}
}

Spring autowiring parameter by name

I have two beans with the type InterfaceA.
I was trying to inject the bean into an argument of a #Bean method using #Qualifier to autowire by name.
I was surprising that Spring can't resolve the proper bean unless your parameter name is matching the bean name.
I was trying:
#Component
public class ClassA implements InterfaceA {
}
#Component
public class ClassB implements InterfaceA {
}
#Configuration
public class AppConfig {
#Bean
#Autowired
#Qualifier("classA")
public SomeOtherClass someOtherClass(InterfaceA object) {...}
}
But got the NoUniqueBeanDefinitionException.
However if I use parameter name matching the component name it works fine.
#Configuration
public class AppConfig {
#Bean
#Autowired
public SomeOtherClass someOtherClass(InterfaceA classA) {...}
}
Could someone explain why I can't use autowiring by name with #Resource or #Qualifier here?
Add the #Qualifier annotation to the parameter not to the method:
public SomeOtherClass someOtherClass(#Qualifier("classA") InterfaceA object) {...}

How to instantiate a Class/Bean in Spring passing parameter in constructor

I need to Autowire service interface in my controller, passing parameter logcode in not default service constructor
#Controller
public class FooController {
private Foo foo;
#Autowired
private FooService fooService //(I like passe parameter here);
}
Here's my Service:
I need to Autowire service interface in my controller, passing parameter logcode in not default service constructor
#Service
public class FooServiceImpl implements FooService {
#Autowired
private FooDAO fooDAO;
public FooServiceImpl(String pLogCode)
{
}
#Transactional
public void addFoo(Foo foo) {
fooDAO.addFoo(foo);
}
}
Passing arguments when autowiring interfaces it's only possible in XML config. Simmilar question is here:
Spring autowire interface

#Producer annotation in Java EE

I am learning Java EE CDI, dependency injection, and #Produces in particular. I am wondering why in getGreedingCard() method, it needs a #Produces annotation at all, since the two classes GreetingCardImpl and AnotherGreetingCardImpl are already imported into the space. This is just like the regular package/class dependency and a simple import solves the problem. Why does it need a dependency injection through a #producer annotation?
Thanks for explanation in advance.
public interface GreetingCard {
void sayHello();
}
public class GreetingCardImpl implements GreetingCard {
public void sayHello() {
System.out.println("Hello!!!");
}
}
public class AnotherGreetingCardImpl implements GreetingCard {
public void sayHello() {
System.out.println("Have a nice day!!!");
}
}
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.AnotherGreetingCardImpl;
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.GreetingCardImpl;
#SessionScoped
public class GreetingCardFactory implements Serializable {
private GreetingType greetingType;
#Produces
public GreetingCard getGreetingCard() {
switch (greetingType) {
case HELLO:
return new GreetingCardImpl();
case ANOTHER_HI:
return new AnotherGreetingCardImpl();
default:
return new GreetingCardImpl();
}
}
}
I am wondering why in getGreedingCard() method, it needs a #Produces
annotation at all, since the two classes GreetingCardImpl and
AnotherGreetingCardImpl are already imported into the space.
Well, it's not that getGreetingCard needs the #Produces annotation. The point is to enable other classes to recieve GreetingCards via Dependency Injection.
public class Foo {
#Inject // <--- will invoke #Producer method
GreetingCard foosGreetingCard
...
}
See here for more details:
A producer method is a method that acts as a source of bean instances.
The method declaration itself describes the bean and the container
invokes the method to obtain an instance of the bean when no instance
exists in the specified context.
In your case it doesn't need #Produces as you will be injecting factory bean and using its method directly to create instances, and not injecting the greetingCard beans themseleves.
#Inject
GreetingCardFactory factory;
...
GreetingCard card = factory.getGreetingCard();
If you would define it as #Produces method, and the try to inject GreetingCard, then you would get exception that I've described in the comment.
However, if you would additionally create qualifier, like this:
#Qualifier
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})
public #interface ProducedCard {}
and add it to the producer method:
#Produces #ProducedCard
public GreetingCard getGreetingCard() {
...
then you would be able to inject just GreetingCard beans using your producer method like this:
#Inject #ProducedCard
GreetingCard card;
since now there is no ambiguity, as there is only one place to create greeting cards marked with #ProducedCard :-)

#PostConstruct Interceptor with #Named #ViewScoped not invoked

I have read carefully the article about Interceptors in the Seam/Weld documentation and implemented a InterceptorBinding:
#InterceptorBinding
#Retention(RetentionPolicy.RUNTIME)
#Target({ElementType.METHOD, ElementType.TYPE})
public #interface MyLog {}
and a Interceptor class:
#MyLog #Interceptor
public class ErpLogInterceptor implements Serializable
{
#AroundInvoke
public Object logMethodEntry(InvocationContext invocationContext) throws Exception
{..}
#PostConstruct
public Object logPostConstruct(InvocationContext invocationContext) throws Exception
{...}
}
No I tried to activated the interceptor in the #Named #ViewScoped bean:
#javax.inject.Named;
#javax.faces.bean.ViewScoped
public class MyBean implements Serializable
{
#PostConstruct #MyLog
public void init()
{...}
#MyLog public void toggleButton()
{..}
}
If I push a button on my JSF page the method toggleButton is invoked correctly and the Interceptor method logMethodEntry is called. But it seems the method #PostConstruct (I am interested in) is never intercepted by my class.
The question seems to be related to Java EE Interceptors and #ViewScoped bean but actually my interceptor is working in normal methods.
You should set return type of #PostConstruct interceptor to void not Object.
Change:
#PostConstruct
public Object logPostConstruct(InvocationContext invocationContext) throws Exception
{...}
to:
#PostConstruct
public void logPostConstruct(InvocationContext invocationContext) throws Exception
{...}

Categories