The API demonstrates how to create and consume REST services for managing a list of companies and their owners using Spring and HATEOAS. Two @RepositoryRestResource are created for management of entities Company and Owner and relation between them. These repositories are extended with search functionality.
There are two options to use the services:
-
Directly use deployed services. For demonstration purposes the services were deployed on http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com. You can directly consume the services using the
curl
sample commands from chapter How to Consume the REST Services. -
Deploy services on your machine. In this case you will build and deploy the services locally using steps from Deploy the Services on Your Environment. Since now the default address for accessing the services will be http://localhost:8080/ don’t forget to replace the address if you use the sample
curl
commands below.
A description containg the request and response is added for each service. Sample curl
command is added for ease of use; just copy-paste into terminal and adapt the data to your needs. Of course, you can use any other HTTP client.
By accessing root context of the application via HTTP GET you get information about available services.
$ curl 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/' -i -X GET
GET / HTTP/1.1
Host: company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
Content-Length: 466
{
"_links" : {
"owners" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners{?page,size,sort}",
"templated" : true
},
"companies" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/profile"
}
}
}
We see in this response that we have two sets of services, one for managenent of /companies
and one for management of /owners
.
/profile
serves for application profiling, we will not go into details of this service in this document. For more information see
Sprint Boot Actuator
To create a new company you should do a HTTP POST with a company information in JSON format.
$ curl 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-d '{"name" : "MOMENTUM SOFTWARE", "address" : "Valea Frumoasei", "city" : "Sibiu", "country" : "Romania", "email" : "[email protected]", "phoneNumber" : "+40"}'
POST /companies HTTP/1.1
Content-Type: application/json;charset=UTF-8
Host: company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com
Content-Length: 167
{"name" : "MOMENTUM SOFTWARE", "address" : "Valea Frumoasei", "city" : "Sibiu", "country" : "Romania", "email" : "[email protected]", "phoneNumber" : "+40"}
See below a detailed description of company attributes which can be passed to the service.
Path | Type | Description |
---|---|---|
|
|
Company name (mandatory) |
|
|
Address of the company (mandatory) |
|
|
City where company is located (mandatory) |
|
|
Country where company is located (mandatory) |
|
|
Email where company can be contacted |
|
|
Phone number where company can be contacted |
In case of success, the service will send us back the location where we can access created company. Remark the important part of the link /companies/1
- this identifies the created company.
HTTP/1.1 201 Created
Location: http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1
If mandatory attributes are not specified (see table above) the company will not be created and service will return an error.
To obtain details of a company you should do a HTTP GET on the HTTP location of the company. This is returned in response of Create Company service.
$ curl 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1' -i -X GET
Service will return the details of company in JSON format together with links for related services.
Important
|
An important link is found under section `beneficialOwners'. This allow management of list of beneficial owners of this company. |
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
Content-Length: 591
{
"name" : "MOMENTUM SOFTWARE",
"address" : "Valea Frumoasei",
"city" : "Sibiu",
"country" : "Romania",
"email" : "[email protected]",
"phoneNumber" : "+40",
"_links" : {
"self" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1"
},
"company" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1"
},
"beneficialOwners" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1/beneficialOwners"
}
}
}
In case you request a company that does not exist, the service will return HTTP code 404 and empty response body.
HTTP/1.1 404 Not Found
To update any attribute of an already created company you should do a HTTP PUT to company location with new values for attributes you want to update in JSON format. You can include in the request one or all company attributes.
Important
|
Target HTTP address will be the location of the company as it was returned in response of Create Company service. |
$ curl 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/2' -i -X PUT \
-H 'Content-Type: application/json;charset=UTF-8' \
-d '{ "name" : "MOMENTUM SOFTWARE 2", "address" : "Valea Frumoasei 10", "city" : "Sibiu 550310", "country" : "RO", "email" : "[email protected]", "phoneNumber" : "+401"}'
PUT /companies/1 HTTP/1.1
Host: company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com
Content-Length: 178
{ "name" : "MOMENTUM SOFTWARE 2", "address" : "Valea Frumoasei 10", "city" : "Sibiu 550310", "country" : "RO", "email" : "[email protected]", "phoneNumber" : "+401"}
See below a detailed description of company attributes which can be passed to the service. Since we do an update, mandatory attributes of create company are optional now.
Path | Type | Description |
---|---|---|
|
|
Company name |
|
|
Address of the company |
|
|
City where company is located |
|
|
Country where company is located |
|
|
Email where company can be contacted |
|
|
Phone number where company can be contacted |
To retrieve the list of companies you should to a HTTP GET on service address, as in the example below.
$ curl 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies' -i -X GET
Response will be in JSON format and will consist in a list of first 20 companies (default value), information related to complete list and links to this service and related services.
Note
|
List allows customizable pagination of retrieved results. |
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
Content-Length: 1912
{
"_embedded" : {
"companies" : [ {
"name" : "MOMENTUM SOFTWARE",
"address" : "Valea Frumoasei",
"city" : "Sibiu",
"country" : "Romania",
"email" : "[email protected]",
"phoneNumber" : "+40",
"_links" : {
"self" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1"
},
"company" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1"
},
"beneficialOwners" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1/beneficialOwners"
}
}
}, {
"name" : "ABC",
"address" : "Other Street",
"city" : "SB",
"country" : "RO",
"email" : "[email protected]",
"phoneNumber" : "+40",
"_links" : {
"self" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/2"
},
"company" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/2"
},
"beneficialOwners" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/2/beneficialOwners"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/profile/companies"
},
"search" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/search"
}
},
"page" : {
"size" : 20,
"totalElements" : 2,
"totalPages" : 1,
"number" : 0
}
}
To create a new owner you should do a HTTP POST with owner information in JSON format.
$ curl 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners' -i -X POST \
-H 'Content-Type: application/json;charset=UTF-8' \
-d '{"email" : "[email protected]", "firstName" : "Marius", "lastName" : "Seiceanu"}'
POST /owners HTTP/1.1
Content-Type: application/json;charset=UTF-8
Host: company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com
Content-Length: 89
{"email" : "[email protected]", "firstName" : "Marius", "lastName" : "Seiceanu"}
See below a detailed description of owner attributes which can be passed to the service.
Path | Type | Description |
---|---|---|
|
|
Owner email address (mandatory, unique) |
|
|
User first name (mandatory) |
|
|
User last name (mandatory) |
In case of success, the service will send us back the location where we can access created owner. Remark the important part of the link /owners/1 - this identifies the created owner.
HTTP/1.1 201 Created
Location: http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/1
If mandatory attributes are not specified (see table above) the company will not be created and service will return an error.
To add a beneficial owner to a company you should do a HTTP POST to location company beneficialOwners` (see Get Details of a Company) and sned one or more URI references to exiting owners, references which are returned by Create Owner service. This time content type of request body will be text/uri-list
.
$ curl 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1/beneficialOwners' -i -X POST \
-H 'Content-Type: text/uri-list;charset=UTF-8' \
-d 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/2'
POST /companies/1/beneficialOwners HTTP/1.1
Content-Type: text/uri-list;charset=UTF-8
Host: company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com
Content-Length: 77
http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/2
To retrieve the list of beneficial owners of a company you need to do a HTTP GET on the location of company beneficial owners returned in response of Get Details of a Company service.
$ curl 'http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1/beneficialOwners' -i -X GET
Response consists in a JSON formatted text that contains the list of company owners and related service links. Example below.
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
Content-Length: 1283
{
"_embedded" : {
"owners" : [ {
"email" : "[email protected]",
"firstName" : "Marius",
"lastName" : "Seiceanu",
"_links" : {
"self" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/2"
},
"owner" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/2"
},
"companies" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/2/companies"
}
}
}, {
"email" : "[email protected]",
"firstName" : "Marius",
"lastName" : "Oancea",
"_links" : {
"self" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/3"
},
"owner" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/3"
},
"companies" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/owners/3/companies"
}
}
} ]
},
"_links" : {
"self" : {
"href" : "http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com/companies/1/beneficialOwners"
}
}
}
This part briefly describes how to build and run the services on your machine. You can skip this part in case you only access the pre-installed services on http://company-bo-companybo.1d35.starter-us-east-1.openshiftapps.com .
The following aplications are needed to be installed before you continue.
Download and unzip the source repository or clone it using Git:
git clone https://github.com/mariusseiceanu/companyws.git
cd companyws
Run Maven package task:
mvn clean package
After some seconds you should see in console a successfull message like the one below:
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 23, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ companyws ---
[INFO]
[INFO] --- spring-boot-maven-plugin:2.0.3.RELEASE:repackage (default) @ companyws ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Previous step created a JAR
package containing our service set. To start it you should execute:
java -jar target/companyws-0.0.1-SNAPSHOT.jar
After some seconds you will see in console
INFO 9221 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
INFO 9221 --- [ main] ro.momsw.companyws.CompanyWSApplication : Started CompanyWSApplication in 7.571 seconds (JVM running for 8.037)
Done. Now you can start using the services by calling them as described in How to Consume the REST Services. If you use the sample curl
commands don’t forget the change the links to point to http://locahost:8080/ .
As it can be seen, services can be freely accessed now. In a next step we should add authentication mechanism to restrict access only to authorized users.
A good choise for this is using OAuth2 mechanism to reduce the complexity on the client and benefit of inhenrent limited access to service.
In order to build a fault tolerant system and have high availability of the servies we should deploy on multiple containers (at least two). On top of this we put a load balancer (e.g. NGINX) so that we expose a single entry point to client and take care of session replication if our services will become stateful. This architecture will also increase the scalability of the whole systems until the point where the bottleneck will be on persistence layer (DB).