Proviso:请不要将数据库用于以下用途。

我收到一个封闭的套接字异常,这归因于在本地主机上运行的leafnode的延迟。预计会有延迟,但我不确定该如何处理。

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

nntp: <68 <[email protected]>
nntp: <69 <[email protected]>
nntp: <70 <[email protected]>
nntp: <71 <[email protected]>
nntp: <72 <[email protected]>
nntp: <73 <[email protected]>
nntp: <74 <[email protected]>
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单实例? 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上的leafnode进行交互,因此从CLI来看它相当快。但是,对于facelets来说,显然不够快,因为我不断收到套接字错误。

从登录到Glassfish,我看到leafnode将文章正确地返回到实用程序类,并且最终,MessageBean甚至有一个很大的List。

问题似乎在于,也许应该有多个MessageBean实例。但是,大概并不能全部同时查询leafnode并取得成功。也许这是套接字错误的根源。

无论如何,我都不想将javax.mail.Message持久保存到数据库中,leafnode已经很好地保存了消息。我严格希望与localhost上的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);
        }
    }
}

最佳答案

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

10-07 16:55