Java 有没有办法访问POJO中的SlingRepository?
有没有一种方法可以访问非OSGI管理的POJO中的Java 有没有办法访问POJO中的SlingRepository?,java,osgi,aem,sling,Java,Osgi,Aem,Sling,有没有一种方法可以访问非OSGI管理的POJO中的SlingRepository 例如,我们可能有一个名为Site的POJO: public class Site { private String domainName; public String getDomainName() { return domainName; } public void setDomainName(String domainName) { this.domainName = domain
SlingRepository
例如,我们可能有一个名为Site
的POJO:
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
}
}
这是这样使用的:
Site site = new Site();
site.validate();
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
}
}
更新(关于托梅克的回答) 我无法使用
@Reference
或当前请求的resourcesolver
的原因是因为我正在尝试实现JSR-303(又名Bean验证)验证器
在我们的Sling应用程序中,我们有一组servlet从浏览器接收JSON有效负载。然后我们将其转换为POJO:
Person p = new Gson().fromJson(json, Person.class)
validate(p); // Validate p using Bean Validation
Person
是一个简单的POJO,带有JSR-303注释:
public class Person {
@NotNull
private String name;
@UniqueProperty(
name = "email",
path = "/content/myapp",
nodeType = "cq:PageContent"
)
private String email;
}
简而言之,我的目标是实现@UniqueProperty
验证。在上面的示例中,如果存在/content/myapp
下的cq:PageContent
类型的节点,并且该节点具有与此模型相同的email
属性,则验证失败
验证程序类本身如下所示:
Site site = new Site();
site.validate();
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实现ConstraintValidator通常,您不应该从pojo检索外部资源。只需添加一个constructor或setter,将SlingRepository注入到执行新操作的位置。这样做的好处是pojo独立于OSGi,可以在不同的环境中使用。使用这种方法,单元测试也更容易
Site site = new Site(slingRepository);
当然,这只是将问题转移到创建实例的类。我想在某个时候,您可以从激活器开始,在激活器中您可以访问BundleContext并可以查找服务
在极少数情况下,如果您确实希望直接查找服务,请使用
FrameworkUtil.getBundle(this.getClass()).getBundleContext();
从那里您可以查找服务。正如Christian Schneider所写,您可以使用以下内容:
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
ServiceReference serviceReference = bundleContext.getServiceReference(SlingRepository.class);
SlingRepository slingRepository;
if (serviceReference != null) {
slingRepository = (SlingRepository) bundleContext.getService(serviceReference);
}
首先,如果您使用Sling,那么使用ResourceResolver
通常比SlingRepository
更可取。它为您提供了一个有用的资源
抽象层,您仍然可以使用adapto()
方法获得底层JCR会话
对象
但回到你的问题,POJO总是生活在一个环境中,有一些入口点运行着整个过程。在Sling中有几个这样的地方:JSP、servlet或OSGi组件。在所有这些入口点中,至少有一种方法可以访问存储库:
JSP
- 使用
resourcesolver
绑定
- 使用
getService(resourcesolverfactory.class)
创建管理冲突解决程序
Servlet或过滤器
- 使用
request.getResourceResolver()
获取请求会话
- 或者看看下一点
任何OSGi服务(包括servlet或过滤器)
- 使用
@Reference resourcesolverfactory
获取工厂并创建管理解析程序
之后,您可以将资源解析器传递给POJO构造函数。我认为这是一个比在FrameworkUtil
中使用hack更好的选择,原因如下:
- 如果将
resourcesolver
传递给POJO构造函数,很明显,这个特定的类在存储库上运行
- 您不必担心关闭会话(因为POJO可能没有定义的生命周期)
- 如果您在servlet或组件(案例1和案例2)中创建POJO,最好使用请求的会话来避免处理管理会话李>
刚刚找到了一个解决方案,您可以利用ConstraintValidator的生命周期
见:
第2.5章。ConstraintValidatorFactory可能会帮助您。如果您在例如Activator中注册ConstraintValidatorFactory,则可以将其与SlingRepository一起提供。然后,工厂可以将SlingRepository转发给它创建的验证器。因此,您可以将OSGi逻辑排除在验证器之外。谢谢您的回答。我已经更新了问题,以便更清楚地说明为什么我需要访问SlingRepository
,并且我不能使用resourcesolver
。这将使模型依赖Sling,这不是一个好主意。想想如果我们必须在基于JDBC的程序中向POJO传递JDBC连接,会发生什么。或者,如果我们必须将EntityManager传递给JavaEE应用程序中的实体。回头看我。我见过人们按照你在Sling应用程序中的建议去做,我认为他们这样做只是因为他们别无选择。我还更新了帖子,提到POJO实际上是一个JSR-303验证器,由Hibernate验证器实例化,而不是由我显式实例化。在您的问题中,您表示希望在站点内部使用SlingRepository。这就是为什么我在示例中显示了这一点。在更新的问题中,您似乎更需要UniquePropertyValidator中的存储库。由于您不控制此类的生命周期,FrameworkUtl方法看起来是一个很好的解决方案。