简体   繁体   English

使用 GlassFish 5 在 JNDI 中存储 Singleton Bean

[英]Storing Singleton Bean in JNDI with GlassFish 5

I have a working Glassfish 5 setup inside of Eclipse.我在 Eclipse 中有一个可用的 Glassfish 5 设置。

I have modules set up like this:我有这样设置的模块:

common常见的

  • contains remote interface for singleton bean with @remote and @local annotation包含带有 @remote 和 @local 注释的单例 bean 的远程接口
  • included in all other modules as a pom dependency包含在所有其他模块中作为 pom 依赖项

core

  • contains a singleton bean that implements the interface in common包含一个实现通用接口的单例 bean
  • intended to contain service classes stored in JNDI that allow any number of clients to lookup and store data and/or access other service logic旨在包含存储在 JNDI 中的服务类,允许任意数量的客户端查找和存储数据和/或访问其他服务逻辑
  • builds a war file that deploys onto GlassFish构建部署到 GlassFish 上的 war 文件

desktop桌面

  • does an InitialContext lookup of the singleton bean.对单例 bean 进行 InitialContext 查找。 (I intend to abstract this into the Service Lookup design pattern). (我打算将其抽象为服务查找设计模式)。
  • intended to be a desktop client that remotely accesses beans stored on the server.旨在成为远程访问存储在服务器上的 bean 的桌面客户端。
  • Right now, I'm just trying to get it to remotely access the service in core and print some text to the console proving it worked.现在,我只是想让它远程访问核心中的服务并将一些文本打印到控制台以证明它有效。

I think my problem stems from a misunderstanding of how to store a custom bean in JNDI in the first place.我认为我的问题源于对如何在 JNDI 中存储自定义 bean 的误解。 I looked on Google, but I mostly find articles and answers to questions telling me to add name and mappedName to the Singleton annotation or they only show how to add a predefined bean into JDNI such as a Boolean or String, and not something custom defined.我在 Google 上查看过,但我主要找到了一些文章和问题的答案,这些文章和问题的答案告诉我将 name 和 mapsName 添加到 Singleton 注释中,或者它们只显示如何将预定义的 bean 添加到 JDNI(例如布尔或字符串)中,而不是自定义定义的内容。

My bean is defined like this:我的 bean 定义如下:

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

    private static final long serialVersionUID = 1L;

which results in this on the Glassfish server: Core Server Screenshot这会在 Glassfish 服务器上产生这个结果: Core Server Screenshot

but nothing appears in JNDI: JNDI Screenshot但 JNDI 中什么也没有出现: JNDI 截图

The client does it's InitialContext lookup like this (I've tried multiple ways of writing the JNDI name):客户端像这样执行 InitialContext 查找(我尝试了多种编写 JNDI 名称的方法):

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

using these configurations (I defined my domain with a base port of 8000, so every port is 8000 + something):使用这些配置(我用 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");

I get an error like this when I run it:当我运行它时,我收到这样的错误:

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]

I think my InitialContext is configured properly because when I manually define the bean in JNDI like this (The ServiceFactory doesn't do anything, because I don't know how to properly extend ObjectFactory):我认为我的 InitialContext 配置正确,因为当我像这样在 JNDI 中手动定义 bean 时(ServiceFactory 不做任何事情,因为我不知道如何正确扩展 ObjectFactory):

Bean defined in JNDI JNDI 中定义的 Bean

I get this:我明白了:

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

Is there simple fix to this I am missing, or am I mixing oil and water trying to get an EJB Singleton into JNDI?是否有我缺少的简单解决方法,或者我是否将油和水混合以试图将 EJB Singleton 导入 JNDI? Or am I missing something big like an EJBHome or a Servlet?或者我是否缺少像 EJBHome 或 Servlet 这样的大东西?

Do I need to extend the factory class to add my service classes into JDNI, or should ObjectFactory work?我是否需要扩展工厂类以将我的服务类添加到 JDNI,或者 ObjectFactory 应该工作? If I must extend the factory class, how would I go about it?如果我必须扩展工厂类,我会怎么做?

I hope I've defined the scope of the question well enough, but this is all new to me, so if anybody has experience implementing something like this, I appreciate any input that gets me closer to doing it right.我希望我已经很好地定义了问题的范围,但这对我来说是全新的,所以如果有人有实施这样的事情的经验,我感谢任何让我更接近做正确事情的意见。

I figured it out.我想到了。 I did two things I shouldn't have.我做了两件我不应该做的事。

  1. I forgot to maven install my common module before building my war file... doh!在构建我的战争文件之前,我忘了 maven 安装我的通用模块......天哪!
  2. It seems that the @Remote and the @Local annotations cannot be in the same interface or it will fail (which is a shame, because I was trying to set it up so I didn't have to have two nearly identical interfaces).似乎@Remote 和@Local 注释不能在同一个界面中,否则会失败(这是一种耻辱,因为我试图设置它所以我不必有两个几乎相同的界面)。

Here are some more details in case someone else has a similar issue and needs to see something that works (I haven't done @Local here, because I haven't tried it yet. It should be trivial to add though):这里有一些更多细节,以防其他人有类似的问题并且需要看到一些有效的东西(我没有在这里做@Local,因为我还没有尝试过。尽管添加应该很简单):

  1. For remote execution, you need an interface annotated with @Remote that extends Serializable (Serialization is required for Client/Server interface).对于远程执行,您需要一个用@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. Your war file needs to contain the BookServiceImpl您的 war 文件需要包含 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. Your client pom.xml must include the common module and this:你的客户端 pom.xml 必须包含 common 模块和这个:
<dependency>
 <groupId>org.glassfish.main.appclient</groupId>
 <artifactId>gf-client</artifactId>
 <version>5.1.0</version>
</dependency>
  1. Your client main method can use this by creating an InitialContext and doing a lookup(My base port was 8000, so my ORBInitialPort is 8000+37=8037):您的客户端主方法可以通过创建 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());

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

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