diff --git "a/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050HTML\051.md" "b/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050HTML\051.md" new file mode 100644 index 0000000..a58ec64 --- /dev/null +++ "b/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050HTML\051.md" @@ -0,0 +1,28 @@ +The `add-student.html` page in the `Web Pages` folder is where we need to add the form that allows the user to enter the details for a student. + +Add the following HTML to the `
` tag: + +```html +

Add New Student

+ +
+ + Student Details + +
+ + + + +
+ +
+ +Back to Menu +``` + +This contains a title heading and a form for the student's details. We are also adding a navigation link to the bottom of the page so that the user can get back to the menu. + +Build and redeploy the application by copying the WAR file into the webapps folder again, **replacing** the original file. + +Click the 'Add New Student' link in the index/menu page to view the form. It will look pretty ugly at the moment, but it should have all of the components to allow a user to enter the details for a student. diff --git "a/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050HTML\051.md.meta" "b/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050HTML\051.md.meta" new file mode 100644 index 0000000..ee82532 --- /dev/null +++ "b/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050HTML\051.md.meta" @@ -0,0 +1,4 @@ +section: 7 +tags: lab lab04 +title: /Labs/04/Adding a Student (HTML) +type: text/x-markdown \ No newline at end of file diff --git "a/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050Servlet\051.md" "b/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050Servlet\051.md" new file mode 100644 index 0000000..af1df30 --- /dev/null +++ "b/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050Servlet\051.md" @@ -0,0 +1,48 @@ +1. Take a quick look at the code for the form again. Note the `action` and `method` attributes of the `
` tag. + + When the form is submitted, a POST request is going to be sent to the `add-student` path of the web application. This is the path that the `AddNewStudent` servlet is attached to. + +1. The servlet is currently only handling GET requests. Change the name of the `doGet` method to `doPost` so that the servlet will handle POST requests. + +1. Delete the line of code in the `doPost` method that prints the 'Hello World' message. + +1. We need somewhere to store the students as they are entered. Eventually we would expect the student data to be stored in a database, but for the purposes of this lab we will be storing the students in an `ArrayList` that is itself stored in the user's session. Add the following code to the `doPost` method: + + ```java + // get the user's session + HttpSession session = req.getSession(); + + // get the studentList from the session + Collection students = (Collection) session.getAttribute("studentList"); + + // if the studentList has not yet been added to the session then add it + if (students == null) { + students = new ArrayList(); + session.setAttribute("studentList", students); + } + ``` + + The comments describe what is happening here. + +1. Add the following code to the `doPost` method below the previous code to extract the form data and create a `Student` domain object: + + ```java + // extract the form data + String id = req.getParameter("id"); + String name = req.getParameter("name"); + String address = req.getParameter("address"); + + // create the student object + Student student = new Student(id, name, address); + + // add the student to the list + students.add(student); + ``` + + The `id`, `name`, and `address` parameters are the ones declared in the `name` attributes of the form componets in the `add-student.html` page. + +1. The final step is to redirect the web browser to the next page. We will redirect the browser back to the index/menu page. Add the following line below to the bottom of the `doPost` method: + + ```java + resp.sendRedirect("index.html"); + ``` diff --git "a/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050Servlet\051.md.meta" "b/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050Servlet\051.md.meta" new file mode 100644 index 0000000..ab6a936 --- /dev/null +++ "b/tiddlers/content/labs/lab04/_Labs_04_Adding a Student \050Servlet\051.md.meta" @@ -0,0 +1,4 @@ +section: 8 +tags: lab lab04 +title: /Labs/04/Adding a Student (Servlet) +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Apache Tomcat.md b/tiddlers/content/labs/lab04/_Labs_04_Apache Tomcat.md new file mode 100644 index 0000000..b7eacf5 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Apache Tomcat.md @@ -0,0 +1,24 @@ +We will be using a web server called Apache Tomcat. Tomcat is a web server that is able to execute Java code to generate the dynamic parts of a web page. + +Tomcat is already installed in Linux desktop. We won't be using Tomcat again, so there is no need for you to install it on your own computers. + +Run the following command from a terminal: + +``` +tomcat9-instance-create /tmp/$USER/tomcat +``` +Enter that exactly as written --- you should **not** swap the `$USER` part for your username. + +This command will create a Tomcat server that you are able to deploy your own applications to without needing administrator privileges. + +You can start the web server using the following command: + +``` +/tmp/$USER/tomcat/bin/startup.sh +``` + +Point a web browser at: + +http://localhost:8080 + +You should see a `404 / Not Found` error page since there is currently no web pages to display. Despite the error, we can see that the web server is running and responding to requests from the user's web browser so is ready for us to add some web pages. \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Apache Tomcat.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Apache Tomcat.md.meta new file mode 100644 index 0000000..a44ce7e --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Apache Tomcat.md.meta @@ -0,0 +1,4 @@ +section: 3 +tags: lab lab04 +title: /Labs/04/Apache Tomcat +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Configure the Browser for Development.md b/tiddlers/content/labs/lab04/_Labs_04_Configure the Browser for Development.md new file mode 100644 index 0000000..c864183 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Configure the Browser for Development.md @@ -0,0 +1,9 @@ +Web browsers will cache files so that they don't need to be downloaded from the web server each time the user views a page. This can be annoying while developing web sites since we always want to be looking at the latest version of a file rather than looking at old, cached versions. Most browsers allow you to disable the cache whenever you have the developer tools open. + +1. Press F12. This key will open the developer tools in most web browsers. + +1. Click somewhere in the developer pane to give that pane focus and then press F1. This key will open the developer tools settings. + +1. Scroll down until you find the option to disable the cache while the developer tools are open. Check the box for that option. + +1. You have probably just opened the dev tools for the INFO201 Tiddlywiki. Switch to the tab that has your student system in it and hit F12 again to open the dev tools for that site (the disable cache option will still be set so you don't need to set that again). Leave the dev tools open whenever you are working on a web page --- the cache will only be disabled while the dev tools are open. \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Configure the Browser for Development.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Configure the Browser for Development.md.meta new file mode 100644 index 0000000..a34b4ea --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Configure the Browser for Development.md.meta @@ -0,0 +1,4 @@ +section: 4 +tags: lab lab13 +title: /Labs/04/Configure the Browser for Development +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Deleting Products.md b/tiddlers/content/labs/lab04/_Labs_04_Deleting Products.md deleted file mode 100644 index 43d8f7e..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Deleting Products.md +++ /dev/null @@ -1,35 +0,0 @@ -Add a feature that allows a user to select a product in the product viewer and then delete that product: - -1. Add an issue for this feature if you haven't already done so. - -1. We need to fix the type of object that the `JList` on your `ProductViewer` dialog is expecting. By default NetBeans assumes it will hold strings which is not the case since we will be storing products in the `JList`. - - There is a section in the reference ([Swing/List Components (JList and JComboBox)/Fixing the JList & JComboBox Type Problem](#/Reference/Swing/List%20Components%20(JList%20and%20JComboBox)/Fixing%20the%20JList%20&%20JComboBox%20Type%20Problem)) that explains how to fix this problem. Follow the instructions on that page to make the `JList` use your product domain class instead of strings. - -1. Add a button to the `ProductViewer` dialog for deleting a product (if you haven't already done so). - - Refer to section [4.1.2.3](https://isgb.otago.ac.nz/info202/shared/project/raw/master/output/info202_project.html#%2FMilestones%201%20%26%202%2FViewing%20Products) of the project specification for the lo-fi mock-up of the dialog to see where the delete button fits into things. - -1. Add code to the delete button's handler that: - - * Gets the selected product from the `JList`. - - Refer to the reference section ([Swing/List Components (JList and JComboBox)/Retrieving the Value Selected by the User](#/Reference/Swing/List%20Components%20%28JList%20and%20JComboBox%29/Retrieving%20the%20Value%20Selected%20by%20the%20User)). - - * Calls the `removeProduct` method on the DAO field passing the selected product. - - * Updates the `JLists`'s model object. If we don't do this then the user interface will continue to show the deleted product. The model is the `SimpleListModel` field that is declared at the top of the class. - - Call the `updateItems` method on the model passing in the updated collection of products (use the DAO method that gets the products). - -1. Test your system (by running it). You should now see that when you select a product and press the delete button, the product is removed. - -1. Finally you should add a confirmation dialog to ensure the user doesn't accidentally delete a product. - - There is a section in the reference ([Swing/Message Dialogs (JOptionPane)](#/Reference/Swing/Message%20Dialogs%20(JOptionPane))) that describes how to use confirmation dialogs. - -1. What happens if the user clicks delete without selecting a product? - - The `JList` component has an `isSelectionEmpty` method that you can use to prevent crashes here. - - Don't bug the user unnecessarily with message boxes here. Simply preventing the system from crashing is sufficient. The user will quickly recognise their mistake and throwing up a message box every time the user makes a minor and easily recognisable mistake is a great way of training them to close message boxes without reading them. diff --git a/tiddlers/content/labs/lab04/_Labs_04_Deleting Products.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Deleting Products.md.meta deleted file mode 100644 index 5287830..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Deleting Products.md.meta +++ /dev/null @@ -1,6 +0,0 @@ -created: 20200702091026430 -modified: 20200707005526287 -section: 3 -tags: lab04 hidden -title: $:/Labs/04/Deleting Products -type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Download and Open the Project.md b/tiddlers/content/labs/lab04/_Labs_04_Download and Open the Project.md new file mode 100644 index 0000000..ae8d3fc --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Download and Open the Project.md @@ -0,0 +1,35 @@ +Java has an entire standard that covers what a Java web application looks like, so we need to use a NetBeans project that will produce an application that is in the correct format. + +1. Download the starting project from: + + https://isgb.otago.ac.nz/info201/shared/lab13 + + Use the {{$:/ou/clipart/octicon-cloud-download}} Download Zip button again rather than cloning the project since this makes it easier to save the project in your `labs` repository (since you don't have to worry about problems caused by nesting repositories inside of repositories). + +1. Extract the downloaded zip file into your `labs` repository. + +1. Hopefully the NetBeans plugins are finished installing by now. You will need to restart NetBeans to complete the installation. + +1. Open the project folder in Netbeans using < Open Project">>. + +1. Build the project to get rid of the warning. + +1. You should see two source folders in the project pane: + + * `Web Pages` --- which is were the HTML, JSP, and CSS files go. Basically, anything that is part of the web site goes in this folder. + + * `Source Packages` --- which is the usual Java source packages that contains your Java classes. + +1. Note that we have already created all of the files for you. You should see: + + **Source Packages** + * `domain.Student` --- a typical student domain class. This class is already complete. + * `servlets.AddNewStudent` --- a servlet for processing the data entered by the user when creating a new student. + + **Web Pages** + * `index.html` --- a static web page that contains a menu for the system. + * `add-student.html` --- a static web page that contains the form for adding a new student. + * `view-students.jsp` --- a dynamic web page that will display the students that have been entered in to the system. + * `style.css` --- the CSS file for styling all of the web pages. + +1. Also take a quick look at the Gradle build script at `Build Scripts/build.gradle`. The only thing that we really need to create a web application project via Gradle is the `war` plugin. This will cause Gradle to produce a `war` file that can be deployed to a Java web server such as Tomcat. WAR is short for **W**eb **A**pplication a**R**chive and is a Zip file that packages the web files and compiled Java classes together into a standardised layout that Java web servers can use. \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Download and Open the Project.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Download and Open the Project.md.meta new file mode 100644 index 0000000..93823d8 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Download and Open the Project.md.meta @@ -0,0 +1,4 @@ +section: 5 +tags: lab lab04 +title: /Labs/04/Download and Open the Project +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Duplicate Categories & Products.md b/tiddlers/content/labs/lab04/_Labs_04_Duplicate Categories & Products.md deleted file mode 100644 index 06c40a6..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Duplicate Categories & Products.md +++ /dev/null @@ -1,19 +0,0 @@ -You might have noticed that you have a bug in your system that causes duplicate categories to appear in the comboboxes. To test this, add two products with the same category and then check what appears in the combobox. - -The fix here is easy. Instead of using an `ArrayList` to hold the categories we should be using a `HashSet`. Sets are collections that will only allow unique objects. If you try to add another object with the same value (as determined by the `equals` method) the `add` method will not add the new object. This was discussed in lecture 5. - -Change all of the collections (including the collection that stores the products) in your DAO class from `ArrayList` to `HashSet`. As a general rule, you should be using `HashSet` as your default collection class rather than `ArrayList` since there are also some performance advantages in addition to enforcing uniqueness (refer to lecture 5). - -If you have been following the principle of 'programming to an interface' (see INFO202 lecture 1, slide 14; and INFO201 lecture 12, slides 14 to 17) this will be nice and easy. If not then you have made life harder for yourself since you will also need to change all of your declarations and your method return types. You should be using `Collection` in the declaration. For example: - -```java -Collection products = new HashSet<>(); -``` - -The method return types should also use `Collection`. For example: - -```java -public Collection getProducts() { - return products; -} -``` \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Duplicate Categories & Products.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Duplicate Categories & Products.md.meta deleted file mode 100644 index 3730fd8..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Duplicate Categories & Products.md.meta +++ /dev/null @@ -1,6 +0,0 @@ -created: 20200702091026430 -modified: 20200707005526287 -section: 2 -tags: lab04 hidden -title: $:/Labs/04/Duplicate Categories & Products -type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Examining HTTP.md b/tiddlers/content/labs/lab04/_Labs_04_Examining HTTP.md new file mode 100644 index 0000000..45032f4 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Examining HTTP.md @@ -0,0 +1,17 @@ +Let's take a look at the HTTP messages that are being sent between the web browser and web server. + +1. Run the following command from a terminal: + + ``` + tcpflow port 8080 + ``` + + This will run a network monitor that will show you everything that is happening between the browser and web server. Note that this network monitor will only allow you to monitor local (loopback) connections --- ITS security would get grumpy if we let you sniff data that was travelling on the real network. + +1. Add a student via the form. You should see the POST request being sent to the server. + +1. View the students. You should see a GET request being sent to the server and the server sending back the HTML to the browser. Note that the HTML already has the student data --- there is no Java code being sent to the browser. SSR means that the server has done all of the hard work of adding the dynamic content, so all that the browser sees is the final HTML. + + You will probaly also see the CSS being requested, so scroll up a bit to find the HTML. + +1. Leave the `tcpflow` terminal running --- we will use it again in the next section. diff --git a/tiddlers/content/labs/lab04/_Labs_04_Examining HTTP.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Examining HTTP.md.meta new file mode 100644 index 0000000..9803d5d --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Examining HTTP.md.meta @@ -0,0 +1,4 @@ +section: 11 +tags: lab lab04 +title: /Labs/04/Examining HTTP +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Examining the Sessions.md b/tiddlers/content/labs/lab04/_Labs_04_Examining the Sessions.md new file mode 100644 index 0000000..c565037 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Examining the Sessions.md @@ -0,0 +1,13 @@ +Lecture 24 described how cookies are used to identify a user so that the correct session object can be used for that user. Let's take a closer look at that now. + +1. First, open a private window in the browser. Private windows start with no cookies, so this is effectively the same as having a different user using the system. + +1. Add a couple of students with different details to what you have used previously via the private window. + +1. Notice that the students that the non-private user can see are not the same students that the private user can see --- as mentioned, the private user starts with no cookies, so a new session token cookie will be created for them. This means the private user has a different session to the non-private user. + +1. Click the 'View All Students' link to view the students for the non-private user. + +1. Switch to the `tcpflow` window and find the most recent GET request. You should see that the header section has a `cookie` header which has a `JSESSIONID` cookie. This is the session token. + +1. Do the same for the private user. You should see that the private user has a different session token. It is this token that the server uses to identify which user is sending the request. diff --git a/tiddlers/content/labs/lab04/_Labs_04_Examining the Sessions.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Examining the Sessions.md.meta new file mode 100644 index 0000000..f725acd --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Examining the Sessions.md.meta @@ -0,0 +1,4 @@ +section: 12 +tags: lab lab04 +title: /Labs/04/Examining the Sessions +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Filter by Category.md b/tiddlers/content/labs/lab04/_Labs_04_Filter by Category.md deleted file mode 100644 index 5cf4204..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Filter by Category.md +++ /dev/null @@ -1,25 +0,0 @@ -Add a *filter by category* feature to the `ProductViewer` dialog. This will require you to: - -1. Add another method to the DAO for performing the filtering. Think about the signature for this method yourself. What are the inputs (parameters)? What is the output (return type)? Is the output going to be a single value or a collection? - - Name the method `filterByCategory`. - -1. Implement the method so that it returns all products in the specified category. - - This is an example of a one-to-many relationship. There are many products per category. We should use a collection class that allows us to represent the one-to-many relationships between the categories and the products. The best type of collection for doing this is known as a *multimap*. Java does not have a built-in multimap, but there are a several third-party libraries that provide a multimap collection. - - The Google Guava library has a very good multimap implementation. You will need to add Guava as a dependency to your `build.gradle` file as shown in the reference document in the [Java/Guava Multimap](#/Reference/Java/Guava%20Multimap) section. Adding this dependency will cause Gradle to download the Guava JAR file and add it to the project. - - Refer to the reference section for an example of how to use Guava multimaps. - - **Hint**: Your keys are categories (String) and the values are products. - -1. Add components to the `ProductViewer` dialog for facilitating the filter feature if you haven't already done so (refer to the project mock-ups if you are not sure what is needed). - -1. Add code to the dialog to make the categories appear in the combobox (if you haven't done so already). - - This is the same code that you used in the `ProductEditor` to display the categories in the combobox on that dialog. - -1. Add code to the filter combobox's click handler that gets the selected category and uses it to call the new DAO method to find the associated products. - - You can then call the `updateItems` method on the JList's model to display the filtered products. \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Filter by Category.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Filter by Category.md.meta deleted file mode 100644 index a43ab39..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Filter by Category.md.meta +++ /dev/null @@ -1,6 +0,0 @@ -created: 20200702091026430 -modified: 20200707005526287 -section: 5.1 -tags: lab04 hidden -title: $:/Labs/04/Filter by Category -type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_First Experiments.md b/tiddlers/content/labs/lab04/_Labs_04_First Experiments.md new file mode 100644 index 0000000..a561b87 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_First Experiments.md @@ -0,0 +1,78 @@ +Let's make sure that everything works. + +## Static HTML + +1. Add the following tag **between** the open `
` and closing `
` tag in the `index.html` file. The `
` tag is where the 'main' content of the page goes --- this is an optional tag that is used to style the main content. + + ```html +

Student Management — Menu

+ ``` + + This should display a title heading on the page. The `mdash` part is a special character that will display an em dash. + +1. Add the following below the `

` tag: + + ```html + Add New Student + View All Students + ``` + + This will add a couple of navigation links to the page that can be used to access the other pages of the system. + +## JSP + +1. Add the following to the `
` tag of `view-students.jsp`: + + ```html + <% String name = "Doris"; %> + +

Hello <%= name %>

+ ``` + + Put your name in the place of 'Doris'. + + Since this file is a JSP file, Tomcat will compile and execute any Java code that is contained in the file. The first tag is declaring a name variable using standard Java code. Note the surrounding tags --- Java code must be contained within blocks that are surrounded by `<%` and `%>`. This is referred to as a *scriptlet*. + + The second line is adding a normal HTML heading, but is inserting the value of the variable using a different variant of the starting block `<%=`. This is known as an *expression*. + + Scriptlets and expressions are the two main mechanisms that you can use to create dynamic pages using JSP. + +## Servlets + +1. Open the `servlets.AddStudentServlet` class in the `Source Packages`. You should see that the class contains a method named `doGet`. This method will be called by the web server (Tomcat) when a GET request is sent to a particular path --- in this case the path is `/add-student` as declared in the `@WebServlet` annotation above the class header. + +1. Add the following code to the `doGet` method: + + ```java + resp.getWriter().println("Hello World"); + ``` + + This code will print a string to the response body which will then be sent to the web browser by the web server. + +## Building + +We need to build the project to create the WAR file. You can click the hammer icon on the tool bar, or press the F11 key. + +## Deploying + +We need to copy the WAR file into Tomcat's deployment folder. We have added a task to the Gradle build script that will open the project's build folder in the system file manager. Select the root of the project in the project pane and double click < openBuildFolder">> in the navigator pane. If you don't see the navigator pane then you can display it using the <> menu. + +The WAR file is stored in the `libs` folder. + +Run the following command to open the deployment folder in the file manger: + +``` +thunar /tmp/$USER/tomcat/webapps & +``` + +Copy the WAR file from your project's build folder into Tomcat's `webapps` folder. + +Tomcat will automatically unpack and deploy the WAR file --- you might see the new folder appear in the file manager after a couple of seconds. + +## Testing + +Open `http://localhost:8080/lab13` in a web browser. You should now see the rather ugly looking menu page with the two navigation links. + +Click the 'View All Students' link. This will take you to the JSP page. You should see a 'Hello' message with your name. Remember that your name was declared inside a Java variable --- Tomcat has had to compile the Java code in the JSP file and execute it in order to add your name to that page. + +Open `http://localhost:8080/lab13/add-student` in the browser. This is the URL for the servlet. You should see the 'Hello World' message that was generated in the `AddStudentServlet` class. diff --git a/tiddlers/content/labs/lab04/_Labs_04_First Experiments.md.meta b/tiddlers/content/labs/lab04/_Labs_04_First Experiments.md.meta new file mode 100644 index 0000000..a33adfa --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_First Experiments.md.meta @@ -0,0 +1,4 @@ +section: 6 +tags: lab lab04 +title: /Labs/04/First Experiments +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Install the NetBeans SSR Web Development Plugins.md b/tiddlers/content/labs/lab04/_Labs_04_Install the NetBeans SSR Web Development Plugins.md new file mode 100644 index 0000000..5ca1a86 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Install the NetBeans SSR Web Development Plugins.md @@ -0,0 +1,15 @@ +The SSR web development plugins are currently not installed in NetBeans. We will install them now. + +1. Start NetBeans. + +1. Open the plugins dialog using < Plugins > Available Plugins">>. If the list is empty, click the <> button. + +1. Search for 'ee base'. You should see a single result named 'Java EE Base'. + +1. Select the check box and then click <>, and then <>. + +1. You will have to wait for a minute or so while licenses are discovered. When that process finishes, select the 'I accept...' check box (they are all open source licenses, so you aren't agreeing to anything too scary) and click <>. + +The installation process will take a few minutes. Unfortunately the SSR web development tools are part of the Java Enterprise Edition tools which is quite a large set of plugins. + +Move on to the next section while you wait for the installation to complete. diff --git a/tiddlers/content/labs/lab04/_Labs_04_Install the NetBeans SSR Web Development Plugins.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Install the NetBeans SSR Web Development Plugins.md.meta new file mode 100644 index 0000000..23f0a8f --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Install the NetBeans SSR Web Development Plugins.md.meta @@ -0,0 +1,4 @@ +section: 2 +tags: lab lab04 +title: /Labs/04/Install the NetBeans SSR Web Development Plugins +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Introduction.md b/tiddlers/content/labs/lab04/_Labs_04_Introduction.md index 98d1c26..d87b39b 100644 --- a/tiddlers/content/labs/lab04/_Labs_04_Introduction.md +++ b/tiddlers/content/labs/lab04/_Labs_04_Introduction.md @@ -1,21 +1,27 @@ -In this lab we will work on the following: +You will need to use the Linux desktop for this lab, so switch to that environment now if you are using your own computer. -* Using different collection classes in the DAO to facilitate: +There are 3 main ways of creating web sites: - * Automatic filtering of duplicate products and categories. +* **Static** --- Where all of the web pages are static in that they do not contain any dynamic elements --- all of the information is contained directly within the web pages. You create (or generate) an HTML file for each of your web pages and store them somewhere that the web server can find them. The web server does not need to do any work beyond loading the correct HTML file and sending it to the user's web browser. - * Finding a product by its ID. +* **Server-Side Rendering (SSR)** --- Where you are creating a web application that has some pages that contain dynamic elements. - * Filtering the products by their category. + An example would be a web page for displaying the details for a single product that your online shop sells. If we used a static web site then we would need to create an HTML file for each of the products that we sell. This would be a lot of work and would require a lot of ongoing work to keep the prices and stock quantities up to date and add/remove products as necessary. -* Adding the ability to *delete* products via the product viewer dialog. + It would make much more sense to create a single web page that pulls the product details from a database. It would have place-holders for the dynamic parts of the page (such as the details for a specific product) that would be replaced by some code that the web server executes in response to a user requesting the page for a particular product. -Choosing the appropriate collection(s) for the job can save you from having to write a lot of code that a collection should be doing for you. Note that Java calls these things *collections*, so that is the term that we will use, but the more generic term is *data structures*. + Since the code that provides the dynamic parts of the page is executed by the web server (or an application that the web server delegates to) then this method of creating dynamic web pages is called server-side rendering (SSR). -Note that at this point in the course we have introduced you to most of the basic concepts, so we will start tapering off the level of details in the instructions a little bit. Between the previous lab documents and the reference section, you have everything that you need. +* **Client-Side Rendering (CSR)** --- Where the page template, domain data, and dynamic code required to produce a dynamic web page are all sent to the web browser separately. The browser would run the code (which is generally JavaScript) which would merge the domain data with the page template to create the web page that the user sees. -## Milestone 1 Marking + Since the code that produces the dynamic content is executed on the client-side (the client in this case is the user's web browser) then this method of creating dynamic web pages is called client-side rendering (CSR). This method also goes by the name **AJAX** --- Asynchronous JavaScript and XML. -We will start marking the milestone 1 project in the labs this week. Carry on working on the rest of this lab and we will visit each of you to carry out the marking. You can continue to make commits and push. We probably won't get to everyone this week, so we will continue with the marking next week --- we took note of the commit ID for your submission so we can easily roll your system back to that version for marking. +SSR is the traditional way of creating dynamic web applications. -Please log in to GitBucket now so that you are ready to be marked. \ No newline at end of file +In recent years we have seen a large shift away from creating desktop applications in favour of creating equivalent web applications. This means that we are now creating web applications that are a lot more complex that need to serve a lot more users than what has been the case in the past. SSR is not really up to the task of creating these sort of applications (the web server and associated infrastructure becomes a significant bottleneck), so CSR is the way things are done now. + +In this lab we will focus on static pages and SSR. Milestone 1 of the course project (which will be released soon) will be SSR, while milestone 2 will be CSR. + +We will be creating a simple student management system for the Julienned school. The system should allow users to add the details for a new student and then view the details of all of the students that have been entered. + +This lab will assume that you are familiar with lecture 24, so take a quick look at that lecture now if you haven't done so already. \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Introduction.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Introduction.md.meta index f9a3613..a806a3e 100644 --- a/tiddlers/content/labs/lab04/_Labs_04_Introduction.md.meta +++ b/tiddlers/content/labs/lab04/_Labs_04_Introduction.md.meta @@ -1,6 +1,4 @@ -created: 20200702091026430 -modified: 20200707005526287 section: 1 -tags: lab04 hidden -title: $:/Labs/04/Introduction +tags: lab lab04 +title: /Labs/04/Introduction type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_JSP and Servlets.md b/tiddlers/content/labs/lab04/_Labs_04_JSP and Servlets.md new file mode 100644 index 0000000..6bacaee --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_JSP and Servlets.md @@ -0,0 +1,6 @@ +Java web applications have two primary mechanisms for creating dynamic web pages: + +* **JSP (Java Server Pages)** --- HTML with embedded Java code. You use HTML to create the bulk of the page and Java for the dynamic parts. +* **Servlets** --- Java objects that receive HTTP request and generate HTTP responses. These are useful for processing the data that is sent to the server when the user submits a form. + +We will be using a mixture of JSP and servlets. JSP is good at displaying data to the user, and servlets are good at processing the data that the user sends to the web server (via forms). \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_JSP and Servlets.md.meta b/tiddlers/content/labs/lab04/_Labs_04_JSP and Servlets.md.meta new file mode 100644 index 0000000..e05fb9c --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_JSP and Servlets.md.meta @@ -0,0 +1,4 @@ +section: 3.1 +tags: lab lab04 +title: /Labs/04/JSP and Servlets +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Lab 4_ Delete, Search, and Filter Features.tid b/tiddlers/content/labs/lab04/_Labs_04_Lab 4_ Delete, Search, and Filter Features.tid deleted file mode 100644 index e3176fc..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Lab 4_ Delete, Search, and Filter Features.tid +++ /dev/null @@ -1,11 +0,0 @@ -created: 20200702091026430 -modified: 20200707005526287 -tags: lab toc hidden -title: $:/Labs/04/Lab 4: Delete, Search, and Filter Features -type: text/vnd.tiddlywiki - -!! Contents -<$set name="path" value="/Labs/04/"> -<$macrocall $name="contents-tree" path=<> /> -
<$macrocall $name="openByPath" path=<> />
- diff --git a/tiddlers/content/labs/lab04/_Labs_04_Lab 4_ Web Development Using SSR.tid b/tiddlers/content/labs/lab04/_Labs_04_Lab 4_ Web Development Using SSR.tid new file mode 100644 index 0000000..5d02ad8 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Lab 4_ Web Development Using SSR.tid @@ -0,0 +1,12 @@ +alias: +tags: lab toc lab04 +title: /Labs/04/Lab 4: Web Development Using SSR +type: text/vnd.tiddlywiki + +! Contents +<$set name="path" value="/Labs/04/"> + +<$macrocall $name="contents-tree" path=<> /> +
<$macrocall $name="openByPath" path=<> />
+ + \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_New DAO Tests.md b/tiddlers/content/labs/lab04/_Labs_04_New DAO Tests.md deleted file mode 100644 index e1522d7..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_New DAO Tests.md +++ /dev/null @@ -1,7 +0,0 @@ -You now have two new DAO methods (`searchById` and `filterByCategory`). Add tests to your existing DAO test class to test these two new methods. - -It is important to remember to test for the *negative* case as well as the *positive* case. In other words, as well as checking that you get only 'apple' and 'orange' when you filter by the 'fruit' category --- you should also ensure that you don't also get a 'velociraptor' which would be the case if your method is not doing any filtering at all (it returns everything). - -In the case of the `searchById` method, the negative case would be to ensure that the method correctly handles a non-existent ID (it should return `null`). - -You may want to refer to reference section [Testing/Hamcrest](#/Reference/Testing/Hamcrest) for more examples of using Hamcrest assertions. \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_New DAO Tests.md.meta b/tiddlers/content/labs/lab04/_Labs_04_New DAO Tests.md.meta deleted file mode 100644 index e69a32c..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_New DAO Tests.md.meta +++ /dev/null @@ -1,6 +0,0 @@ -created: 20200702091026430 -modified: 20200707005526287 -section: 5.2 -tags: lab04 hidden -title: $:/Labs/04/New DAO Tests -type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Project Tasks.md b/tiddlers/content/labs/lab04/_Labs_04_Project Tasks.md deleted file mode 100644 index eb0dfbb..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Project Tasks.md +++ /dev/null @@ -1 +0,0 @@ -Try to complete these tasks before the next lab (which will assume that these tasks have been completed). Adding these features will complete all of the required use cases described in section [4.1.1](https://isgb.otago.ac.nz/info202/shared/project/raw/master/output/info202_project.html#%2FMilestones%201%20%26%202%2FRequirements%20Analysis) of the project specification making your system functionally complete. We still have some work to do (data persistence, input validation, error handling, and some more testing), but the product catalogue system now has all of the features that it needs. \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Project Tasks.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Project Tasks.md.meta deleted file mode 100644 index 3244c0f..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Project Tasks.md.meta +++ /dev/null @@ -1,6 +0,0 @@ -created: 20200702091026430 -modified: 20200707005526287 -section: 5 -tags: lab04 hidden -title: $:/Labs/04/Project Tasks -type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Search by ID.md b/tiddlers/content/labs/lab04/_Labs_04_Search by ID.md deleted file mode 100644 index 50446c2..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Search by ID.md +++ /dev/null @@ -1,21 +0,0 @@ -Add a *search by ID* feature to the product viewer. This will require: - -1. Adding another collection to the `ProductCollectionsDAO` class that associates products with their IDs. You should use a map for this. Refer to the [Java/Maps](#/Reference/Java/Maps) section of the reference for an example of how to use maps. You might want to take another look at lecture 5 if you are unsure of why a map is an appropriate data structure to use for this feature. - -1. Adding code to the `saveProduct` method that will also add the product being saved to the new collection (hint --- use the `put` method). - -1. Adding a new method to the DAO class for performing the search. It will take a product ID as a parameter and return a product. Name this method `searchById`. - - Implement the method to find the product that matches the given ID and return it. - - The method should return `null` if no matching product is found. This is useful for two reasons: - - * We can use this method to check if a product already exists. A `null` result would indicate that the product does **not** exist. - - * The `JList` will display nothing if you tell the model to display `null`, so this means we don't have to explicitly handle the *'no product found'* exceptional case in the GUI. - -1. Adding components to the `ProductViewer` dialog for the search feature (if you haven't already). Refer to the user interface mock-ups in the project specification if you are not sure what this should look like. - -1. The search button click handler should take the ID entered by the user and use it to call the new method on the DAO to find the associated product. - -1. Use the `updateItems` method from the model (the `SimpleListModel` object that the `JList` is using) to display the product once you find it. \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Search by ID.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Search by ID.md.meta deleted file mode 100644 index 4e5981c..0000000 --- a/tiddlers/content/labs/lab04/_Labs_04_Search by ID.md.meta +++ /dev/null @@ -1,6 +0,0 @@ -created: 20200702091026430 -modified: 20200707005526287 -section: 4 -tags: lab04 hidden -title: $:/Labs/04/Search by ID -type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Styling.md b/tiddlers/content/labs/lab04/_Labs_04_Styling.md new file mode 100644 index 0000000..9824630 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Styling.md @@ -0,0 +1,127 @@ +As you have probably noticed, unstyled HTML pages are pretty ugly. It is time to fix that. + +We are not going to explain how the styling works since this was covered in lecture 24 and most of it is fairly obvious from the context. However, there are something things you need to know that are not obvious. + +* There are block components and inline components. Block components will appear on their own line and will usually fill their containers unless a `width` has been applied to them. Inline components will share a line with other inline components. + + You can change an inline component to a block component using `display: block`. + +* `margin` will add space around the outside of components. If you set a block component's `margin` to `auto` it will usually centre the component in its container. + +* `padding` will add additional space to the interior of a component. + +We will incrementally add the styling so that you can see what is happening: + +1. Note that each of the HTML and JSP pages link in the `style.css` file in the `` section. This means that we have a single file that we can use to style the entire web applicaion. + +1. Add the following to the `style.css` file: + + ```css + /* main content area */ + main { + max-width: 600px; + margin: auto; + } + + /* page headings */ + h1 { + text-align: center; + padding: 10px; + } + ``` + + This will centre the main content area and headings. Build, redeploy, and reload the page in the browser. You should see the new style in action. + +1. The following will make the navigation links look like buttons. + + ```css + /* navigation links */ + a.nav { + display: block; + width: 10em; + margin: 5px; + margin-left: auto; + margin-right: auto; + padding: 5px; + border: solid; + border-radius: 10px; + text-decoration: none; + text-align: center; + } + ``` + Build, redeploy, and reload. + +1. The following will make the table a little more presentable: + + ```css + /* tables */ + table { + margin: 20px; + margin-left: auto; + margin-right: auto; + border-spacing: 0px 0px; + } + + td, th { + border: thin; + border-width: 0px 0px 1px 0px; + border-style: solid; + padding: 5px; + padding-left: 20px; + padding-right: 20px; + } + ``` + + Build, redeploy, and reload. + +1. The following will make the forms more presentable: + + ```css + /* forms */ + fieldset { + margin-bottom: 20px; + } + + fieldset textarea { + height: 4em; + resize: vertical; + } + + label { + display: block; + } + + input, textarea { + width: 560px; + margin-bottom: 10px; + } + + button { + width: 560px; + display: block; + margin: auto; + padding: 5px; + } + ``` + + Build, redeploy, and reload. + +1. The following will add some colour: + + ```css + /* colours */ + th, a.nav, legend, label { + color: darkslategray; + } + + h1, button { + background-color: darkslategrey; + color: white; + } + + td, th { + border-color: darkslategrey; + } + ``` + + Build, redeploy, and reload. diff --git a/tiddlers/content/labs/lab04/_Labs_04_Styling.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Styling.md.meta new file mode 100644 index 0000000..245be85 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Styling.md.meta @@ -0,0 +1,4 @@ +section: 10 +tags: lab lab04 +title: /Labs/04/Styling +type: text/x-markdown \ No newline at end of file diff --git a/tiddlers/content/labs/lab04/_Labs_04_Viewing Students.md b/tiddlers/content/labs/lab04/_Labs_04_Viewing Students.md new file mode 100644 index 0000000..0c9fcc0 --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Viewing Students.md @@ -0,0 +1,43 @@ +The `view-students.jsp` page is where we are going to display all of the students that have been saved in the session. + +1. Delete the two lines of code that were added to the `
` tag earlier in the lab. + +1. Add the following code the the `
` tag: + + ```html +

Students

+ + + + + + + + + + + <% + Collection students = (Collection) session.getAttribute("studentList"); + if (students != null) { + for (Student student : students) { + %> + + + + + + <% + } + } + %> + +
IDNameAddress
<%= student.getId() %><%= student.getName() %><%= student.getAddress() %>
+ + Back to Menu + ``` + + This code is creating an HTML table. It gets the students list out of the session and loops through each student in the list. The loop will cause the `` (table row) tag to be repeated for as many students as there are in the list. The `` tags contain expressions that will add the student's details to the table. + +1. Build and redeploy the web application. + +1. The system should now be functionally complete. Try adding a couple of students and then viewing them. diff --git a/tiddlers/content/labs/lab04/_Labs_04_Viewing Students.md.meta b/tiddlers/content/labs/lab04/_Labs_04_Viewing Students.md.meta new file mode 100644 index 0000000..9ebdcfa --- /dev/null +++ b/tiddlers/content/labs/lab04/_Labs_04_Viewing Students.md.meta @@ -0,0 +1,4 @@ +section: 9 +tags: lab lab04 +title: /Labs/04/Viewing Students +type: text/x-markdown \ No newline at end of file