Difference between #Qualifier and #order - spring-4

I started learning spring, i got confused in the #qualifer and #order Annotation.
My doubt is both the Annotation are used for get the particular auto wire component?

#Qualifier used when you have multiple beans of the same type and you want to inject particular one (specified by name)
#Qualifier("beanOne")
#Autowired
private beanType beanName
#Order used to provide sorting in annotated components.
#Component
#Order(1)
public class RankOne implements Ranks{
}
#Component
#Order(1)
public class RankTwo implements Ranks{
}
#Component
public class Results {
#Autowired
private List ranks ;
}
ranks will have rankOne, rankTwo in sorted order.

Related

autowiring selective beans into a list reference

I have a service interface I with implementaions I1,I2,I3...I10 out of which I want to use I1-I5 to be autowired as a List<I> in controller class C. The I6-I10 should not be be autowired. How can I achieve this. Moreover the I implementations are annotated #Service beans. I do not want to move them to xml declarations.
Based on the comment by mvb13 I have tried to weave a solution for the problem....
So I write a class extending ArrayList and mark it a Component
#Component("mysublist")
public class MyList extends ArrayList implements ApplicationContextAware
{
#Value("comma.sep.eligible.beans.classnames")
private String eligibles;
private ApplicationContext appCtx;
#PostConstruct
public void init()
{
Map allBeans = appCtx.getBeansOfType(I.class);
for(Object bean:allBeans.values())
{
if(eligibles.contains(bean.getClass().getSimpleName()))
{
add(bean);
}
}
}
public void setApplicationContext(ApplicationContext appCtx)
{
this.appCtx = appCtx;
}
}
Now I can autowire the above bean in my required class definition as:
#Service
public class MyService
{
#Resource(name="mysublist")
private List<I> myReqdBeans;
......
}
*Please ignore the generics related implications in the code.
You should use #Qualifier. It defines any subset that you need.
#Autowired
#Qualifier("MySubset")
private List<I> list;
But I think you should move your bean definitions in xml to use <qualifier ... /> property. I think you haven't another option to specify qualifier.
The #Qualifier annotation should give you what you need. You need to apply it in two places:
On the #Service beans that you wish to include in the sub-list
On the #Autowired list injected into your controller
So addressing the #Service beans first:
#Service
#Qualifier("MySubList")
public class MyService implements IMyService
{
}
And then within your Controller:
#Controller
public class MyController
{
#Qualifier("MySubList")
#AutoWired
private List<IMyService> myServices;
}
This instructs Spring to #AutoWire all IMyService implementations #Qualified as "MySubList"

How can I use same EJB in two different CDI beans and retrieve the values set from one bean into the another?

I have a stateful session bean where a list is maintained:
#Stateful
public class CartDAO{
private List<ShoppingCart> tempCart;
public void add(ShoppingCart shoppingCart){
tempCart.add(shoppingCart);
}
public List<ShoppingCart> getCart(){
return tempCart;
}
#PostConstruct
public void init(){
tempCart = new ArrayList<>();
}
}
Controller1 to add to the cart:
#Named
#SessionScoped
public class Controller1 implements Serializable {
#EJB
CartDAO cartDao;
public String addToShoppingCart() {
cartDao.add(shoppingCart);
}
}
Now, i want to ask you could i get the added items to the list from another cart?
#Named
#SessionScoped
public class Controller2 implements Serializable {
#EJB
CartDAO cartDao;
public String getShoppingCart() {
System.out.println(cartDao.getCart());//returns null
}
}
Obviously the above code returns null.
How do I retrieve the list from another controller. Any help will be much appreciated.
I don't see any obvious mistake here (are you sure that you don't call Controller2#getShoppingCart() before adding any items do your CartDAO?) but here are couple of my notions
you should have your CartDAO implement some interface or make it #LocalBean
all stateful beans should have method annotated with #Remove so you can clean the resources used in the bean (close datasources and son) and bean will be removed from the memory after this call
now it's recommended to use #Inject everywhere instead of #EJB, it's the same (you have to use #EJB only when you inject remote beans)
And also one point, if the System.out.println(cartDao.getCart()); returns null than it means the #PostConstruct haven't been called which is strange. Can you provide some more info about container and your environment?Also show us imports, this is big source of mistakes.

Seam Classes and #Asynchronous processing related issue

I have an Interface defined as:
public interface DocExporter{
public void exportDoc();
}
with two implementing classes defined as:
#Service(value="docExporter")
#Scope(value="BeanDefinition.SCOPE_PROTOTYPE)
public class PdfDocExporter implements DocExporter{
public void exportDoc(){
// do Pdf Export stuff
}
}
AND
#Service(value="docExporter")
#Scope(value="BeanDefinition.SCOPE_PROTOTYPE)
public class ExcelDocExporter implements DocExporter{
public void exportDoc(){
// do Excel Export stuff
}
}
So can I say like :
#Name("docExportReporter")
#Scope(ScopeType.EVENT)
public class DocExportReporter {
#In("#{docExporter}")
private DocExporter pdfDocExporter;
#In("#{docExporter}")
private DocExporter excelDocExporter;
#Asynchronous
public void reportGen(){
**excelDocExporter.exportDoc()** // THIS THROWS Seam Exception #In attribute requires a not null value
}
}
I am new to Seam with Spring and would like to know if in both impl classes #Service would have values as "docExporter" (name of interface) or would it be like "pdfDocExporter" "excelDocExporter" ?
And with the above, I get #In attribute requires a non null value exception when using pdfDocExporter or excelDocExporter objects within the reportGen async method. Can two implementations of an interface be declared in a third class and work fine
with Seam #Asynchronous annotation ?
You cannot have two components with the same name, otherwise Seam would not know which one to inject. Use two different names.

WELD-001408 Unsatisfied dependencies when injecting EJBs that implement interfaces

Here is the situation.
I've got the following interfaces:
public interface Parent { }
public interface ChildOne extends Parent { }
public interface ChildTwo extends Parent { }
and 2 EJBs:
#Stateless
public class FirstBean implements ChildOne { }
#Stateless
public class SecondBean implements ChildTwo { }
And also this CDI Bean:
#Named
#SessionScoped
public class TestController implements Serializable {
#Inject
private FirstBean firstBean;
#Inject
private SecondBean secondBean;
}
While trying to deploy this on Glassfish 3.1 I get the following exception:
Exception while loading the app : WELD-001408 Unsatisfied dependencies for type [FirstBean]
with qualifiers [#Default] at injection point [[field] #Inject private com.test.controllers.TestController.firstBean]
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [FirstBean]
with qualifiers [#Default] at injection point [[field] #Inject private com.test.controllers.TestController.firstBean]
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:305)
When both EJBs implement the Parent interface, the exception is the same.
Also, I tried adding qualifiers, but that didn't change anything.
I just played around with your construct, read a bit of the weld docu and found out the following.
You are using EJBs that implement an interface, so the no-interface view is not possible anymore (obviously), but you are trying to directly access the implementation. As soon as you declare it as an EJB you have to keep in mind the conventions. So, if you define an interface you have to use it to get access to the EJB. Changing it to the following, should work out:
#Inject
private ChildOne firstBean;
Accessing the implementation even though an interface is defined is just possible for plain CDI Managed Beans (classes without the #Stateless/#Stateful annotations). So get rid of your annotation and it will work out.
Just for your information, if you are using Glassfish. If you stick to your EJBs and try to access the parent interfaces method you will run into this bug / exception.
Better late than never:
Annotating the SLSB aditionally with #LocalBean works for me with JBoss AS 7.1.1. I don't like the idea of creating the interface for no added value.
Using your example:
#Stateless
#LocalBean
public class FirstBean implements ChildOne { }
#Stateless
#LocalBean
public class SecondBean implements ChildTwo { }
Have you tried using #EJB annotation rather then the CDI #inject annotation?
E.g.
#Named
#SessionScoped
public class TestController implements Serializable {
#EJB
private FirstBean firstBean;
#EJB
private SecondBean secondBean;
}

EJB 3.1. Is #Local annotation needed?

So far, I almost always worked with no-interface EJBs and have a slight understanding about the need of #Local annotation. Consider this example:
public interface MyBeanIntf { void doStuff(); }
#Stateless
public class MyBean implements MyBeanIntf { public void doStuff(){ } }
Should the MyBeanIntf be marked as #Local? I don't see any benefit from that, because even when I don't annotate it as #Local, I still can use DI to properly inject it into UI Controller:
#Named
#SessionScoped
public class TestController implements Serializable {
// injection works perfectly, even when MyBeanIntf is not marked as #Local
#Inject
private MyBeanIntf myBean;
// or even like this:
// #EJB
// private MyBeanIntf myBean;
}
Let's make it more complex:
public interface MyBeanIntf { void doStuff(); }
public class MySuperBean implements MyBeanIntf { public void doStuff() { } }
#Stateless
public class MyBean extends MySuperBean { }
Is MyBean now considered a valid Local EJB bean? I have some doubts because it implements the interface indirectly.
If your EJB implements some interface but you don't specify (neither on the EJB nor the interface itself) which interface it is (#Remote, #Local) than it's assumed that it's a #Local one.
Therefore your code:
public interface MyBeanIntf { void doStuff(); }
#Stateless
public class MyBean implements MyBeanIntf { public void doStuff(){ } }
is semantically identical to the following:
#Local
public interface MyBeanIntf { void doStuff(); }
#Stateless
public class MyBean implements MyBeanIntf { public void doStuff(){ } }
When it comes to the second part of your question, I think that section 4.9.2.1 Session Bean Superclasses from EJB 3.1 FR spec would be interesting for you. From my understanding (so it might not be correct), it seems that your bean should not be considered as exposing a valid Local interface because of the following excerpt:
#Stateless
public class A implements Foo { ... }
#Stateless
public class B extends A implements Bar { ... }
Assuming Foo and Bar are local business interfaces and there is no
associated deployment descriptor, session bean A exposes local
business interface Foo and session bean B exposes local business
interface Bar, but not Foo.
Session bean B would need to explicitly include Foo in its set of
exposed views for that interface to apply.
Update:
As an addition one more excerpt from the spec:
A session bean class is permitted to have superclasses that are
themselves session bean classes. However, there are no special rules
that apply to the processing of annotations or the deployment
descriptor for this case. For the purposes of processing a particular
session bean class, all superclass processing is identical regardless
of whether the superclasses are themselves session bean classes.

Resources