使用GlassFish 5在JNDI中存储单例Bean

问题描述 投票:0回答:1

我在Eclipse中有一个工作正常的Glassfish 5设置。

我有这样设置的模块:

普通

  • 包含具有@remote和@local批注的Singleton bean的远程接口
  • 作为pom依赖项包含在所有其他模块中

核心

  • 包含一个实现通用接口的单例bean
  • 旨在包含存储在JNDI中的服务类,该服务类允许任意数量的客户端查找和存储数据和/或访问其他服务逻辑
  • 构建一个部署到GlassFish上的战争文件

桌面

  • 对单例bean进行InitialContext查找。 (我打算将其抽象为服务查找设计模式)。
  • 打算是一个远程访问服务器上存储的bean的桌面客户端。
  • 现在,我只是想让它可以远程访问核心服务,并在控制台上打印一些文本以证明其有效。

我认为我的问题源于对如何在JNDI中存储自定义bean的误解。我查看了Google,但大多数时候都找到文章和问题的答案,告诉我在Singleton批注中添加name和maptedName,或者它们仅显示如何将预定义的bean(例如Boolean或String)添加到JDNI中,而不是自定义的。

我的bean是这样定义的:

@Singleton(name = "BookService", mappedName = "ejb/BookService")
public class BookServiceImpl implements BookService {

    private static final long serialVersionUID = 1L;

这将在Glassfish服务器上显示以下内容:Core Server Screenshot

但是JNDI中什么也没有出现:JNDI Screenshot

客户端以这种方式进行InitialContext查找(我尝试了多种写JNDI名称的方法:]

BookService bookService = (BookService) initialContext.lookup("java:global/core/BookService");

使用这些配置(我定义的域的基本端口为8000,因此每个端口均为8000或更高):

glashfishEnvironmentTable = new Hashtable<String, String>();
glashfishEnvironmentTable.put(Context.INITIAL_CONTEXT_FACTORY,
            "com.sun.enterprise.naming.impl.SerialInitContextFactory");
glashfishEnvironmentTable.put(Context.STATE_FACTORIES,
            "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
glashfishEnvironmentTable.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming");
//glashfishEnvironmentTable.put(Context.PROVIDER_URL, "ejbd://localhost:8080/");
// on a different host than the appserver   
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialHost", "localhost");
// optional.  Defaults to 3700.  Only needed if target orb port is not 3700.
glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialPort", "8037");

运行时出现这样的错误:

Exception in thread "main" javax.naming.CommunicationException: Communication exception for SerialContext[myEnv={org.omg.CORBA.ORBInitialPort=8037, java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, org.omg.CORBA.ORBInitialHost=localhost, java.naming.factory.url.pkgs=com.sun.enterprise.naming, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl} [Root exception is java.rmi.MarshalException: CORBA MARSHAL 1330446343 No; nested exception is: 
org.omg.CORBA.MARSHAL: FINE: 00810007: Underflow in BufferManagerReadStream after last fragment in message  vmcid: OMG  minor code: 7  completed: No]

我认为我的InitialContext配置正确,因为当我这样在JNDI中手动定义bean时(ServiceFactory不会做任何事情,因为我不知道如何正确扩展ObjectFactory):

Bean defined in JNDI

我明白了:

Exception in thread "main" java.lang.ClassCastException: javax.naming.Reference cannot be cast to common.service.BookService

我是否有简单的解决方法,或者是将油和水混合在一起以使EJB Singleton进入JNDI?还是我缺少EJBHome或Servlet之类的大物件?

我需要扩展工厂类以将服务类添加到JDNI中,还是ObjectFactory应该工作?如果必须扩展工厂课程,该如何处理?

我希望我已经很好地定义了问题的范围,但这对我来说是新的,因此,如果有人有实施类似内容的经验,我将感谢您提供的所有使我接近正确解决问题的意见。

java jakarta-ee glassfish ejb jndi
1个回答
0
投票

我知道了。我做了两本不该做的事。

  1. 我在构建战争文件之前忘了先行安装我的通用模块... Doh!
  2. 似乎@Remote和@Local批注不能在同一个接口中,否则它将失败(这很可惜,因为我试图进行设置,因此我不必具有两个几乎相同的接口) 。

[这里有更多详细信息,以防其他人遇到类似的问题并需要查看有效的方法(我尚未在这里进行@Local,因为我还没有尝试过。不过添加起来应该很简单):

  1. 对于远程执行,您需要一个带有@Remote注释的接口,该接口扩展了Serializable(可扩展性(客户端/服务器接口要求序列化)。
import java.io.Serializable;

public interface Remote extends Serializable{

}
import javax.ejb.Remote;

@Remote
public interface BookServiceRemote extends Remote {

    public String readBook();

}
  1. 您的战争文件需要包含BookServiceImpl
import javax.ejb.Singleton;

import us.boggs.template.common.service.BookServiceRemote;

@Singleton(name = "BookService")
public class BookServiceImpl implements BookServiceRemote {

    private static final long serialVersionUID = 1L;

    @Override
    public String readBook() {
        return "Read the book.";
    }
}
  1. 您的客户端pom.xml必须包含通用模块,并且此:
<dependency>
 <groupId>org.glassfish.main.appclient</groupId>
 <artifactId>gf-client</artifactId>
 <version>5.1.0</version>
</dependency>
  1. 您的客户端主要方法可以通过创建InitialContext并进行查找来使用它(我的基本端口是8000,所以我的ORBInitialPort是8000 + 37 = 8037):
private static Hashtable<String, String> glashfishEnvironmentTable;

static {
    glashfishEnvironmentTable = new Hashtable<String, String>();
    glashfishEnvironmentTable.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.enterprise.naming.impl.SerialInitContextFactory");
    glashfishEnvironmentTable.put(Context.STATE_FACTORIES,
                "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
    glashfishEnvironmentTable.put(Context.URL_PKG_PREFIXES, "com.sun.enterprise.naming"); 
    glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialHost", "localhost");
    // optional.  Defaults to 3700.  Only needed if target orb port is not 3700.
    glashfishEnvironmentTable.put("org.omg.CORBA.ORBInitialPort", "8037");
}
InitialContext initialContext = new InitialContext(glashfishEnvironmentTable);
        BookServiceRemote bookService = (BookServiceRemote) initialContext.lookup("java:global/core/BookService");
System.out.println(bookService.readBook());
© www.soinside.com 2019 - 2024. All rights reserved.