[英]How to do a remote JNDI lookup from Spring Boot Client to GlassFish Server?
我從一個可用的 Spring Boot 應用程序開始,使用最新版本的 Spring Boot 和嵌入式 Tomcat。 它包含一個 HomeController,其 index 方法映射到 webapp 目錄中相應的 .jsp。
@RequestMapping(value={"/", "/home", "/home/index"})
public ModelAndView index() {
ModelAndView mv = new ModelAndView("/home/index");
return mv;
}
我的目標是對 glassfish 服務器進行遠程 JNDIlookup 以訪問 EJB 單例服務。 我之前已經使用一個簡單的桌面客戶端驗證過,對我的 Glassfish 服務器的遠程 JNDI 查找工作正常。
我遵循了 WildFly 的本教程,將其重新用於 Glassfish: https ://www.baeldung.com/spring-ejb
看起來很簡單。 我會導入 Glassfish 的而不是 WildFly 的客戶端模塊,並且我會使用 Glassfish 的而不是 WildFly 的 InitialContext 屬性。
所以我用這個更新了我的 pom.xml(我還添加了一個包含遠程接口的依賴項):
<dependency>
<groupId>org.glassfish.main.appclient</groupId>
<artifactId>gf-client</artifactId>
<version>5.1.0</version>
</dependency>
像這樣更新 McvConfig.java(GlassFish 的基本端口是 8000,它為 JNDI 端口增加了 37):
@Bean
public Context ejbInitialContext() {
InitialContext initialContext = null;
try {
Properties jndiProps = new Properties();
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.impl.SerialInitContextFactory");
jndiProps.put(Context.STATE_FACTORIES,
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
jndiProps.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
jndiProps.put("org.omg.CORBA.ORBInitialHost", "localhost");
// optional. Defaults to 3700. Only needed if target orb port is not 3700.
jndiProps.put("org.omg.CORBA.ORBInitialPort", "8037");
initialContext = new InitialContext(jndiProps);
} catch (NamingException e) {
}
return initialContext;
}
並像這樣更新了 HomeController:
@Autowired
Context ejbInitialContext;
@RequestMapping(value={"/", "/home", "/home/index"})
public ModelAndView index() {
ModelAndView mv = new ModelAndView("/home/index");
ServiceRemote service = (ServiceRemote) ejbInitialContext.lookup("java:global/core/Service");
mv.addObject("Hello", service.hello());
return mv;
}
我運行了 GlassFish 服務器,然后嘗試運行我的 Spring Boot 應用程序。 Sprint 啟動日志沒有出現,過了一會兒,我得到了這個(完整日志在這里: https : //pastebin.com/E11xLmFN ):
org.omg.CORBA.COMM_FAILURE: FINE: 00410001: Connection failure: socketType: IIOP_CLEAR_TEXT; hostname: localhost; port: 3700 vmcid: OMG minor code: 1 completed: No
...
Caused by: java.lang.RuntimeException: java.net.ConnectException: Connection refused: connect
...
Caused by: java.net.ConnectException: Connection refused: connect
我嘗試訪問本地主機,它只是說:
This site can’t be reached
折騰了一會,總結了幾點:
Spring 正在嘗試與 GlashFish 集成,因為堆棧跟蹤包括以下內容:
在 org.springframework.jndi.JndiTemplate.lambda$lookup$0(JndiTemplate.java:157) 在 org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:92) 在 org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.lookup(JndiTemplate. java:157) 在 org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:179)
Spring 完全忽略了我的 Bean 並使用默認的 GlassFish InitialContext,因為日志中的端口號仍然是 3700,GlassFish 的默認值,但我指定了 8048。
Spring 以某種方式檢測客戶端模塊並定期嘗試連接到 Glassfish。 問題是我完全不知道如何告訴 Spring 使用我的自定義 InitialContext 屬性。
我在網上到處尋找解決方案。 大部分類似的問題都沒有問的很好,也沒有得到答案,還有一些是專門關於DataSource的,這對我來說太具體了,因為我試圖把整個Service層放在一個Jakarta EE服務器上。
沒關系。 我只是想知道該怎么做。 如果您查看堆棧跟蹤,它從 Spring Boot 應用程序的開頭開始: SpringApplication.run(App.class, args);
Spring Boot 就是在它自己的初始化中初始化 GlassFish AppClient。 當我寫這個問題時,這很清楚。
事實證明,這樣做的唯一方法是將 InitialContext 中的相同屬性放入系統屬性中,如下所示:
@SuppressWarnings("unused")
private static ApplicationContext applicationContext;
public static void main( String[] args ) throws NamingException
{
Properties props = System.getProperties();
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.enterprise.naming.impl.SerialInitContextFactory");
jndiProps.put(Context.STATE_FACTORIES,
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
jndiProps.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
jndiProps.put("org.omg.CORBA.ORBInitialHost", "localhost");
// optional. Defaults to 3700. Only needed if target orb port is not 3700.
jndiProps.put("org.omg.CORBA.ORBInitialPort", "8037");
System.setProperties(props);
applicationContext = SpringApplication.run(App.class, args);
}
在用新的屬性集覆蓋系統屬性之前,您必須首先獲取初始系統屬性並添加到其中,否則您將破壞整個事情。
它也必須在運行 SpringApplication 之前完成,因為這是初始化發生的地方。
我必須做的最后一件事是將前面提到的 GlassFish AppClient 移到 pom.xml 中所有 Spring 依賴項下。 讓它靠近頂部是為我認為在 Tomcat 服務器本身中的連接器類創建一個 NoClassDefFoundError 。
<dependency>
<groupId>org.glassfish.main.appclient</groupId>
<artifactId>gf-client</artifactId>
<version>5.1.0</version>
</dependency>
之后,我打開了我的網頁,在我的 GlassFish 服務器上的 EJB Singleton 中創建的測試文本通過我的 Spring Boot 客戶端傳遞到我的瀏覽器中。 證明系統按預期工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.