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
的并发控制是否可以解决问题。