UDP メッセージをリッスンするシンプルなアプリがあります。アプリは無期限に実行する必要があります。作成した MySQLConnect オブジェクトをインスタンス化することで、単一の jdbc データベース接続をインスタンス化します。次のようになります。
public MySQLConnect() {
this.instantiateConnection();
}
//Open the database connection. Done iniitally in
//the main class and only called again if the connection
//is closed due to an error in processing a message
public Connection instantiateConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/mydb?"
+ "user=user&password=pwd");
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
MySQLConnect クラス コンストラクターは、アプリが起動されると、UDPReceiver クラスから呼び出されます。その後、エラー処理が発生し、データベース接続が閉じられた場合にのみ再度呼び出されます。このクラスは次のようになります。
public class UDPReceiver {
private static int port = 2140;
private static int byteSize = 1024;
private static int timeOut = 5000;
@SuppressWarnings("unused")
private static int count;
static MySQLConnect dbConnect;
public static void main(String[] args) {
recvUDPMessage();
}
public static String recvUDPMessage() {
DataTransferService dts = new DataTransferServiceImp();
dbConnect = new MySQLConnect();
try {
DatagramSocket dsocket = null;
if (dsocket == null) {
dsocket = new DatagramSocket(port);
dsocket.setBroadcast(true);
dsocket.setReuseAddress(false);
}
byte[] inbuf = new byte[byteSize];
byte[] rcvMsg;
InetAddress fromIP;
DatagramPacket receivepacket = new DatagramPacket(inbuf,
inbuf.length);
dsocket.setSoTimeout(timeOut);
//Infinitely loop and listen for UDP messages
count = 0;
boolean loopRecv = true;
while (loopRecv) {
try {
count++;
dsocket.receive(receivepacket);
// temp = receivepacket.getAddress().toString();
fromIP = receivepacket.getAddress();
String fromIPString = fromIP.toString();
rcvMsg = receivepacket.getData();
String rcvString = new String(rcvMsg, 0, rcvMsg.length);
String rcvMessage = "Message Received from: "
+ fromIPString + " Message: " + rcvString + "\n";
System.out.println(rcvMessage);
ArrayList<String> al = getMessageElements(rcvString);
//Send array of message elements to service layer
dts.saveUDPMessage(dbConnect, al, Utils.getTimeStamp());
loopRecv = true;
} catch (IOException e) {
System.out.println("Listening . . .");
loopRecv = true;
}
}
} catch (SocketException e) {
System.err.println("Sockets Exception: " + e.getMessage());
} catch (Exception e) {
System.err.println(" Exception: " + e.getMessage());
} finally {
System.out.println(". . . Close DB");
dts.closeDBConnection(dbConnect);
// I added the creation MySQLConnect object after I was getting an error that the database was closed when trying to insert.
dbConnect = new MySQLConnect();
}
return "end of routine";
}
//Extract comma delimited message elements into an array
private static ArrayList<String> getMessageElements(String rcvString) {
StringTokenizer st = new StringTokenizer(rcvString, ",");
ArrayList<String> al = new ArrayList<String>();
while (st.hasMoreElements()) {
String messageElement = (String) st.nextElement();
al.add(messageElement);
}
return al;
}
}
これは約 8 時間実行され、次のエラーが表示されます。
スレッドのメイン java.lang.stackoverflowerror での例外
例外: メインスレッドの uncaughtexceptionhandler から java.lang.outofmemoryerror がスローされました
以前は、データベースが閉じられた後に MySQLConnect オブジェクトを再インスタンス化しませんでした。問題は、データベース接続が閉じられたというエラーを受け取ったことですが、私のプログラムはまだ jdbc 挿入を実行しようとしていました。jdbc挿入は、最初にインスタンス化された接続があるかどうかを確認し、インスタンス化されていない場合はインスタンス化します。MySQLConnect クラスのこのコードは次のようになります。
PreparedStatement prep = null;
if (connection == null) {
connection = this.instantiateConnection();
}
try {
prep = connection
.prepareStatement("insert into MyTable (UDPMessage)"
+ "values (?);");
prep.setString(1, udpMessage);
prep.addBatch();
prep.executeBatch();
UDP メッセージを無期限に処理し、エラーが発生した場合でもデータベースに書き込むように、このプロセスを正しく設計するにはどうすればよいでしょうか?
また、データの処理中に例外が発生したときに MySQLConnect クラスを再インスタンス化するときにメモリ不足エラーが発生することを解決するにはどうすればよいですか?
例外の後にこのクラスをインスタンス化することが正しくない場合、データベースへの接続を再インスタンス化してデータの処理を続行するにはどうすればよいですか?
ご協力いただきありがとうございます!