Lab 3 Details for MPCS 51221

Each lab will consist of a small problem and details of  how to proceed. Each lab is intended to give every student hands-on experience with the core technologies utilized during the course.  A student may concentrate, as a team member, on one technology over another for the final project, but labs are designed to give each and every student exposure to all the technologies that come into play.  You need to submit labs to the TAs for grading--see submission instructions below.  Generally, unless otherwise specified, you will have one week to complete each assigned lab.

See the syllabus for information on grading.  Turning in lab assignments on time is required, without exception, and all late deliveries will be penalized, regardless of cause.  Submit your assignments to the subversion repository according to the directions on the syllabus page.

You may write these solutions in either Java or C++...your choice.

Lab 3   Due: 5:00 pm, Sunday, November 12, 2017

Problem 1:  Playing With Docker and MySQL: 

BACKGROUND:

Like all programming problems, learning a new technology is not an exercise in reading but rather and exercise in typing.  This lab is designed to give you hands-on experience in (a) running a dockerized RMI client program that (b) communicates with an RMI server program in another docker container which then gets sample data from a MySQL database and (b) returns that data to the dockerized RMI client program.  You will generally find the References section below helpful in addition to the required and recommended reading.  When we talk about "Docker", we are talking specifically about the Stable Community Edition of Docker, which is the version we will be using in this class.  The Stable Community Edition provides the basic container engine and built-in orchestration, networking, and security.

Note that this lab will focus on and exercise interprocess communication and accessing MySQL from a remote client via an RPC metaphor (Java RMI).  Please keep in mind that in your actual microservices architecture that you are creating for the final project deliverable, as each microservice has its own datastore, you will likely only be hitting MySQL from a local microservice, which is of course simpler, and not remotely...as shared persistence among microservices is a NO-NO.  Consider also that each microservice will likely have an instance of either MySQL or MongoDB as their datastore, and will be making local calls to that datastore.

WHAT YOU NEED TO DO:

STEP 1:

For this third lab, we are going to code a little microservice that will accept a synchronous call over RMI to a server with a backing MySQL database.  That RMI Server will obtain data from the MySQL database, and return it to an RMI Client running in a separate container.  You will not need to run a script capture on this lab, as you will be submitting your two client and server docker containers.

First, make sure docker is running either on your laptop (Option I from the first lab) or in your VM (Option II from the first lab).

STEP 2:

Get Java RMI working in a Docker Container (CLIENT)

First, get down the Apache Httpd Server version 2.4 container.  Do this by executing the following command (make sure you understand the meaning and significance of -p 8080:8080):

docker run -dit -p 8080:8080 --name Lab3HttpdServer httpd:2.4

Once you have that container down (and running), obtain a bash shell in that container by running docker exec into the container.  Once you are in that httpd container, install some software in the container. 
You will update the ubuntu OS, then install the vi editor, the Java 1.7.x JDK, and net-tools, which will allow you to run network-related utilities including ifconfig.

apt-get update
apt-get install vim
apt-get install default-jdk
apt-get install net-tools
apt-get install openssh-client

Create a subdirectory called "/src/lab3/RMI".  Next, download ~mark/pub/51221/src/RMI.tgz and copy it into your container and untar the contents into your RMI subdirectory.  You could also scp it from the Linux cluster directly into your container as well.  Cat the README file and compile the java client and server.  Then execute the server and in a new terminal window execute the client, to make sure everything is running.  Refer again to the README file on how to run the client and server.   You can just use "localhost" for the <server host address> on the client command line.

This container will server as your "Client" container for the synchronous exercise of this lab.  Don't be confused by the name of this container.  Although it is the httpd server and is named
Lab3HttpdServer, it will still function as our CLIENT for this lab.


STEP 3:

Get MySQL working in a Docker Container (SERVER)

Next, in a separate terminal window get down a mysql container by running this command:

docker run --name Lab3MySQLServer -e MYSQL_ROOT_PASSWORD=secret -p 3306:3306 -d mysql

Docker exec a bash shell into your new mysql server and poke around a bit.  Run the following updates in your mysql_server:

apt-get update
apt-get install vim
apt-get install default-jdk
apt-get install net-tools
apt-get install openssh-client
apt-get install unzip

Go here:
https://dev.mysql.com/doc/employee/en/employees-installation.html and follow the instructions to download and load your mysql instance with the sample employees database.  You may find that obtaining the test_db-master.zip file onto your host system, and then copying it into your container will be easiest.  You may also find it easier to obtain the tarball of this sample database off my pub directory ~mark/pub/51221/src/test_db-master.tgz.  It's contents are identical to the zip file refered to on the dev.mysql.com website above.   Once you've decompressed the sample employees database file, run the instructions at the website above to install the sample database into your mysql container (mysql -t < employees.sql).

Create a new subdirectory called "/src/lab3/RMI" in your Lab3MySQLServer container.  Next, download ~mark/pub/51221/src/RMI.tgz and copy it into your container and untar the contents into your RMI subdirectory.  You could also scp it from the Linux cluster directly into your container as well.  Cat the README file and compile the java client and server.  Then execute the server and in a new terminal window execute the client, again making sure everything is running.  Refer again to the README file on how to run the client and server.  Again you can use "localhost" for the <server host address> on the client command line.

Now, let's test out the MySQL installation.  In your Lab3MySQLServer container, execute the following commands:

mysql --user=root --password=secret

mysql> show databases;
mysql> use employees;
mysql> show tables;
mysql> desc employees;
mysql> select * from departments;
mysql> select count(*) from departments;
mysql> select count(*) from employees;
mysql> select * from employees where first_name like 'D%';

Are you having fun yet?  Assuming that's all working just dandy, you can exit out of the "mysql>" prompt by simply typing "quit". 

This container will serve as your SERVER container for the synchronous exercise of this lab.

STEP 4:

Verify the Java JDK in the MySQL working in the Docker Client Container

Exec into your httpd client container
Lab3HttpdServer (if you're not already there).

Now, let's make sure that our Java programs can hit our MySQL server.  Get the MySQL java driver down.  You can get it from my pub server at ~mark/pub/51221/src/mysql-connector-java-5.1.44.tar.  Untar that and store it somewhere like /mysql-driver or /
mysql-connector-java-5.1.44 in your Lab3HttpdServer container.  Now, set your CLASSPATH so that it includes this directory, something like:

export CLASSPATH=mysql-connector-java-5.1.44/mysql-connector-java-5.1.44-bin.jar:.

Make sure that you don't forget the final ":." in that line above!

Now, get JdbcTest.java from the cluster at ~mark/pub/51221/src/JdbcTest.java, and copy it into your Lab3MySQLServer container, maybe into the same subdirectory you're using for you RMI code.  Now compile JdbcTest.java.  Make sure whatever terminal you use to execute javac has the CLASSPATH set above.  Edit that file, and change the following lines to match your configuraion:

                        String connectionUrl = "jdbc:mysql://172.17.0.3:3306/employees";
                        String connectionUser = "root";
                        String connectionPassword = "secret";

Find out the IP address of the Server container.  Inside your Lab3HttpdServer container, type ifconfig.  Note the IP address of the eth0 interface in that container (it should be something like "inet addr:172.17.0.2" or something like that). Pay particular attention to the proper IP address of your mysql server container.  It may be 172.17.0.2 or 172.17.0.3 or something else.  You will need to replace the connectionUrl string's IP address above with the correct actual server IP.  Note that the root user and password secret lines should be fine.  Recompile JdbcTest.java and run it.  Hopefully, you will get (after perhaps a warning or two) a bunch of dept_no's and Department Names.  If so, you're in great shape.  Your JdbcTest java test program running on the CLIENT just hit your MySQL instance in your SERVER.

STEP 5:

Verify that your RMIClient program running in your docker client can talk to the RMIServer program running in your docker server. 

Find out the IP address of the Server container.  Inside your Lab3MySQLServer container, type ifconfig.  Note the IP address of the eth0 interface in that container (it should be something like "inet addr:172.17.0.3" or something like that).

Now we need to connect our RMIClient running on our CLIENT (
Lab3HttpdServer) to the RMIServer running on our SERVER (Lab3MySQLServer).  To do this, on your Lab3MySQLServer SERVER execute the RMIServer program.

On your
Lab3MySQLServer SERVER, execute java RMIServer.   Note the "using address" line, especaially the IP address.

Now, in your CLIENT container (
(Lab3HttpdServer), execute your client against your server, using a command similar to this:  "java RMIClient 172.17.0.3 hi".  Of course you would use the correct IP address.  Make sure that your RMIServer prints out the string  you passed in.  Once that's done, you're almost finished.

STEP 6:

Modify your RMIServer and RMIClient to execute a remote database access call and return the result to the remote client. 

On your Lab3MySQLServer SERVER that is running your MySQL instance, use vi (or whatever you've installed as its alternative) to modify the RemoteInterface.java code.  Change the RemoteInterface classes's recieveMessage method so that instead of returning void, it returns an int. 

Then, modify on the CLIENT the source code for RMIClient.java, and change the return value of the receiveMessage() call from void to int, as your new receiveMessage() function will be returning an int instead of a void.

Then, create a function in your RMIServer.java source (very similar to the main() function in JdbcTest class in JdbcTest.java) that when called and passed in a String tablename, hits the (local to the container) mysql database table whose name was passed in, and executes a SELECT COUNT(*) on that table, and returns the numeric result of the number of records in the table returned from the SELECT call.  So, for example, if you pass in the table name "employees" to the client, the remote server would return the int 300024 to the client, because there are 300,024 records in the employees table.  If you were to pass in the table name "departments" to the client (running on CLIENT
(Lab3HttpdServer), such as:

# java RMIClient 172.17.0.3 12345 departments

the remote server would return 9, because there are 9 records in the departments table on the server.  So the prototype of the new function might be something like:

    public int execute_it(String tablename)
    {
        //this code will hit the local mysql database table "tablename" and execute a query similar to
"select * from departments",
        //and will return the result set's result, in this case, the int "9" because there are 9 records in the departments table...

    }

Then simply have your receiveMessage function that implements RemoteInterface call your new function and return the result, such as:

    public int receiveMessage(String tableName) throws RemoteException
    {
        System.out.println("In RMIServer's receiveMessage method.  Received TableName: " + tableName);
        int y = JdbcTest.execute_it(tableName);  // the return value is the number of rows in tableName
        return y; 
    }



STEP 7:

Run it all. 

Once you have your new changes all executing properly, you're done.  Submit as instructed below.

References:

You may find the following references helpful (in addition to the links from previous labs):

Ubuntu package commands
The docker page for mysql

General Docker Tutorial Links

Docker Cheat Sheet

Submitting:


Create a Bitbucket Repository called Lab 3. Upload your Lab 3 CLIENT and SERVER tarballs (docker export) to this repo.  gzip each tarball before submitting.  Make sure that the user name "johnhb" has access to this repo.  Please include a README text file that contains any instructions for the TAs to assist with grading (especially with instructions on how to run/launch your containers), and design notes are often a useful thing to provide.