EJB3 instantiation - java

I got some propably trivial question.
If I got defined EJB3+ interface, lets say it's remote like that:
#Remote
public class FooServiceRemote {
void foo();
}
and one implementation
#Stateless
public class FooService implements FooServiceRemote {
void foo() { ... }
}
How does the application server by default resolves what implementation to use (and call via proxy) if he knows only #EJB annotation for dependency injection like on interface:
public class SomeClass {
#EJB
private FooServiceRemote fooService;
}
Is it done by reflection (shortening name of interface)? Or he scans possible implementations of such interface, choosing one. Or.. ? And what if I want to create more implementations of one interface, is it possible and how to specify what implementation should be instantiated (maybe it is possible via some argument of annotation).
Thanks:-)

In the rare case that you need to have two beans implementing the same interface (not a good practice), you can name them and choose which one you want by name.
#Stateless(name="FooService1")
public class FooService1 implements FooService { }
#Stateless(name="FooService2")
public class FooService2 implements FooService { }
public class SomeClass {
#EJB(beanName="FooService1")
private FooService fooService;
}
Other possible approaches are looking it up using JNDI or the mappedName property.
See the javadoc for EJB annotation here: http://download.oracle.com/javaee/6/api/javax/ejb/EJB.html

Just a fix,
#Remote
interface FooServiceRemote {
void foo();
}
#Stateless
public class FooService implements FooServiceRemote {
void foo() { ... }
}
With this, application server knows which classes implements the specified interface.
If you have two classes, you must specifify which class do you need.

Related

Spring boot inject bean at runtime based on request endpoint/request param

I have an interface that has two implementations, and I'd like to conditionally inject either of the two implementations in a spring boot service.
The point is that the eligible implementation should be picked up based on the request message (JSON mapped to a POJO).
My searches leaded me to implement a FactoryBean to control selecting between those two implementations, and to keep the factory telling spring that the beans are not singleton (by returning false for the isSingleton method).
But if this is the right way, I am still not sure how to get the request message to check it and return the right bean.
Can you please tell me if I am on the right track for what I am trying to attain?
=============
UPDATE
I do not want to pollute my code and deal with managing the relation between my service and the dependencies' implementation in the service.
Considering that I will need to deal with more implementations in the future, I need my service to care only about its responsibility.
I need my service to have only one reference of the generic interface and deal with it in an abstracted way.
I need to find a spring-based way to choose the right implementation for each request based on a condition that is derived from the request itself, and inject it in the service.
One option is to inject both beans and conditionally pick the required bean. You can autowire classes implementing same interface into a Map.
Following example uses a factory class to hide the conditional check.
#Component("type1")
public class Type1 implements SomeInterface{}
#Component("type2")
public class Type2 implements SomeInterface{}
#Component
public class MyTypeFactory {
#Autowired
private Map<String, SomeInterface> typesMap;
public SomeInterface getInstance(String condition){
return typesMap.get(condition);
}
}
#Component
public class MyService {
#Autowired
private MyTypeFactory factory;
public void method(String input){
factory.getInstance(input).callRequiredMethod();
}
}
You could #Autowire both beans in the controller and decided based on the request which one to return.
Consider the below interface:
public interface MyInterface { ... }
Sample config:
#Configuration
public class MyConfig {
#Bean("first")
public MyInterface firstBean() { ... }
#Bean("second")
public MyInterface secondBean() { ... }
}
Sample controller:
#RestController
public class MyController {
#Autowire
#Qualifier("first")
public MyInterface first;
#Autowire
#Qualifier("second")
public MyInterface second;
#GetMapping
public MyInterface doStuff(#RequestBody body) {
if(shouldReturnFirst(body)){
return first;
} else {
return second;
}
}
}
Note that you should most likely not do it this way though, but have a single service, say MyService that should implement this logic for you.
#Component
public class MyService {
public MyInterface doStuff(body) {
if(shouldReturnFirst(body)){
// build your response here
} else {
// build your response here
}
}
}
And just delegate to the service from the controller
#GetMapping
public MyInterface doStuff(#RequestBody body) {
return myService.doStuff(body);
}
Spring has a concept of Conditional Bean...
Have a look here https://www.intertech.com/Blog/spring-4-conditional-bean-configuration/

Change method based on environment

How can I switch between two method calls of the same name based on the environment?
I know that this can be done at the class level with #Profile, but is there a way to do this at the method level? So ideally, I would want something like the below snippet.
Example
public class Foo {
#Profile('local')
public void bar() {...}
#Profile('prod')
public void bar() {...}
Since Spring 4.x is possible newly to control the profile directly with annotating by #Profile on the method level.
... as a method-level annotation on any #Bean method
Personally, I do not use profiles on the method level, read more at Is Spring's #Profile on methods a good practice?
In your case, I rather suggest you the following approach:
Create two classes and make the implement the common interface.
public interface Foo {
public void bar();
}
Annotate each with #Profile based on the environment.
#Component
#Profile("local")
public class LocalFoo implements Foo {
#Override
public void bar() { ... }
}
#Component
#Profile("prod")
public class ProdFoo implements Foo {
#Override
public void bar() { ... }
}
Since now, they are ready to be injected according to the active profile.

Spring autowire priority with more than two layers

How am I able to override an autowired bean more than once? Consider this 3-layer construct:
Library 1 defines an interface and a default implementation.
public interface Foo {}
#Component
public class FooImpl1 implements Foo {}
Throughout all 3 layers the interface will be used for autowiring.
#Autowired
private Foo foo;
Library 2 depends on library 1 and provides its own implementation which has to override the first one, i.e. be autowired into existing code of library 1.
#Component
public class FooImpl2 implements Foo {}
The actual application depends on library 2 and also provides another implementation that has to override the former one.
#Component
public class FooImpl3 implements Foo {}
How do I configure this? If there were only two layers, I could use #Primary but this doesn't work with more than two layers because #Primary can't be overriden again. Is there a more fine-grained way of prioritizing beans that I'm overlooking or can I accomplish a second override using a #Configuration or do you simply can not overide a bean more than once and I have to resort to some kind of static helper like FooProvider.getFoo() instead of autowiring?
Maybe is not the case, however when you have more than one implementation and want to establish some kind of ordination, existe the annotation #order
#order(3)
#Component
public class FooImpl1 implements Foo {}
#order(1)
#Component
public class FooImpl2 implements Foo {}
#order(2)
#Component
public class FooImpl3 implements Foo {}
public class PrintFoo {
List<Foo> fooList;
#autowired
public PrintFoo() {
for(Foo fooImpl: fooList) {
System.out.println(fooImpl.getClass().getSimpleName());
}
}
the output should be:
FooImpl2
FooImpl3
FooImpl1

#inject doesn't work when the bean is not created via hk2

I have been trying to inject a service to a contract:
#org.jvnet.hk2.annotations.Contract
public interface CategoryDAO{
}
#org.jvnet.hk2.annotations.Service
public class HibernateCategoryDAO implements CategoryDAO
}
#org.jvnet.hk2.annotations.Service
public class MyCategoryManager implements CategoryManager {
#javax.inject.Inject
CategoryDAO categoryDAO;
}
But categoryDAO is null.
I tried even to bind it:
public class ServiceBinder implements Binder {
#Override
public void bind(DynamicConfiguration config) {
config.bind(BuilderHelper.link(HibernateCategoryDAO.class).to(CategoryDAO.class).build());
}
}
But still it stays null.
I init the MyCategoryManager with Reflections framework like this:
Set<?> managers = Reflections.getSubTypesOf(CategoryManager.class);
If you create your own object but still want it injected with hk2 you can use the ServiceLocator.inject method. In your case the descriptor HibernateCategoryDAO must be already in the ServiceLocator (perhaps using ServiceLocatorUtilities.addClass). Be aware that the instances you created yourself will not be managed or tracked by HK2 so they cannot be injected into other objects. Of course, you can add the objects you created yourself using ServiceLocatorUtilities.addOneConstant if you DO want it to be injected into other objects.
Hope that helps.

Spring 3.2 Autowire generic types

So I have a number of generics in Spring 3.2 and ideally my architecture would look something like this.
class GenericDao<T>{}
class GenericService<T, T_DAO extends GenericDao<T>>
{
// FAILS
#Autowired
T_DAO;
}
#Component
class Foo{}
#Repository
class FooDao extends GenericDao<Foo>{}
#Service
FooService extends GenericService<Foo, FooDao>{}
Unfortunately with multiple implementations of the generics the autowiring throws an error about multiple matching bean definitions. I assume this is because #Autowired processes before type erasure. Every solution I've found or come up with looks ugly to me or just inexplicably refuses to work. What is the best way around this problem?
How about adding a constructor to the GenericService and move the autowiring to the extending class, e.g.
class GenericService<T, T_DAO extends GenericDao<T>> {
private final T_DAO tDao;
GenericService(T_DAO tDao) {
this.tDao = tDao;
}
}
#Service
FooService extends GenericService<Foo, FooDao> {
#Autowired
FooService(FooDao fooDao) {
super(fooDao);
}
}
Update:
As of Spring 4.0 RC1, it is possible to autowire based on generic type, which means that you can write a generic service like
class GenericService<T, T_DAO extends GenericDao<T>> {
#Autowired
private T_DAO tDao;
}
and create multiple different Spring beans of it like:
#Service
class FooService extends GenericService<Foo, FooDao> {
}
Here is a closest solution. The specialized DAOs are annotated at the business layer. As in the question from OP, the best effort would be having an annotated DAO in the EntityDAO generic template itself. Type erasure seems to be not allowing the specialized type information to get passed onto the spring factories [resulting in reporting matching beans from all the specialized DAOs]
The Generic Entity DAO template
public class EntityDAO<T>
{
#Autowired
SessionFactory factory;
public Session getCurrentSession()
{
return factory.getCurrentSession();
}
public void create(T record)
{
getCurrentSession().save(record);
}
public void update(T record)
{
getCurrentSession().update(record);
}
public void delete(T record)
{
getCurrentSession().delete(record);
}
public void persist(T record)
{
getCurrentSession().saveOrUpdate(record);
}
public T get(Class<T> clazz, Integer id)
{
return (T) getCurrentSession().get(clazz, id);
}
}
The Generic Entity Based Business Layer Template
public abstract class EntityBusinessService<T>
implements Serializable
{
public abstract EntityDAO<T> getDAO();
//Rest of code.
}
An Example Specialized Entity DAO
#Transactional
#Repository
public class UserDAO
extends EntityDAO<User>
{
}
An Example Specialized Entity Business Class
#Transactional
#Service
#Scope("prototype")
public class UserBusinessService
extends EntityBusinessService<User>
{
#Autowired
UserDAO dao;
#Override
public EntityDAO<User> getDAO()
{
return dao;
}
//Rest of code
}
You can remove the #autowire annotation and perform delayed “autowire” using #PostConstruct and ServiceLocatorFactoryBean.
Your GenericService will look similar to this
public class GenericService<T, T_DAO extends GenericDao<T>>{
#Autowired
private DaoLocator daoLocatorFactoryBean;
//No need to autowried, autowireDao() will do this for you
T_DAO dao;
#SuppressWarnings("unchecked")
#PostConstruct
protected void autowireDao(){
//Read the actual class at run time
final Type type;
type = ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[1];
//figure out the class of the fully qualified class name
//this way you can know the bean name to look for
final String typeClass = type.toString();
String daoName = typeClass.substring(typeClass.lastIndexOf('.')+1
,typeClass.length());
daoName = Character.toLowerCase(daoName.charAt(0)) + daoName.substring(1);
this.dao = (T_DAO) daoLocatorFactoryBean.lookup(daoName);
}
daoLocatorFactoryBean does the magic for you.
In order to use it you need to add an interface similar to the one below:
public interface DaoLocator {
public GenericDao<?> lookup(String serviceName);
}
You need to add the following snippet to your applicationContext.xml
<bean id="daoLocatorFactoryBean"
class="org.springframework.beans.factory.config.ServiceLocatorFactoryBean">
<property name="serviceLocatorInterface"
value="org.haim.springframwork.stackoverflow.DaoLocator" />
</bean>
This is a nice trick and it will save you little boilerplate classes.
B.T.W I do not see this boilerplate code as a big issue and the project I working for uses matsev approach.
Why do you want a generic service ? Service classes are meant for specific units of work involving multple entities. You can just inject a repository straight into a controller.
Here is an example of generic repository with constructor argument, you could also make each method Generic instead and have no constructor argument. But each method call would require class as parameter:
public class DomainRepository<T> {
#Resource(name = "sessionFactory")
protected SessionFactory sessionFactory;
public DomainRepository(Class genericType) {
this.genericType = genericType;
}
#Transactional(readOnly = true)
public T get(final long id) {
return (T) sessionFactory.getCurrentSession().get(genericType, id);
}
Example of bean definition for the generic repository - you could have multple different beans, using different contstructor args.
<bean id="tagRepository" class="com.yourcompnay.data.DomainRepository">
<constructor-arg value="com.yourcompnay.domain.Tag"/>
</bean>
Depdncy injection of bean using resource annotation
#Resource(name = "tagRepository")
private DomainRepository<Tag> tagRepository;
And this allows the Domainreposiroty to be subclassed for specific entities/methods, which woul dallow autowiring :
public class PersonRepository extends DomainRepository<Person> {
public PersonRepository(){
super(Person.class);
}
...
You should use autowiring in classes which extends these generics
For this question one needs to understand about what autowire is. In common terms we can say that through autowire we create a object instance/bean at the time of deployment of the web app. So now going with the question if you are declaring autowiring in multiple places with the same name. Then this error comes. Autowiring can be done in multiple ways so if you are using multiple type of autowiring technique, then also one could get this error.
Complete Generic Solution using Spring 4:
Domain Class
#Component
class Foo{
}
#Component
class Bar{
}
DAO Layer
interface GenericDao<T>{
//list of methods
}
class GenericDaoImpl<T> implements GenericDao<T>{
#Autowired
SessionFactory factory;
private Class<T> domainClass; // Get Class Type of <T>
public Session getCurrentSession(){
return factory.getCurrentSession();
}
public DaoImpl() {
this.domainClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), DaoImpl.class);
}
//implementation of methods
}
interface FooDao extends GenericDao<Foo>{
//Define extra methods if required
}
interface BarDao extends GenericDao<Bar>{
//Define extra methods if required
}
#Repository
class FooDao extends GenericDaoImpl<Foo> implements FooDao{
//implementation of extra methods
}
#Repository
class BarDao extends GenericDaoImpl<Bar> implements BarDao{
//implementation of extra methods
}
Service Layer
interface GenericService<T>{
//List of methods
}
class GenericServiceImpl<T> implements GenericService<T>{
#Autowire
protected GenericDao<T> dao; //used to access DAO layer
}
class FooService extends GenericService<Foo>{
//Add extra methods of required
}
class BarService extends GenericService<Bar>{
//Add extra methods of required
}
#Service
class FooServiceImpl extends GenericServiceImpl<Foo> implements GenericService<Foo>{
//implementation of extra methods
}
#Service
class BarServiceImpl extends GenericServiceImpl<Bar> implements GenericService<Bar>{
//implementation of extra methods
}

Categories

Resources