Adobe CQ/AEM - 从自定义登录模块连接到数据库

Adobe CQ/AEM - connect to DB from custom login module

我有一个扩展 org.apache.jackrabbit.core.security.authentication.AbstractLoginModule 的工作自定义登录模块。它根据 LDAP 源检查凭据,现在我想去数据库获取一些额外的数据以写入配置文件。我想使用 JDBC 连接池服务,但我不知道如何获取对它的引用。

我的第一个猜测是,可能有办法让doInit()方法中传递的Session对象提供服务,但我找不到办法。

Session本身似乎是由CallbackHandler设置的。有什么方法可以通过编写 Callback?

来获取服务参考

编辑: 根据有用的评论,我还尝试了以下方法

BundleContext context = FrameworkUtil.getBundle(JdbcPoolService.class).getBundleContext();
//ServiceReference[] serviceRefs = context.getServiceReferences(JdbcPoolService.class.getName(), String.format("(%s=%s)", Constants.OBJECTCLASS, JdbcPoolService.class.getName()));
ServiceReference serviceRefs = context.getServiceReference(JdbcPoolService.class.getName());

FrameworkUtil 确实让我可以访问正确的捆绑包。 (我可以在调试器中看到包 ID,它确实与 JDBC 池提供程序匹配。)但我无法访问该服务。所有对参考的请求都返回空值。我试过获取单个引用,但因为 JDBC 池是一个服务工厂,我也尝试(注释掉代码)获取数组 - 使用 class 名称和过滤器作为参数,或者null 和过滤器作为 getServiceReferences 的参数。 如果我使用 @Reference 注释,我会包含目标参数。我猜这就是我所缺少的。也许 getServiceReferences 的过滤器是错误的?

此 link 提供有关连接到 SQL 数据库的信息:https://docs.adobe.com/docs/en/cq/5-6-1/developing/jdbc.html。 从本质上讲,它展示了如何部署将 HSQLDB 驱动程序包装在 OSGi 包中的包。这是他们使用的 POM:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">


<modelVersion>4.0.0</modelVersion>

  <groupId>com.adobe.example.myapp</groupId>
  <artifactId>hsqldb-jdbc-driver-bundle</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>wrapper-bundle-hsqldb-driver</name>
  <url>www.adobe.com</url>
  <description>Exports the HSQL JDBC driver</description>
  <packaging>bundle</packaging>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.felix</groupId> 
        <artifactId>maven-bundle-plugin</artifactId>
        <version>1.4.3</version> 
        <extensions>true</extensions> 
        <configuration> 
         <instructions> 
            <Embed-Dependency>*</Embed-Dependency>
            <_exportcontents>org.hsqldb.*</_exportcontents>
          </instructions>
        </configuration> 
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>hsqldb</groupId>
      <artifactId>hsqldb</artifactId>
      <version>2.2.9</version>
    </dependency>
  </dependencies>
</project>

然后你可能会得到DataSourcePool服务来获取一个javax.sql.DataSource对象。文章在JSP:

中展示了如何获取
<%@include file="/libs/foundation/global.jsp"%><%
%><%@page session="false"%><%
%><%@ page import="com.day.commons.datasource.poolservice.DataSourcePool" %><%
%><%@ page import="javax.sql.DataSource" %><%
%><%@ page import="java.sql.Connection" %><%
%><%@ page import="java.sql.SQLException" %><%
%><%@ page import="java.sql.Statement" %><%
%><%@ page import="java.sql.ResultSet"%><%
%><html>
<cq:include script="head.jsp"/>
<body>
<%DataSourcePool dspService = sling.getService(DataSourcePool.class);
  try {
     DataSource ds = (DataSource) dspService.getDataSource("hsqldbds");   
     if(ds != null) {
         %><p>Obtained the datasource!</p><%
         %><%final Connection connection = ds.getConnection();
          final Statement statement = connection.createStatement();
          final ResultSet resultSet = statement.executeQuery("SELECT * from INFORMATION_SCHEMA.SYSTEM_USERS"); 
          int r=0;
          while(resultSet.next()){
             r=r+1;
          } 
          resultSet.close();
          %><p>Number of results: <%=r%></p><%
      } 
   }catch (Exception e) {
        %><p>error! <%=e.getMessage()%></p><%
    } 
%></body>
</html>

在 servlet 或服务中,您可以使用 @Reference 注释获取对 DataSourcePool 服务的引用:

@Reference
private DataSourcePool pool;

编辑:您可以尝试使用 FrameworkUtil class

在组件外部获取服务
BundleContext context = FrameworkUtil.getBundle(serviceClass).getBundleContext();
ServiceReference serviceRef = context.getServiceReference(serviceClass.getName());
Object service = context.getService(serviceRef);

编辑(通过 jwepurchase):对于 JDBC 服务,您需要通过其持久 ID

获取服务
ServiceReference[] serviceRefs = context.getServiceReferences(null, String.format("(%s=%s)", Constants.SERVICE_PID, "com.day.commons.datasource.jdbcpool.JdbcPoolService.[your-id-here]"));
JdbcPoolService pool = (JdbcPoolService) context.getService(serviceRefs[0]);

请注意 getServiceReferences 的第一个参数为空。将 class 名称作为第一个参数传递似乎不起作用。