2

We have used Google Guice framework for dependency injection. I need to create multiple insatnce of an interface in java.

The execution starts from here: KfhRecordValidator.java class in the below code:

public class KfhRecordValidator implements RequestHandler<Request, Response> {
       public Response handleRequest(Request request, Context context) 
        {
     // Resolve the necessary dependencies, and process the request.
       Injector injector = Guice.createInjector(new 
                      DependencyModule());
            Processor processor = 
                 injector.getInstance(Processor.class);
              return processor.process(request, context);
}}

The process class is having reference of RecordValidationHelper class and the injection is through constructor. IRecordValidationService.java is an interface that is having validate method.

public interface IRecordValidationService {
              void validate(Record record) throws ValidationException;}

class processor is having one method called process that is being called in RecordValidationHelper class.

class Processor {
   private final RecordValidationHelper recordValidationHelper;
@Inject
@SuppressWarnings({"WeakerAccess"})
public Processor(IRecordValidationService recordValidationService, 
IRecordService<ErrorRecord> recordService,
                 S3UtilsInterface s3Utils, IEnvironmentVariableReader 
                 environmentVariableReader) {
                 this.recordValidationHelper = new 
                 RecordValidationHelper(recordValidationService);
                 this.errorRecordHelper = new 
                 ErrorRecordHelper(recordService, environmentVariableReader);
}

public Response process(Request request, @SuppressWarnings("unused") Context context) {

    // Validate records
    List<LambdaRecord> records = recordValidationHelper.processRecords(request.getRecords());}

Class DependencyModule.java extneds AbstractModule class of Guice injection that is having configure method.

class DependencyModule extends AbstractModule {
@Override
protected void configure() {
    String validationType = System.getenv("ValidationType");

    validationType= validationType.toLowerCase(Locale.ENGLISH);

    String valType[]= validationType.split(",");
    int length= valType.length;

    for(int i=0;i<length;i++){

        switch(valType[i]){
         case "json":
             bind(IRecordValidationService.class).to(JsonValidationService.class);
             break;
         case "avro":
             bind(IRecordValidationService.class).to(AvroSchemaValidationService.class);
             break;
         case "clientlogging":
             bind(IRecordValidationService.class).to(ClientLoggingValidationService.class);
             break;
         case "servicelogs":
             bind(IRecordValidationService.class).to(ServiceLoggingValidationService.class);
             break;
         default:
             throw new UnsupportedOperationException(String.format("Encountered an unsupported ValidationType of '%s'.", valType[i]));
        }

    } } }

SO the issue is if I am getting validation type as AVRO, JSON then it will bind IRecordValidationService to respective JsonValidationService/AvroSchemaValidationService class. I need to create multiple instance for that but it supports only once instance at a time. Below is the RecordValidationHelper.java class

public class RecordValidationHelper extends AbstractModule { private final IRecordValidationService recordValidationService;

@Inject
public RecordValidationHelper(IRecordValidationService recordValidationService) {
    this.recordValidationService = recordValidationService;
}

public List processRecords(List requestRecords) { List records = new ArrayList<>();

    for (RequestRecord record : requestRecords) {
        try {

            Record domainRecord = new Record();
            domainRecord.setKey(record.getRecordId());
            domainRecord.setValue(new String(Base64.getDecoder().decode(record.getData())));

            // Use the injected logic to validate the record.
            ((IRecordValidationService) 
           recordValidationService).validate(domainRecord);}
           catch (ValidationException ex) {}}}
           return records;}

Anyone having any idea about how it should be implemented to get multiple instance suitable for this.

1 Answer 1

3

Use @Named bindings

In your DependencyModule, bind using names:

bind(IRecordValidationService.class)
  .annotatedWith(Names.named("json"))
  .to(JsonValidationService.class);
bind(IRecordValidationService.class)
  .annotatedWith(Names.named("avro"))
  .to(AvroSchemaValidationService.class);
bind(IRecordValidationService.class)
  .annotatedWith(Names.named("clientlogging"))
  .to(ClientLoggingValidationService.class);
bind(IRecordValidationService.class)
  .annotatedWith(Names.named("servicelogs"))
  .to(ServiceLoggingValidationService.class);

Then in your injectee:

@Inject
public RecordValidationHelper(
    @Named("json") IRecordValidationService jsonValidation,
    @Named("avro") IRecordValidationService avroValidation,
    @Named("clientlogging") IRecordValidationService clientLoggingValidation,
    @Named("servicelogs") IRecordValidationService serviceLogsValidation,
  ) {
    this.jsonValidation = jsonValidation;
    this.avroValidation = avroValidation;
    this.clientLoggingValidation = clientLoggingValidation;
    this.serviceLogsValidation = serviceLogsValidation;
}

See Guice's BindingAnnotation wiki page for more info.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.