Project Scenario for OpX. High-level Overview In the Test GUI Controller, opXController, for the opX...

18
Project Scenario for OpX

Transcript of Project Scenario for OpX. High-level Overview In the Test GUI Controller, opXController, for the opX...

Project Scenario for OpX

High-level Overview

In the Test GUI Controller, opXController, for the opX command there is conceptually a call to an appropriate Class, C, of the form

OpXResponseInfo opXResponse = C.opX(OpXRequest);

Where OpXRequst is an instance of OpXRequestInfo.

Then we show the response in the response window with

IView.setResponse(opXResponse.toString());

Things to Understand• First, things to do in the OpXController of the GUI is to get ready to

make the call• The class, C, is not on the same machine as the GUI. So, how do we

call the operation across the internet?– We use a client and a server

• We call the opX command on the client communicator, CC.OpXResponseInfo opXResponse = CC.opX(opXRequest);

• The client communicator encodes the operation and its parameters (opXRequest) and sends them to the server.

• The server gets the operation and parameters (bundled in the object opXRequest) and decodes them.

• The server then calls C.opX(opXRequest) and gets a response, opXResponse, of type OpXResponseInfo

Getting Ready to make the call

• Get the parameters from the GUI– Use IView.getParameters()

• Use them to create an instance of OpXRequestInfo, opXRequest– I have a constructor whose single parameter is the output of

IView.getParameters()• OpXRequestInfo opXRequest = new

OpXRequestInfo(Iview.getParameters)

• Get a string representation of the opXRequest– String stringRepresentation = opXRequest.toString();

• Use IView.setRequst(stringRepresentation) to display the string in the GUI

Calling the opX operation across the Internet

• We use a client and a server– In the opXController we call the opX command in the client

communicator, CC.OpXResponseInfo opXResponse = CC.OpX(OpXRequest);

– The client communicator encodes the operation and its parameters (opXRequest) and sends them to the server.

– The server gets the operation and parameters (bundled in the object opXRequest) and decodes them.

– The server then makes the call we wanted to make in the first placeOpXResponseInfo opXResponse = C.opX(opXRequest)

– The server then encodes the response and sends it back to the client

– The client communicator then decodes the response (opXResponse) as the return value for the method call made in the opXController.

The Client Communicator Design

• There exists one method for every operation opX.– OpXRequestInfo opX(OpXRequestInfo opXRequest)

• Each of the methods for the 7 commands are all most identical.

• We will take all of the common code and put it in its own method which we will call “doPost”

• If done well, theOpXResponseInfo opX(OpXRequestInfo)

method becomes a one liner:return (OpXResponseInfo) doPost(opXName, opXRequest)

The “doPost” method

• First, set up the connection• Encode the opXRequest and send it• Handle any problems (the connection failed,

the response is not OK, or the response is empty).

• Decode the response as an object and send it to the opX method that called “doPost”

Setting up the Connection

• Create a string representation of the address of the server– http://localhost:8080/ + opXName

• opXName is an input parameter to doPost

• Create a URLURL url = new URL(the string you just created)

• Create HttpURLConnectionHttpURLConnection connection =

(HttpURLConnection)url.open();• The HttpURLConnection class is in the Java library

Setting up the Connection(Continued)

• Set the request method typeconnection.setRequestMethod(“POST”);

• Indicate there will be information in the body of the requestconnection.setDoOutput(true);

• Now connectconnection.connect();

Encoding and Sending using XStream

• Encode and store in the body of the requestxStream.toXML(opXRequst, connection.getOutputStream())

– The opXRequest is a parameter to doPost– The xStream is an instance of XStream

• Send the request to the serverconnection.getOutputStream.close();

Handling the Response

• Get the response codeconnection.getResponseCode()

• Get the response lengthconnection.getResponseLength()

• If everything is correct– Decode the response and store it in an objectObject object = xStream.fromXML(connection.getInputStream)

• Return the object to the opX method that called doPost (the calling method then casts the object to the appropriate type)

Handling Errors

• Use a try/catch block• Throw errors for– Response code not equal to

HttpURLConnection.HTTP_OK– contentLength not equal to 0– IOException• Thrown when trying to connection or communicate

The Server Perspective• Create a Server class containing a HttpServer we will call httpServer.• When you set up the server

– Initialize anything that you need• For example, initialize the datebase

– You may need to use the DataImporter to fill the Database

– Create the HttpServerHttpServer httpServer = HttpServer.create(new InetSocketAddress(8080), 10)

– Set the ExecutorhttpServer.setExecutor(null)

– Create the contexts for each command. For the opX command it might behttpServer.createContext(“/opX”, opXHandler);

– There are 7 such commands– The name of the operation is the one appended to the end of the url string in the client

» There is one context (“/”, fileTransfer) for the 8th command.– The opXHandler is described on the next page

– Start the server• server.start()

Server Handlers• Each of the handlers is an instance of a subClass of the library class HttpHandler

abstract public HttpHandler {public HttpHandler(){}abstract void handle(HttpExchange exchange);

}

• Create an HttpHandler for every operation opX. This is done in the Server class– Do this by subclassing HttpHandler, overloading the handle method, and creating an

instance. This is best done using an anonymous inner class.– Assign it to a variable name of your choice which is the name used when creating a

context (see previous slide)– Example

private HttpHandler opXHandler = new HttpHandler() { public void handle(HttpExchange exchange) throws IOException {

//see next slide }}

The Body of every Handler• Retrieve and decode the request

OpXRequestInfo opXRequestInfo =(OpXRequestInfo)xStream.fromXML(exchange.getRequestBody())

• The xStream is a variable in the Server class• The exchange is the input parameter in the handle method• getRequestBody() actually gets an InputStream

• Execute the operation on the appropriate classOpXResponseInfo opXResponse = C.opX(opXRequestInfo)

• Encode the response and send it back to the client communicator– First, set the headers

Exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, 0);– Endcode and write the response to the response body

xStream.toXML(opXResponse, exchange.getResponseBody())• getResponseBody actually returns an OutputStream

– Send the responseexchange.getResponseBody.close();

Handling Errors on the Server Side

• Wrap everything in try/catch block– Catch IOExceptions when creating the server– Catch any exceptions thrown when the operation in

the model class is called• If there is an error send and error response back

exchange.sendResponseHeaders(HttpURLConnection.HTTP_INTERNAL_ERROR, -1)

– You don’t have to write anything to the response body (using xStream.toXML) nor do you perform

exchange.getResponseBody().close()

The opX operations in the Server

• This is up to you• I use a single Class called Controller that has a

method for each of the 8 commands• Most of the logic should go here– Including error detection and reporting

• The database access classes should primarily by “getters” and “setters”– The may be of a higher level and thus not match

one for one with sql commands on a table.

The 8th CommandFileDownload Command

• Differences– We don’t really use the “/opX” method of identifying the corresponding

handler for file downloading• You might consider

httpServer.createContext(“/”, fileDownloader);

– The fileDownloader doesn’t encode the response.• It opens up the output file (an OutputStream) of the exchange• It also opens the source file as an InputStream.• It then copies the contents of the source file into the output stream of the

exchange• When finished, it closes the OutputStream.