Injecting dependent bean - java

I have a class
EntiyFacadeImpl.java
#Stateless
public class EntityFacadeImpl implements EntityFacade {
#EJB
ICustomerBean customerBean;
public void printCustomer(Customer c) {
customerBean.printCustomer(c);
customerBean.additionalFieldsHandler(c.getAdditionalFields().toString());
}
}
Where ICustomerBean is #Local interface and have two implementation classes CustomerBean.java and CustomerBeanExt.java where later one extends CustomerBean.java
#Stateless(name = "CustomerBean")
public class CustomerBean implements ICustomerBean {
public void printCustomer(Customer customer) {
System.out.println(customer);
}
public void additionalFieldsHandler(String additionalFields) {
// an empty implemetation here
}
}
#Stateless(name = "CustomerExtBean")
public class CustomerExtBean extends CustomerBean implements ICustomerBean {
#Override
public void additionalFieldsHandler(String additionalFields) {
// some custom implemetation
System.out.println("Additional Fields: "+additionalFields);
}
}
ICustomer interface looks like this
#Local
public interface ICustomerBean {
public void printCustomer(Customer c);
public void additionalFieldsHandler(String additionalFields);
}
My aim is that whenever I inject my EntityFacade (interface for EntityFacadeImpl) in SimpleRESTPojo.java only, I want CustomerExtBean to be inject in it, while when any other class injects it I want CustomerBean to be injected
#Path("/pojo")
public class SimpleRESTPojo {
#EJB
private EntityFacade entityFacade;
}
My app's entry point is EntityFacade only. Is there a way to achieve this?

Actually, after reading your question, it looks like you're trying to introduce tight coupling. CDI doesn't make EntityFacade aware of where it was injected in to. I don't see a way to do this.
What you could do is create an extended version of EntityFacade that used this injection point:
#Inject
#Extended //or whatever qualifier you come up with
private ICustomerBean customerBean;
and then use that same qualifier on the extended EntityFacade.

Related

Java: using inheritance if only constructor differs

I need to implement the same sequence of commands in a service, but operating on several different database objects, depending on a case. I'm wondering whether it is a good practice to use an inheritance in such case - which would consist in passing a different dao in a specifc class's constructor only. Something like this:
public abstract class Service{
private Dao dao;
public Service(Dao dao){
this.dao = dao;
}
public void mainMethod(){
dao.step1();
subMethod();
dao.step2();
}
public void subMethod(){
//...
}
}
public class ServiceImpl1 extends Service{
public ServiceImpl1(DaoImpl1 daoImpl1){
super(daoImpl1);
}
}
Inheritance is useful for delegating messages (method calls) to the superclass with few changes. You're not delegating messages to the parent class though, you're changing the parameter of the constructor. So there is no need to inherit anything.
This is fine:
public class Service{
private Dao dao;
public Service(Dao dao){
this.dao = dao;
}
public void mainMethod(){
dao.step1();
subMethod();
dao.step2();
}
public void subMethod(){
//...
}
}
You can then make instances like
Service posgresService = new Service(new PosgresDao());
Service redisService = new Service(new RedisDao());
See depenency injection for more details
I think that if -sequence of commands- refers to the exact same commands, I think you should create overloaded methods such as: if not, inheritance would be a good choice in order to keep orden in the code.
Since you are talking about inheritance and from the sample code provide, it seems like there will be one ServiceImpl class for each DaoImpl class. It will work, however you could also settle with a single ServiceImpl class for all Dao classes:
public class ServiceImpl implements Service {
public void mainMethod(Dao dao) {
dao.step1();
subMethod();
dao.step2();
}
public void subMethod() {
// ...
}
}
elsewhere
Service service = new ServiceImpl();
// ...
Dao dao1 = new DaoImpl1();
Dao dao2 = new DaoImpl2();
// ...
service.mainMethod(dao1);
service.mainMethod(dao2);

what is the best way to autowire parent class field in spring?

When I use spring framework, I find something that should be extract, for example, the service component (or member variable that is autowired).
Code show as below:
abstract class Payment {
PaymentService paymentService;
void setPaymentService(OrderPaymentService paymentService) {
this.paymentService = paymentService;
}
}
#Component
public class CancelPayment extends Payment{
private OtherService2 otherSerivce2;
#Autowired
#Override
public void setPaymentService(PaymentService paymentService) {
super.setPaymentService(paymentService);
}
#Autowired
public CancelPayment(OtherService2 s2) {
this.otherSerivce2 = s2;
}
}
#Component
public class CreatePayment extends Payment{
private OtherService1 otherSerivce1;
#Autowired
#Override
public void setPaymentService(PaymentService paymentService) {
super.setPaymentService(paymentService);
}
#Autowired
public CreatePayment (OtherService1 s1) {
this.otherSerivce1 = s1;
}
}
As you can see, I use setter injection in each child class. Is this a better practice than autowire their parent's member variable?
Here are DI guidelines by Spring team:
A general guideline, which is recommended by Spring (see the sections on Constructor-based DI or Setter-based DI) is the following:
For mandatory dependencies or when aiming for immutability, use
constructor injection
For optional or changeable dependencies, use setter injection
Avoid field injection in most cases
Now if you are sure you will use PaymentService I would suggest you to use constructor injection in your abstract class like this so object won't instantiate without dependency, also making it more immutable, clearer and thread safe:
abstract class Payment {
PaymentService paymentService;
public Payment(OrderPaymentService paymentService) {
this.paymentService = paymentService;
}
}
Then you can simply call super on your extended classes like this:
#Component
public class CreatePayment extends Payment{
private OtherService1 otherSerivce1;
#Autowired
public CreatePayment(PaymentService paymentService) {
super(paymentService);
}
}
This simply allows you to inject parent class using constructor (if paymentService is mandatory).

How to specify which version of a concrete implementation for an abstract class to autowire in Spring?

Having the following class structure:
public abstract class A {
String someProperty = "property"
public abstract void doSomething();
}
#Service
public class Aa extends A {
#Override
public abstract void doSomething() {
System.out.println("I did");
}
}
#Service
public class Ab extends A {
#Override
public abstract void doSomething() {
System.out.println("I did something else");
}
}
I need a way to tell Spring which A concrete class to Autowire in my Foo service, based on a property in a properties file.
#Service
public class Foo {
#Autowire
private A assignMeAConcreteClass;
}
And in my properties file I have this:
should-Aa-be-used: {true, false}
Remove the #Service annotation, instead write a #Bean-annotated method in a configuration class that reads the properties, and returns the appropriate A instance.
Not a new way but in your case I think that a possible suitable way would be to use
FactoryBean in the class that wants to inject the bean conditionally.
The idea is simple : you implement FactoryBean by parameterizing it with the interface of the bean that you want to inject and override getObject() to inject the wished implementation :
public class FactoryBeanA implements FactoryBean<A> {
#Autowired
private ApplicationContext applicationContext;
#Value("${should-Aa-be-used}")
private boolean shouldBeUsed;
#Override
public A getObject() {
if (shouldBeUsed) {
return applicationContext.getBean(Aa.class));
return applicationContext.getBean(Ab.class));
}
}
But FactoryBean instances are not classic beans. You have to configure it specifically.
You could configure it in a Spring Java configuration in this way :
#Configuration
public class FactoryBeanAConfiguration{
#Bean(name = "factoryBeanA")
public FactoryBeanA factoryBeanA() {
return new FactoryBeanA();
}
#Bean
public beanA() throws Exception {
return factoryBeanA().getObject();
}
}

Spring injected beans null in nested class

I have a class with 2 static nested classes that do the same operation on 2 different generic types.
I exposed the 2 classes as beans and added #Autowired for the constructors as I usually do.
Here is the basic setup
abstract class <T> Parent implements MyInterface<T> {
private final Service service;
Parent(Service service){ this.service = service; }
#Override public final void doInterfaceThing(T thing){
T correctedT = map(thing);
service.doTheThing(correctedT);
}
protected abstract T map(T t);
#Service
public static class ImplA extends Parent<A> {
#Autowired ImplA (Service service){ super(service); }
A map(A a){ //map a }
}
#Service
public static class ImplB extends Parent<B> {
#Autowired ImplB (Service service){ super(service); }
B map(B b){ //map b }
}
}
And in another class I have
#Service
public class Doer {
private final List<MyInterface<A>> aImpls;
#Autowired public Doer(List<MyInterface<A>> aImpls){ this.aImpls = aImpls; }
public void doImportantThingWithA(A a){
aImpls.get(0).doInterfaceThing(a);
}
}
When I run the app, everything appears to be injected correctly and when I put a breakpoint in the ImplA and ImplB constructors, I have a not-null value for "service". I also have an ImplA bean in the aImpls list in Doer.
When I call doImportantThingWithA(a) however, "service" is null inside ImplA and I obviously die.
I'm not sure how this is possible because:
I see a nonnull value in my constructors for service which is a final field.
If spring is injecting ImplA and ImplB into another class, it should already have either injected a Service into ImplA or ImplB, or thrown an exception on bean initialization. I have nothing set to lazily load and all bean dependencies are required.
The reason for the nested classes is because the only thing that changes between the 2 implementations is the map() function. Trying to avoid extra classes for 1 line of varying code.
More info:
When I add a breakpoint in Parent.doInterfaceThing(), if I add a watch on "service" I get null as the value. If I add a getService() method, and then call getService() instead of referring directly to this.service, I get the correct bean for service. I don't know the implications of this but something seems weird with the proxying.
It looks like what is causing the issue is Parent.doInterfaceThing();
If I remove final from the method signature, "service" field is correctly populated and the code works as expected.
I don't understand at all why changing a method signature affects the injected value of final fields in my class... but it works now.
What I meant with my "use mappers" comment was something like this:
class MyInterfaceImpl implements MyInterface {
#Autowired
private final Service service;
#Override public final <T> void doInterfaceThing(T thing, UnaryOperator<T> mapper){
T correctedT = mapper.apply(thing);
service.doTheThing(correctedT);
}
// new interface to allow autowiring despite type erasure
public interface MapperA extends UnaryOperator<A> {
public A map(A toMap);
default A apply(A a){ map(a); }
}
#Component
static class AMapper implements MapperA {
public A map(A a) { // ... }
}
public interface MapperB extends UnaryOperator<B> {
public B map(B toMap);
default B apply(B b){ map(b); }
}
#Component
static class BMapper implements MapperB {
public B map(B a) { // ... }
}
}
This does have a few more lines than the original, but not much; however, you do have a better Separation of Concern. I do wonder how autowiring works in your code with the generics, it does look as if that might cause problems.
Your client would look like this:
#Service
public class Doer {
private final List<MapperA> aMappers;
private final MyInterface myInterface;
#Autowired public Doer(MyInterface if, List<MapperA> mappers){
this.myInterface = if;
this.aImpls = mappers; }
public void doImportantThingWithA(A a){
aMappers.stream().map(m -> m.map(a)).forEach(myInterface::doInterfaceThing);
}
}

Polymorphic EJB client

I am using EJB 3.1 and jersey for a restapi. I would like to have a SuperResource as below, which is then inherited by the actual rest resources as below. The way I have it now, my #EJB object is null. Does anyone know how to fix this?
#Stateless
public class SuperResource {
#EJB
protected GenericDao<DomainObject> dao;
. . .
}
public class MyResource extends SuperResource{
public String doGet(){
return dao.get(...);
}
}
I have tried the whole truth table between #Stateless and #Local, and SuperResource and MyResource. None of the permutations seems to work.
I don't know if that's important, my server is Glassfish 3.1.2
EDIT TO ADD DETAILS:
I didn't think so , but it seems that more detail may be necessary here:
Structure of my application:
#Local
public interface GenericDao<T extends DomainObject> {…}
public interface LoginDao extends GenericDao<Login>{...}
#Stateless
public class GenericDaoImpl<T extends DomainObject> implements GenericDao<T> {…}
#Stateless
public class LoginDaoImpl extends GenericDaoImpl<Login> implements LoginDao {…}
#Entity
public class Login implements java.io.Serializable, DomainObject {…}
What works:
#Stateless
#Path("mypath")
public class MyResource{  
#EJB
private LoginDao dao; 
public String doGet(){
return dao.get(...);
}
}
MyResource has to be an EJB bean as well, by annotating it with #Stateless:
#Stateless
public class MyResource extends SuperResource{
public String doGet(){
return dao.get(...);
}
}
If you only need the injected DAO, you could choose to inject your JAX-RS resource with that DAO using CDI instead. If you resources -becomes- a stateless bean, then this has certain consequences that you need to be aware of (like a transaction that starts for every method, unless you explicitly disable that, etc).
It looks like EJB injection issue. Depending on Server, you need to play around mappedName/name/beanName
What I can confirm is that, the following code works on JBoss 7.1.1.
#Local
public interface HelloWorldLocal {
public String sayHello();
}
#Stateless
public class HelloWorldBean implements HelloWorldLocal {
public String sayHello(){
return "Hello..............................................................................";
}
}
#Remote
public interface BaseRemote {
public String test();
}
#Stateless
public class BaseBean implements BaseRemote{
#EJB
HelloWorldLocal bean;
public String test() {
return "Base Bean";
}
}
#Remote
public interface DerivedRemote {
String test();
}
#Stateful
public class DerivedBean extends BaseBean implements DerivedRemote{
public String test() {
return bean.sayHello();
}
}

Categories