Spring 的 SimpleNamingContextBuilder 和 LDAP
我目前正在尝试为我们现有的网络应用程序开发一个新模块。我正在尝试添加 LDAP 功能,但在初始化 LDAP 上下文时遇到问题,因为 SimpleNamingContextBuilder 注册的上下文不能与 LdapTemplate。
在我们的 spring applicationContext.xml
中,我们有多个 JNDI 查找,因此在运行测试用例之前,我必须使用 SimpleNamingContextBuilder 在测试用例构造函数中。
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind("someJNDIname",someObject); //e.g. for some datasource
builder.activate();
在我们的 Spring application-context-test.xml
中,我们有以下 ldapConfiguration:
<bean id="ldapContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://ourserver:389" />
<property name="base" value="CN=Groups,CN=ourcompany,DC=com" />
<property name="userDn" value="CN=binduser" />
<property name="password" value="password" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="ldapContextSource" />
</bean>
我们运行测试用例:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application-context-test.xml"})
public class TestClass {
public TestClass(){
.. //init the SimpleNamingContextBuilder
}
@Autowired
private LdapTemplate template;
@Test
public void someTestcase(){
ldapTemplate.search("", "(objectclass=user)" ,new LdapUserMapper());
}
}
由于 SimpleNamingContextBuilder 已经注册了一个简单的 InitialContext,我收到以下错误:
org.springframework.ldap.NotContextException: DirContext object is required.; nested exception is javax.naming.NotContextException: DirContext object is required.
at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:198)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:319)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:259)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:571)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:556)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:411)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:431)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:451)
at com.somecompany.TestClass.someTestcase(TestClass.java:30)
[...]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: javax.naming.NotContextException: DirContext object is required.
at javax.naming.directory.InitialDirContext.castToDirContext(InitialDirContext.java:106)
at javax.naming.directory.InitialDirContext.getURLOrDefaultInitDirCtx(InitialDirContext.java:112)
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:245)
at org.springframework.ldap.core.LdapTemplate$4.executeSearch(LdapTemplate.java:253)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:293)
... 35 more
该错误告诉我, LDAP 需要 DirContext
。如何让 SimpleNamingContextBuilder 创建和使用这样的 目录上下文。
如果我不注册 SimpleNamingContextBuilder,则创建 LDAPTemplate 将会起作用。但是,我会遇到其他问题,因为应用程序的其他部分需要 JNDI 查找。
I'm currently trying to develop a new module for our existing web application. I'm trying to add LDAP functionality and have problems initializing the LDAP context as the SimpleNamingContextBuilder registers a context that is not working together with the LdapTemplate.
In our spring applicationContext.xml
we have several JNDI lookups, so before running a test case I have to create mock JNDI-Resources using the SimpleNamingContextBuilder in the test cases constructor.
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
builder.bind("someJNDIname",someObject); //e.g. for some datasource
builder.activate();
In our Spring application-context-test.xml
we have the following ldapConfiguration:
<bean id="ldapContextSource" class="org.springframework.ldap.core.support.LdapContextSource">
<property name="url" value="ldap://ourserver:389" />
<property name="base" value="CN=Groups,CN=ourcompany,DC=com" />
<property name="userDn" value="CN=binduser" />
<property name="password" value="password" />
</bean>
<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
<constructor-arg ref="ldapContextSource" />
</bean>
We run the testcase with:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application-context-test.xml"})
public class TestClass {
public TestClass(){
.. //init the SimpleNamingContextBuilder
}
@Autowired
private LdapTemplate template;
@Test
public void someTestcase(){
ldapTemplate.search("", "(objectclass=user)" ,new LdapUserMapper());
}
}
As the SimpleNamingContextBuilder is already registering a simple InitialContext I get the following error:
org.springframework.ldap.NotContextException: DirContext object is required.; nested exception is javax.naming.NotContextException: DirContext object is required.
at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:198)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:319)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:259)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:571)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:556)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:411)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:431)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:451)
at com.somecompany.TestClass.someTestcase(TestClass.java:30)
[...]
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: javax.naming.NotContextException: DirContext object is required.
at javax.naming.directory.InitialDirContext.castToDirContext(InitialDirContext.java:106)
at javax.naming.directory.InitialDirContext.getURLOrDefaultInitDirCtx(InitialDirContext.java:112)
at javax.naming.directory.InitialDirContext.search(InitialDirContext.java:245)
at org.springframework.ldap.core.LdapTemplate$4.executeSearch(LdapTemplate.java:253)
at org.springframework.ldap.core.LdapTemplate.search(LdapTemplate.java:293)
... 35 more
The error tells me that the LDAP requires a DirContext
. How can I get the SimpleNamingContextBuilder to create and use such a DirContext.
If I don't register the SimpleNamingContextBuilder then creating the LDAPTemplate
will work. However I will run into other problems as other parts of the application require the JNDI lookups.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我没有设法让 SimpleNamingContextBuilder 创建 DirContext 的实例,但使用自定义 DirContextBuilder 是解决此限制的解决方案。
模拟的 SimpleNamingContext 主要是通过例如方法提供绑定对象
- 让这些方法工作并为例如 LDAP DirContext 实例提供适当的支持,只需省略对“已激活”上下文的检查 - 您将引导代码应用 activate()无论如何,所以这不是问题 - 至少对于给定的 JNDI + LDAP 测试用例来说不是。
如果缺少此检查,代码将查找“java.naming.factory.initial”环境键,如果环境为空(InitialContext.doLookup(String name) 就是这种情况),您将得到使用绑定对象模拟 SimpleNamingContext。
如果您使用 LdapTemplate,则环境不为空,并且键“java.naming.factory.initial”设置为“com.sun.jndi.ldap.LdapCtxFactory”或类似的东西至少(希望)是一个 DirContext。
在这种情况下,您从 createInitialContextFactory 调用返回一个工作 DirContext 实例,并且 LdapTemplate 查找成功。
因此,只需创建一个类 DirContextBuilder - 从 SimpleNamingContextBuilder 中获取代码 - 如下所示:
省略对 activated == null 的检查,然后您就可以测试绑定的 JNDI 对象并拥有一个可用的 LdapTemplate。
I did not manage to get the SimpleNamingContextBuilder to create an instance of DirContext, but using a custom DirContextBuilder was the solution to get around this limitation.
The mocked SimpleNamingContext is mainly there to provide bound objects via e.g.
methods - to let those ones work and provide proper support for e.g. LDAP DirContext instances, just omit the check for the "activated" context - you will bootstrap your code to apply activate() anyway, so this is no problem - at least not for the given JNDI + LDAP test case.
Missing this check, the code looks for the "java.naming.factory.initial" environment key and if the environment is empty (this is the case for InitialContext.doLookup(String name)) you get the mocked SimpleNamingContext with your bound objects.
If you use the LdapTemplate the environment is not empty and the key "java.naming.factory.initial" is set to "com.sun.jndi.ldap.LdapCtxFactory" or something similar which is at least (hopefully) a DirContext.
In this case you get a working DirContext instance back from the createInitialContextFactory call and the LdapTemplate lookup is successful.
So just create a class DirContextBuilder - take the code from SimpleNamingContextBuilder - like this:
Omit the check for activated == null and you are ready to test your bound JNDI objects and have a working LdapTemplate.
我遇到了同样的问题。但可以用下面的技巧克服它,
这会将您的数据库与 some/name 绑定,并让您正确连接到 ldap。
I faced the same issue. But overcome it with the below trick
This will bind your database with some/name and also let you to connect to the ldap correctly.
我也面临同样的问题。我研究了 Java 和 SpringLdap 中发生这种情况的原因和内部行为。我做出了以下决定。
我定制了 ContextSource bean 创建来解决这个问题。这种方法很困难,需要修改检查测试模式的配置。但它有效。
下面我用一个简单的项目来演示一下。对于嵌入式 LDAP 服务器,我使用了 Apache Directory Server。
CommonConfig.java
包含这个拐杖:MainTest.java
,使用JNDI
和LdapOperations
:ApacheDsEmbededConfiguration.java< /code>:
Pojo
LdapSettings.java
:使用 JNDI 变量的 Bean
JndiExplorer.java
:以及pom.xml:
I also faced the same issue. I researched causes and internal behaviour in
Java
andSpringLdap
why it happens. I came to the following decision.I customized ContextSource bean creation in order to solve it. This method is crutch and requires modification config that checking test mode. But it works.
Below I present simple project demostrated it. For embeded LDAP server I used Apache Directory Server.
CommonConfig.java
consisted this crutch:MainTest.java
usingJNDI
andLdapOperations
:ApacheDsEmbededConfiguration.java
:Pojo
LdapSettings.java
:Bean using JNDI-variable
JndiExplorer.java
:And
pom.xml
: