-2

Most Java EE guidelines suggest that we should define Abstract EJB services (APIs) and then define concrete implementations in order to conform with OO design principles.

But at the injection point, either the EJB is Local or Remote, we are forced to provide the concrete implementation class.

Eg:

@EJB(jndi="java:global/moduleName/ConcreteClassName:fullyQualifiedInterfaceName")
ServiceI service;

Therefore, the question: How on earth does this injection maintains Inversion of Control and one step further: How this may be polymorphic?

EDIT:

Having realized that the question might not be clear, I will try to give an example.

Let us have a system that must calculate salaries for employees. Two salary types exist for now, by it is highly possible that a third will come:

public class Employee{
    String name;
    SalaryCalcService salaryService;
}

public interface SalaryCalcService {
  public double abstract calculateSalary();
}

public class PerMonthCalc implements SalaryCalcService {
  public double calculateSalary(){
     //return salary with per month calculations
  }
}

public class PerHourCalc implements SalaryCalcService {
  public double calculateSalary(){
     //return salary with per hour calculations
  }
}

Somewhere in the system concrete objects are created:

SalaryCalcService perMonth = new PerMonthCalc();
SalaryCalcService perHour = new PerHourCalc();

During system everyday work, new employees are created:

Employee emp1 = new Employee();
emp1.serSalaryService(perMonth);
 //...

And finally, client code needs to use all these entities and run a calculation for payments:

for(Employee emp : employees){
   double salary = emp.getSalaryService().calculateSalary();
}

In the client code, i don't have to know, neither care about what's the specific implementation of SalaryCalcService is.

More importantly, if a third salary calculation method will come. I will just create a third SalaryCalcService subclass and modify the point where the Concrete objects are created. NO CLIENT CODE WILL BE MODIFIED.

How can i implement this on an Java EE environment, where the service performs DB and other transactions and has to be an EJB?

  • 3
    If you can explain why you think this is not polymorphic, you will likely get better responses. – JimmyJames Jun 22 '18 at 18:30
  • 1
    I'm not actually sure this deserves down votes... I think we have a question here, it's just difficult to see the problem that the OP is seeing. – Greg Burghardt Jun 22 '18 at 19:00
  • @Theodore: is it because you must provide the concrete implementation you want as an annotation above the property in the class that wants to use an interface? – Greg Burghardt Jun 22 '18 at 19:02
  • Enterprise Java Beans is not a great design to begin with. It's mostly a pragmatic solution to a pragmatic problem. I'm not sure applying lofty design principles to it is productive. – Robert Harvey Jun 22 '18 at 19:14
  • 1
    @GregBurghardt in that case surely the question is unclear, which is one of the reasons the tooltip suggests for down voting? – jonrsharpe Jun 22 '18 at 19:57
2

I'll make an attempt to answer, by inventing a concrete example having written very little Java and having never used Enterprise Java Beans, so here goes.


It does not violate polymorphic behavior because the instance methods of the class do not use the concrete type, and instead use the interface.

Let's take a more concrete example.

We have a "UserDataAccess" interface to deal with users in the system.

public interface UserDataAccess {
    User find(String username);
    void create(User user);
}

Now we have a "UserService" object wired up by the EJB container:

public class UserService {
    @EJB(name="OracleUserDataAccess")
    private UserDataAccess users;

    public User createNewUser(String username, String password) {
        User user = new User(username, password);

        users.create(user);

        return user;
    }
}

We see the @EJB annotation referencing a concrete type (OracleUserDataAccess), which knows how to talk directly with an Oracle database. This annotation is evaluated at run time, and through class reflection an instance of UserService is given an OracleUserDataAccess object, however the UserService still sees it as a UserDataAccess object -- the interface. This is due to the type specified for the "users" property in UserService.

So when any instance method of UserService calls methods on the "users" property it is dealing with an interface, not a concrete implementation, and therefore does not violate polymorphism.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.