Dependency inversion in EJB based application - java

I want to make some of parts my JEE application independent from others ones using dependency inversion and dependency injection. Below is some code of main core part, that uses MyService, but is independent from other module that should provide implementation of MyService.
public interface MyService {
public void send(MyObject myObject);
}
.
#Stateless
#LocalBean
public class MyServiceWrapper implements MyService {
#Inject
private MyService myService;
#Override
public void send(MyObject myObject) {
myService.send(myObject);
}
}
To clarify:
Module A contains classes:
MyObject,
MyService,
MyServiceWrapper,
Module B contains implementation of MyService.
I want MyServiceWrapper to have injected implementation of MyService provided by module B, so module A can call implementation of MyService by using MyServiceWrapper, but in te same time module A is independent from module B.
The problem with above code, is that container do not know which implementation of MyService should be injected.
How it should be written so MyServiceWrapper, so it won't be injected to itself, but proper implementation (provided in other module) will be injected instead?

The correct way would be to use what is known as a Qualifier , one example from CDI would be the annotation #Named, this would get rid of ambiguity for the container.
public interface MyService {
void send(MyObject myObject);
}
and the implementation of MyService :
#Named("fromModuleA")
#ApplicationScoped
public class MyServiceWrapper implements MyService {
#Inject
#Named("fromModuleB")
private MyService someOtherBean;
#Override
public void send(MyObject myObject) {
this.someOtherBean.send(myObject);
}
}
#Named("fromModuleB")
#ApplicationScoped
public class SomeOtherBeanFromModuleB implements MyService{
#Override
public void send(MyObject myObject) {
// implementation
}
}
The #Inject comes from a Java specification called CDI (Context and Dependency Injection), with this annotation it doesn't matter whether you use it on EJBs or CDI beans, but #EJB will only work with the EJB Container. Also note you don't really need the Interface MyService at least not anymore but it's a good practice to code to the interface.

Related

Dynamically inject service implementation with Spring

I've already gone through some tips on how to do this, like this one: stack overflow; but my problem is that my own implementation needs other things to be injected in it. Here's the example:
public interface MyService {}
public class ServiceImplA implements MyService {
#Autowired
private final SomeStuffA a_stuff;
}
public class ServiceImplB implements MyService {
#Autowired
private final SomeStuffB b_stuff;
}
#Configuration
public class SpringConfig {
#Bean
#Scope("singleton")
public MyService getService() {
boolean useA = // read config file and decide impl
return useA ? new ServiceImplA() : new ServiceImplB();
// I can't instantiate this, so i need them to be injected as well
}
}
I'm familiar with Google Guice, where I would do something like this:
bind(MyServicle.class).to(useA ? ServiceImplA.class : ServiceImplB.class);
So, I need a way to do this using Spring
I think your problem is that your base class MyService is not marked for any profile.
When you define profile the beans that have such specification will override beans that implement the same interface and do not have profile definition. This does not work this way.
When working with active profile X spring starts all beans that are not targeted for any profile and beans targeted for current profile. In your case you can choose wisely.
I think that if you want to use profiles you should define at least 2: A and B (the names are taken just for example.)
Now mark ServiceImplA as A and ServiceImplB as B:
#Service
#Profile("A")
public ServiceImplA interface MyService { ... }
and some development implementation
#Service
#Profile("B")
public ServiceImplB interface MyService { ... }
More about profiling you will get here

EJB override injection of abstract bean

I have an abstract bean with injected ISomeOtherBean interface:
public abstract class AbstractBean {
#EJB ISomeOtherBean myService;
}
The ISomeOtherBean is interface. He have many implementations, for example: SomeBeanA, SomeBeanB...
#Stateless
public class SomeBeanA implements ISomeOtherBean {
}
#Stateless
public class SomeBeanB implements ISomeOtherBean {
}
How can I inject concrete implementation of ISomeOtherBean inside some implementation of the AbstractBean?
#Stateless
public class BeanImpl extends AbstractBean {
// how write that I want inject SomeBeanB which implements ISomeOtherBean
}
First i tried to inject concrete implementation inside BeanImpl, then I passed it to additional method of superclass (Abstractbean) which writed it to field myService.
But this solution is bad for me. I remember Spring has ability to pass some beans to constructor of given bean. But it was inside XML configuration. I want something like this, but with EJB and annotation configurations.
Anyone knows how do it?

Injecting EJB via interface in Wildfly application

I am using wildfly 10.1.0 and JavaEE 7
I've got this interface:
public interface TestEjb {
String something();
}
and this Ejb class implementing it:
#LocalBean
#Stateless
public class TestEjbImpl implements TestEjb {
#Override
public String something() {
return "Hello world";
}
}
When I am injecting it to my #Path annotated jax-rs class using
#Inject
private TestEjb testEjb;
It gives an error saying "WELD-001408: Unsatisfied dependencies for type TestEjb with qualifiers #Default"
But when I inject it like
#Inject
private TestEjbImpl testEjb;
it works fine.
And which is surprising both ways work with no problems in jboss-eap-6.4. But why?
First of all, you are mixing CDI injection with EJB injection. Rather use #EJB (instead of #Inject) when injecting your EJB.
#LocalBean has a no-interface view. So, you have an interface with no view annotation and a bean with a no-interface view annotation. The EJB Container understands it as a no interface view.
The best way will be to annotate the TestEjb interface with #Local view and remove the #LocalBean from the TestEjbImpl implementation in order for your solution to work.
Interface
#Local
public interface TestEjb {
String something();
}
EJB
#Stateless
public class TestEjbImpl implements TestEjb {
#Override
public String something() {
return "Hello world";
}
}
Injection time
#EJB
private TestEjb testEjb;
I hope this helps.
Further reading...

How to provide a default bean in Spring by condition?

I'd like to provide a default bean by a custom jar. Only if the user implements a specific abstract class the default bean injection should be skipped.
The following setup already works fine, except one thing: any injected classes within the default wired class are null! What might I be missing?
#Configration
public class AppConfig {
//use the default service if the user does not provide an own implementation
#Bean
#Conditional(MissingServiceBean.class)
public MyService myService() {
return new MyService() {};
}
}
#Component
public abstract class MyService {
#Autowired
private SomeOtherService other;
//default impl of the method, that may be overridden
public void run() {
System.out.println(other); //null! Why?
}
}
public class MissingServiceBean implements Condition {
#Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getBeanFactory().getBeansOfType(MyService.class).isEmpty();
}
}
The MyService bean is created and can also be injected. But contained classes are null.
If I remove the #Conditioanl annotation everything works as expected.
Your simplest possibility is the usage of the #Primary annotation. You define your interface/abstract class and build a default implementation. Until here thats the basic spring autowiring.
Now you create another implementation with #Primary and make it available in the application context. Spring will now pick up the primary implementation for the autowiring.
Another possibilty in Spring 4.1+ would be to autowire an ordered List<Intf> and ask the interface with a supports(...) call to fetch the current implementation for whatever parameter you give into supports. You give the default implementation a low priority and the more detailed ones a higher priority. Like this you can even build a more detailed default behavior. I'm using this approach for several configurations to handle different classes with default and specific implementations.
One example would be during permission evaluation where we have a default config for the base classes, another higher one for domain classes, and a even higher possible one for specific domain entities. The permission evaluator goes through the list and checks each implementation if it supports that class and delegates to the implementation in that case.
I dont have the code here but i could share it later if desired to make that more clear.
Change your code to the following:
public abstract class MyService {
private final SomeOtherService other;
public MyService(SomeOtherService other) {
this.other = other;
}
//default impl of the method, that may be overridden
public void run() {
System.out.println(other);
}
}
#Configration
public class AppConfig {
#Autowired
private SomeOtherService other;
//use the default service if the user does not provide an own implementation
#Bean
#Condition(MissingServiceBean.class)
public MyService myService() {
return new MyService(other) {};
}
}

What's the proper way to inject Entity-based classes in Spring IoC

Please bear with me:
We have a setup of Hibernate and Spring IoC, in which for each entity (User, Customer, Account, Payment, Coupon, etc) there's a bunch of "singleton" interfaces and implementation classes that support it.
For example: forCustomer:
#Entity
public class Customer extends BaseEntity {
...
public name();
}
/* base API */
public interface Service {
public create();
public list();
public find();
public update();
public delete();
}
/* specific API */
public interface CustomerService extends Service {
public findByName();
}
/* specific implementation */
public class CustomerServiceImpl extends BaseService implements CustomerService {
...
}
And this pattern goes on and on (CustomerManager, CustomerDataProvider, CustomerRenderer, etc.).
finally, in order work against an instance of a specific API (e.g. CustomerService.findByName()), a static global holder had evolved - which makes references like the following available:
public class ContextHolder {
private static AbstractApplicationContext appContext;
public static final CustomerService getCustomerService() {
return appContext.getBean(CustomerService.class);
}
//... omitting methods for each entity class X supporting class
}
#Configuration
public class ServicesConfiguration {
#Bean(name = "customerService")
#Lazy(false)
public CustomerService CustomerService() {
return new CustomerServiceImpl();
}
//... omitting methods for each entity class X supporting class
}
So, the question is:
what would be the proper way to inject those supporting classes, e.g. CustomerService, given an entity instance, for the following uses:
I have a specific entity (e.g. a Customer), and would like to get a service and call a specific API (e.g. findByName())?
I have an entity (don't care which one in specific), and would like to call a general API (e.g. find())
All this, while avoiding global static references (and thus, swap implementations in e.g. tests, and simplify the caller code).
So i can get a any supporting class if I have an entity instance
BaseEntity entity = ... // not injected
Iservice service = ...// should be injected
service.create(entity);
or, get all the supporting classes I need for a given entity type
/* specific implementation */
public class CustomerServiceImpl extends BaseService implements CustomerService {
// inject specific supporting classes
#Autowire CustomerManager manager;
#Autowire CustomerDataProvider provider;
#Autowire CustomerRenderer renderer;
#Autowire CustomerHelper helper;
...
}
and, change the configuration a bit in other scenarios
// how to configure Spring to inject this double?
Class CustomerManagerDouble extends CustomerManager {...}
#Autowired #Test public void testSpecificAPI(CustomerService service) {
service.doSomethingSpecific();
assert ((CustomerManagerDouble) service.getManager()).checkSomething();
}
I'm not entirely sure what you're asking, but I think you want to inject entity objects (created by Hibernate) with services, right?
If that's the case, use the #Configurable annotation as described in the Spring 3.1 documentation:
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/aop.html#aop-atconfigurable
Note that you have to use AspectJ to weave the entity classes (load-time or compile-time) for this to work.

Categories