This coursework is designed to give you experience building Java EE 7 applications and deploying them to the Cloud. You will build a real-world application using real enterprise technologies. This coursework provides you with an opportunity to work on an entire application, from the data-storage through to the web frontend. As a result you will need to become familiar with a wide range of technologies. It is important that you start the work early and ask for help when needed. By completing this coursework, you will gain some useful experience and skills.
Before attempting this coursework, please complete this tutorial.
In Part One you will build a simple service, hosted on a Platform as a Service Cloud. The service should be accessible through a RESTful JSON api and accompanied by a selection of tests to demonstrate that it satisfies the provided requirements.
In Part Two you will implement some advanced functionality upon the base service from Part One, such as cascading updates for related entities and a transactional endpoint.
In Part Three you will create a new, more complex, service. It will make requests to your Part One service, along with those of two colleagues. This service should also be accompanied by more tests and JSON endpoints. You should end up with a fully functioning booking service for all 3 commodities.
|
Important
|
You must complete the provided Tutorial before attempting this coursework. There are a number of pre-requisite steps in the tutorial that must be done for the coursework to function. |
This coursework covers a large number of technologies. The challenge here is to learn the right bits of each technology in order to complete the coursework.
-
Java EE 7. Java Enterprise Edition is the technology you will use to develop your application.
-
JPA. The Java Persistence API provides a Java API onto your application’s data.
-
JTA. The Java Transaction API is a general API for managing transactions in Java. It allows you to start, commit and rollback transactions in a resource neutral way.
-
JSON. This is the data serialization and interchange format used by Javascript and commonly returned by HTTP APIs.
-
Bean Validation. This technology allows you to specify constraints on your data and assists with validation.
-
Arquillian. With this tool you will be able to write tests that run inside the application server.
-
Maven. Your application will be built and deployed with this tool.
-
OpenShift. This is the Platform as a Service (PaaS) that you will use to deploy your application to the Cloud.
-
JAX-RS. This technology provides the Java EE API for developing REST services. You will use this technology to communicate between distributed components of your application (web-interfaces & other services).
-
Git. This is a distributed version control system and will be used to backup your code and for deploying it to OpenShift.
-
Swagger. Swagger is a simple yet powerful representation of your RESTful API. Using Java @Annotations Swagger will generate documentation for JAX-RS endpoints as part of the project build process.
Building your work
For this project you must use a Maven build for your application. You may use the Maven build file (pom.xml) provided as part of the tutorial.
Storing your work
You should save your work using the Git version control system, regularly commiting changes and pushing to the provided GitHub repositoy.
You should push commits of your coursework regularly to your GitHub repo. It is a good idea to do so every time you get a small piece of functionality working. This ensures that you can move back to a working state if you get in a mess. It also ensures that you have a backup and that the demonstrators can view your code and track progress.
|
Tip
|
You will be awarded a considerable number of marks for your distribution and use of version control. We expect to see a steady flow of sensible commits to Github over the coursework period. |
Testing your work
You must produce Arquillian tests for testing your application. These tests will be executed as part of your Maven build.
You should build on the contacts-swagger example from the tutorial. You do not have time to create a new application from scratch. Don’t worry about renaming the packages or the OpenShift application name, doing so is likely to get you into a mess.
The easiest way to work, is to deploy your application to a local version of JBoss EAP during development. Only create new builds from your code in OpenShift periodically, when you have a new set of features working and all your tests pass. This is especially important for part three, as you will cause your colleagues problems if your service becomes unavailable.
During parts 1 & 2 you will only test your API through Arquillian tests and one of the other methods presented to you during the tutorial (The Swagger documentation or CURL).
After having completed part 3 of the coursework, if you are trying to "wire up" your service to the provided frontend application, it may help to briefly familiarise yourself with the Angular.js framework. We suggest going through the official tutorial to achieve this. Please note, there are no marks provided for the AngularJS integration, and that this is entirely optional.
Produce an API offering either Taxi, Hotel or Flight bookings. You have been allocated a specific service type (see the end of the tutorial document). Your API must conform to RESTful design principles and should return JSON. Finally you must construct Arquillian tests to demonstrate that your service satisfies those user stories relevant to your allocated service.
|
Important
|
You have been allocated a service to implement. See the allocation you have been emailed for details. You MUST implement the service that you have been allocated. |
The following diagram shows the architecture you will need to implement for your application:
Through this architecture you can support multiple different forms of client to the service. Here your automated tests and Swagger documentation act as the primary examples, but you could quite easily also develop a mobile application or website using the same REST services.
-
Unit Tests. These are implemented using the Arquillian testing framework and send requests to your REST services, validating the responses against some expected response.
-
REST Services. These are implemented using RESTEasy (a JBoss implementation of the JAX-RS Java Standards Recommendation (JSR)) and provide a service interface to your application. These services are responsible for managing bookings, users and taxis/hotels/flights.
-
Persistence layer. This layer provides a Java interface for accessing the data in the database, using the Java Persistence API (JPA).
-
Database. This is where your data is stored. Your application won’t access this directly as it will use JPA to interface with the data.
You will need to produce three RESTful resources:
-
Customer. (A user)
-
Taxi/Hotel/Flight. (A commodity)
-
Booking. (A relationship between a user and a commodity, with additional attributes)
Your API should provide endpoints to perform the following actions on your resources:
-
Create & List Customers.
-
Create & List Taxis, Rooms or Flights.
-
Create, List & Cancel Bookings.
You must document your endpoints using Swagger @Annotations, including:
-
Their purpose.
-
Their expected URL structure & request method.
-
Their expected request values.
-
Their expected response format.
-
Possible HTTP response codes and the reasons for them.
This is essential for any third-party who wishes to use your service. You will need to refer any colleagues using your service in Part 3 to your Swagger doc page, which will be deployed to Openshift along with your service. An example of good Swagger documentation is included in the base quickstart.
|
Tip
|
Much of the information about each REST endpoint, such as URL structure and request method, may be automatically discovered by Swagger. All Swagger @Annotations should be included in the relevant *RestService class.
|
|
Tip
|
If you are unfamiliar with the specifics of RESTful APIs there are some good resources available here & here. |
|
Tip
|
When adding new packages for your new restful resources, make sure to add them to the Swagger config in ContactServiceApplication, as per the comments in that class.
|
You will probably need an Entity for each of your resources.
-
Customer. A bean to hold the data you wish to collect about each customer.
-
Taxi/Flight/Hotel. A bean to hold the data you wish to collect about each item you have available for booking.
-
Booking. A bean representing the booking and linking to the customer who made the booking and to the item being booked.
|
Tip
|
Keep these entities simple. Just provide the minimum information required to fulfil the requirements. Use @Annotations, like those found in the base contacts-swagger Contact class, to specify validation constraints on your information (like the minimum length of a name). You may however wish to read about entity relationship @Annotations.
|
|
Tip
|
When you are testing your application you may find it useful to pre-populate your database with a number of example entities. One way to achieve this is to add SQL insert statements into src/main/resources/import.sql.
|
|
Tip
|
When you are testing your application you will find it useful to view the queries run against your database. You can enable logging of this information by setting the hibernate.show_sql property to true in src/main/resources/META-INF/persistence.xml.
|
-
Describe the composition of your service, including each of the JAX-RS services and how they interact. You might like to draw a diagram like the one above to help explain your architecture.
You will now need to add some advanced features to your base REST resources from Part One. These features are:
-
REST endpoints to allow for the deletion of Customer and Commodity (Taxi/Hotel/Flight) resources.
-
Cascading deletion of related entities. Specifically, if a Commodity entity is deleted then any bookings made for it should also be deleted. Likewise, if a Customer entity is deleted, any bookings made by it should also be deleted.
-
A
GuestBookingtransactional endpoint which creates a customer and a booking in a single transaction.
|
Important
|
The automatic deletion of related entities must be handled with JPA Entity relationship @Annotations (e.g. @ManyToOne, @ManyToMany etc…), which are provided by Hibernate. You should therefore implement all relationships between entities using these annotations, even if you did not do so in Part 1.
|
|
Tip
|
This will mean that you should store full objects (or lists of objects) in your models, rather than just Ids. You should be careful to familiarise yourself with the Jackson JSON annotations if you have not already (particularly @JsonIgnore which prevents the "recursive" definition problem).
|
You must create a GuestBooking Bean and RestService class.
The Bean is not persisted and should not be a Hibernate @Entity.
It should simply contain fields (and getters and setters) for a Customer object and a Booking object.
Its purpose is simply to allow the Jackson JSON library to deserialize a request Body containing both a Customer and a Booking.
|
Tip
|
You may leave the customer field of a Booking object’s JSON blank, then use setCustomer(Customer c) to set a Booking customer to be a newly created Customer object, before attempting to persist the Booking itself.
|
The GuestBookingRestService should be a stateless bean (i.e. use the @Stateless annotation like other *RestService classes) - it should also use Bean-Managed Transactions to manually demarcate a transaction using javax.transaction.UserTransaction.
In addition to the @Stateless annotation you must mark the GuestBookingRestService with the javax.ejb.TransactionManagement annotation with the value javax.ejb.TransactionManagementType.BEAN.
This specifies that you wish to manually manage transaction boundaries inside the class.
Your GuestBookingRestService must provide a single method which accepts a GuestBooking parameter and serves a POST request.
This method should then use the CustomerService and BookingService classes to persist the appropriate fields of the GuestBooking object inside a UserTransaction and return a Response containing the Booking, and a status of 201 if successful.
If either Entity should fail to be persisted, you should rollback the transaction with an appropriate error message.
-
Why are transactions useful here? What scenario do they help to prevent.
-
What is the advantage of the JTA? How might it help when using multiple distinct transactional services?
-
Discuss the benefits and drawbacks of using JPA @Annotations to automatically handle entity relationships. Highlight any pitfalls you encountered.
You will now need to integrate three commodity REST resources to produce a fourth, aggregate, resource: a TravelAgent resource. You will use your own resources along with two more made available through the APIs of your colleagues.
You will do this using the RESTEasy client framework, as exemplified by the contact-swagger quickstart’s area package.
The resources you need to integrate are:
-
1 x Hotel resource
-
1 x Taxi resource
-
1 x Flight resource
You must ensure that either every part of a booking is made, or no parts of the booking are made. Remember, each part of the booking can be cancelled using the provided cancel operation. For example, the user would not want to book a flight, if they didn’t have somewhere to stay at the destination. This will allow you to easily control which booking fails and which succeeds. You should set up a scenario where the first two bookings succeed and the remaining booking fails. Your TravelAgent resource should detect this failure and cancel the previous bookings that succeeded.
|
Important
|
It is very important that the user does not end up with a partial booking. Otherwise they may end up paying for a flight, without having a hotel to stay in. |
The diagram above shows the type of interaction that you should have achieved by completing part 3.
|
Tip
|
You may find that you are ready to use your colleagues’ services before they are ready to make them available. If this happens then you can temporarily use your own service three times and then switch to your colleagues’ services when they become available. |
|
Tip
|
You may also find it hard to utilize the exact service types specified above, due to the progress of your colleagues. In this case you may duplicate the service types; for example, two Taxi services and one Flight service. However, you must make sure that the two services you select are offered by two different colleagues! |
|
Tip
|
You should create a Customer record in each of your colleague’s applications to represent your travel agent, and make all booking’s using this customer. You should not try and create a new customer with each base service for every TravelAgent booking. This makes the TravelAgent service more complex to implement, and is not how a real travel agent would work in any case. |
|
Tip
|
When storing your TravelAgentBooking locally, as with part two, you can link the Booking for your local commodity using Entity relationship @Annotations, and simply store the ID’s of the upstream bookings locally. |
Your TravelAgent resource should provide endpoints to perform the following actions:
-
Create, List & Cancel aggregate Bookings.
As with Part 1, you should document your API endpoints using Swagger @Annotations. You should take care to detail the possible failure responses, including their causes. This means that error handling may be tests.
-
What problems did you have utilising your colleagues’ services? How would these problems be exacerbated had the producers of these services not been in the same room?
-
What problems did you have offering your service to your colleagues?
-
Can you retrieve a list of TravelAgent bookings for a given Customer?
-
If a booking is invalid for just one of the base commodities, are the bookings made with other remote services successfully removed?
-
Can you create a TravelAgent booking?
|
Warning
|
This section is now mostly deprecated and untested. No marks are provided for the integration. |
You have been provided with a complete frontend for your Travel Agent application, written in Javascript using the Angular.js framework. This code found in the contacts-swagger quickstart in src/main/webapp/travelagent/. When your service is deployed, the frontend application will be accessible at localhost:8080/travelagent/
You may modify this frontend application to correctly interact with, and act as a client for, the TravelAgent API you have produced. To do this you simply provide the base urls which corresponds to the url of your TravelAgent REST endpoints in the files:
-
travelagent/app/travel-booking/travel-booking.js -
travelagent/app/customer/customer.js -
travelagent/app/travel-booking/travel-booking-form-controller.js
Where to provide the URL in the javascript sources is marked inline with comments for you.
The frontend application is what is known as a Single Page Application: communicating asynchronously with APIs via AJAX, rather than requiring a page refresh.
The diagram above gives a high level overview of application architecture from a clientside centric perspective.
-
Views. These constitute the user interface markup, written in HTML.
-
Controllers. These define the actions and interactions of a View, written in Javascript.
-
ngResource. The Angular module used for communication with your RESTful server side resources.
|
Tip
|
The ngResource module makes some fairly strict assumptions about the structure of a RESTful API. If your API does not follow REST best practices then the frontend will not work even after you have provided the url. |
Your frontend application, when provided with the correct service URL, provides the ability to perform the following additional actions:
-
View a list of all currently stored records for all three basic commodities.
-
Create a new Customer record.
-
View a list of all Customer records currently stored by the TravelAgent service.
-
Record a new TravelAgent Booking, with a: Customer id and all appropriate Commodity ids.
-
View and manage a list of all currently stored TravelAgent Booking records associated with a particular customer.
The application will also generally provide appropriate visual indication of the success or failure of any actions taken.
Prior to submission you will provide a 10-15 minute demonstration to one of the Course Demonstrators. You will be expected to describe your technical solution and discuss your personal experiences throughout the project.
A sign-up sheet for demonstration slots will be sent via email during the first week of practical sessions. It is very important that you demonstrate your work, failing to do so may result in a loss of marks.
You must submit all work via the coursework submission system (NESS). This should constitute a zip file containing the project source code and Maven build scripts. We will use this zip file to test your submission, so it should contain everything necessary to build and test your project.
You should also submit a short report via NESS (roughly three pages) summarising the work carried out on this project, and an evaluation of how much you achieved. We are particularly interested in any assumptions you made, and how they motivated particular design decisions. You should also provide a brief discussion of your personal experience of the development process; e.g. which aspects of the project did you find particularly easy/hard?
We have provided a list of things you should cover in your report in the "Report Hints" sections of this document.
Demonstrators will be available in your cluster rooms during all practical sessions. You should go and see them if you are having any difficulties. This includes understanding what you have to do.
Discussion Boards will also be available for CSC8104 in Canvas (http://canvas.ncl.ac.uk) and Teams. You may post any questions about the tutorial or coursework assignment here, and the discussion boards will be monitored by Course Demonstrators. Also, any question which demonstrators encounter frequently (either on Teams or in practical) will be placed in a Frequently Asked Questions document which we maintain here. Before asking a question we encourage you to check both these places to see if it has already been answered.
In particular, notice the answer which refers to documentation. The use of 3rd party documentation is absolutely essential throughout this coursework, and demonstrators may often answer questions by pointing you to the relevant websites.
|
Tip
|
If you see a question on the discussion boards you know how to answer, we strongly encourage you to assist your colleagues! |


