IOException doesn't give enough information - java

My android program isn't working. I am using normal client-server sockets. I have tested my server with telnet and it works fine, but when I try it with my android program, it doesn't work (more details in a second). Here's my code:
Socket s = null;
try
{
String SocketServerAddress = db.getPhSsServerAddress();
Integer SocketServerPort = db.getPhSsServerPort();
s = new Socket(SocketServerAddress, SocketServerPort);
Log.d(MY_DEBUG_TAG, "Setting up Socket: " + SocketServerAddress + ":" + SocketServerPort);
DataOutputStream out = new DataOutputStream(s.getOutputStream());
DataInputStream in = new DataInputStream(s.getInputStream());
Log.d(MY_DEBUG_TAG, "Connected to: " + s.getInetAddress() + " on port " + s.getPort());
out.writeUTF("Helo, Server");
out.flush();
Log.d(MY_DEBUG_TAG, "Bytes written: " + out.size());
String st = in.readUTF();
Log.d(MY_DEBUG_TAG, "SocketServerResponse: " + st);
}
catch (UnknownHostException e)
{
Log.e(MY_ERROR_TAG, "UnknownHostException: " + e.getMessage() + "; " + e.getCause());
}
catch (IOException e)
{
Log.e(MY_ERROR_TAG, "IOException: " + e.getMessage() + "; " + e.getCause() + "; " + e.getLocalizedMessage());
}
finally
{
try {
s.close();
} catch (IOException e) {
Log.e(MY_ERROR_TAG, "IOException on socket.close(): " + e.getMessage() + "; " + e.getCause());
}
}
All I ever get here is a thrown IOException with no message or cause attached. The specific line causing the error is the String st = in.readUTF(). If I comment out that line, my code runs fine (no exceptions thrown), but my server does not acknowledge that any data has been sent to it. And of course I don't get any data back since that line is commented out.
So, how can I figure out what the problem is? Tonight I am going to try and see what is being passed with wireshark to see if that gives any insight.

Is the server using readUTF() and writeUTF() too? writeUTF() writes data in a unique format that can only be understood by readUTF(), which won't understand anything else.
EDIT EOFException means that there is no more data. You should catch it separately and handle it by closing the socket etc. It can certainly be caused spuriously by readUTF() trying to read data that wasn't written with writeUTF().
And deciding it was an IOException when it was really an EOFException means you didn't print out or log the exception itself, just its message. Always use the log methods provided for exceptions, or at least use Exception.toString().

As I remember I had a problem with DataInpuStream some day... try doing so:
in = new DataInputStream(new BufferedInputStream(socket.getInputStream()));

Related

OutputStream.write only writing part of a String in Java

I'm working on a Java-based IRC client as a way to learn both Java and more about writing networked applications.
The client I've designed mostly works, except when I post a message. The message goes through alright, but only up to the first space. I've tried everything: I've dumped my text into a StringArray, into a byte array, in a loop. But each time, only the first word of the intended message gets posted.
Here's the part of the code that I believe is relevant, although I'm happy to post the entire code if necessary (it's only a few hundred lines, and I can cut out the unimportant parts):
public void send(String msg) throws UnsupportedEncodingException {
if ( ! msg.startsWith("/")) {
msg = ("PRIVMSG " + chan + " " + msg);
// DEBUG confirm that msg == command+chan+userText
System.out.println(msg);
} else if ( msg.toUpperCase().startsWith("/JOIN ")) {
// System.out.println("\nJoin mode");
chan = msg.substring(6);
msg = (msg.toUpperCase().substring(1) + "\r\n");
} else { // some other command
msg = (msg.toUpperCase().substring(1) + "\r\n");
}
System.out.println(msg);
ostream.print(msg + " \r\n"); // doesn't work
ostream.flush();
}
}
I have also tried this sort of thing:
CRS = msg.split("\\s+");
CharSequence chars = msg;
ostream.printf( "%s,\r\n", msg); // doesn't work
ostream.print( String.join(" ", CRS) + "\r\n" ); // nope
And this:
ostream.append(chars);
ostream.append("\r\n"); // nope
I've also tried all of the above with byte arrays.
This sort of thing, however, does work:
// this, however, works as expected
void pong(String ping) {
String msg = "PONG " + ping;
byte[] bs = null;
bs = (msg.substring(1) + "\r\n").getBytes();
try {
ostream.write(bs);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I've also tried changing my OutputStream object (the connection to the IRC server) to a PrintStream. Same results.
What about OutputStream am I not comprehending?
The IRC protocol requires you to escape messages that contain spaces with a preceding colon (":"). I think your code actually works, you've just not implemented the IRC protocol correctly.
Try making your PRIVMSG command:
msg = ("PRIVMSG " + chan + " :" + msg);
Only the first word is appearing because the IRC server ignores the trailing content after the first space. A valid message should look like:
PRIVMSG #target :Hello, world

JTOpen ProgramCall Socket Timeout

I'm working on a web app (running on Tomcat) that calls programs on an IBM i (AS/400) using the JTOpen ProgramCall class (com.ibm.as400.access.ProgramCall). My problem is with program calls that take more than 30s to respond, which are triggering a java.net.SocketTimeoutException: Read timed out exception.
There is a setTimeout() method available for this class, but it doesn't seem to have an effect on the socket timeout. I've also checked my Tomcat configurations and didn't see anything that would cause this behavior.
Does anyone know of a way to alter the timeout for such an implementation?
Code:
pgmCall.setProgram(getCompleteName(), parmList);
initializeAS400TextParameters();
// Run the AS/400 program.
try {
Trace.setTraceDiagnosticOn(true);
Trace.setTraceInformationOn(true);
Trace.setTraceWarningOn(true);
Trace.setTraceErrorOn(true);
Trace.setTraceDatastreamOn(true);
if (pgmCall.run() != true) {
messageList = pgmCall.getMessageList();
for (int i = 0; i < messageList.length; i++) {
log.debug("Error Message " + i + " " + messageList[i]);
}
setCompletionMsg("Program call failed.");
log.debug("442 Program call failed.");
return false;
} else {
messageList = pgmCall.getMessageList();
for (int i = 0; i < messageList.length; i++) {
log.debug("Success Message " + i + " " + messageList[i]);
}
setCompletionMsg("Program called ok.");
log.debug("452 Program called ok.");
return true;
}
} catch (Exception e) {
// This is where the timeout exception is thrown
log.debug("Error Running Program: " + e.getMessage() + " " + e.getLocalizedMessage());
setCompletionMsg(e.getMessage());
}
Well, after several more hours I've found the solution. Apparently the original developer added a socket timeout parameter to the JDBC connection string - simply removing the parameter did the trick as the default value is 0, or infinite timeout.
Before:
String connectionStr = "jdbc:as400://" + systemInfo.getIPAddress() + ":1527" + ";naming=system;socket timeout=30000;thread used=false;errors=full;prompt=false;date format=iso;block size=128;transaction isolation=none;user=" + systemInfo.getUserName() + ";password=" + systemInfo.getPassword();
After:
String connectionStr = "jdbc:as400://" + systemInfo.getIPAddress() + ":1527" + ";naming=system;thread used=false;errors=full;prompt=false;date format=iso;block size=128;transaction isolation=none;user=" + systemInfo.getUserName() + ";password=" + systemInfo.getPassword();
:\

Java's System.getRuntime().exec not behaving as if the shell user called it

I am running a java application from the console on an HP-UX machine. In it, I generate some reports, zip them, and then email them. Everything is working, except the email.
I am using the mail binary to send mail from the command line. Since it's HP-UX, it's a bit different than the standard GNU sendmail.
This is the code I'm using to send the mail:
public static void EmailReports(String[] recipients, String reportArchive, String subject){
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy");
String today = dateFormat.format(new Date());
File tempEmailFile;
BufferedWriter emailWriter;
try {
tempEmailFile = File.createTempFile("report_email_" + today, "msg");
emailWriter = new BufferedWriter(new FileWriter(tempEmailFile));
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not create temporary file.");
return;
}
try {
emailWriter.write("SUBJECT: " + subject + "\n");
emailWriter.write("FROM: " + FROM + "\n");
emailWriter.write(BODY + "\n");
emailWriter.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not write to temporary file.");
}
//read the archive in
try {
FileInputStream archiveIS = new FileInputStream(new File(reportArchive));
OutputStream archiveEncoder = MimeUtility.encode(new FileOutputStream(tempEmailFile, true), "uuencode", Zipper.getArchiveName(reportArchive));
//read archive
byte[] buffer = new byte[archiveIS.available()]; //these should never be more than a megabyte or two, so storing it in memory is no big deal.
archiveIS.read(buffer);
//encode archive
archiveEncoder.write(buffer);
//close both
archiveIS.close();
archiveEncoder.close();
} catch (FileNotFoundException e) {
System.out.println("Failed to send email. Could not find archive to email.");
e.printStackTrace();
} catch (MessagingException e) {
System.out.println("Failed to send email. Could not encode archive.");
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not encode archive.");
}
System.out.println("Sending '" + subject + "' email.");
try {
Process p = Runtime.getRuntime().exec("mail me#example.com < " + tempEmailFile.getAbsolutePath());
System.out.println("mail me#example.com < " + tempEmailFile.getAbsolutePath());
StringBuffer buffer = new StringBuffer();
while(p.getErrorStream().available() > 0){
buffer.append((char) p.getErrorStream().read());
}
System.out.println("STDERR: " + buffer.toString());
buffer = new StringBuffer();
while(p.getInputStream().available() > 0){
buffer.append((char) p.getInputStream().read());
}
System.out.println("STDOUT: " + buffer.toString());
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not get access to the shell.");
}
}
When I run the program, and it sends the email, I get a blank email, no subject, no body, no attachment, and it's from the user#hostname from the HP-UX box instead of from the email specified in FROM.
However, when I run the same line that it runs (see the command printed out after I call exec), I get the correct email, from the correct user, with a subject, body, and attachment.
STDOUT and STDERR are both empty. It's almost as if I'm sending mail a blank file, but when I print the file before I call the exec, it's there.
What's going on here?
Edit: Attempts made:
Using Ksh:
try {
String cmd = "mail me#example.com.com < " + tempEmailFile.getAbsolutePath();
Runtime.getRuntime().exec(new String[] {"/usr/bin/ksh", cmd});
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not get access to the shell.");
}
Using STDIN:
try {
System.out.println("mail me#example.com < " + tempEmailFile.getAbsolutePath());
Process p = Runtime.getRuntime().exec("mail me#example.com ");
FileInputStream inFile = new FileInputStream(tempEmailFile);
byte[] byteBuffer = new byte[inFile.available()];
inFile.read(byteBuffer);
p.getOutputStream().write(byteBuffer);
inFile.close();
p.getOutputStream().close();
StringBuffer buffer = new StringBuffer();
while(p.getErrorStream().available() > 0){
buffer.append((char) p.getErrorStream().read());
}
System.out.println("STDERR: " + buffer.toString());
buffer = new StringBuffer();
while(p.getInputStream().available() > 0){
buffer.append((char) p.getInputStream().read());
}
System.out.println("STDOUT: " + buffer.toString());
} catch (IOException e) {
e.printStackTrace();
System.out.println("Failed to send email. Could not get access to the shell.");
}
I strongly suspect the problem is the redirection. That's normally handled by the shell - and there's no shell here.
Either you need to execute the process normally and then get the process's standard input stream and write to it from Java, or (probably simpler) run /bin/sh (or whatever) to get the shell to do the redirection.
Try exec'ing { "ksh", "-c", "mail me#example.com < " + etc }. The -c option tells the shell specifically to parse the next argument as a shell command with possible redirection and so on. Without the -c, ksh follows a heuristic to decide what to do with its command line, and it may not be running the command in the way you want it to.
Split into two lines, just to get better readability:
String cmd = "mail me#example.com < " + tempEmailFile.getAbsolutePath () ;
Process p = Runtime.getRuntime().exec (cmd);
This will look for a program named "mail me#example.com < " + tempEmailFile.getAbsolutePath (). It will not do redirection - for that to do you have to read the output of that process yourself.
Furtermore it will not lookup the path, so you might have to specify the whole path /usr/bin/mail or whatever it is.
And you have to split command and parameters; use an Array of String instead: ("/path/to/prg", "param1", "param2", "foo=bar");
You can use redirection, if you call as program a script, like
String cmd = "/usr/bin/mail me#example.com < " + tempEmailFile.getAbsolutePath () ;
String cmdarr = new String [] {"/bin/bash", "-c", cmd};
Process p = Runtime.getRuntime().exec (cmdarr);
It is shorter than invoking file redirection from Java yourself, more simple but you lose the ability to react sensible on different errors.

Process.waitFor() waits forever during mysql backup

I am trying to use Process.waitFor() to wait until mysqldump finishes its backup process. Here is my code.
///i use this mysql command, its working fine
String dump = "bkprefs/mysqldump "
+ "--host=localhost "
+ "--port=3306 "
+ "--user=root "
+ "--password= "
+ "--add-drop-table "
+ "--add-drop-database "
+ "--complete-insert "
+ "--extended-insert "
+ "test";
//execute the command
Process run = null;
try {
run = Runtime.getRuntime().exec(dump);
int stat = run.waitFor();
} catch (Exception ex) {
ex.printStackTrace();
}
The problem is that, run.waitfor() hangs. It seems like it keeps on waiting for something that will not happen.
When I replace the line int stat = run.waitFor() with Thread.sleep(5) the backup is working fine. But I can't stick to this because backing up time will vary depending on the size of the database so using Thread.sleep to wait for backup process to finish is not safe.
Please help me. Replies are greatly appreciated.
Edit :
I consume its inputstream using the following code.
InputStream in = run.getInputStream();
FileWriter fstream = null;
try {
fstream = new FileWriter("haha.sql");
} catch (IOException ex) {
ex.printStackTrace();
}
BufferedWriter out = new BufferedWriter(fstream);
int nextChar;
StringBuffer sb = new StringBuffer();
try {
while ((nextChar = in.read()) != -1) {
out.write((char) nextChar);
//sb.append((char) nextChar);
}
out.flush();
out.close();
} catch (IOException ex) {
ex.printStackTrace();
}
you need to consume the output streams from the sub process. This article details everything you need to do to use Process successfully. (also, this has probably been answered many times on stackoverflow already).
mysqldump dumps to stdout. You might want read it the stream, or use option -r redirecting the output.

closing MQ connection

Good afternoon, I wrote a project to Get Park Queue Info from the IBM MQ, it has producing an error when attempting to close the connection though. It is written in java.
Under application in Event Viewer on the MQ machine it displays two errors. They are:
“Channel program ended abnormally.
Channel program ‘system.def.surconn’ ended abnormally. Look at previous error messages for channel program ‘system.def.surconn’ in the error files to determine the cause of the failure.
The other message states:
“Error on receive from host rnanaj (10.10.12.34)
An error occurred receiving data from rnanaj (10.10.12.34) over tcp/ip. This may be due to a communications failure. The return code from tcp/ip recv() call was 10054 (X’2746’). Record these values.”
This must be something how I try to connect or close the connection, below I have my code to connect and close, any ideas??
Connect:
_logger.info("Start");
File outputFile = new File(System.getProperty("PROJECT_HOME"), "run/" + this.getClass().getSimpleName() + "." + System.getProperty("qmgr") + ".txt");
FileUtils.mkdirs(outputFile.getParentFile());
Connection jmsConn = null;
Session jmsSession = null;
QueueBrowser queueBrowser = null;
BufferedWriter commandsBw = null;
try {
// get queue connection
MQConnectionFactory MQConn = new MQConnectionFactory();
MQConn.setHostName(System.getProperty("host"));
MQConn.setPort(Integer.valueOf(System.getProperty("port")));
MQConn.setQueueManager(System.getProperty("qmgr"));
MQConn.setChannel("SYSTEM.DEF.SVRCONN");
MQConn.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
jmsConn = (Connection) MQConn.createConnection();
jmsSession = jmsConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
Queue jmsQueue = jmsSession.createQueue("PARK");
// browse thru messages
queueBrowser = jmsSession.createBrowser(jmsQueue);
Enumeration msgEnum = queueBrowser.getEnumeration();
commandsBw = new BufferedWriter(new FileWriter(outputFile));
//
String line = "DateTime\tMsgID\tOrigMsgID\tCorrelationID\tComputerName\tSubsystem\tDispatcherName\tProcessor\tJobID\tErrorMsg";
commandsBw.write(line);
commandsBw.newLine();
while (msgEnum.hasMoreElements()) {
Message message = (Message) msgEnum.nextElement();
line = dateFormatter.format(new Date(message.getJMSTimestamp()))
+ "\t" + message.getJMSMessageID()
+ "\t" + message.getStringProperty("pkd_orig_jms_msg_id")
+ "\t" + message.getJMSCorrelationID()
+ "\t" + message.getStringProperty("pkd_computer_name")
+ "\t" + message.getStringProperty("pkd_subsystem")
+ "\t" + message.getStringProperty("pkd_dispatcher_name")
+ "\t" + message.getStringProperty("pkd_processor")
+ "\t" + message.getStringProperty("pkd_job_id")
+ "\t" + message.getStringProperty("pkd_sysex_msg");
_logger.info(line);
commandsBw.write(line);
commandsBw.newLine();
}
}
Close:
finally {
IO.close(commandsBw);
if (queueBrowser != null) { try { queueBrowser.close();} catch (Exception ignore) {}}
if (jmsSession != null) { try { jmsSession.close();} catch (Exception ignore) {}}
if (jmsConn != null) { try { jmsConn.stop();} catch (Exception ignore) {}}
}
As per the Javadoc for the connection object, the function of the stop() method is...
Temporarily stops a connection's
delivery of incoming messages.
So stop() doesn't actually sever the connection. You want the close() method.

Categories

Resources