2011-11-30 75 views
2

我正在嘗試爲我們現有的Web應用程序開發一個新模塊。我試圖添加LDAP功能,並且在初始化LDAP上下文時遇到問題,因爲SimpleNamingContextBuilder註冊了與LdapTemplate不能一起工作的上下文。Spring的SimpleNamingContextBuilder和LDAP

在我們的春天applicationContext.xml我們有幾個JNDI查找,所以在運行測試案例之前,我必須創建模擬JNDI的資源使用測試用例構造的SimpleNamingContextBuilder

SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); 
builder.bind("someJNDIname",someObject); //e.g. for some datasource 
builder.activate(); 

在我們的春天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創建並使用這樣的DirContext

如果我沒有註冊SimpleNamingContextBuilder,那麼創建LDAPTemplate將工作。但是我會遇到其他問題,因爲應用程序的其他部分需要JNDI查找。

回答

3

我沒有設法讓SimpleNamingContextBuilder創建DirContext的實例,但使用自定義的DirContextBuilder是解決此限制的解決方案。

嘲笑的SimpleNamingContext主要用於通過例如提供綁定對象。

InitialContext.doLookup(String name) 

方法 - 讓這些方法可以正常工作併爲例如, LDAP DirContext實例,只是省略了對「激活」上下文的檢查 - 無論如何你都會引導你的代碼來應用activate(),所以這沒有問題 - 至少不是對於給定的JNDI + LDAP測試用例。

缺少此檢查,代碼看起來爲「java.naming.factory.initial的」環境鍵,如果環境是空的(這是InitialContext.doLookup(字符串名稱)的情況下),你得到的嘲笑SimpleNamingContext與綁定對象。

如果使用LdapTemplate環境不是空的,鑰匙「java.naming.factory.initial的」設置爲「com.sun.jndi.ldap.LdapCtxFactory」或類似的東西是在最少(希望)DirContext。

在這種情況下,您將從createInitialContextFactory調用返回一個工作的DirContext實例,並且LdapTemplate查找成功。

所以只需要創建一個類DirContextBuilder - 採取從SimpleNamingContextBuilder代碼 - 這樣的:

public class DirContextBuilder implements InitialContextFactoryBuilder { 

... 

public InitialContextFactory createInitialContextFactory(Hashtable<?,?> environment) { 
    if (environment != null) { 
... 
} 

省略激活檢查== NULL,你準備好測試綁定JNDI對象和有工作LdapTemplate。

+0

這並不能解決混合問題。我想在同一個上下文中初始化數據庫的JNDI數據源。 –

+0

如果你需要在同一個上下文中,這也應該可以使用自定義的DirContextBuilder - 只需創建你自己的DirContext實現,或者使用JBoss one(org.jnp.interfaces.NamingContextFactory)。 –

+0

我需要在相同的背景下,你能告訴我如何完全做到這一點?會真的很感激它!謝謝 –

1

我面臨同樣的問題。但隨着下方招

@BeforeClass 
public static void setUp(){ 
    OracleDataSource ods = null; 
    try { 
     ods= new OracleDataSource(); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 
    ods.setURL("jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=....; 
    ods.setUser(..); 
    ods.setPassword(..);   

    SimpleNamingContextBuilder builder = null; 
    try { 
     builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder(); 
     builder.bind("some/name", ods); 
    } catch (NamingException e) { 
     e.printStackTrace(); 
    } 
} 

@Before 
public void beforeTest(){ 
     SimpleNamingContextBuilder.getCurrentContextBuilder().deactivate(); 
} 

@Test 
public void yourTest(){ 
    ..... 
} 

這將數據庫與一些/名綁定,也讓你正確連接到LDAP克服它。

+0

我在'@ ContextConfiguration'配置需要jdbc數據源的jndi的spring上下文之前使用'@ BeforeClass'來註冊jndi。不過,我需要添加'builder.activate()'以使其工作。感謝這個技巧+1':)' – albciff