Solved

null pointer exception -- object instantiation problem??

Posted on 2003-11-23
20
289 Views
Last Modified: 2010-03-31
For what I have, please refer to:
http://www.experts-exchange.com/Programming/Programming_Languages/Java/Q_20805617.html

I have a problem where when I test the program with "type == 2" which goes through sendToOne() method in Server class, I get a NullPointerException at:

ServerThread.run() line94 -------------> server.sendToOne(distributeMessage.substring(2));
Server.sendToOne() line118 ------------>int r = scBack.write(buffer);

I declared a local ByteBuffer at the top of both methods to clear the buffer used in those methods.   Still, NullPointerException is thrown.   One possibility I think what's causing the error is the way I deal with the methods in DataHandler class, namely, addSocketChannel() and addUserInfo().   In particular, addSocketChannel() need to be invoked first to add an instance of SocketChannel into a LinkedList and this LinkedList is used when the latter addUserInfo() is called.   Since I call addUserInfo() at the Clinet constructor and addSocketChannel() at the Server constructor, the ordering of invokation might not seem to be a problem but the Server calls addSocketChannel() after there is an incoming request for connection meaning that by that time, Clinet is processed.   Also if I moved addSocketChannel() to right before the invokation of addUserInfo() in Clinet instead, there is no NullPointer but none of the test System.out outputs are printed.   Another possibility is that I have two instances of DataHandler object in Clinet and Server which they are both trying to access the same data.   Can this be a problem as well?   Since neither Client nor Server can access each other, if this causes a problem do I need to have a connection to a database to store the data which DataHandler is handling?   Even though it is indicated where the problem is caused, so far I find no effective method of tracking where in the transfer process or data storage something is going wrong.   Please give me a suggestion if someone can guide me in fixing this problem.   Thanks.  
0
Comment
Question by:skyblue01
  • 11
  • 9
20 Comments
 
LVL 92

Expert Comment

by:objects
ID: 9808984
scBack must be null.
0
 
LVL 92

Expert Comment

by:objects
ID: 9808996
addUserInfo() is never called on the server, so privateChannles is never populated.
0
 

Author Comment

by:skyblue01
ID: 9809014
>addUserInfo() is never called on the server, so privateChannles is never populated.

The user info, such as username, groupname can only be retreived from the Clinet GUI.   So those information are not available for class Server (and cannot instantiate Client in Server since that would start another session for another user...)   This is the problem I was pointing out.   Is there a way to solve this while preserving the DataHandler class or this whole structure simply does not work?   Please give me your opinion.  
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 92

Accepted Solution

by:
objects earned 350 total points
ID: 9809033
You need some way on the server to map which connections correspond to what user, perhaps the user details info should be passed from the client to the server when it connects.
0
 

Author Comment

by:skyblue01
ID: 9809066
But if Server is started first to listen for incoming connection, then in Clinet class if I want to have the user info passed from the Clinet to the Server when it connects, it will have another Server running, wouldn't it?  
0
 
LVL 92

Expert Comment

by:objects
ID: 9809090
I don't see why. Why do u think that?
0
 

Author Comment

by:skyblue01
ID: 9809108
By "passing from Client to Server", don't you mean that you'll do something like:

// Client
Server server = new Server(username, groupname, socketchannel...)

or

server.setInfo(username, groupname, socketchannel...)

Then for every instance of Ciient, an instance of Server will be created though I have one Server hanling all Client connections...
0
 
LVL 92

Expert Comment

by:objects
ID: 9809181
No I mean pass the details on the connection, like how you pass messages.
0
 

Author Comment

by:skyblue01
ID: 9809224
But then I'll need a place to store the data (such as DataHandler) for function like private chat, where one user specifies which other user it wants to talk to (which entails that when destination user is specified, it also have to get an instance of socketchannels, one from initiating client to the server, and another from destination client to server.   So I don't think just passing the user info would do it.   Also from the way I set up my classes, though Server can keep track of each individual socketchannels and perhaps store it in a Vector or LinkedList, as it receives the passed info, it has no way of identifying which info belongs to which channel...
0
 
LVL 92

Expert Comment

by:objects
ID: 9809232
When the server recieves a private message it needs some way to determine which connection to send that message out on. So whenever a connection is made it needs to provide details about the user that is making that connection.
0
 
LVL 92

Expert Comment

by:objects
ID: 9809236
>  it has no way of identifying which info belongs to which channel...

exactly you need to store that mapping.
0
 

Author Comment

by:skyblue01
ID: 9809337
Appending socketchannel at the end of message in processMessage method in Client, passed all the way to sendToOne method in Serever, which has some sort of Vector that keeps all socketchannels stored when its constructor is called, tokenize received message to get socketchannel, compare it to what's in the Vector from a beginning to an end, if matches, store the associated username and groupname which was also appended in the received message along with the matched socketchannel into a hashtable or something (keyed by socketchannel), then have everything stored in class Server, and finally write into the channel only the message part of the received message.   Would that work?   Although I'm using String message to be passed to sendToOne(), is it possible to have an object like socketchannel being appended to this data perhaps by changing this thing from String into Byte and then after decrypting it retreive the necessary object socketchannel and the string part of message?   Is such conversion or encryption/decryption of string+socketchannel into Byte and then back into string+socketchannel possible??
0
 
LVL 92

Expert Comment

by:objects
ID: 9813967
Not sure I understand what you mean, if you are saying pass the SocketChannel instance over the wire with the message then no.
0
 

Author Comment

by:skyblue01
ID: 9814206
What I mentioned above is the only way I could come up with.   I thought that was what you meant by "pass the details on the connection"...   Could you give me an example of what you mean by that?  
0
 

Author Comment

by:skyblue01
ID: 9814262
Or could you show me how it can be accomplished?
0
 
LVL 92

Expert Comment

by:objects
ID: 9814292
All you need to pass is whatever is needed to identify the user which I assume is the same as being passed with the message to identify who the message needs to go to.
0
 

Author Comment

by:skyblue01
ID: 9814386
Right, what identifies the user is its username and socketchannel.   So I was saying that I want to try doing something like below since data must be sent as bytes through a channel and String must be wrapped to get charbuffer.   But you said I can't do something like this...   Did you mean I can't do the concatenation of message and sc to form a string or this whole idea doesn't work?   I'm a little confused...

// in Clinet.java
private SocketChannel sc;
private String username;
private void processMessage(String message) { // message retrieved from the GUI
        try {
            if (type == 1)
                buffer = encoder.encode(CharBuffer.wrap(type + ":" + message + sc)); // <-------------------sc
            else if (type == 2 || type == 3)
                buffer = encoder.encode(CharBuffer.wrap(type + ":" + destUser + ":" + message + sc)); <--------sc

            int r = sc.write(buffer); // sends it to the server

            while (buffer.hasRemaining()) { // TEST
                int numWritten = sc.write(buffer); // sends it to the server
                buffer.compact(); // TEST
                buffer.flip(); // TEST
            }

            //System.out.println("numWritten at Client: " + numWritten); // TEST

            tf.setText(""); // clears the text input field
        } catch(IOException ie) { System.out.println(ie); }
    }
0
 
LVL 92

Expert Comment

by:objects
ID: 9814427
The server knows which channel a message is coming in from (as that is where it is reading it from), what it needs to know is what channel to send the message to.

Users need to identify themselves when they connect, otherwise the server has no idea which user is on which channel and thus no way to know what channel to send private messages on.

Does that make sense?
0
 

Author Comment

by:skyblue01
ID: 9924572
Hey objects, I solved the problem and came back to this question and figured out that what you told me was exactly right.   I couldn't understand what you meant since your explanation was kind of vague at that time.   I used a hashtable with a userinfo key and storing the received socket channel as its value -- i guess the term "mapping" you used was what confused me but please forgive me for not getting back to you...   And thanks for helping me out.  
0
 
LVL 92

Expert Comment

by:objects
ID: 9924602
I do have problems explaining myself sometimes.
Good to hear you got it solved :)

http://www.objects.com.au/staff/mick
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

733 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question