Java 如何从Spring引导客户端到GlassFish服务器进行远程JNDI查找?

Java 如何从Spring引导客户端到GlassFish服务器进行远程JNDI查找?,java,spring,spring-boot,ejb,jndi,Java,Spring,Spring Boot,Ejb,Jndi,我从一个正常工作的Spring Boot应用程序开始,使用最新版本的Spring Boot和嵌入式Tomcat。它包含一个HomeController,其索引方法映射到webapp目录中相应的.jsp @RequestMapping(value={"/", "/home", "/home/index"}) public ModelAndView index() { ModelAndView mv = new ModelAndView("/home/index"); return

我从一个正常工作的Spring Boot应用程序开始,使用最新版本的Spring Boot和嵌入式Tomcat。它包含一个HomeController,其索引方法映射到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:

看起来很简单。我将导入Glassfish而不是WildFly的客户端模块,并使用Glassfish而不是WildFly的InitialContext属性

因此,我用以下内容更新了pom.xml(我还添加了一个包含远程接口的依赖项):

并更新了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;
}
@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);
}
我运行了GlassFish服务器,然后尝试运行我的Spring Boot应用程序。Sprint启动日志没有显示,过了一会儿,我得到了这个(这里是完整日志:):

我尝试访问localhost,它只是说:

This site can’t be reached
我把它弄得一团糟了一会儿,得出了一些结论:

  • 添加新的依赖项是打破SpringMVC并关闭我的web服务所需要的全部
  • Spring正试图与GlashFish集成,因为堆栈跟踪包括以下内容:

    位于org.springframework.jndi.jndemplate.lambda$lookup$0(jndemplate.java:157) 位于org.springframework.jndi.jndemplate.execute(jndemplate.java:92) 位于org.springframework.jndi.jndemplate.lookup(jndemplate.java:157) 位于org.springframework.jndi.jndemplate.lookup(jndemplate.java:179)

  • Spring完全忽略我的Bean并使用默认的GlassFish InitialContext,因为日志中的端口号仍然是3700,GlassFish的默认端口号,但我指定了8048

  • Spring以某种方式检测客户端模块,并定期尝试连接到Glassfish。问题是我完全不知道如何告诉Spring使用我的自定义InitialContext属性


    我在网上到处寻找解决办法。大多数类似的问题没有被很好地问到,也没有得到回答,其他问题是关于数据源的,这对我来说太具体了,因为我试图将整个服务层放在Jakarta EE服务器上。

    。我刚想好该怎么办。如果您查看堆栈跟踪,它将从Spring启动应用程序的开头开始:SpringApplication.run(app.class,args)

    Spring Boot实际上是在自己的初始化中初始化GlassFish AppClient。当我写这个问题的时候,这一点已经很清楚了

    唯一的方法是将InitialContext中的相同属性放入系统属性中,如下所示:

    @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;
    }
    
    @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依赖项下面。把它放在最上面就是为一个连接器类创建一个NoClassDefFoundError,我认为这个连接器类在Tomcat服务器本身中

    <dependency>
      <groupId>org.glassfish.main.appclient</groupId>
      <artifactId>gf-client</artifactId>
      <version>5.1.0</version>
    </dependency>
    
    
    org.glassfish.main.appclient
    gf客户端
    5.1.0
    
    在那之后,我打开了我的网页,在GlassFish服务器上的EJB单例中创建的测试文本通过我的SpringBoot客户端传递到我的浏览器中。证明系统按预期工作

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