HomeCode Reference › OSGi service snippets

OSGi service snippets

Purpose: Service, configuration, scheduler and job skeletons with current DS annotations.

Who this page is for

AudienceWhy it matters to you
Backend engineersDaily

Configured service

public interface PremiumFormatter { String format(double amount); }

@Component(service = PremiumFormatter.class)
@Designate(ocd = PremiumFormatterImpl.Config.class)
public class PremiumFormatterImpl implements PremiumFormatter {

    @ObjectClassDefinition(name = "PHI Premium Formatter")
    @interface Config {
        @AttributeDefinition(name = "Currency symbol") String currencySymbol() default "$";
        @AttributeDefinition(name = "Suffix") String suffix() default "/month";
    }

    private Config cfg;
    @Activate @Modified void activate(Config cfg) { this.cfg = cfg; }

    @Override public String format(double amount) {
        return String.format("%s%.2f %s", cfg.currencySymbol(), amount, cfg.suffix());
    }
}

Config file (ui.config): com.academy.phi.core.services.impl.PremiumFormatterImpl.cfg.json

{ "currencySymbol": "$", "suffix": "/month" }

Service-user repository access

@Reference private ResourceResolverFactory resolverFactory;

private static final Map<String, Object> AUTH =
    Map.of(ResourceResolverFactory.SUBSERVICE, "rating-sync");

public void updateRates(List<Rate> rates) {
    try (ResourceResolver rr = resolverFactory.getServiceResourceResolver(AUTH)) {
        Resource root = rr.getResource("/var/phi/rates");
        // … write, then:
        rr.commit();
    } catch (LoginException | PersistenceException e) {
        LOG.error("Rate update failed", e);
    }
}

(Plus the mapper config: org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~phi.cfg.json{"user.mapping": ["com.academy.phi.core:rating-sync=phi-rating-sync"]}pattern.)

Scheduled task + durable job pair

@Component(service = Runnable.class)
@Designate(ocd = NightlyRateSync.Config.class)
public class NightlyRateSync implements Runnable {
    @ObjectClassDefinition interface Config {
        @AttributeDefinition String scheduler_expression() default "0 0 2 * * ?";
        @AttributeDefinition boolean scheduler_concurrent() default false;
    }
    @Reference private JobManager jobManager;
    @Override public void run() { jobManager.addJob("phi/rates/sync", Map.of()); }
}

@Component(service = JobConsumer.class,
           property = JobConsumer.PROPERTY_TOPICS + "=phi/rates/sync")
public class RateSyncConsumer implements JobConsumer {
    @Override public JobResult process(Job job) {
        // idempotent work; OK / FAILED (retry) / CANCEL (drop)
        return JobResult.OK;
    }
}

Quick navigation