My instructions assume you will be doing this on the computer you have been issued, running the Ubuntu distribution of Linux. You can actually use any system that has a current version of Java EE 7; only the installation instructions are Ubuntu-specific.
To get Java EE 7 installed requires quite a few steps. Hopefully I've remembered to list them all here:
Install Oracle Java 7 as described on the linked web page and also set the environment variables as described on that same page.
Install the maven project management tool:
sudo apt-get install maven
Install some libraries that are needed by the updatetool for glassfish, the Java EE server:
sudo apt-get install ia32-libs sudo apt-get install libjpeg62:i386
Install the Java EE 7 Software Development Kit as described in the tutorial.
Run the updatetool as as described in the tutorial. You should be able to do this using the following command in a shell:
It is particularly important that you download the update for the Java EE 7 Tutorial. There were some changes in the JMS example software we'll be using. Working around the differences in the old version would be possible, but updating to the latest will save you grief.
Note that if you set your shell's command search path as the tutorial suggests, you would be able to abbreviate the above command to just
Similar abbreviation would be possible with other commands that I show below. I'm showing the full versions so that even if you don't set your search path, you'll be OK.
If you like working within an integrated development environment (IDE), you might consider installing the NetBeans IDE as described in the tutorial, because it is the IDE that the tutorial describes. I haven't tried it out myself. Other IDEs such as Eclipse might also be options. I just edited the Java source files using a normal text editor (emacs) and ran the Maven build process from within a shell.
The installation process normally will start up the GlassFish server, but you'll need to restart it every time you reboot. This is described in detail in the tutorial but the short version is to use this command in a shell:
Create the resources for the tutorial's simple JMS examples. We'll be using those examples as a starting point, and for simplicity our puzzle program will use the same resources. In particular, our client and server will communicate through a queue called
jms/MyQueue and a topic called
jms/MyTopic. The directions for creating these resources are in the tutorial; a more full version of the commands follows:
cd ~/glassfish4/docs/javaee-tutorial/examples/jms/simple/producer ~/glassfish4/bin/asadmin add-resources src/main/setup/glassfish-resources.xml
Build the simple JMS examples as described in the tutorial. Assuming you are doing this in the shell rather than with NetBeans or another IDE, the full version of the commands would be as follows:
cd ~/glassfish4/docs/javaee-tutorial/examples/jms/simple mvn install
Check that you can use the example programs to send and receive messages using the queue and topic as described in the tutorial. Note that these programs will be slow in starting up and will produce some extra informational messages at the start. For an example of the full version of the commands, here are the ones for running the producer:
cd ~/glassfish4/docs/javaee-tutorial/examples/jms/simple/producer ~/glassfish4/glassfish/bin/appclient -client target/producer.jar queue 3
Because I am providing a working server for the puzzle program, it is entirely possible that you could just test your client using this. If you want to see the messages, you can also use one of the consumer example programs from the tutorial. However, you might find it interesting to be able to manually send messages as well during the testing and debugging process. I know I found that helpful while working on the server side.
The example producer program has the limitation that it sends a specific format of message that is hardwired into it. Your program won't be interested in receiving messages saying "This is message 1 from the producer". Therefore, I have made a slight variant of the tutorial's producer, called flexproducer, which reads from the standard input (normally your keyboard) and sends each line of input as a message.
You can download this program as flexproducer.zip, unzip it, and then build and run it analogously to the tutorial's examples:
cd flexproducer mvn package ~/glassfish4/glassfish/bin/appclient -client target/flexproducer-1.0.0.jar topic Something to send. More to send. (control-D when done)
You can download the puzzle application as puzzle.zip, unzip it, and build it using
cd puzzle mvn package
After building the application in its supplied form you can run any of the following three commands:
~/glassfish4/glassfish/bin/appclient -client target/puzzle-1.0.0.jar ~/glassfish4/glassfish/bin/appclient -client target/puzzle-1.0.0.jar server ~/glassfish4/glassfish/bin/appclient -client target/puzzle-1.0.0.jar client
These run the stand-alone version of the program, the server, and the client. However, the client will report an error because the
ModelProxy.java source file is just a template waiting for you to fill it in.
We will spend class time on November 26th on the structure and function of this program.
Here is a suggested plan of work for what you need to do in
Delete the throwing of
"Not yet written" errors from
setModelListener and the
ModelProxy constructor. Rebuild the puzzle package using the
mvn package command. At this point, you ought to be able to start up a puzzle client as shown on the assignment web page. It will come up with all the tiles blank. If you push on the Initialize button or any of the blank tile buttons, you will set a
"Not yet written" error. Exit from the client.
In the body of
initializeTiles, replace the throwing of a
"Not yet written" error with a line of code that sends to the
Destination the text
including the brackets and double quote marks. This is a one-element JSON array containing the string
"init". You can find examples of sending text to a JMS
Destination in both the puzzle's
Listener class (the server side) and the Java EE tutorial's
producer example (as well as my
flexproducer variant). In order to make this possible, you will also need to add some instance variables to the
ModelProxy class and put some code in the constructor to initialize these instance variables. Rebuild the puzzle package again and re-run it. Again it should come up with all tiles blank. But now if you press the Initialize button, you won't get an error. In another terminal window, run the Java EE tutorial's
asynchconsumer program with the
queue destination. You should see the
["init"] message that the client program should have queued up. If you click the button again, you should see the message again. If your client passes these tests, you can kill the
asynchconsumer (using control-c) and rerun it with the
topic command line argument instead of
queue. Now in a third terminal window, run the puzzle server. Although the client tiles will remain blank, you should see using
asynchconsumer that the server is retransmitting the initial board configuration each time you click on the Initialize button. Exit from the client after testing it. If these tests aren't passing work to get them to pass before moving on.
pushTile method in the
ModelProxy class analogously to
initializeTiles. The message it sends should have this form
for a push in the upper right corner (row 0, column 3). This is a three-element JSON array. Rebuild and run the puzzle client. You still should have blank tiles, but now if you push them you should be able to see in the
asynchconsumer's output that the server is actually sliding the tiles appropriately. For example, pushing the upper right tile results in the first row now being
["1","2","3",""] and the last row being
["13","14","15","12"]. If this isn't working, you can get more insight into what is going wrong by killing off the puzzle server and the
asynchconsumer and restarting the
queue. That will show you whether your puzzle client is sending the correct command. As usual, get this portion of the work debugged before moving on.
Fill in the
setModelListener method with code that does two things: (a) records the
ModelListener into an instance variable for later use, (b) transmits a
["send"] command to the
commands destination analogously to the
["init"] command. If you rebuild and re-execute the client, you should be able to see that when it first starts up, it uses the
["send"] command to prompt the server to transmit its state.
ModelProxy constructor to set
ModelProxy to be the
MessageListener for a
consumer on the
You can find an example of this in the puzzle's
Listener class (the server) as well as in the tutorial's
If you re-build and re-execute the client, you should find that now whenever the sever (or
flexproducer) sends a puzzle state to the topic, the
"Not yet written" error is thrown by the
Fill in the
onMessage method with code to store the received state into an instance variable and invoke the
onModelChanged method (assuming a non-
ModelListener has been set). Whenever the server transmits a puzzle state, you should see
"Not yet written" being thrown by the
get method because the
GUI will call this method (16 times) in response to the
onModelChanged invocation. (To further confirm that you are on the right track, you could put in some temporary code to print out the state.)
Finally, you should fill in the
get method with code to extract the relevant
String from the instance variable where
onMessage stashed away the incoming state. At this point, the client should be fully functional.
You should email me a completed version of
ModelProxy.java. If you want to do something that extends beyond this, I'd be happy to talk it over with you. However, I'd be satisfied with just a working version of this one class.
Instructor: Max Hailperin