【问题标题】:@Named bean synchronization with localhost@Named bean 与 localhost 同步
【发布时间】:2012-04-15 17:38:30
【问题描述】:

附带条件:我不想将数据库用于以下用途。

我收到一个关闭的套接字异常,我将其归因于在 localhost 上运行的叶子节点的延迟。预计会有延迟,我只是不知道如何处理。

我知道,从一个单独的 CLI 程序中,叶子节点的响应正确并且实用程序类正在工作。对于这个应用程序,我可以从 glassfish 日志中看到:

nntp: <68 <x1-QQumhvcthNpaS3eWCQlR7Bleszk@gwene.org>
nntp: <69 <x1-N15vT7mtEkMzewjHjlTmjzBSpFY@gwene.org>
nntp: <70 <x1-cfsH29WrlKvYMd+t1ohsVSekIy0@gwene.org>
nntp: <71 <x1-DaQK7LTcaCQP3O3Us+8HTxTDALQ@gwene.org>
nntp: <72 <x1-1+PG1MuOkVUmzmY2XWRAWCKwbD8@gwene.org>
nntp: <73 <x1-sXoWsN3I56qalgUJAuT6+jWCYLE@gwene.org>
nntp: <74 <x1-osEXmt5CXnwu3eVGVAb4e11PZnY@gwene.org>
nntp: <.
nntp: >QUIT
nntp: <205 Always happy to serve!
INFO: GOT MESSAGES AS SO..
INFO: [gnu.mail.providers.nntp.NNTPMessage@1e2218b, gnu.mail.providers.nntp.NNTPMessage@10838ec, gnu.mail.providers.nntp.NNTPMessage@d14f1b, gnu.mail.providers.nntp.NNTPMessage@1a0b187, gnu.mail.providers.nntp.NNTPMessage@e74409, gnu.mail.providers.nntp.NNTPMessage@123ce36, gnu.mail.providers.nntp.NNTPMessage@1b7515a, gnu.mail.providers.nntp.NNTPMessage@3e0a57, gnu.mail.providers.nntp.NNTPMessage@118d5e0, gnu.mail.providers.nntp.NNTPMessage@1819b07, gnu.mail.providers.nntp.NNTPMessage@1e91886, gnu.mail.providers.nntp.NNTPMessage@493ab5, gnu.mail.providers.nntp.NNTPMessage@1ad7ec5, gnu.mail.providers.nntp.NNTPMessage@15dbf8d, gnu.mail.providers.nntp.NNTPMessage@1cae695, gnu.mail.providers.nntp.NNTPMessage@1e86f47, gnu.mail.providers.nntp.NNTPMessage@e1d295, gnu.mail.providers.nntp.NNTPMessage@1c87547, gnu.mail.providers.nntp.NNTPMessage@18b9691, gnu.mail.providers.nntp.NNTPMessage@14a0c6f, gnu.mail.providers.nntp.NNTPMessage@765340, gnu.mail.providers.nntp.NNTPMessage@53b2e4, gnu.mail.providers.nntp.NNTPMessage@10597ed, gnu.mail.providers.nntp.NNTPMessage@396c01, gnu.mail.providers.nntp.NNTPMessage@1e1f03d, gnu.mail.providers.nntp.NNTPMessage@63410a, gnu.mail.providers.nntp.NNTPMessage@433231, gnu.mail.providers.nntp.NNTPMessage@1945928, gnu.mail.providers.nntp.NNTPMessage@696ea0, gnu.mail.providers.nntp.NNTPMessage@1dde855, gnu.mail.providers.nntp.NNTPMessage@1c0559e, gnu.mail.providers.nntp.NNTPMessage@352a35, gnu.mail.providers.nntp.NNTPMessage@660b04, gnu.mail.providers.nntp.NNTPMessage@15d401f, gnu.mail.providers.nntp.NNTPMessage@11cddfb, gnu.mail.providers.nntp.NNTPMessage@31917d, gnu.mail.providers.nntp.NNTPMessage@46be43, gnu.mail.providers.nntp.NNTPMessage@7523ed, gnu.mail.providers.nntp.NNTPMessage@89a405, gnu.mail.providers.nntp.NNTPMessage@6f5b1b, gnu.mail.providers.nntp.NNTPMessage@c649d6, gnu.mail.providers.nntp.NNTPMessage@19882d, gnu.mail.providers.nntp.NNTPMessage@3b8201, gnu.mail.providers.nntp.NNTPMessage@d44937, gnu.mail.providers.nntp.NNTPMessage@112e45c, gnu.mail.providers.nntp.NNTPMessage@14e8cfc, gnu.mail.providers.nntp.NNTPMessage@a15e3, gnu.mail.providers.nntp.NNTPMessage@22f041, gnu.mail.providers.nntp.NNTPMessage@1cb71d7, gnu.mail.providers.nntp.NNTPMessage@19ee882, gnu.mail.providers.nntp.NNTPMessage@1b2d490, gnu.mail.providers.nntp.NNTPMessage@1a16b05, gnu.mail.providers.nntp.NNTPMessage@79412e, gnu.mail.providers.nntp.NNTPMessage@a66063, gnu.mail.providers.nntp.NNTPMessage@10203ea, gnu.mail.providers.nntp.NNTPMessage@14f0db5, gnu.mail.providers.nntp.NNTPMessage@10ceef3, gnu.mail.providers.nntp.NNTPMessage@1bc33e, gnu.mail.providers.nntp.NNTPMessage@af5b1a, gnu.mail.providers.nntp.NNTPMessage@860956, gnu.mail.providers.nntp.NNTPMessage@1cf1146, gnu.mail.providers.nntp.NNTPMessage@1770fb1, gnu.mail.providers.nntp.NNTPMessage@1a76bc3, gnu.mail.providers.nntp.NNTPMessage@940c94, gnu.mail.providers.nntp.NNTPMessage@1c5d10c, gnu.mail.providers.nntp.NNTPMessage@1fa00d, gnu.mail.providers.nntp.NNTPMessage@44ecf0, gnu.mail.providers.nntp.NNTPMessage@11f88e8, gnu.mail.providers.nntp.NNTPMessage@1554648, gnu.mail.providers.nntp.NNTPMessage@17921a7, gnu.mail.providers.nntp.NNTPMessage@1905dbf, gnu.mail.providers.nntp.NNTPMessage@fad175]
INFO: ..GOT MESSAGES AS SO

NNTP 消息最终会被加载。只是它似乎没有及时返回到 bean,或者,如果它确实返回,它可能是 bean 的错误实例。我推断第一个 bean 可以正常通过,但是另一个 bean 出现套接字问题,因为 Leafnode 很忙。看起来 bean 构造函数被多次调用,这当然没问题,但可能是第二个 bean 关闭套接字的原因。

那么,我如何隔离延迟问题,以便任何 MessageBean 都获得 err ?enum 单例? javax.mail.Message 的正确吗? (我使用的是 GNU NNTP 库,它比 Apache 好得多,而且运行良好。)

这是 facelets 客户端:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                template="./template.xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:c="http://java.sun.com/jsp/jstl/core"
                xmlns:f="http://java.sun.com/jsf/core">
    <ui:define name="left">
        <h:button id="submit" value="click me" />
    </ui:define>
    <ui:define name="content">
        <ui:repeat value="#{messageBean.messages}" var="message">
            <li>
                <h:outputText value="#{message.messageNumber}" />
                <h:outputText value="#{message.subject}" />
            </li>
        </ui:repeat>
    </ui:define>
</ui:composition>

和支持 MessageBean 一样:

package net.bounceme.dur.nntp;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.mail.Message;

@Named
@SessionScoped
public class MessageBean implements Serializable {

    private static final long serialVersionUID = 1;
    private static Logger logger = Logger.getLogger(MessageBean.class.getName());
    private static Level level = Level.INFO;

    public MessageBean() {
        logger.log(level, "MessageBean..");
    }

    public List<Message> getMessages() throws Exception {
        logger.log(level, "MessageBean.getMessages..");
        List<Message> messages = new ArrayList<Message>();
        messages = NNTP.getMessages();
        logger.log(level, "GOT MESSAGES AS SO..");
        logger.log(level, messages.toString());
        logger.log(level, "..GOT MESSAGES AS SO");
        return messages;
    }
}

现在,MessageBean 调用实用程序 NNTP 类,该类与 localhost 上的叶节点交互,因此从 CLI 中它非常快。但是,对于 facelets,显然不够快,因为我不断收到套接字错误。

从记录到 Glassfish,我看到叶子节点正确地将文章返回到实用程序类,并且最终 MessageBean 甚至有一个大列表。

问题似乎是 MessageBean 可能有多个实例,应该有。然而,他们并不是都能够同时查询叶子节点,大概是成功的。也许这就是套接字错误的根源。

无论如何,我不想将 javax.mail.Message 持久化到数据库,leafnode 已经很好地持久化了消息。我非常想与本地主机上的叶子节点交互。

我需要某种可怕的枚举单例吗?这是我所知道的唯一“模式”,所以我认为它必须适用于这种情况。或者,是否有一些替代方法可以减慢 MessageBean 的速度,以确保它在将消息传递给 facelet 之前确实从实用程序 NNTP 类获取消息?或者,这样的延迟会导致某种错误吗?

这里有什么好的方法?我不是在尝试构建一个功能齐全的 NNTP 客户端,只是在摆弄leafnode,它有一些延迟。

-----------------------------------

解决方案:关闭套接字 properly 并使用容器类,如下面的 setEntities :

package net.bounceme.dur.nntp;

import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.mail.*;

public enum SingletonNNTP {

    INSTANCE;
    private final Logger logger = Logger.getLogger(SingletonNNTP.class.getName());
    private final Level level = Level.INFO;
    private Properties props = new Properties();
    private List<Message> messages = new ArrayList<Message>();
    private boolean loaded = false;
    private List<MessageEntity> messageEntities = new ArrayList<MessageEntity>();

    private SingletonNNTP() {
        logger.logp(level, "SingletonNNTP", "SingletonNNTP", "only once...");
        props = PropertiesReader.getProps();
        if (!loaded) {
            try {
                loaded = setMessages();
            } catch (Exception ex) {
                Logger.getLogger(SingletonNNTP.class.getName()).log(Level.SEVERE, "FAILED TO LOAD MESSAGES", ex);
            }
        }
    }

    public List<Message> getMessages(boolean debug) throws Exception {
        logger.logp(level, "SingletonNNTP", "getMessages", "returning messages");
        return Collections.unmodifiableList(messages);
    }

    private boolean setMessages() throws Exception {
        logger.logp(level, "SingletonNNTP", "setMessages", "connecting to leafnode");
        Session session = Session.getDefaultInstance(props);
        session.setDebug(false);
        Store store = session.getStore(new URLName(props.getProperty("nntp.host")));
        store.connect();
        Folder root = store.getDefaultFolder();
        Folder folder = root.getFolder(props.getProperty("nntp.group"));
        folder.open(Folder.READ_ONLY);
        Message[] msgs = folder.getMessages();
        messages = Arrays.asList(msgs);
        setEntities();
        folder.close(false);
        store.close();
        return true;
    }

    public List<MessageEntity> getEntities() {
        logger.logp(level, "SingletonNNTP", "getEntities", "getting entities");
        for (MessageEntity m : messageEntities) {
            for (Header h : m.getHeaders()) {
                logger.log(level, h.toString());
            }
        }
        return Collections.unmodifiableList(messageEntities);
    }

    private void setEntities() throws Exception {
        logger.logp(level, "SingletonNNTP", "loadEntities", "trying to convert");
        messageEntities = new ArrayList<MessageEntity>();
        for (Message message : messages) {
            MessageEntity entity = new MessageEntity();
            Enumeration allHeaders = message.getAllHeaders();
            List<Header> headers = new ArrayList<Header>();
            while (allHeaders.hasMoreElements()) {
                Header hdr = (Header) allHeaders.nextElement();
                headers.add(hdr);
            }
            entity.setHeaders(headers);
            entity.setSubject(message.getSubject());
            entity.setContent(message.getContent().toString());
            entity.setSentDate(message.getReceivedDate());
            messageEntities.add(entity);
        }
    }
}

【问题讨论】:

    标签: java sockets jsf glassfish facelets


    【解决方案1】:

    根据我对您的问题的理解,您实际上需要同步并发 访问NNTP.getMessages()。如果是这样并且您在 EJB 上下文中使用托管 bean,我相信 Managing Concurrent Access in a Singleton Session Bean 可以帮助您。如果没有直接帮助,我相信您可以利用ReentrantLock 来测试对NNTP 的并发控制是否可以解决问题。

    【讨论】:

    • 同步并发访问 NNTP.getMessages 听起来不错。我想我问的问题很糟糕,感谢您涉足它。这是一个并发问题,是的。我会相应地编辑主题并可能接受这个答案。谢谢。我只是想让 bean 等待实用程序类返回响应,即使它会导致延迟。
    • 工作,非常好。在我的@Named bean 中,MessageBean.getMessages() 将处理传递给同步的 getNNTP()。实用程序类未更改,仅 MessageBean.getNNTP() 需要同步。我不认为 MessageBean.getMessages() 可以同步?只有一次我真正不得不使用同步,哈哈。再次感谢。
    • 很高兴听到这个消息,很高兴更新您的问题以反映可能对其他人有用的解决方案。
    • 最终,同步方法并不能解决问题,我不太确定我做了什么让它像上面那样运行。或者,至少,它目前没有运行,所以我没有工作代码可以发布。当我(再次)获得一些工作代码时,我肯定会更新。再次感谢,它让我朝着正确的方向前进。
    • 好的,我添加了我理解的解决方案,即用我想要的数据创建我自己的类,一个容器,然后正常关闭套接字。我不能说为什么同步有效,因为它然后又开始产生错误。这个问题非常有缺陷,因为我问的不是我需要的。一个更好的问题应该是“为什么会发生这个套接字错误?”对不起,我应该问这个问题。我仍然不知道为什么同步工作了一段时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 2013-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多