Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.

Java Custom Annotation

Avatar

Community Advisor

Hi members,

I am trying to create a custom annotation. The idea was very simple, it would set the data in a string field.

Here is the code I have done till now,

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface RunMode {

}
@component(service = Injector.class, immediate = true)
public class RunModeInjector implements Injector {
    @reference
    private AppSettingService appSettingService;

    @Override
    public String getName() {
        return "runmode";
    }

    @Override
    public @nullable Object getValue(@NotNull Object adaptable, String name, @notnull Type type,
                           @notnull AnnotatedElement annotatedElement,
                           @notnull DisposalCallbackRegistry disposalCallbackRegistry) {

        if (annotatedElement.isAnnotationPresent(RunMode.class)) {
            return appSettingService.getRunMode();
        }
        return null;
    }
}

Usages,

// Sling Model
// value is assigned
// But I was supposed to it will work without the extra @inject annotation.
@Inject @RunMode
private String runMode;


// OSGI Service/servlet
// value is null, 
// The annotatedElement.isAnnotationPresent(RunMode.class) condition is not satisfied from injector class.
@RunMode
private String runMode;

What I missed, or how to make it work? 

Thanks in advance.
 

3 Replies

Avatar

Community Advisor

Thanks for the related blogs. But those all are related to only sling model. Those are not working for service/servlet level.
However, I got an alternative solution, which is for service/servlet.

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;

@Component(immediate = true, service = OSGiFieldInjector.class)
public class OSGiFieldInjector {

    private static final Logger log = LoggerFactory.getLogger(OSGiFieldInjector.class);

    @reference
    private AppSettingService appSettingService;

    @activate
    protected void activate(ComponentContext context) {
        BundleContext bundleContext = context.getBundleContext();

        bundleContext.addServiceListener(event -> {
            ServiceReference<?> serviceReference = event.getServiceReference();
            Object serviceInstance = bundleContext.getService(serviceReference);
            injectRunModeFields(serviceInstance);
        });
    }

    private void injectRunModeFields(Object serviceInstance) {
        Field[] fields = serviceInstance.getClass().getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(RunMode.class)) {
                try {
                    field.setAccessible(true);
                    String runModeValue = appSettingService.getRunMode();
                    field.set(serviceInstance, runModeValue);
                } catch (IllegalAccessException e) {
                    log.error("Failed to inject run mode into field", e);
                }
            }
        }
    }
}

But I don't like this solution, since it's behind-work complexity is too high.

Avatar

Administrator

@Sady_Rifat Did you find the suggestion helpful? Please let us know if you require more information. Otherwise, please mark the answer as correct for posterity. If you've discovered a solution yourself, we would appreciate it if you could share it with the community. Thank you!



Kautuk Sahni