0

I am currently refactoring some legacy code and came across a snippet as below. How do I avoid the instantiation of 'CompanyAuditor' class and use CDI to hanldle it?

return compDAO.getAll()
                .stream()
                .map( CompanyAuditor::new )
                .collect( Collectors.toList() );
ShellDragon
  • 1,712
  • 2
  • 12
  • 24
  • It's unlikely that the provided snippet is the legacy code as it requires Java-8 features. Please provide the legacy code as well. – Tagir Valeev Aug 20 '15 at 06:50
  • @TagirValeev Thanks for the repsonse. It was originally a 'for loop' over a list of Company objects returned by CompanyDAO.getAll(), creating CompanyAuditor objects for each 'Company' object and returning list of CompanyAuditor objects. Someone else has already rewritten it using streams. – ShellDragon Aug 20 '15 at 08:15

1 Answers1

1

The only way is to define constructor without arguments for CompanyAuditor, create new instances using javax.enterprise.inject.Instance.get. And afterwards pass all arguments using public methods. Therefore your constructor with an argument must be separated into one without arguments and additional public method to set this argument. Also, you must write your own lambda expression, which is more complicated than just CompanyAuditor::new.

Full example:

@Inject
@New  // javax.enterprise.inject.New to always request a new object
private Instance<CompanyAuditor> auditorInjector;

public List returnAllWrappedAuditors() {
    return compDAO.getAll()
             .stream()
             .map( ca -> {
                     CompanyAuditor auditor = auditorInjector.get();
                     auditor.setWrappedObject( ca );
                     return auditor;
                 })
             .collect( Collectors.toList());
}

Afternote:

CDI is not very easy to use when dynamically constructing objects, it excells in injecting dependencies. Therefore it is a bit more verbose than calling constructor to create new objects.

CDI beans must have either constructor without parameters or all parameters annoted with @Inject (which does not help in your case) See Java EE 7 tutorial

OndroMih
  • 7,280
  • 1
  • 26
  • 44
  • That's a comprehensive answer. Thanks @OnderjM – ShellDragon Aug 20 '15 at 13:54
  • The use of `@New` is highly discouraged within CDI and this approach is generally known for many performance issues. If `CompanyAuditor` is a DTO/domain class, it should just be instantiated, unless its also intended to have injection points then this is the right approach but can have memory leaks. – John Ament Aug 21 '15 at 23:27
  • @JohnAment It's true that `@New` is deprecated in CDI2, but I wanted to make my answer short. It is preffered to use normál injection and ensure it has `@Dependent` scope. In that case I would at least mark injection point with custom qualifier, like `@NewInstance` whatever, just to mark that we request to create a new object here each time. – OndroMih Aug 22 '15 at 08:00