为什么企业bean不能监听或接受套接字上的连接?

时间:2018-01-19 13:36:58

标签: java-ee ejb netty

我想从像Wildfly这样的Java EE容器中提供套接字,但在Oracle site上发现了这个EJB限制:

  

为什么企业bean不能监听或接受套接字上的连接?

     

因为如果企业bean正在监听套接字,它就无法被钝化 - 它必须始终可用。

我向Java EE专家提出了同样的问题并回答说#34;只有状态bean被钝化,所以从单独的无状态启动bean中提供套接字是好的,因为它没有被钝化"。

然而,我随后查阅了EJB 3.2规范并找到了另一种解释:

  

企业bean不得尝试侦听套接字,接受连接   套接字上的离子,或使用套接字进行多播

     

EJB体系结构允许企业bean实例成为网络套接字客户端,但它不允许它成为网络服务器。允许实例成为网络服务器会与企业bean的基本功能发生冲突 - 为EJB客户端提供服务。

唉。现在我很困惑。我真的不明白。

此限制是否已过时? 是否是没有单例启动bean(< EJB 3.1)?

的时候的遗留问题

类似于以下方法(使用Netty)甚至更简单的方法与Java ServerSocketChannel接受托管线程中的客户端连接有什么错误。 (不确定Netty是否会产生自己的线程)。

有人可以解释这个限制吗?

@Singleton
@Startup
public class SocketServerBean {

    @Resource
    private ManagedExecutorService managedExecutorService;

    private Channel channel;

    @PostConstruct
    private void startup() {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1, managedExecutorService);
        EventLoopGroup workerGroup = new NioEventLoopGroup(1, managedExecutorService);
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            // ...
                        }
                    })
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // Bind and start to accept incoming connections.
            channel = b.bind(6789).channel();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @PreDestroy
    private void shutdown() {
        channel.close();
    }
}

1 个答案:

答案 0 :(得分:1)

  

为什么企业bean不能监听或接受套接字上的连接?

因为EJB必须充当客户端,而不是服务器。这是EJB 3.2规范确认的。技术原因是EJB本质上是可序列化的,开放流(套接字,文件等)肯定不可序列化。

您的功能需求的正确方法是仅使用CDI托管bean,而不是EJB。

@ApplicationScoped
public class SocketServerBean {

    public void startup(@Observes @Initialized(ApplicationScoped.class) ServletContext context) {
        // ...

    }

    @PreDestroy
    private void shutdown() {
        // ...
    }
}

@Observes @Initialized(ApplicationScoped.class)将确保在应用程序初始化期间构造它。

在这个CDI托管bean中,如果需要,您可以反过来注入EJB。

另见:

无关到具体问题,在stinks上从Java EE应用程序手动打开套接字。你确定你也没有用这种方法遇到另一个XY-problem吗?也许你真的想用网络套接字?如果是这样,请改用JSR-356 @ServerEndpoint