The parts of the API assignment make up a single assignment that is broken into focus areas that relate 1:1 with the lecture topics. You have the individual choice to start with any one area and either advance or jump repeatedly between them as you complete it as one overall solution. However, you are likely going to want to start out with modules area so that you have some concrete modules to begin your early work. It is always good to be able to perform a successful root level build of all targeted modules before you begin adding detailed dependencies, plugins, and Java code.
1. Overview
The API will include three main concepts. We are going to try to keep the business rules pretty simple at this point:
-
Home - an individual home that will be part of a sale
-
Homes can be added, modified, listed, and deleted
-
Homes can be deleted entirely at any time
-
-
Buyer - identification for a person that may be part of a Home purchase and is not specific to any one Home
-
Buyer information can be created, modified, listed, and deleted
-
Buyer information can be modified or deleted at any time
-
-
HomeSale - identifies a Home to be sold and purchased by a Buyer
-
HomeSales can be created for an existing Home to form a "listing"
-
Any Home information pertinent to Home will be locked into this HomeSale at creation time
-
-
HomeSales can be updated for an existing Buyer to complete a purchase
-
Any Buyer information will be permanent once assigned
-
-
HomeSale cannot be updated with a new Buyer once it has been purchased
-
HomeSale can be deleted and re-created.
-
1.1. Grading Emphasis
Grading emphasis will be focused on the demonstration of satisfaction of the listed learning objectives and --with the exception of the scenarios listed at the end — not on quantity. Most required capability/testing is focused on demonstration of what you know how to do. You are free to implement as much of the business model as you wish, but treat the individually stated requirements and completing the listed scenarios at the end of the assignment as the minimal functionality required.
1.2. HomeBuyer Support
You are given a complete implementation of Home and Buyer as examples and building blocks in order to complete the assignment. Your primary work with be in completing HomeSales.
1.2.1. HomeBuyer Service
The homebuyers-support-api-svc
module contains a full @RestController/Service/Repo thread for both Homes and Buyers. The module contains two Auto-configuration definitions that will automatically activate and configure the two services within a dependent application.
The following dependency can be added to your service solution to bring in the Homes and Buyers service examples to build upon.
<dependency>
<groupId>info.ejava.assignments.api.homesales</groupId>
<artifactId>homebuyers-support-api-svc</artifactId>
<version>${ejava.version}</version>
</dependency>
1.2.2. HomeBuyer Client
A client module is supplied that includes the DTOs and client to conveniently communicate with the APIs. Your HomeSale solution may inject the Homes and Buyers service components for interaction but your API tests will use the Home and Buyer APIs.
The following dependency can be added to your solution to bring in the Homes and Buyers client artifact examples to build upon.
<dependency>
<groupId>info.ejava.assignments.api.homesales</groupId>
<artifactId>homebuyers-support-api-client</artifactId> (1)
<version>${ejava.version}</version>
</dependency>
1 | dependency on client will bring in both client and dto modules |
1.2.3. HomeBuyer Tests
You are also supplied a set of tests that are meant to assist in your early development of the end-to-end capability. You are still encouraged to write your own tests and required to do so in specific sections and for the required scenarios. The supplied tests are made available to you using the following Maven dependency.
<dependency>
<groupId>info.ejava.assignments.api.homesales</groupId>
<artifactId>homebuyers-support-api-svc</artifactId>
<version>${ejava.version}</version>
<classifier>tests</classifier> (1)
<scope>test</scope>
</dependency>
1 | tests have been packaged within a separate -tests.java |
The tests require that
-
your HomeSale DTO class implement a
SaleDTO
"marker" interface provided by the support module. This interface has nothing defined and is only used to identify your DTO during the tests. -
implement a
ApiTestHelper<T extends SaleDTO>
and make that available to be injected into the test. A full skeleton of this class implementation has been supplied in the starter. -
supply a
@SpringBootTest
class that pulls in theHomeSalesApiNTest
test case as a base class from the support module. This test case evaluates your solution during several core steps of the assignment. Much of the skeletal boilerplate for this work is provided in the starter.
Enable the tests whenever you are ready to use them. This can be immediately or at the end.
2. Assignment 2a: Modules
-
2022-10-03: Updated API list response element name from type-specific "homes"/"buyers" to generic "contents".
2.1. Purpose
In this portion of the assignment, you will demonstrate your knowledge of establishing Maven modules for different portions of an application. You will:
-
package your implementation along proper module boundaries
2.2. Overview
In this portion of the assignment you will be establishing your source module(s) for development. Your new work should be spread between two modules:
-
a single client module for DTO and other API artifacts
-
a single application module where the Spring Boot executable JAR is built
Your client module should declare a dependency the provided homebuyers-support-api-client
to be able to make use of any DTO or API constructs.
Your service/App module should declare a dependency on homebuyers-support-api-svc
to be able to host the Home and Buyer services.
You do not copy or clone these "support" modules.
Create a Maven dependency on these and use them as delivered.
2.3. Requirements
-
Create your overall project as two (or more) Maven modules under a single parent
-
client module(s) should contain any dependencies required by a client of the Web API. This includes the DTOs, any helpers created to implement the API calls, and unit tests for the DTOs. This module produces a regular Java JAR.
homebuyers-support-api-client/dto
has been supplied for you use as an example and be part of your client modules. Create a dependency on the client module for access toHome
andBuyer
client classes. Do not copy/clone the support modules. -
svc module to include your HomeSales controller, service, and repository work.
homebuyers-support-api-svc
has been supplied for you to both be part of your solution and to use as an example. Create a Maven dependency on this support module. Do not copy/clone it. -
app module that contains the
@SpringBootApplication
class will produce a Spring Boot Executable JAR to instantiate the implemented services.The app and svc modules can be the same module. In this dual role, it will contain your HomeSale service solution and also host the @SpringBootApplication
.The Maven pom.xml in the assignment starter for the App builds both a standard library JAR and a separate executable JAR (bootexec) to make sure we retain the ability to offer the HomeSale service as a library to a downstream assignment. By following this approach, you can make this assignment immediately reusable in assignment 3. -
parent module that establishes a common groupId and version for the child modules and delegate build commands. This can be the same parent used for assignments 0 and 1. Only your app and client modules will be children of this parent.
-
-
Define the module as a Web Application (dependency on
spring-boot-starter-web
). -
Add a
@SpringBootApplication
class to the app module (already provided in starter for initial demo). -
Once constructed, the modules should be able to
-
build the project from the root level
-
build regular Java JARs for use in downstream modules
-
build a Spring Boot Executable JAR (bootexec) for the
@SpringBootApplication
module -
immediately be able to access the
/api/homes
and/api/buyers
resource API when the application is running — because of Auto-Configuration.Example Calls to Homes and Buyers Resource API$ curl -X GET http://localhost:8080/api/homes {"contents":[]} $ curl -X GET http://localhost:8080/api/buyers {"contents":[]}
-
2.4. Grading
Your solution will be evaluated on:
-
package your implementation along proper module boundaries
-
whether you have divided your solution into separate module boundaries
-
whether you have created appropriate dependencies between modules
-
whether your project builds from the root level module
-
whether you have successfully activated the Home and Buyer API
-
2.5. Additional Details
-
Pick a Maven hierarchical groupId for your modules that is unique to your overall work on this assignment.
3. Assignment 2b: Content
2022-10-03 - changed list attribute name to contents
in drawing and recommend you follow that naming
3.1. Purpose
In this portion of the assignment, you will demonstrate your knowledge of designing a Data Transfer Object that is to be marshalled/unmarshalled using various internet content standards. You will:
-
design a set of Data Transfer Objects (DTOs) to render information from and to the service
-
define a Java class content type mappings to customize marshalling/unmarshalling
-
specify content types consumed and produced by a controller
-
specify content types accepted by a client
3.2. Overview
In this portion of the assignment you will be implementing a set of DTO classes that will be used to represent a HomeSale. All information expressed in the HomeSale will be derived from the Home and Buyer objects — except for the ID and the milestone dates.
Lecture/Assignment Module Ordering
It is helpful to have a data model in place before writing your services.
However, the lectures are structured with a content-less (String) domain up front and focus on the Web API and services before tackling content.
If you are starting this portion of the assignment before we have covered the details of content, it is suggested that you simply create sparsely populated HomeSaleDTO class with at least an id field and the HomeSaleListDTO class to be able to complete the API interfaces.
Skip the details of this section until we have covered the Web content lecture.
|
HomeSale.id Avoids Compound Primary Key
The HomeSaleDTO id was added to keep from having to use a compound (homeId + buyerId) primary key.
This makes it an easier 1:1 example with Home and Buyer to follow.
|
String Primary Keys
Strings were used for the primary key type.
This will make it much easier and more portable when we use database repositories in a later assignment.
|
The provided homebuyers-support-api-dto
module has the Home and Buyer DTO classes.
-
HomeDTO - provides information specific to the home
-
BuyerDTO - provides information specific to the buyer
-
StreetAddress - provides properties specific to a location
-
MessageDTO - commonly used to provide error message information for request failures
-
<Type>ListDTO - used used to conveniently express typed lists of objects
MessageDTO is from ejava-dto-util Class Examples
The MessageDTO is supplied in the ejava-dto-util package and used in most of the class API examples.
You are free to create your own for use with the HomeSales portion of the assignment.
|
3.3. Requirements
-
Create a DTO class to represent HomeSale
-
use the attributes in the diagram above as candidate properties for each class
-
HomeSale.saleAge should be a calculation of years, rounded down, between the
Home.yearBuilt
and the date the HomeSale was added. -
buyerName should be the concatenation of non-blank Buyer.firstName and Buyer.lastName values
-
streetAddress should be a deep copy of the Home.location
Create a constructor that assembles the HomeSaleDTO
attributes from the availableHomeDTO
andBuyerDTO
attributes.
-
-
Create a
HomeSaleListDTO
class to provided a typed collection ofHomeSaleDTO
.I am recommending you name of the collection within the class a generic contents
for later reuse reasons. -
Map each DTO class to:
-
Jackson JSON (the only required form)
-
mapping to Jackson XML is optional
-
-
Create a unit test to verify your new DTO type(s) can be marshalled/unmarshalled to/from the targeted serialization type.
-
API TODO: Annotate controller methods to consume and produce supported content type(s) when they are implemented.
-
API TODO: Update clients used in unit tests to explicitly only accept supported content type(s) when they are implemented.
3.4. Grading
Your solution will be evaluated on:
-
design a set of Data Transfer Objects (DTOs) to render information from and to the service
-
whether DTO class(es) represent the data requirements of the assignment
-
-
define a Java class content type mappings to customize marshalling/unmarshalling
-
whether unit test(s) successfully demonstrate the ability to marshall and unmarshal to/from a content format
-
-
API TODO: specify content types consumed and produced by a controller
-
whether controller methods are explicitly annotated with consumes and produces definitions for supported content type(s)
-
-
API TODO: specify content types accepted by a client
-
whether the clients in the unit integration tests have been configured to explicitly supply and accept supported content type(s).
-
3.5. Additional Details
-
This portion of the assignment alone primarily produces a set of information classes that make up the primary vocabulary of your API and service classes.
-
Use of
lombok
is highly encouraged here and can tremendously reduce the amount of code you write for these classes -
Java
Period
class can easily calculate age in years between twoLocalDates
. -
There are several states for a
HomeSaleDTO
. It would be helpful to create constructors and compound business methods around these states within the in theHomeSaleDTO
class.-
proposed Sale - this is built client-side and is input to a createHomeSale()
-
homeId
is mandatory and comes from the (server-side) Home -
amount
andlistDate
are optional overrides. Otherwise they would default to Home.value and today’s date on the server-side.
-
-
listing - this is built server-side. All home details obtained are from the (server-side) Home and proposed HomeSale. Buyer properties are not used.
-
purchaseInfo - this is built client-side and is input to purchase()
-
homeId
andbuyerId
are mandatory and come from (listing) HomeSale.id and Buyer.id obtained from the server-side. -
amount
andsaleDate
are optional overrides. Otherwise they would default to the current HomeSale.amount and today’s date on the server-side.
-
-
completed Sale - this is built server-side. All HomeSale details are obtained from the (server-side) HomeSale listing, (client provided) HomeSale purchaseInfo, and (server-side) Buyer
-
-
The
homebuyers-support-api-client
module also provides aHomeDTOFactory
,BuyerDTOFactory
, andStreetAddressDTOFactory
that makes it easy for tests and other demonstration code to quickly assembly example instances. You are encouraged to follow that pattern. However, keep your known client-side states and information sources in mind when creating the factory methods. -
The
homebuyers-support-api-client
test cases for Home and Buyer demonstrate marshalling and unmarshalling DTO classes within a JUnit test. You should create a similar test of yourHomeBuyerDTO
class to satisfy the testing requirement. Note that those tests leverage aJsonUtil
class that is part of the class utility examples and simplifies example use of the Jackson JSON parser. -
The
homebuyers-support-api-client
and supplied starter unit tests make use of JUnit@ParameterizedTest
— which allows a single JUnit test method to be executed N times with variable parameters — pretty cool feature. Try it. -
Supporting multiple content types is harder than it initially looks — especially when trying to mix different libraries. WebClient does not currently support Jackson XML and will attempt to resort to using JAXB in the client. I provide an example of this later in the semester (Spring Data JPA End-to-End) and advise you to address the optional XML mapping last after all other requirements of the assignment are complete. If you do attempt to tackle both XML and WebClient together, know to use JacksonXML mappings for the server-side and JAXB mappings for the client-side.
4. Assignment 2c: Resources
4.1. Purpose
In this portion of the assignment, you will demonstrate your knowledge of designing a simple Web API. You will:
-
identify resources
-
define a URI for a resource
-
define the proper method for a call against a resource
-
identify appropriate response code family and value to use in certain circumstances
4.2. Overview
In this portion of the assignment you will be identifying a resource to implement the HomeSale API. Your results will be documented in a @RestController class. There is nothing to test here until the DTO and service classes are implemented.
The API will include three main concepts:
-
Homes (provided) - an individual home that can be part of a home sale
-
Home information can be created, modified, listed, and deleted
-
Home information can be modified or deleted at any time but changes do not impact previous home sales
-
-
Buyers (provided) - identification for a person that may participate in a home sale
-
Buyer information can be created, modified, listed, and deleted
-
Buyer information can be modified or deleted at any time but changes do not impact previous home sales
-
-
HomeSales (your assignment) - a transaction for one Home and 0..1 Buyer
-
HomeSales can be created for an existing Home (aka the "listing state")
-
HomeSales can be updated with a Buyer (aka the "puchased state")
-
Up to one Buyer can be added to a HomeSale
-
HomeSales can be listed and deleted at any time
-
Modifications are Replacements
All modifications are replacements. There are no individual field edits requested. |
4.3. Requirements
Capture the expression of the following requirements in a set of @RestController
class(es) to represent your resources, URIs, required methods, and status codes.
-
Identify your base resource(s) and sub-resource(s)
-
create URIs to represent each resource and sub-resource
Example Skeletal API Definitionspublic interface HomesAPI { public static final String HOMES_PATH="/api/homes"; public static final String HOME_PATH="/api/homes/{id}"; ...
-
create a separate
@RestController
class — at a minimum — for each base resourceExample Skeletal Controller@RestController public class HomesController {
-
-
Identify the
@RestController
methods required to represent the following actions for HomeSale. Assign them specific URIs and HTTP methods.-
create new resource
-
get a specific resource
-
update a specific resource
-
list resources with paging
-
accept optional pageNumber, pageSize, and optional query parameters
-
return
HomeSaleListDTO
containing contents ofList<HomeSaleDTO>
-
-
delete a specific resource
-
delete all instances of the resource
Example Skeletal Controller Method@RequestMapping(path=HomesAPI.HOME_PATH, method = RequestMethod.POST, consumes = {...}, produces = {...}) public ResponseEntity<HomeDTO> createHome(@RequestBody HomeDTO newHome) { throw new RuntimeException("not implemented"); }
-
-
CLIENT TODO: Identify the response status codes to be returned for each of the actions
-
account for success and failure conditions
-
authorization does not need to be taken into account at this time
-
4.4. Grading
Your solution will be evaluated on:
-
identify resources
-
whether your identified resource(s) represent thing(s)
-
-
define a URI for a resource
-
whether the URI(s) center on the resource versus actions performed on the resource
-
-
define the proper method for a call against a resource
-
whether proper HTTP methods have been chosen to represent appropriate actions
-
-
CLIENT TODO: identify appropriate response code family and value to use in certain circumstances
-
whether proper response codes been identified for each action
-
4.5. Additional Details
-
This portion of the assignment alone should produce a
@RestController
class with annotated methods that statically define your API interface (possibly missing content details). There is nothing to run or test in this portion alone. -
A simple and useful way of expressing your URIs can be through defining a set of public static attributes expressing the collection and individual instance of the resource type.
Example Template Resource Declarationpublic static final String (RESOURCE)S_PATH="(path)"; public static final String (RESOURCE)_PATH="(path)/{identifier(s)}";
-
If you start with this portion, you may find it helpful to
-
create sparsely populated DTO classes —
HomeSaleDTO
with just anid
andHomeSaleListDTO
— to represent the payloads that are accepted and returned from the methods -
have the controller simply throw a RuntimeException indicating that the method is not yet implemented. That would be a good excuse to also establish an exception advice to handle thrown exceptions.
-
-
The details of the HomeSale will be performed server-side — based upon IDs and optional properties provided by the client and the Home and Buyer values found server-side. The client never provides more than an ID to reference information available server-side.
-
There is nothing to code up relative to response codes at this point. However:
-
Finding zero resources to list is not a failure. It is a success with no resources in the collection.
-
Not finding a specific resource is a failure and the status code returned should reflect that.
-
Instances of Action Verbs can be Resource Nouns
If an action does not map cleanly to a resource+HTTP method, consider thinking of the action (e.g., cancel) as one instance of an action (e.g., cancellation) that is a sub-resource of the subject (e.g., subjects/{subjectId}/cancellations). How might you think of the action if it took days to complete? |
5. Assignment 2d: Client/API Interactions
5.1. Purpose
In this portion of the assignment, you will demonstrate your knowledge of designing and implementing the interaction between a Web client and API. You will:
-
implement a service method with Spring MVC synchronous annotated controller
-
implement a client using Spring MVC RestTemplate or Spring Webflux (in synchronous mode)
-
pass parameters between client and service over HTTP
-
return HTTP response details from service
-
access HTTP response details in client
5.2. Overview
In this portion of the assignment you will invoke your resource’s Web API from a client running within a JUnit test case.
There will be at least two primary tests in this portion of the assignment: handling success and handling failure. The failure will be either real or simulated through a temporary resource stub implementation.
5.3. Requirements
-
Implement stub behavior in the controller class as necessary to complete the example end-to-end calls.
Example Stub Responsereturn ResponseEntity.status(HttpStatus.CREATED) .body(HomeDTO.builder() .id("1") .build());
-
Implement a unit integration test to demonstrate a success path
-
use either a
RestTemplate
orWebClient
API client class for this test -
make at least one call that passes parameter(s) to the service and the results of the call depend on that passed parameter value
-
access the return status and payload in the JUnit test/client
-
evaluate the result based on the provided parameter(s) and expected success status
Example Response Evaluationthen(response.getStatusCode()).isEqualTo(HttpStatus.CREATED); then(homeResult).getId()).isNotBlank(); then(homeResult).isEqualTo(homeRequestDTO.withId(homeResult.getId()));
-
Examples use RestTemplate
The Home and Buyer examples only use the RestTemplate approach.
|
One Success, One Failure, and Move On
Don’t put too much work into more than a single success and failure path test before completing more of the end-to-end.
Your status and details will likely change.
|
5.4. Grading
Your solution will be evaluated on:
-
implement a service method with Spring MVC synchronous annotated controller
-
whether your solution implements the intended round-trip behavior for an HTTP API call to a service component
-
-
implement a client using Spring MVC RestTemplate or Spring Webflux WebClient (in synchronous mode)
-
whether you are able to perform an API call using either the RestTemplate or WebClient APIs
-
-
pass parameters between client and service over HTTP
-
whether you are able to successfully pass necessary parameters between the client and service
-
-
return HTTP response details from service
-
whether you are able to return service response details to the API client
-
-
access HTTP response details in client
-
whether you are able to access HTTP status and response payload
-
5.5. Additional Details
-
Your DTO class(es) have been placed in your Client module in a separate section of this assignment. You may want to add an optional API client class to that Client module — to encapsulate the details of the RestTemplate or WebClient calls. The
homebuyers-support-client
module contains example client API classes for Homes and Buyers usingRestTemplate
. -
Avoid placing extensive business logic into the stub portion of the assignment. The controller method details are part of a separate section of this assignment.
-
This portion of the assignment alone should produce a simple, but significant demonstration of client/API communications (success and failure) using HTTP and service as the model for implementing additional resource actions.
-
Inject the dependencies for the test from the Spring context. Anything that depends on the server’s port number must be delayed (
@Lazy
)@Bean @Lazy (2) public ServerConfig serverConfig(@LocalServerPort int port) { (1) return new ServerConfig().withPort(port).build(); } @Bean @Lazy (3) public HomesAPI homesAPI(RestTemplate restTemplate, ServerConfig serverConfig) { return new HomesAPIClient(restTemplate, serverConfig, MediaType.APPLICATION_JSON); } @SpringBootTest(...webEnvironment=... public class HomeSalesAPINTest { @Autowired private HomesAPI homesAPI;
1 server’s port# is not known until runtime 2 cannot eagerly create @Bean
until server port number available3 cannot eagerly create dependents of port number
6. Assignment 2e: Service/Controller Interface
6.1. Purpose
In this portion of the assignment, you will demonstrate your knowledge of separating the Web API facade details from the service implementation details and integrating the two. You will:
-
implement a service class to encapsulate business logic
-
turn @RestController class into a facade and delegate business logic details to an injected service class
-
implement an error reporting strategy
6.2. Overview
In this portion of the assignment you will be implementing the core of the HomeSale components and integrating them as seamlessly as possible.
-
the controller will delegate commands to a service class to implement the business logic.
-
the service will use internal logic and external services to implement the details of the business logic.
-
the repository will provide storage for the service.
Your Assignment is Primarily HomeSale and Integration
You have been provided complete implementation of the Homes and Buyers services.
You only have to implement the HomeSales components and integration that with Home and Buyer services .
|
A significant detail in this portion of the assignment is to design a way to convey success and failure when carrying out an API command. The controller should act only as a web facade. The service(s) will implement the details of the services and report the results.
Under the hood of the HomeSaleService
is a repository and external clients.
-
You will create a
HomeSaleService
interface that usesHomeSaleDTO
as its primary data type. This interface can be made reusable through the full semester of assignments.
This assignment will only work with the DTO types (no entities/BOs) and a simulated/stub Repository.
-
You will create a repository interface and implementation that mimic the behavior of a CRUD and Pageable Repository in a future assignment.
-
You will inject and implement calls to the Home and Buyer services. An API client is provided for both those interfaces.
6.3. Requirements
-
Implement a HomeSaleDTORepository interface and implementation component to simulate necessary behavior (e.g., save, findById) for the base HomeSaleDTO resource type. Don’t go overboard here. We just need some place to generate IDs and hold the data in memory.
-
implement a Java interface (e.g.,
HomeSaleDTORepository
).Try to make this interface conceptually consistent with the Spring Data CrudRepository and PagingAndSortingRepository (including the use of Pageable and Page) to avoid changes later on. This is just a tip and not a requirement — implement what you need for now. Start with just save()
. -
implement a component class stub (e.g.,
HomeSaleDTORepositoryStub
) using simple, in-memory storage (e.g.,HashMap
orConcurrentHashMap
) and an ID generation mechanism (e.g.,int
orAtomicInteger
)
You are free to make use of the POJORepositoryMapImpl<T>
class in thehomesales_support_api
module as your implementation for the repository. It comes with aPOJORepository<T>
interface and the Buyer repository and service provide an example of its use. Report any bugs you find. -
-
Implement a HomeSale service to implement actions and enforce business logic on the base resources
-
implement a Java interface This will accept and return HomeSaleDTO types.
-
implement a component class for the service.
-
inject the dependencies required to implement the business logic
-
(provided)
HomesService
- to verify existence of and obtain details of homes -
(provided)
BuyersService
- to verify existence of and obtain details of buyers -
(your)
HomeSaleDTORepository
- to store details that are important to home salesYou are injecting the service implementations (not the HTTP API) for the Home and Buyer services into your HomeSale service. That means they will be part of your application and you will have a Java ⇒ Java interface with them.
-
-
implement the business logic for the service
-
a HomeSale can only be created for an existing Home and will be populated using the values of that Home on the server-side
-
input a proposed HomeSale as a
HomeSaleDTO
filled in with only the following properties. The homeId will be used to obtain the current Home values from the HomeService.-
homeId (mandatory)
-
listingDate (optional — server-side default to now)
-
amount (optional — server-side default to Home.value)
-
-
-
during a purchase change, the HomeSale will be updated with sale information. A
HomeSaleDTO
will be filled in with only the following properties. homeId is also required but can be made more prominent as a parameter.-
buyerId (mandatory)
-
saleDate (optional - server-side default is today’s UTC date)
-
amount (optional) — server-side default is the original HomeSale.amount)
-
-
a HomeSale cannot be purchased more than once.
-
implement a basic getHomeSale returning the current state of the HomeSale
-
implement a paged
findHomeSales
that returns all. Use the Spring DataPageable
andPage
(andPageImpl
) classes to express pageNumber, pageSize, and page results (i.e.,Page findHomeSales(Pageable)
). You do not need to implement sort. -
augment the
findHomeSales
to optionally include a search for matching homeId, buyerId, or both.Implement Search Details within Repository classDelegate the gory details of searching through the data — to the repository class.
-
-
-
Design a means for service calls to
-
indicate success
-
indicate failure to include internal or client error reason. Client error reasons must include separate issues "not found" and "bad request" at a minimum.
-
-
Integrate services into controller components
-
complete and report successful results to API client
-
report errors to API client, to include the status code and a textual message that is specific to the error that just occurred
-
-
Implement a unit integration test to demonstrate at least one success and error path
-
access the return status and payload in the client
-
evaluate the result based on the provided parameter(s) and expected success/failure status
-
6.4. Grading
Your solution will be evaluated on:
-
implement a service class to encapsulate business logic
-
whether your service class performs the actions of the service and acts as the primary enforcer of stated business rules
-
-
turn @RestController class into a facade and delegate business logic details to an injected service class
-
whether your API tier of classes act as a thin adapter facade between the HTTP protocol and service component interactions
-
-
implement an error reporting strategy
-
whether your design has identified how errors are reported by the service tier and below
-
whether your API tier is able to translate errors into meaningful error responses to the client
-
6.5. Additional Details
-
This portion of the assignment alone primarily provides an implementation pattern for how services will report successful and unsuccessful requests and how the API will turn that into a meaningful HTTP response that the client can access.
-
The
homebuyers-support-api-svc
module contains a set of example DTO Repository Stubs.-
The
Homes
package shows an example of a fully exploded implementation. Take this approach if you wish to write all the code yourself. -
The
Buyers
package shows an example of how to use the templatedPOJORepository<T>
interface andPOJORepositoryMapImpl<T>
implementation. Take this approach if you want to delegate to an existing implementation and only provide the custom query methods.
POJORepositoryMapImpl<T>
provides a protectedfindAll(Predicate<T> predicate, Pageable pageable)
that returns aPage<T>
. All you have to provide are the predicates for the custom query methods. -
-
You are required to use the
Pageable
andPage
classes (from theorg.springframework.data.domain
Java package) for paging methods in your getAllHomeSales() service interface — to be forward compatible with later assignments that make use of Spring Data. You can find example use ofPageable
andPage
(andPageImpl
) in Home and Buyer examples. -
It is highly recommend that exceptions be used between the service and controller layers to identify error scenarios and specific exceptions be used to help identify which kind of error is occurring in order to report accurate status to the client. Leave non-exception paths for successful results. The Homes and Buyers example leverage the exceptions defined in the
ejava-dto-util
module. You are free to define your own. -
It is highly recommended that
ExceptionHandlers
andRestExceptionAdvice
be used to handle exceptions thrown and report status. The Homes and Buyers example leverage theExceptionHandlers
from theejava-web-util
module. You are free to define your own.
7. Assignment 2f: Required Test Scenarios
There are a set of minimum scenarios that are required of a complete project.
-
Creation of HomeSale for a Home
-
success (201/
CREATED
) -
failed creation because Home unknown (422/
UNPROCESSABLE_ENTITY
)
-
-
Update of HomeSale for a Buyer (purchase)
-
success (200/
OK
) -
failed because HomeSale does not exist (404/
NOT_FOUND
) -
failed because Buyer does not exist (422/
UNPROCESSABLE_ENTITY
)
-
7.1. Scenario: Creation of HomeSale for a Home
In this scenario, a HomeSale is created for a Home.
7.1.1. Primary Path: Success
In this primary path, the Home exists and the API client is able to successfully create a HomeSale for the Home. The desired status in the response is a 201/CREATED. A follow-on query for HomeSales will report the new entry.
7.1.2. Alternate Path: Home unknown
In this alternate path, the Home does not exist and the API client is unable to create a HomeSale for the Home. The desired response status is a 422/UNPROCESSABLE_ENTITY. The HomeSales resource understood the request (i.e., not a 400/BAD_REQUEST), but request contained information that could not be processed.
getHome() will return a 404/NOT_FOUND — which is not the same status requested here. HomeSales will need to account for that difference. |
7.2. Scenario: Update of HomeSale for a Buyer
In this scenario, a HomeSale is updated with a Buyer.
7.2.1. Primary Path: Success
In this primary path, the identified Buyer exists and the API client is able to successfully update a HomeSale with the Buyer. This update should be performed all on the server-side. The client primarily expresses Ids. A follow-on query for HomeSales will report the updated entry.
7.2.2. Alternate Path: HomeSale does not exist
In this alternate path, the requested HomeSale does not exist.
The expected response status code should be 404/NOT_FOUND
to express that the target resource could not be found.
7.2.3. Alternate Path: Buyer does not exist
In this alternate path, the requested HomeSale does exist but the identified Buyer does not.
The expected response status code should be 422/UNPROCESSABLE_ENTITY
to express that the request was understood and the target resource could be found. However, the request contained information that could not be processed.
7.3. Requirements
-
Implement the above scenarios within one or more integration unit tests.
-
Name the tests such that they are picked up and executed by the Surefire test phase of the maven build.
-
Turn in a cleaned source tree of the project under a single root parent project. The Home and Buyer modules do not need to be included.
-
The source tree should be ready to build in an external area that has access to the ejava-nexus repository.
7.4. Grading
-
create an integration test that verifies a successful scenario
-
whether you implemented a set of integration unit tests that verify the primary paths for HomeSales
-
-
create an integration test that verifies a failure scenario
-
whether you implemented a set of integration unit tests that verify the failure paths for HomeSales.
-
7.5. Additional Details
-
Place behavior in the proper place
-
The unit integration test is responsible for populating the Homes and Buyers. It will supply HomeDTOs and BuyerDTOs populated on the client-side — to the Homes and Buyers APIs/services.
-
The unit integration test will pass sparsely populated HomeSaleDTOs to the server-side with homeId, buyerId, etc. values express inputs for creating a listing or making a purchase. All details to populate the returned
HomeSaleDTOs
(i.e., Home and Buyer info) will come from the server-side. There should never be a need for the client to self-create/fully-populate a HomeSaleDTO.
-