Is there a way to access SlingRepository
in a POJO that is not managed by OSGI?
For example, we might have a POJO named Site
:
public class Site {
private String domainName;
public String getDomainName() { return domainName; }
public void setDomainName(String domainName) { this.domainName = domainName; }
public void validate() throws Exception {
SlingRepository repo = ...;
// validation logic dependent on repo
}
}
That is used like this:
Site site = new Site();
site.validate();
The reason why I cannot use @Reference
or the current request's ResourceResolver
is because I am trying to implement a JSR-303 (aka Bean validation) validator.
In our Sling app, we have a bunch of servlets that receive JSON payloads from the browser. Then we convert them to pojos:
Person p = new Gson().fromJson(json, Person.class)
validate(p); // Validate p using Bean Validation
Person
is a simple POJO annotated with JSR-303 annotations:
public class Person {
@NotNull
private String name;
@UniqueProperty(
name = "email",
path = "/content/myapp",
nodeType = "cq:PageContent"
)
private String email;
}
In short, my goal is to implement the @UniqueProperty
validation. In the example above, if a node of type cq:PageContent
under /content/myapp
exists that has an email
property with the same value as this model, the validation fails.
The validator class itself will look like this:
public class UniquePropertyValidator implements ConstraintValidator<UniqueProperty, String {
@Override
public void initialize(UniqueProperty constraintAnnotation) {
...
}
@Override
public boolean isValid(String object, ConstraintValidatorContext constraintContext) {
// need to execute a JCR query here
}
}
UniquePropertyValidator
will be instantiated by the JSR-303 implementation (e.g. Hibernate Validator) as needed, and there's no way it can access the current request's resource resolver, hence why I was looking for a way to access the SlingRepository
.
In general you should not retrieve external resources from a pojo. Simply add a contructor or setter where you inject the SlingRepository at the position where you do the new. This has the advantage that your pojo is independent of OSGi and can be used in different environments. Also unit testing is easier with this approach.
Site site = new Site(slingRepository);
Of course this just moves the problem to the class that creates the instance. I guess at some point you start at an activator where you have access to the BundleContext and can lookup the service.
In the rare cases where you really want to lookup a service directly use
FrameworkUtil.getBundle(this.getClass()).getBundleContext();
From there you can lookup the service.