cs636 class 4

CS636 Class 4 Notes

Quick look at: Pizza1 Project Lots of directories for packages

Compiling a whole tree of Java files as in pizza1 is not easy using just the javac and java commands, as we would expect to do on topcat where we don't have eclipse working for us. 

Solution: use ant, a very useful build tool (put it on your resume!).

Easy once set up: use <javac> and <java> Ant tasks, in build.xml

They wrap javac and java in programmer-friendly ways

<javac>  srcdir and destdir attributes: just specify the tops of the src and .class file trees, and the whole tree of .java files gets compiled

<java> classpath and classname, similar to command. Also put fork=”true” to get a brand-new JVM for your program rather than executing in the used one of Ant itself, which sometimes can cause weird problems. 

<javac> is using sourcepath for us, and also finding all the source files in the src tree for us: javac itself can handle oata/*.java on its command line, but not */*.java, etc.

<javac> compiles all java files in the file tree, that is, all files below the top dir that you specify by srcdir  and puts class file in the file tree specified by dstdir.

Note that <javac> is “smart”: it only compiles sources that are newer than their class files, and things it sees as dependent on those.

--It can be fooled if you move things around on the filesystem, so if worried, do “ant clean” and then “ant compile” or “ant build” to do a “full rebuild”. 

--In eclipse, use Project>Clean to do this important action.

Dependencies in build.xml: look at second example in XML and Ant Examples

Need to compile before run

ant looks at  <target> element for “run”, sees depends = compile

so does “ant compile” for us, when we do “ant run”. 

Properties: just name-value associations, i.e., in effect string variables to allow us to avoid stupid repetition inside build.xml.

Evaluation of property foo: ${foo}

Can build up strings from pieces, see classes.dir property.

Can evaluate a property even inside an attribute value: the double-quotes (or single quotes) used in attribute value syntax don’t stop this evaluation.

Ex: srcdir = “${src.dir}”.  Ant evaluates ${...} first, then uses resulting XML.

<path> element: a way to define a path (usually a classpath) once for the project, and then use it over and over in various targets.  It has an id attribute, for pointing to by an IDREF attribute elsewhere.

Ant tasks

<javac> 
task from example 1 of  XML and Ant Examples
         <javac srcdir="src" destdir="build/classes"/>   
Note that
 <foo/> 
is equivalent to
<foo></foo>
This is an element without content, i.e. child elements or text data. Another example:
       <delete dir="${build.dir}"/> 

task from example 2:
         <javac srcdir="${src.dir}" destdir="${classes.dir}">
           <classpath refid="project.classpath"/>
         </javac>
 
Note here how we remove the / from the start tag for
<javac>
to allow it to have a child element.

We need a child element to be the basis of a ref to the "path" element describing the classpath,
because the ID-IDREF mechanism goes from element to element. Here is the result:
<javac> classname="${main-class}" fork="true">
  <classpath  refid="project.classpath"/> 
</javac>
How can you find out all the possible attributes and child elements of an ant task?
Docs linked from class web page at apache.org, or Google “ant task javac”.

What about using jar files?

A jar file represnts a tree of files. To see the tree:

   jar tf foo.jar             --shows classes in jar

   java –classpath ojdbc6.jar:. JdbcCheckup

                            ojdbc6.jar:   holds whole tree of directories, contains driver class

Not covered in class:

How java locates x.y.Foo ‘s class:

It takes each entry in the classpath (here odbj6.jar and .) as the top of a real or virtual tree of class files and looks in the tree at the x/y/Foo.class position in the tree, and if there is a class there it uses it.  JdbcCheckup.class is found relative to “.”.  The oracle driver class is located in the jar file.

In other cases, where your program directly uses the classes in a jar file, you need the jar file in the classpath for the javac command, too. JDBC’s top-level methods are in the JDK, so we don’t need to use the driver jar during compiles, only at runtime.

How does that work? JDBC has a standard that specifies the required classes and methods in the drivers. For example, the line from JdbcCheckup.java:

…DriverManager.getConnection(…)

can compile because the class DriverManager, with static method getConnection, is in the JDK.  The code that executes at runtime for this call largely comes from the driver in the jar file.

 End of material not covered in class

Adding jar files to the classpath in build.xml

We need to add jar files to the classpath, but for that, we need to put them somewhere in the project that we can refer to from build.xml.

Usual solution for java projects: add a lib directory to the base directory, and put the jar files there.

Of course, to save on disk space, you can alternatively put jar files in some globally-known directory, but we will do the simplest thing, resulting in a self-contained project.

Adding lib to the project’s file tree:  

            Basedir
          /     /        \
      src    build     lib
              /                 \
        classes       Put jar files we need in here, like ojdbc6.jar

Now we need to fix up the classpath definition.

Same with added pathelement for jar in lib:

    <path  id="project.classpath">
	<pathelement  location="${classes.dir}"/>   
<pathelement location="lib/ojdbc6.jar"/> </path>

We see that a jar file adds a whole file tree to the classpath, just like a directory at the top of a real file tree does. We can similarly add jar files for the other driver we need for MySQL and HSQLDB.

Advanced Tip: There is a wildcard way to add all jars in the lib directory to the classpath.

The Pizza Project

We’ll start with a client-server implementation, then later, turn it into a web app.

The first step is studying the supplied Pizza1 project, the example to guide our own development project

 Also the pizza project “Project Description”, linked to the class web page

We use the layered architecture discussed in the first class. We see packages for presentation, service, and dao, corresponding to the layers.


What about package “domain”? It has classes PizzaOrder, PizzaTopping, and PizzaSize. These represent the needed domain objects, the subjects of the application. so the domain package does not have its own layer, though is associated closely with the service layer.

The domain objects are acted on by the code in the service layer, the heart of the application. They also are used in the DAO layer, in a more technical way, to allow the data to be persisted in the database

We can show this on the layer diagram as follows: add notation to the following diagram showing that the domain objects flow to and fro between the service layer and the DAO layer.


layers diagram
Now we see we have Java packages for each layer: presentation, service, dao
domain package: objects for PizzaOrder, etc.
config package: setting up the system


Some development groups allow the domain objects to flow also up into the presentation layer, but this can lead to problems, especially if the objects are mutable, so we will stick to the more conservative approach of keeping them inside the main part of the application. We can return to this consideration.

Note that the layers are “call-down” layers: the presentation layer code calls the service API and thus into the service layer. The service layer code calls the DAO API, and the DAO code calls JDBC for pizza1. The presentation layer code never calls the DAO directly.

And nothing ever calls methods of a higher layer. So this is strict layering.

As discussed in the first class, the service layer API is the most important one, defining the actions of the application. We can extract the API by using the fact that all these methods are public, and very little else in the Java source is public. We just cd to the directory of the service package and search the files using "find" or "grep".

C:\cs\cs636>cd pizza1/src/cs636/pizza/service
See the Service API plus a few other lines—

C:\cs\cs636\pizza1\src\cs636\pizza\service>find "public" *Service.java

 ---------- ADMINSERVICE.JAVA

public class AdminService {
        public AdminService(DbDAO db, AdminDAO admDAO,PizzaOrderDAO poDAO, MenuDAO mDAO) {
        public void initializeDb() throws ServiceException {
        public void addTopping(String name) throws ServiceException {
        public void removeTopping(String topping) throws ServiceException {
        public void addSize(String name) throws ServiceException {
        public void removeSize(String size) throws ServiceException {
        public void markNextOrderReady() throws ServiceException {
        public int getCurrentDay() throws ServiceException {
        public void advanceDay() throws ServiceException {
        public List<PizzaOrderData> getOrdersByDay(int day) throws ServiceException {
        public List<PizzaOrderData> getTodaysOrdersByStatus(int status)

---------- STUDENTSERVICE.JAVA
public class StudentService {
        public StudentService(PizzaOrderDAO pizzaDAO, MenuDAO mDAO, AdminDAO admDAO) {

        public Set<String> getSizeNames()throws ServiceException
        public Set<String> getToppingNames()throws ServiceException
        public void makeOrder(int roomNum, String sizeName, Set<String> toppingNames)
        public List<PizzaOrderData> getOrderStatus(int roomNumber) throws ServiceException {
        public void receiveOrders(int roomNumber)throws ServiceException {

First concentrate on the service API calls in bold.

The topping names and size names are provided to the presentation layer as simple Strings.

The PizzaOrder information is provided using PizzaOrderData objects created from PizzaOrder objects just for the purpose of carrying the data to the presentation code.

The service layer does any changing or creation of domain objects, based on actions specified by the service API calls.  For example the makeOrder code, in the service layer, creates a PizzaOrder object. All these methods throw ServiceException.

Not covered in class: Why would you want to call upwards?

For notifications. Consider when the pizza is ready: the admin action “this pizza is ready” calls down and changes the database. If this change triggered a notification to the student user, that would need an upcall to the presentation layer.

Such notifications can be done in say a Swing application (GUI program running on the user’s machine), because the Swing app owns the screen. It can pop up a little note on the screen.

But we are designing for an (eventual) web app, where the service layer runs in the server and doesn’t own the clients’ screens. The clients use HTTP to ask questions and make commands.

So the client has to explicitly ask “is the pizza done?” and this request is handled in a call-down manner.

That’s the simple web app way. We could explore ways to notify, but it is quite difficult, and we need to keep things simple to get where we want to go in one term.

Consider that from the server’s standpoint, the clients are often hidden behind firewalls—how can you send them information at some arbitrary moment?

They don’t have well-known network addresses! The chance to send them information is when they send a request in to you (the server) and you get to reply to it.

Therefore, we will stick to the simple call-down layers.

End of note not covered in class.

Note: Presentation code is not allowed to use domain objects, but it can use information from them.

Example: The presentation code gets topping names (simple Strings) by calling getToppingNames, size names by calling getSizeNames, then displays them as options to the user, and uses the chosen objects in the call to makeOrder.

The domain objects carry info, often “scratch copies” of DB data, or data bound for DB

Next time--look at database for pizza1.