简体   繁体   English

如何从 Spring Boot Client 到 GlassFish Server 进行远程 JNDI 查找?

[英]How to do a remote JNDI lookup from Spring Boot Client to GlassFish Server?

I am starting with a working Spring Boot application, using the latest version of Spring Boot and embedded Tomcat.我从一个可用的 Spring Boot 应用程序开始,使用最新版本的 Spring Boot 和嵌入式 Tomcat。 It contains a HomeController with an index method mapped to a corresponding .jsp in the webapp directory.它包含一个 HomeController,其 index 方法映射到 webapp 目录中相应的 .jsp。

@RequestMapping(value={"/", "/home", "/home/index"})
public ModelAndView index() {
    ModelAndView mv = new ModelAndView("/home/index");
    return mv;
}

My goal is to do a remote JNDIlookup to a glassfish server to access an EJB Singleton Service.我的目标是对 glassfish 服务器进行远程 JNDIlookup 以访问 EJB 单例服务。 I have previously verified using a simple desktop client that Remote JNDI lookups to my Glassfish server are working perfectly.我之前已经使用一个简单的桌面客户端验证过,对我的 Glassfish 服务器的远程 JNDI 查找工作正常。

I followed this tutorial for WildFly, repurposing it for Glassfish: https://www.baeldung.com/spring-ejb我遵循了 WildFly 的本教程,将其重新用于 Glassfish: https ://www.baeldung.com/spring-ejb

Seemed simple enough.看起来很简单。 Instead of WildFly's client module, I would import Glassfish's, and instead of WildFly's InitialContext properties, I would use Glassfish's.我会导入 Glassfish 的而不是 WildFly 的客户端模块,并且我会使用 Glassfish 的而不是 WildFly 的 InitialContext 属性。

So I updated my pom.xml with this (I also added a dependency containing remote interfaces):所以我用这个更新了我的 pom.xml(我还添加了一个包含远程接口的依赖项):

 <dependency>
      <groupId>org.glassfish.main.appclient</groupId>
      <artifactId>gf-client</artifactId>
      <version>5.1.0</version>
 </dependency>

Updated McvConfig.java like this (my base port for GlassFish is 8000, and it adds 37 for the JNDI port):像这样更新 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;
 }

And Updated HomeController like this:并像这样更新了 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;
}

I ran the GlassFish server, and then tried to run my Spring Boot app.我运行了 GlassFish 服务器,然后尝试运行我的 Spring Boot 应用程序。 The Sprint Boot logs did not show up, and after a while, I got this instead (Full Log Here: https://pastebin.com/E11xLmFN ): 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

I tried accessing localhost and it just said:我尝试访问本地主机,它只是说:

This site can’t be reached

I messed around with it for a while, and concluded a few things:折腾了一会,总结了几点:

  1. Adding the new dependency was all it took to break Spring MVC and take down my web service.添加新的依赖项就是破坏 Spring MVC 并关闭我的 Web 服务所需的全部。
  2. Spring is trying to integrate with GlashFish, because the stack trace includes this: Spring 正在尝试与 GlashFish 集成,因为堆栈跟踪包括以下内容:

    at org.springframework.jndi.JndiTemplate.lambda$lookup$0(JndiTemplate.java:157) at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:92) at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:157) at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:179)在 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)

  3. Spring is completely ignoring my Bean and using the default GlassFish InitialContext, because the port number in the logs is still 3700, the default for GlassFish, but I specified 8048. Spring 完全忽略了我的 Bean 并使用默认的 GlassFish InitialContext,因为日志中的端口号仍然是 3700,GlassFish 的默认值,但我指定了 8048。

Spring is somehow detecting the client module and periodically attempting to connect to Glassfish. Spring 以某种方式检测客户端模块并定期尝试连接到 Glassfish。 The problem is that I have absolutely no idea how to tell Spring to use my custom InitialContext properties.问题是我完全不知道如何告诉 Spring 使用我的自定义 InitialContext 属性。

I looked all over the web for a solution.我在网上到处寻找解决方案。 Most of the similar questions were not asked very well, and received no answers, and others were specifically about the DataSource, which is too specific for me, as I am trying to put the entire Service layer on a Jakarta EE server.大部分类似的问题都没有问的很好,也没有得到答案,还有一些是专门关于DataSource的,这对我来说太具体了,因为我试图把整个Service层放在一个Jakarta EE服务器上。

Nevermind.没关系。 I just figured out what to do.我只是想知道该怎么做。 If you look in the stack trace, it is starting at the beginning of the Spring Boot app: SpringApplication.run(App.class, args);如果您查看堆栈跟踪,它从 Spring Boot 应用程序的开头开始: SpringApplication.run(App.class, args);

Spring Boot is literally initializing the GlassFish AppClient inside it's own initialization. Spring Boot 就是在它自己的初始化中初始化 GlassFish AppClient。 That much was clear when I wrote this question.当我写这个问题时,这很清楚。

It turns out the only way to do this is to put the same properties from the InitialContext inside the System Properties like this:事实证明,这样做的唯一方法是将 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);
}

You must take the initial System properties first and add to it, before overwriting the System properties with the new set of properties, or you will break the whole thing.在用新的属性集覆盖系统属性之前,您必须首先获取初始系统属性并添加到其中,否则您将破坏整个事情。

It must also be done before running the SpringApplication, because that is where the initialization is happening.它也必须在运行 SpringApplication 之前完成,因为这是初始化发生的地方。

The very last thing I had to do was move the aforementioned GlassFish AppClient underneath all of the Spring dependencies in the pom.xml.我必须做的最后一件事是将前面提到的 GlassFish AppClient 移到 pom.xml 中所有 Spring 依赖项下。 Having it near the top was creating a NoClassDefFoundError for a Connector class that I think was in the Tomcat server itself.让它靠近顶部是为我认为在 Tomcat 服务器本身中的连接器类创建一个 NoClassDefFoundError 。

<dependency>
  <groupId>org.glassfish.main.appclient</groupId>
  <artifactId>gf-client</artifactId>
  <version>5.1.0</version>
</dependency>

After that I opened my webpage and the test text created inside the EJB Singleton living on my GlassFish server was passed through my Spring Boot client and into my browser.之后,我打开了我的网页,在我的 GlassFish 服务器上的 EJB Singleton 中创建的测试文本通过我的 Spring Boot 客户端传递到我的浏览器中。 Proving the system works as expected.证明系统按预期工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM