I'm getting the following error message and I can't seem to figure out the problem. Would really appreciate any help. The error message reads as:-
BaseStaInstance.java:68: cannot find symbol
symbol : constructor StringTokenizer(java.lang.Object,java.lang.String)
location: class java.util.StringTokenizer
st = new StringTokenizer(buf,",");
^
Here, BaseStaInstance is my main public class.
The class that implements this StringTokenizer is as follows:-
class ServerConnect extends Thread {
Socket skt;
int iProcessId, iInProcessId;
int iOwnTimeStamp, iInTimeStamp;
ServerConnect scnt = null;
ObjectOutputStream myOutput;
ObjectInputStream myInput;
ServerConnect(){}
ServerConnect(Socket connection, int iProcessNo) {
this.skt = connection;
this.iProcessId = iProcessNo;
}
public void run() {
try {
//initialize the object "scnt" using the parameterized constructor
ServerConnect scnt = new ServerConnect(skt, iProcessId);
myInput = new ObjectInputStream(skt.getInputStream());
while(true) {
try{
iOwnTimeStamp = Global.iTimeStamp;
Object buf = myInput.readObject();
//if we got input, print it out and write a message back to the remote client...
if(buf != null){
scnt.replyChoice(buf);
}
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
} catch(IOException e) {
e.printStackTrace();
}
}
void replyChoice(Object buf){
try{
String sDeferReply = "";
myOutput = new ObjectOutputStream(skt.getOutputStream());
//the place where the basestation reads the request from the other basestation
System.out.println("Server read:[ "+buf+" ]");
//extract out the process id and the timestamp from the incoming request
buf = buf.toString();
***StringTokenizer st = new StringTokenizer(buf,",");***
//skip the word request
st.nextToken();
iInProcessId = Integer.parseInt(st.nextToken());
iInTimeStamp = Integer.parseInt(st.nextToken());
//check request is made
//there is a possibility of entering the else loop only on the very first iteration
//the control flows into the if loop even if one request has been made
if(iOwnTimeStamp != 0){
//if the incoming request has a larger timestamp (logical clock value, process id) than the current process, we defer the reply
if(iOwnTimeStamp < iInTimeStamp || iProcessId < iInProcessId){
sDeferReply="iInTimeStamp"+","+"iInProcessId";
Global.v.addElement(new String(sDeferReply));
}
//incoming request has a smaller timestamp than the basestation request itself
else{
myOutput.writeObject("Reply");
myOutput.flush();
}
}
//if the current process is in the critical section then we defer replies
else if(Global.iCriticalSection==1){
sDeferReply="iInTimeStamp"+","+"iInProcessId";
Global.v.addElement(new String(sDeferReply));
}
//start of execution of the thread, there is a possibility that the basestation hasn't issued a request
else{
myOutput.writeObject("Reply");
myOutput.flush();
}
}catch(IOException e){
e.printStackTrace();
}
}
}
The part that implements the StringTokenizer function has *** surrounding it.
Thanks in advance to anyone who might be able to help me out.
Try
StringTokenizer st = new StringTokenizer((String) buf,",");
The reason why you're getting that error is because buf, while referring to a String at that point, is still of type Object.
As an additional tip, you really should make the effort to try to understand the error message given by the compiler. Look at the following:
cannot find symbol constructor StringTokenizer(java.lang.Object,java.lang.String)
location: class java.util.StringTokenizer st = new StringTokenizer(buf,",");
Compiler error messages don't always make sense, but this is as good as it gets. It tells you that:
It found the right type, java.util.StringTokenizer, so it's not an import or name obscuring problem, etc.
It's telling you that a specific method with the given signature can not be found. Indeed, a quick check with the API confirms that StringTokenizer does NOT have a constructor that takes a (java.lang.Object, java.lang.String).
It's telling you exactly the line of code in your program that tries to invoke this non-existent method. And indeed, the type of your first argument is a java.lang.Object, and the type of your second argument is a java.lang.String!!!
That was how I was able to quickly pinpoint the problem in the source code and suggest a quick fix.
Being able to process error messages given by the compiler is an essential skill that you must develop, so I hope this proves to be an educational experience for you.
Related
I am quite new to Java programming. For now I am studying source code of an android app called Evercam. However, I have a problem understanding a part of the code which involves while(true) loop.
Here is the snippet of the code:
while (true)
{
while (true)
{
byte[] responseMessageByteArray = new byte[4000];
DatagramPacket datagramPacketRecieve = new DatagramPacket(responseMessageByteArray, responseMessageByteArray.length);
datagramSocket.receive(datagramPacketRecieve);
String responseMessage = new String(datagramPacketRecieve.getData());
EvercamDiscover.printLogMessage("\nResponse Message:\n" + responseMessage);
StringReader stringReader = new StringReader(responseMessage);
InputNode localInputNode = NodeBuilder.read(stringReader);
EnvelopeProbeMatches localEnvelopeProbeMatches = (EnvelopeProbeMatches)(new Persister()).read(EnvelopeProbeMatches.class, localInputNode);
if (localEnvelopeProbeMatches.BodyProbeMatches.ProbeMatches.listProbeMatches.size() > 0)
{
ProbeMatch localProbeMatch = (ProbeMatch) localEnvelopeProbeMatches.BodyProbeMatches.ProbeMatches.listProbeMatches.get(0);
if (uuidArrayList.contains(localProbeMatch.EndpointReference.Address))
{
EvercamDiscover.printLogMessage("ONVIFDiscovery: Address " + localProbeMatch.EndpointReference.Address + " already added");
}
else
{
uuidArrayList.add(localProbeMatch.EndpointReference.Address);
DiscoveredCamera discoveredCamera = getCameraFromProbeMatch(localProbeMatch);
if (discoveredCamera.hasValidIpv4Address())
{
this.onActiveOnvifDevice(discoveredCamera);
cameraList.add(discoveredCamera);
}
}
}
}
}
Doesn't this create an infinite loop? My fundamentals in Java isn't strong, so I would be so grateful if anyone can tell in in what instances will a while(true){//codes} actually exits without any break or does it ever exit??
EDIT
My bad for actually extracting this snippet from decompiling directly from the android project files. I did not know that it would be different, and then again, I know very little. Here is the original code:
public ArrayList<DiscoveredCamera> probe() {
ArrayList<DiscoveredCamera> cameraList = new ArrayList<DiscoveredCamera>();
try {
DatagramSocket datagramSocket = new DatagramSocket();
datagramSocket.setSoTimeout(SOCKET_TIMEOUT);
InetAddress multicastAddress = InetAddress.getByName(PROBE_IP);
if (multicastAddress == null) {
// System.out.println("InetAddress.getByName() for multicast returns null");
return cameraList;
}
// Send the UDP probe message
String soapMessage = getProbeSoapMessage();
// System.out.println(soapMessage);
byte[] soapMessageByteArray = soapMessage.getBytes();
DatagramPacket datagramPacketSend = new DatagramPacket(
soapMessageByteArray, soapMessageByteArray.length,
multicastAddress, PROBE_PORT);
datagramSocket.send(datagramPacketSend);
ArrayList<String> uuidArrayList = new ArrayList<String>();
while (true) {
// System.out.println("Receiving...");
byte[] responseMessageByteArray = new byte[4000];
DatagramPacket datagramPacketRecieve = new DatagramPacket(
responseMessageByteArray,
responseMessageByteArray.length);
datagramSocket.receive(datagramPacketRecieve);
String responseMessage = new String(
datagramPacketRecieve.getData());
EvercamDiscover.printLogMessage("\nResponse Message:\n"
+ responseMessage);
StringReader stringReader = new StringReader(responseMessage);
InputNode localInputNode = NodeBuilder.read(stringReader);
EnvelopeProbeMatches localEnvelopeProbeMatches = new Persister()
.read(EnvelopeProbeMatches.class, localInputNode);
if (localEnvelopeProbeMatches.BodyProbeMatches.ProbeMatches.listProbeMatches
.size() <= 0) {
continue;
}
ProbeMatch localProbeMatch = localEnvelopeProbeMatches.BodyProbeMatches.ProbeMatches.listProbeMatches
.get(0);
// EvercamDiscover.printLogMessage("Probe matches with UUID:\n"
// +
// localProbeMatch.EndpointReference.Address + " URL: " +
// localProbeMatch.XAddrs);
if (uuidArrayList
.contains(localProbeMatch.EndpointReference.Address)) {
EvercamDiscover.printLogMessage("ONVIFDiscovery: Address "
+ localProbeMatch.EndpointReference.Address
+ " already added");
continue;
}
uuidArrayList.add(localProbeMatch.EndpointReference.Address);
DiscoveredCamera discoveredCamera = getCameraFromProbeMatch(localProbeMatch);
if (discoveredCamera.hasValidIpv4Address()) {
onActiveOnvifDevice(discoveredCamera);
cameraList.add(discoveredCamera);
}
}
} catch (Exception e) {
// ONVIF timeout. Don't print anything.
}
Turns out there is continue statement in the actual code. Thank you so much for the response, I will remember that de-compiled classes should not be depended on.
This looks like an infinite loop. To be absolutely sure, you would have to statically read every statement and follow invoked methods to see if any possible invocations like Activity#finish() or Service#stopSelf() exists which would finish the currently running activity, effectively breaking the loop.
Another possibility is that the code is intended to be running in an infinite loop as a background thread service, and some other component would have an option to kill that service when it reaches a certain condition. For example, it could be part of a Runnable class and executed in a thread pool, and when a timeout exists, the pool is shut down.
the only possible way to exit from while loop is if one of the methods being called in loop throws exception. check code of these methods for exception or share it here
Infinite loops without any breaks could be useful for a Service running in background.
You create a new Thread doing the service infinitely thanks to a while(true) and when you stop your application you simply kill the process corresponding to the service.
readLine() works fine in many cases but few times, the line I read in by BufferedReader.readLine() is incomplete line. This question talks about similar issue. However the solutions are not satisfactory. A solution there says that it maybe because of EOF character. But in my case I am not sending any EOF character at all. Below are my codes:
/*Sending Code*/
public void sendToLocalDaemon(String msg){/*msg have no New line or \r*/
localMachineWriter.println(msg);
}
/*Receiving Code*/
public int receiveFromCoordinator(){
String response = "";
while(true){/*Each message separated from new line will have its independent meaning.*/
try{
coordinator.setSoTimeout(1);
try{
response = coordinatorReader.readLine();
}
catch(java.net.SocketTimeoutException e){
response = null;
}
if(response == null){
return coordinatorsMessage.size();
}
coordinatorsMessage.add(response);
}
catch(IOException e){
log(e.getMessage());
//System.exit(0);
}
}
}
/*This is how I set reader and writer*/
public void setReaderWriter() throws IOException{
this.coordinatorWriter = new PrintWriter(coordinator.getOutputStream(),true);
this.coordinatorReader = new BufferedReader(new InputStreamReader(coordinator.getInputStream()));
}
Please either suggest me someway to make this work correctly. Or suggest me some other way by which I can read whole message, with 100% guarantee.
The problem is your read timeout. If it happens, you can lose data. If readLine() times out in the middle of a line, the part read so far is lost. If you set it too short, you will lose a lot of data, and you're setting it much too short. You should set it much higher, or not use one at all.
I want my program exceptions to be sent to each of the following, preferably simultaneously:
the console which starts it (not necessarily)
a gui
a txt file.
How can I achieve this?
My attempts:
System.setErr(PrintStream err) will forward all exceptions to a new stream. I am not able to state more than
one stream though.
Calling System.setErr(PrintStream err) on a manually written OutputStream:
"You can write your own stream class that forwards to multiple streams and call System.setOut on an instance of that class" – Jeffrey Bosboom
I found a way to do this. It is very nasty though. It "collects" PrintStream's write-bytes, puts them in a puffer (500 ms timeout) and finally shows it to the user (Proceed):
/* ErrorOutput.java */
public static t_ErrBuffer t_activeErrBuffer = new t_ErrBuffer("");
public static void setStdErrToFile(final File file) {
ps = new PrintStream(fos) {
#Override
public void write(byte[] buf, int off, int len) {
byte[] bn = new byte[len];
for (int i = off, j = 0; i < (len + off); i++, j++) {
bn[j] = buf[i];
}
String msg = null;
try {
msg = new String(bn, "UTF-8");
} catch (UnsupportedEncodingException e1) {}
if (msg.matches("[\\w\\W]*[\\w]+[\\w\\W]*")) { // ^= contains at least one word character
if( ! t_activeErrBuffer.isAlive() ) {
t_activeErrBuffer = new t_ErrBuffer(msg);
t_activeErrBuffer.start();
} else {
t_activeErrBuffer.interrupt();
t_activeErrBuffer = new t_ErrBuffer(t_activeErrBuffer.getErrBuffer() + "\n" + msg); // ^= append to buffer and restart.
t_activeErrBuffer.start();
}
}
}
};
System.setErr(ps);
}
/* t_ErrBuffer.java */
public class t_ErrBuffer extends Thread {
private String errBuffer;
public t_ErrBuffer(String buffer) {
this.errBuffer = buffer;
}
protected class Proceed implements Runnable {
public String msg = null;
public Proceed(String msg) {
this.msg = msg;
}
#Override
public void run() {
// todo PRINT ERROR MESSAGE: DO THINGS WITH msg: console, gui, JOptionPane
}
}
#Override
public void run() {
try {
Thread.sleep(500); // collect error lines before output. Needed because PrintStream's "write"-method writes ErrorMessages in multiple pieces (lines)
// each time some new exception line comes in, the thread is stopped, buffer is being appended and thread new started
} catch (InterruptedException e) {
return; // stop
}
// after 500 ms of wait, no new error message line has come in. Print the message out:
Thread t_tmp = new Thread(new Proceed("\n" + this.errBuffer));
t_tmp.start();
return;
}
public String getErrBuffer() {
return this.errBuffer;
}
}
is this what I am expected to do?
Create new exception class which does it for me. Would probably work, but other exceptions than that (IO, FileNotFound, ...) will still be treated the old way
Instead of stating [method name] throws Exception I could enclose all of my code in try/catch-blocks, get the exception and forward it to a method of mine, like this:
/* AnyMethod.java */
// ...
try {
// ... do everything here
} catch (IOException | FileNotFoundException e) { // as many as you like
ErrorOutput.crash(e);
}
// ...
/* ErrorOutput.java */
public static void crash(Exception e) {
FileOutputStream fos_errOutput = new FileOutputStream(new File("ErrorOutput.txt"), true);
// 1st
if (!System.out.equals(fos_errOutput)) {
System.out.println(e.getMessage() + " :"); // to console or the preferred StdOut
e.printStackTrace();
}
// 2nd
JOptionPane.showMessageDialog(Gui.frame, "THE PROGRAM HAS CRASHED!" + "\n\n" + e.getMessage() + "\n\nFor a more detailed report, see ErrorLog.txt"); // gui output
// 3rd
PrintStream ps = new PrintStream(fos_errOutput);
ps.print(new Date().toString() + ":"); // write to file
e.printStackTrace(ps);
ps.close();
// 4th
System.exit(0); // this could also be "throw new Exception" etc., but I don't know why one should do that.
}
this would probably also work, but I'd have to put everything into try/catch-blocks. This cannot be good programming style at all.
Using a logger:
"use log4j and set up a method to write to GUI and also to log to
stdout, and file" – Scary Wombat
Loggers only help me printing my exceptions into desired streams, but they don't help me catching them, right?
But you really should use a logging package for this -- even java.util.logging can do what you need – Jeffrey Bosboom
I have to tell my logging package where and what to log. But this is exactly what I am searching for.
I now can, as user3159253 suggested, use Thread.UncaughtExceptionHandler to catch unhandled exceptions specifically.
What is the right way to handle all thrown exceptions the way I want them to? What else do I have to consider apart from Thread.UncaughtExceptionHandler and System.setErr()(see above)?
First you need get hold of all exception instances thrown from/within your thread (may be try/catch or Thread.UncoughtExceptionHandler or ThreadPoolExecutor.afterExecute(Runnable r, Throwable t)).
Then once you have the exception instance you can simply log it using log4j but configure Log4j appenders to send your exception messages to multiple destinations. You can use File, Console, JDBC, JMS etc types of appenders depending upon your requirement. Also it is best to wrap them with Async appender.
Refer - https://logging.apache.org/log4j/2.x/manual/appenders.html
About pushing the exception message to GUI, it can be implemented in various ways depending upon what tech stack your are using in your application. In our application we are storing the message events (only critical ones) in database which are then picked by event monitoring threads from server and then pushed back to GUI (JQuery, JavaScript) using http://cometd.org/documentation/cometd-java.
Creating an object that extends PrintStream should work. Whenever it receives a line, it can display it and log it as required. Alternatively, all exceptions can be caught and redirected into a method that receives an Exception as a parameter, and the method can take care of logging/displaying the exception, and terminating the program cleanly.
Note: I understand that the console is for debugging and games should use GUI. This is for testing/experience
I'm writing a game that runs at 60fps. Every update, I check to see if the user has entered a String command. If so, it gets passed through, but if not, null is paas through, and the null is ignored.
Scanner is out of the question, since hasNext(), the method used to see if there is data to read, can potentially block and causes problems.
I've tried using BufferedReader.ready(). Not only did I have problems (never returned true), but I've read that it's not recommended for a few reasons.
BufferedReader.available() always returned 0, which in the documentation, it state's that InputStream.available() will always return 0 unless overriden. Here is my attempt:
class Game {
public static void main(String[] args) {
InputReader reader = new InputReader(System.in);
int timePerLoop = 1000/30;
Game game = new Game();
while(true) {
long start = System.nanoTime();
game.update(reader.next());
long end = System.nanoTime();
long sleepTime = timePerLoop + ((start - end) / 10000000);
if(sleepTime > 0)
try {
Thread.sleep(sleepTime);
}catch(InterruptedException e) {
e.printStackTrace();
}
else
Thread.yield();
}
}
public void update(String command) {
if(commands != null) {
//handle command
}
//update game
}
}
InputReader.java
public class InputReader {
private InputStream in;
public InputReader(InputStream stream) {
in = stream;
}
public String next() {
String input = null;
try {
while(in.available > 0) {
if(input == null)
input = "";
input += (char) in.read();
}
}catch(IOException e) {
e.printStackTrace();
}
return input;
}
}
InputStream by itself has the same problem as above. I'm not completely sure what type the object stored in System.in, but using available() yields the same results.
I've tried using the reader() from System.console(), but console() returns null. I've read into the subject, and I am not confused why. This is not the way to do it.
The goal is to check the stream to see if it contains data to read, so I can read the data knowing it won't block.
I do not want to use a separate Thread to handle user input, so please don't recommend or ask why.
The input has to be from the console. No new sockets are to be created in the process. I have read a few topics about it, but none of them clearly states a solution. Is this possible?
As you have said yourself, a custom GUI or an additional thread is the correct way to do this. However in absence of that, have you tried using readLine() for example: String inputR = System.console().readLine();
Some alterations to main():
Replace: InputReader reader = new InputReader(System.in); with:
Console c = System.console();
Replace: game.update(reader.next());
with: game.update(c.readLine());
Edit: This thread could also be helpful: Java: How to get input from System.console()
SOLVED
I found the answer from IBM Technote IZ66146
Hope it helps others with same problem.
I wrote a simple method to a read messages from an MQ Queue.
In a loop, I try to read a message (with waitInterval). After reading a message successfully from the queue, a 2195 return code is returned. How can I resolve this?
Here is simplified version of my code without exception handling or any other thing.
public static void main(String args[]) {
MQException.logExclude(MQException.MQRC_NO_MSG_AVAILABLE);
MQException.logExclude(MQException.MQRC_UNEXPECTED_ERROR);
MQException.log = null;
while (true) {
incomeDeployMsg = readFromQueue(waitReadInterval);
System.out.println(dateFormater.format(new Date()) + " Income msg");
}
}
public String readFromQueue(int waitInterval) throws MQException{
MQMessage message = new MQMessage();
try {
if (m_inQueue == null || !m_inQueue.isOpen())
m_inQueue = m_mqQmgr.accessQueue(m_inQueueName, CMQC.MQOO_INQUIRE + CMQC.MQOO_FAIL_IF_QUIESCING + CMQC.MQOO_INPUT_SHARED);
message.messageId = CMQC.MQMI_NONE;
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.options = CMQC.MQGMO_WAIT;
gmo.waitInterval = waitInterval;
m_inQueue.get(message, gmo);
return message.readStringOfCharLength(message.getMessageLength());
} catch (MQException mqe) {
throw mqe;
} finally {
message.clearMessage();
}
}
The first line in the result is not from my code!!! I think it is IBM's classes that print it out on standard output. How can I resolve the error?
Result:
MQJE001: Completion Code '2', Reason '2195'.
2013-05-15 11:44:27 Income msg
Comment out the 2 lines with MQException.logExclude() and just use:
MQException.log = null;
If you don't want this, then in your catch block, check if the exception's reason code is 2195 and write the code accordingly.
Like:
catch (MQException mqe) {
if(mqe.reasonCode==2195)
{
/* DO NOTHING FOR THIS ERROR */
}
else
{
throw mqe;
}
}
I have face the problem, even I set
MQException.log = null;
It still printed out "MQJE001: Completion Code '2', Reason '2195'. "
End up i found out, the line is printed from MQDataException.
Added below line to solve the issue.
MQDataException.log = null;