Skip to content

Commit b4451b9

Browse files
committed
Merge pull request #6 from ghost/update_db
Replace mysql database with H2 & minor refactoring
2 parents 062633d + 4e89dec commit b4451b9

12 files changed

Lines changed: 378 additions & 72 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
This repository gather resources about the Restlet Framework:
22

3-
* [Source code of the Restlet Framework Web API reference implementation] (https://github.com/restlet/restlet-tutorial/tree/master/modules/org.restlet.tutorial.webapi)
4-
* [Documentation of Restlet Framework Web API Reference Implementation] (https://github.com/restlet/restlet-tutorial/wiki/Restlet-Framework-Web-API-Reference-Implementation)
3+
* [Source code of the Restlet Framework Web API reference implementation] (/modules/org.restlet.tutorial.webapi)
4+
* [Documentation of Restlet Framework Web API Reference Implementation] (/modules/org.restlet.tutorial.webapi/README.md)
55

66

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
# Restlet Framework Web API Reference Implementation
2+
3+
## Prerequisites
4+
5+
* Maven installed on your machine : [Maven documentation link](http://maven.apache.org/index.html)
6+
7+
> The implementation is located [here](https://github.com/restlet/restlet-tutorial/tree/master/modules/org.restlet.tutorial.webapi)
8+
9+
> This example uses [Restlet Framework 2.2.1](http://restlet.com/download/current#release=stable&edition=jse&distribution=zip) (Java SE edition)
10+
and [H2 Database](www.h2database.com)
11+
12+
> Restlet framework user guide is available [here](http://restlet.com/learn/guide/2.3/).
13+
> You can also clone this repository and go to ```/modules/org.restlet.tutorial.webapi/``` folder.
14+
15+
## Installation
16+
17+
### Install Maven project
18+
19+
To install maven :
20+
* Go to the directory
21+
* Execute ```mvn clean install```
22+
* For eclipse users : run ```mvn eclipse:eclipse```
23+
24+
> For further instruction about running a Maven project : [Building a project with Maven](http://maven.apache.org/run-maven/index.html)
25+
26+
### Run this application
27+
28+
The main class is : ```WebApiHost.java```
29+
By default the application is launched at ```http://localhost:9000```, but you can change it in ```WebApiHost.java```.
30+
A logger is configured. Its configuration is made in ```logging.properties``` and declared in ```WebApiHost.java```.
31+
Two files will be created :
32+
* ```webapitutorial-app-x-x.log```
33+
* ```webapitutorial-requests-x-x.log```
34+
35+
They are both situated in ```/tmp``` folder.
36+
To simplify the launch of the application, authentication and authorization are done in-memory
37+
(You should overwrite that with you own authentication system). Here are the login/password available:
38+
39+
* admin/admin : to get admin role
40+
* owner/owner : to get owner role
41+
* user/user : to get user role
42+
43+
It uses HTTP Basic authentication.
44+
45+
> Learn more about authentication, authorization and security with Restlet Framework [here](http://restlet.com/learn/guide/2.3/core/security/).
46+
47+
> You can try this application easily with a REST client like [POSTMAN](http://www.getpostman.com/).
48+
49+
## Database access
50+
51+
To visualize the database, open the H2 console in you browser (`http://localhost:8082`) and connect to the database with the JDBC URL `jdbc:h2:mem:restletWebApi;IFEXISTS=TRUE`.
52+
53+
## Description
54+
55+
This Web API contains 2 main resources :
56+
57+
* Company : identified by an auto-generated id.
58+
* Contact : identified by its email. A contact can be part of a company and get a reference to it.
59+
60+
This is a diagram of the API :
61+
62+
![Diagram](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/RFWebAPIReferenceImplementation.png)
63+
64+
> A Web API definition can be generated with [APISpark extension (RF 2.3)](http://restlet.com/learn/guide/2.3/extensions/apispark).
65+
66+
## Implementation choices
67+
68+
* The persistence layer has been done to be as simple as possible. The aim of this example is to show how to build a reference Web API with Restlet Framework.
69+
* The API was designed to use meaningful URLs. For example, for contacts the email is used as an identifier instead of a technical id (which does not mean anything for a user). On the contrary, for companies an autogenerated id has been chosen.
70+
* There is not POST method for contacts as a contact is defined by his/her email. To add a contact, you must do a PUT on ```/contacts/{email}```
71+
72+
## Next steps
73+
74+
Here are some instructions to go further with this project
75+
76+
* Persistence layer
77+
* For each operation a new connection is created.
78+
It would be useful to use a connection pool like [DBCP](http://commons.apache.org/proper/commons-dbcp/).
79+
* It is possible to totally dissociate the persistence layer from the Server Resources.
80+
It would allow the use of several persitence layers. It would also be possible to use dependency injection.
81+
* Authentication/Authorization
82+
* It is strongly recommended to store users/roles in a database instead of in-memory.
83+
You can create a custom [SecretVerifier](http://restlet.org/learn/javadocs/2.2/jse/api/org/restlet/security/SecretVerifier.html)
84+
and [Enroler](http://restlet.org/learn/javadocs/2.2/jse/api/org/restlet/security/Enroler.html).
85+
* It is possible to handle autorizations in a filter instead of at the beginning of each class.
86+
In fact, in this example, there is a repeating schema : Role user needed to access to GET methods,
87+
Role owner needed to access the others.
88+
89+
## Usage
90+
91+
> These examples are made using the JSON format but you can use XML or YAML if you want.
92+
93+
### Ping resource
94+
95+
A resource ```/ping``` has been created which does not need authentication.
96+
97+
```GET http://localhost:9000/v1/ping```
98+
99+
![Ping Example](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/ping.png)
100+
101+
> For the following examples, Basic Authentication will be needed
102+
103+
### Create a company
104+
105+
``` POST http://localhost:9000/v1/companies/```
106+
107+
```json
108+
{
109+
"name" : "Restlet",
110+
"duns" : "123456789",
111+
"address" : "2 API road",
112+
"zipCode" : "44300",
113+
"creationDate" : "2014-01-01",
114+
"website" : "http://restlet.com",
115+
"city" : "Nantes",
116+
"phoneNumber" : "+1 555 555 555"
117+
}
118+
```
119+
120+
![POST Companies](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/POSTCompanies.png)
121+
122+
> The returned status is : ```201 Created```.
123+
124+
The location of the created company is written is the "location" header.
125+
126+
![POST Companies headers](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/POSTCompaniesHeaders.png)
127+
128+
### Retrieve all created companies
129+
130+
```GET http://localhost:9000/v1/companies/```
131+
132+
> The trailing slash is optional : both ```http://localhost:9000/v1/companies/``` and ```http://localhost:9000/v1/companies``` will work.
133+
134+
It should retrieve :
135+
136+
```json
137+
{
138+
"list" :
139+
[
140+
{
141+
"duns":"123456789",
142+
"address":"2 API road",
143+
"zipCode":"44300",
144+
"creationDate":"2014-01-01",
145+
"website":"http://restlet.com",
146+
"phoneNumber":"+1 555 555 555",
147+
"city":"Nantes",
148+
"name":"Restlet",
149+
"self":"/companies/1"
150+
}
151+
]
152+
}
153+
```
154+
155+
![GET Companies](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/GETCompanies.png)
156+
157+
> ```self``` element refers to the location of the object : ```http://localhost:9000/v1/companies/1```.
158+
> Try ```GET http://localhost:9000/v1/companies/1``` !
159+
160+
### Create a contact related to the created company
161+
162+
```PUT http://localhost:9000/v1/contacts/{email}```
163+
164+
with ```{email}``` representing the email of the contact you want to insert.
165+
166+
For this example, it is :
167+
``` PUT http://localhost:9000/v1/contacts/gblondeau@restlet.com```
168+
169+
```json
170+
{
171+
"name" : "Blondeau",
172+
"firstName" : "Guillaume",
173+
"age" : 22,
174+
"company" : "1"
175+
}
176+
```
177+
178+
It should retrieve :
179+
180+
```json
181+
{
182+
"email":"gblondeau@restlet.com",
183+
"age":22,
184+
"name":"Blondeau",
185+
"firstName":"Guillaume",
186+
"company":"/companies/1"
187+
}
188+
```
189+
190+
![PUT Contacts](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/PUTContacts.png)
191+
192+
> The returned status is : ```201 Created```.
193+
194+
> The field company is a reference to the location of the company, with 1 the id of the company.
195+
ie : /companies/1 refers to http://localhost:9000/v1/companies/1
196+
197+
### Retrieve the list of created contacts
198+
199+
```GET http://localhost:9000/v1/contacts```
200+
201+
> The trailing slash is optional : both ```http://localhost:9000/v1/contacts/``` and ```http://localhost:9000/v1/contacts``` will work.
202+
203+
It should retrieve :
204+
205+
```json
206+
{
207+
"list" :
208+
[
209+
{
210+
"email":"gblondeau@restlet.com",
211+
"age":22,
212+
"name":"Blondeau",
213+
"firstName":"Guillaume",
214+
"company":"/companies/1",
215+
"self":"/contacts/gblondeau@restlet.com"
216+
}
217+
]
218+
}
219+
```
220+
221+
![GET Contacts](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/GETContacts.png)
222+
223+
> The field company is a reference to the location of the company
224+
225+
To display the company information, add the following query parameter : ```?strategy=load```
226+
227+
```GET http://localhost:9000/v1/contacts/?strategy=load```
228+
229+
It should retrieve :
230+
231+
```json
232+
{
233+
"list" :
234+
[
235+
{
236+
"email":"gblondeau@restlet.com",
237+
"age":22,
238+
"name":"Blondeau",
239+
"firstName":"Guillaume",
240+
"company":
241+
{
242+
"duns":"123456789",
243+
"address":"2 API road",
244+
"zipCode":"44300",
245+
"creationDate":"2014-01-01",
246+
"website":"http://restlet.com",
247+
"phoneNumber":"+1 555 555 555",
248+
"city":"Nantes",
249+
"name":"Restlet"
250+
},
251+
"self":"/contacts/gblondeau@restlet.com"
252+
}
253+
]
254+
}
255+
```
256+
257+
![GET Contacts](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/GETContactsLoad.png)
258+
259+
### Modify an existing contact
260+
261+
```PUT http://localhost:9000/v1/contacts/gblondeau@restlet.com```
262+
263+
```json
264+
{
265+
"age" : 23,
266+
"name": "Blondeau",
267+
"firstName": "Guillaume",
268+
"company": "1"
269+
}
270+
```
271+
272+
It should retrieve :
273+
274+
```json
275+
{
276+
"email": "gblondeau@restlet.com",
277+
"age": 23,
278+
"name": "Blondeau",
279+
"firstName": "Guillaume",
280+
"company": "/companies/1"
281+
}
282+
```
283+
284+
![PUT Contacts](https://github.com/restlet/restlet-tutorial/blob/master/modules/org.restlet.tutorial.webapi/images/PUTContacts2.png)
285+
286+
> This time a ```200 OK ``` is returned because it is not a creation but an update.
287+

modules/org.restlet.tutorial.webapi/pom.xml

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<project
2-
xsi:schemaLocation="http://maven.apache.org/POM/1.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3-
<modelVersion>4.0.0</modelVersion>
2+
xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5+
<modelVersion>4.0.0</modelVersion>
46
<groupId>org.restlet.tutorial.webapi</groupId>
57
<artifactId>RFReferenceWebAPI</artifactId>
68
<packaging>jar</packaging>
@@ -46,11 +48,11 @@
4648
<artifactId>org.restlet.ext.wadl</artifactId>
4749
<version>2.2.1</version>
4850
</dependency>
49-
<dependency>
50-
<groupId>mysql</groupId>
51-
<artifactId>mysql-connector-java</artifactId>
52-
<version>5.1.6</version>
53-
</dependency>
51+
<dependency>
52+
<groupId>com.h2database</groupId>
53+
<artifactId>h2</artifactId>
54+
<version>1.4.181</version>
55+
</dependency>
5456
</dependencies>
5557
<build>
5658
<pluginManagement>

modules/org.restlet.tutorial.webapi/src/main/java/org/restlet/tutorial/WebApiHost.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.restlet.tutorial;
22

33
import org.restlet.Component;
4+
import org.restlet.Context;
45
import org.restlet.data.Protocol;
56
import org.restlet.tutorial.persistence.PersistenceService;
67

@@ -29,5 +30,8 @@ public static void main(String[] args) throws Exception {
2930
c.getDefaultHost().attach("/v1", new WebApiTutorial());
3031

3132
c.start();
33+
34+
Context.getCurrentLogger().info("Restlet application started. URL: http://localhost:9000/v1" );
35+
3236
}
3337
}

modules/org.restlet.tutorial.webapi/src/main/java/org/restlet/tutorial/persistence/CompanyPersistence.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ public static synchronized CompanyPersistence getCompanyPersistence() {
3232
}
3333

3434
private CompanyPersistence() {
35-
};
35+
}
3636

3737
@Override
3838
public List<Company> findAll() throws SQLException {

0 commit comments

Comments
 (0)