Search code examples
javalambdafunctional-interface

How to get arguments from an instance of functional interface object passed as lambda?


@FunctionalInterface
public interface ServiceCaller {
    void callService();
}

//common method to execute any service call
public void executeService(ServiceCaller serviceCaller) {
    //do common things
    //i want to access dbValidationRequest/apiValidationRequest here for logging purpose
    try {
        serviceCaller.callService();
    } catch (Exception ex) {
        //do common things
        LogUtils.log(logger, ex);
    }
    //do common things
}

//my clients call this
public void validateFromDb(DbValidationRequest dbValidationRequest){
    commonUtils.executeService(()-> dbValidationService.validate(dbValidationRequest));
}

//my clients call this
public void validateFromApi(ApiValidationRequest apiValidationRequest){
    commonUtils.executeService(()-> apiValidationService.validate(apiValidationRequest));
}


This is a controller of Java Spring Application. Inside the executeService method, i pass an instance of ServiceCaller interface. I call all my service from controller using this method. if i evaluate using intelliJ IDEA then i can view values of the dbValidationRequest/apiValidationRequest inside executeService method (as arg$2, see attached picture). I need to print those objects for logging purpose, i also don't want to use aspect at all. How can i do this. If intelliJ IDEA can see the values, why can't i programatically? enter image description here


Solution

  • arg$1 and arg$2 can be treated as fields of a class, so they can be obtained by reflection.

        String var1 = "Content Var 1";
        String var2 = "Content Var 2";
    
        Supplier<String> stringSupplier = () -> var1 + var2;
    
        Field[] declaredFields = stringSupplier.getClass().getDeclaredFields();
    
        for (Field f : declaredFields) {
            f.setAccessible(true);
            System.out.println(
                "Field Name: " + f.getName() +
                ", value: " + f.get(stringSupplier)
            );
        }
    
        // Field Name: arg$1, value: Content Var 1
        // Field Name: arg$2, value: Content Var 2