現在、2つのクライアント(プロデューサー/コンシューマー)があり、JMSを介して大きなファイルを送信しようとしています。ファイルを正常に作成し、JMSサーバーに問題なく送信しています。問題は、メッセージを消費しようとすると、次の例外が発生することです。
Aug 24, 2012 11:25:37 AM client.Client$1 onException
SEVERE: Connection to the Server has been lost, will retry in 30 seconds. weblogic.jms.common.LostServerException: java.lang.Exception: weblogic.rjvm.PeerGoneException: ; nested exception is:
weblogic.socket.MaxMessageSizeExceededException: Incoming message of size: '10000080' bytes exceeds the configured maximum of: '10000000' bytes for protocol: 't3'
<Aug 24, 2012 11:25:37 AM CDT> <Error> <Socket> <BEA-000403> <IOException occurred on socket: Socket[addr=127.0.0.1/127.0.0.1,port=7001,localport=51764]
weblogic.socket.MaxMessageSizeExceededException: Incoming message of size: '10000080' bytes exceeds the configured maximum of: '10000000' bytes for protocol: 't3'.
weblogic.socket.MaxMessageSizeExceededException: Incoming message of size: '10000080' bytes exceeds the configured maximum of: '10000000' bytes for protocol: 't3'
at weblogic.socket.BaseAbstractMuxableSocket.incrementBufferOffset(BaseAbstractMuxableSocket.java:174)
at weblogic.rjvm.t3.MuxableSocketT3.incrementBufferOffset(MuxableSocketT3.java:351)
at weblogic.socket.SocketMuxer.readFromSocket(SocketMuxer.java:983)
at weblogic.socket.SocketMuxer.readReadySocketOnce(SocketMuxer.java:922)
これは、WebLogicのMaxMessageサイズ設定に関係しており、コードの問題ではないと思います(もちろん、間違っている可能性があります)。これが最大メッセージサイズの設定です
このプロトコルの最大メッセージサイズが例外が主張しているものよりも大きいため、なぜこの例外が発生するのかわかりません...何か考えはありますか?
サーバー開始引数-Dweblogic.MaxMessageSize=200000000も追加しようとしましたが、役に立ちませんでした。
これは、MessageListenerを設定した場所のコードと、メッセージコンシューマー自体です。
public boolean setClient(MessageListener listener) {
try {
Properties parm = new Properties();
parm.setProperty("java.naming.factory.initial",
"weblogic.jndi.WLInitialContextFactory");
parm.setProperty("java.naming.provider.url", iProps.getURL());
parm.setProperty("java.naming.security.principal", iProps.getUser());
parm.setProperty("java.naming.security.credentials",
iProps.getPassword());
ctx = new InitialContext(parm);
final QueueConnectionFactory connectionFactory = (QueueConnectionFactory) ctx
.lookup(iProps.getConFactory());
connection = connectionFactory.createQueueConnection();
((WLConnection) connection)
.setReconnectPolicy(JMSConstants.RECONNECT_POLICY_ALL);
((WLConnection) connection).setReconnectBlockingMillis(30000L);
((WLConnection) connection).setTotalReconnectPeriodMillis(-1L);
session = connection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
queue = (Queue) ctx.lookup(iProps.getQueue());
// The following code in the switch statement is the only code that
// differs for the producer and consumer.
switch (cType)
{
case PRODUCER: {
producer = (WLMessageProducer) session
.createProducer(queue);
// Setting to send large files is done in WebLogic
// Administration Console.
// Set
producer.setSendTimeout(60000L);
break;
}
case CONSUMER: {
consumer = session.createConsumer(queue);
if (listener != null) {
consumer.setMessageListener(listener);
}else{
log.warning("A Message listener was not set for the consumer, messages will not be acknowledged!");
}
break;
}
default:
log.info("The client type " + cType.toString()
+ " is not currently supported!");
return false;
}
connection.setExceptionListener(new ExceptionListener() {
@Override
public void onException(JMSException arg0) {
Logger log2 = new MyLogger().getLogger("BPEL Client");
if (arg0 instanceof LostServerException) {
log2.severe("Connection to the Server has been lost, will retry in 30 seconds. "
+ arg0.toString());
} else {
log2.severe(arg0.toString());
}
}
});
shutdownListener = new ShutdownListener(connection, session, producer, consumer);
connection.start();
log.info("Successfully connected to " + iProps.getURL());
return true;
} catch (JMSException je) {
log.severe("Could not connect to the WebLogic Server, will retry in 30 seconds. "
+ je.getMessage());
try {
Thread.sleep(30000L);
} catch (InterruptedException e) {
log.warning(e.toString());
}
return setClient(listener);
} catch (Exception e) {
log.severe("Could not connect to the WebLogic Server, will retry in 30 seconds. "
+ e.toString());
try {
Thread.sleep(30000L);
} catch (InterruptedException ie) {
log.warning(ie.toString());
}
return setClient(listener);
}
}
これがMessageListenerです:
public class ConsumerListener implements MessageListener {
private Logger log;
private File destination;
private Execute instructions;
public ConsumerListener(Execute instructions, File destination) {
this.instructions = instructions;
this.destination = destination;
log = new MyLogger().getLogger("BPEL Client");
}
@Override
public void onMessage(Message arg0) {
try {
if (arg0.getJMSRedelivered()) {
log.severe("A re-delivered message has been received, and it has been ignored!"
+ arg0.toString());
} else {
try {
if (arg0 instanceof TextMessage) {
consumeMessage((TextMessage) arg0);
} else if (arg0 instanceof BytesMessage) {
consumeMessage((BytesMessage) arg0);
} else {
log.warning("Currently, only TextMessages and BytesMessages are supported!");
}
} catch (JMSException e) {
log.severe(e.toString());
} catch (IOException e) {
log.severe(e.toString());
} catch (Throwable t) {
log.severe(t.toString());
}
}
} catch (JMSException e) {
log.severe(e.toString());
}
}
/**
* Unwraps the JMS message received and creates a file and a control file if
* there are instructions present.
*
* @param textMessage
* JMS message received to be consumed.
* @throws JMSException
* @throws IOException
*/
protected void consumeMessage(TextMessage textMessage) throws JMSException,
IOException {
// ***All properties should be lowercase. for example fileName
// should be
// filename.***
String fileName = textMessage.getStringProperty("filename");
if (fileName == null || fileName.isEmpty()) {
fileName = textMessage.getStringProperty("fileName");
}
if (fileName != null && !fileName.isEmpty()) {
// Check if the
// file name is equal to the shutdown file. If it
// is, shutdown the consumer. This is probably not a good way to
// do this, as the program can no longer be shutdown locally!
// We have a file in the queue, need to create the file.
createFile(destination.getAbsolutePath() + "\\" + fileName,
textMessage.getText());
log.info("Done creating the file");
String inst = textMessage.getStringProperty("instructions");
// If there are instructions included, then create the
// instruction file, and route the message based on this file.
if (inst != null && !inst.isEmpty()) {
// We need to rout the file.
log.info("Instructions found, executing instructions");
String[] tokens = fileName.split("\\.");
String instFileName = "default.ctl";
if (tokens.length == 2) {
instFileName = tokens[0] + ".ctl";
}
File controlFile = createFile(destination.getAbsolutePath()
+ "\\" + instFileName, inst);
Control control = new Control(controlFile);
instructions.execute(control);
log.info("Done executing instructions");
} else {
log.info("No instructions were found");
}
log.info("Done consuming message: " + textMessage.getJMSMessageID());
}
}
/**
* Unwraps the JMS message received and creates a file and a control file if
* there are instructions present.
*
* @param bytesMessage
* The bytes payload of the message.
* @throws JMSException
* @throws IOException
*/
protected void consumeMessage(BytesMessage bytesMessage)
throws JMSException, IOException {
// ***All properties should be lowercase. for example fileName
// should be
// filename.***
log.info("CONSUME - 1");
String fileName = bytesMessage.getStringProperty("filename");
if (fileName == null || fileName.isEmpty()) {
fileName = bytesMessage.getStringProperty("fileName");
}
if (fileName != null && !fileName.isEmpty()) {
// Check if the
// file name is equal to the shutdown file. If it
// is, shutdown the consumer. This is probably not a good way to
// do this, as the program can no longer be shutdown locally!
// We have a file in the queue, need to create the file.
byte[] payload = new byte[(int) bytesMessage.getBodyLength()];
bytesMessage.readBytes(payload);
createFile(destination.getAbsolutePath() + "\\" + fileName, payload);
log.info("Done creating the file");
String inst = bytesMessage.getStringProperty("instructions");
// If there are instructions included, then create the
// instruction file, and route the message based on this file.
if (inst != null && !inst.isEmpty()) {
// We need to rout the file.
log.info("Instructions found, executing instructions");
String[] tokens = fileName.split("\\.");
String instFileName = "default.ctl";
if (tokens.length == 2) {
instFileName = tokens[0] + ".ctl";
}
File controlFile = createFile(destination.getAbsolutePath()
+ "\\" + instFileName, inst);
Control control = new Control(controlFile);
instructions.execute(control);
log.info("Done executing instructions");
} else {
log.info("No instructions were found");
}
log.info("Done consuming message: "
+ bytesMessage.getJMSMessageID());
}
}
/**
* Creates a file with the given filename (this should be an absolute path),
* and the text that is to be contained within the file.
*
* @param fileName
* The filename including the absolute path of the file.
* @param fileText
* The text to be contained within the file.
* @return The newly created file.
* @throws IOException
*/
protected File createFile(String fileName, String fileText)
throws IOException {
File toCreate = new File(fileName);
FileUtils.writeStringToFile(toCreate, fileText);
return toCreate;
}
/**
* Creates a file with the given filename (this should be an absolute path),
* and the text that is to be contained within the file.
*
* @param fileName
* The filename including the absolute path of the f ile.
* @param fileBytes
* The bytes to be contained within the file.
* @return The newly created file.
* @throws IOException
*/
protected File createFile(String fileName, byte[] fileBytes)
throws IOException {
File toCreate = new File(fileName);
FileUtils.writeByteArrayToFile(toCreate, fileBytes);
return toCreate;
}
}