This project requires JVM version of at least 1.7
h2zero-extension-routemaster-restful top
Routemaster extension for h2zero to generate restful services
Table of Contents top
- h2zero-extension-routemaster-restful
- Table of Contents
- Overview
- A simple (ish) example
- Things to note
- Building the Package
- How to test
- Running the Tests
Overview top
This project is an extension to h2zero
that generates a restful interface to the database (GET, POST, PUT, DELETE).
What you need to do top
- Create an extension class that
extends
synapticloop.h2zero.extension.Extension
- Implement the
public void generate(JSONObject extensionOptions, Database database, Options options, File outFile, boolean verbose) throws RenderException, ParseException;
method - Set-up the h2zero file:
- Away you go
The h2zero configuration file top
see the src/test/resources/sample-include-sqlite3.h2zero
file for a configuration example below
A simple (ish) example top
The main class entry point is the RoutemasterRestfulServletExtension.java
{
"options": {
"metrics": false,
"database": "sqlite3",
"generators": [ "java", "sql", "reports" ],
"extensions" : [
"synapticloop.h2zero.extension.routemaster.RoutemasterRestfulServletExtension"
],
"synapticloop.h2zero.extension.routemaster.RoutemasterRestfulServletExtension": {
"pathPrefix": "extension"
},
"validators": {
"UpdaterNameValidator": {
"allowablePrefixes": "reset,"
},
"FinderNameValidator": {
"allowablePrefixes": "find,calculate"
}
},
"output": {
"code": "src/test/java/",
"resources": "src/test/resources/",
"build": "build/"
}
},
"database": {
"schema": "sample",
"package": "synapticloop.sample.h2zero.sqlite3",
"defaultStatementCacheSize": 1024,
"tables": [
{ "include": "./user_type.json" },
{ "include": "./user_title.json" },
{ "include": "./user.json" },
{ "include": "./pet.sqlite3.json" },
{ "include": "./user_pet.json" }
],
"views": [
{ "include": "./view-pet.json" },
]
}
}
Things to note from the above top
"options:{
...
"extensions" : [
"synapticloop.h2zero.extension.routemaster.RoutemasterRestfulServletExtension"
],
"synapticloop.h2zero.extension.routemaster.RoutemasterRestfulServletExtension": {
"pathPrefix": "extension"
},
...
}
Extension are placed in the String JSON Array with the extensions
key. For any
other options or configuration that is required by the extension, place another
JSON object within the options
object key on the class name that the extension
uses.
A simple (ish) example top
The main class entry point is the RoutemasterRestfulServletExtension.java
package synapticloop.h2zero.extension.routemaster;
/*
* Copyright (c) 2018 synapticloop.
*
* All rights reserved.
*
* This source code and any derived binaries are covered by the terms and
* conditions of the Licence agreement ("the Licence"). You may not use this
* source code or any derived binaries except in compliance with the Licence.
* A copy of the Licence is available in the file named LICENCE shipped with
* this source code or binaries.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* Licence for the specific language governing permissions and limitations
* under the Licence.
*/
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONObject;
import synapticloop.h2zero.extension.Extension;
import synapticloop.h2zero.model.Database;
import synapticloop.h2zero.model.Options;
import synapticloop.h2zero.model.Table;
import synapticloop.h2zero.validator.BaseValidator;
import synapticloop.templar.Parser;
import synapticloop.templar.exception.ParseException;
import synapticloop.templar.exception.RenderException;
import synapticloop.templar.utils.TemplarContext;
/**
* This extension generates files that create a RESTful interface to a database
* through RouteMaster, based on NanoHTTPD
*/
public class RoutemasterRestfulServletExtension extends Extension {
@Override
public void generate(JSONObject extensionOptions, Database database, Options options, File outFile, boolean verbose) throws RenderException, ParseException {
// you __ALWAYS__ want to get the defaultTemplarContext.
TemplarContext templarContext = getDefaultTemplarContext(extensionOptions, database, options);
// write out the BaseRestServant class
writeBaseRestServant(database, options, outFile, verbose, templarContext);
// write out the rest servants, one for each table
writeRestServants(database, options, outFile, verbose, templarContext);
// write out the routemaster routes file
writeRestServantRoutes(database, options, outFile, verbose, templarContext);
}
/**
* Write out the base rest servant - which is a single class, upon which all
* other files are dependent.
*
* @param database The h2zero database model
* @param options The h2zero options
* @param outFile The base directory
* @param verbose whether the user wants verbose output
* @param templarContext the templar context
*
* @throws ParseException If there was an error parsing the templar template
* @throws RenderException If there was an error rendering the file
*/
private void writeBaseRestServant(Database database, Options options, File outFile, boolean verbose, TemplarContext templarContext) throws ParseException, RenderException {
// get the templar parser
Parser baseRestServantTemplarParser = getParser("/java-create-routemaster-base-rest-servant.templar", verbose);
// determine the file path
String pathname = outFile + options.getOutputCode() + database.getPackagePath() + "/routemaster/servant/BaseServant.java";
// render to the file
renderToFile(templarContext, baseRestServantTemplarParser, pathname, verbose);
}
/**
* Write out the RESTful servant, one for each table
*
* @param database The h2zero database model
* @param options The h2zero options
* @param outFile The base directory
* @param verbose whether the user wants verbose output
* @param templarContext the templar context
*
* @throws ParseException If there was an error parsing the templar template
* @throws RenderException If there was an error rendering the file
*/
private void writeRestServants(Database database, Options options, File outFile, boolean verbose, TemplarContext templarContext) throws RenderException, ParseException {
// get the templar parser
Parser restServantTemplarParser = getParser("/java-create-routemaster-rest-servant.templar", verbose);
// get all of the tables
List<Table> tables = database.getTables();
for (Table table : tables) {
// for each table, add it to the context
templarContext.add("table", table);
// determine the file path
String pathname = outFile + options.getOutputCode() + database.getPackagePath() + "/routemaster/servant/" + table.getJavaClassName() + "Servant.java";
// render to the file
renderToFile(templarContext, restServantTemplarParser, pathname, verbose);
}
}
/**
* Write out the example routes for the RESTful interface
*
* @param database The h2zero database model
* @param options The h2zero options
* @param outFile The base directory
* @param verbose whether the user wants verbose output
* @param templarContext the templar context
*
* @throws ParseException If there was an error parsing the templar template
* @throws RenderException If there was an error rendering the file
*/
private void writeRestServantRoutes(Database database, Options options, File outFile, boolean verbose, TemplarContext templarContext) throws ParseException, RenderException {
// get the templar parser
Parser baseRestServantTemplarParser = getParser("/java-create-routemaster-rest-servant-routes.templar", verbose);
// render to the file
String pathname = outFile + options.getOutputResources() + "routemaster.rest.properties";
// render to the file
renderToFile(templarContext, baseRestServantTemplarParser, pathname, verbose);
}
@Override
public List<BaseValidator> getValidators() {
return(new ArrayList<BaseValidator>());
}
}
Things to note top
Looking at the above class, it is relatively straight-forward to generate multiple files. Below is a list of things to note:
Always get the default context top
// you __ALWAYS__ want to get the defaultTemplarContext.
TemplarContext templarContext = getDefaultTemplarContext(extensionOptions, database, options);
This will set everything up, and place the following things into the context.
TemplarContext templarContext = new TemplarContext(templarConfiguration);
templarContext.add(JSONKeyConstants.DATABASE, database); // key is "database"
templarContext.add(JSONKeyConstants.OPTIONS, options); // key is "options"
templarContext.add(JSONKeyConstants.EXTENSION_OPTIONS, extensionOptions); // key is "extensionOptions"
Get the parser top
Use the getParser("/classpath/to/template.templar", verbose)
method which will set up the parser for you.
Render top
Use the renderToFile(templarContext, templarParserFile, "output/path/file.name", verbose);
which will also
add the output to the summary statistics.
Building the Package top
*NIX/Mac OS X top
From the root of the project, simply run
./gradlew build
Windows top
./gradlew.bat build
This will compile and assemble the artefacts into the build/libs/
directory.
Note that this may also run tests (if applicable see the Testing notes)
How to test top
As the extension will generate additional code for the project, there is a slight roundabout way of testing the code.
- build the code and publish it to maven local
- have a separate build.gradle file that will reference the class path (including maven local repository)
The simplest way is to:
gradle build -x test
then
gradle -b build.h2zero.sqlite3.gradle h2zero
or more simply (for *NIX machines)
gradle build -x test; gradle -b build.h2zero.sqlite3.gradle h2zero
Running the Tests top
*NIX/Mac OS X top
From the root of the project, simply run
gradle --info test
if you do not have gradle installed, try:
gradlew --info test
Windows top
From the root of the project, simply run
gradle --info test
if you do not have gradle installed, try:
./gradlew.bat --info test
The --info
switch will also output logging for the tests
Dependencies - Gradle top
dependencies {
runtime(group: 'synapticloop', name: 'h2zero-extension-routemaster-restful', version: '2.1.0', ext: 'jar')
compile(group: 'synapticloop', name: 'h2zero-extension-routemaster-restful', version: '2.1.0', ext: 'jar')
}
or, more simply for versions of gradle greater than 2.1
dependencies {
runtime 'synapticloop:h2zero-extension-routemaster-restful:2.1.0'
compile 'synapticloop:h2zero-extension-routemaster-restful:2.1.0'
}
Dependencies - Maven top
<dependency>
<groupId>synapticloop</groupId>
<artifactId>h2zero-extension-routemaster-restful</artifactId>
<version>2.1.0</version>
<type>jar</type>
</dependency>
Dependencies - Downloads top
You will also need to download the following dependencies:
net.sourceforge.cobertura:cobertura:2.1.1
: (It may be available on one of: bintray mvn central)
synapticloop:h2zero:3.1.0
: (It may be available on one of: bintray mvn central)synapticloop:routemaster:2.3.0
: (It may be available on one of: bintray mvn central)
synapticloop:h2zero:3.1.0
: (It may be available on one of: bintray mvn central)synapticloop:routemaster:2.3.0
: (It may be available on one of: bintray mvn central)
mysql:mysql-connector-java:6.0.6
: (It may be available on one of: bintray mvn central)org.xerial:sqlite-jdbc:3.21.0.1
: (It may be available on one of: bintray mvn central)commons-io:commons-io:2.5
: (It may be available on one of: bintray mvn central)synapticloop:h2zero:3.0.0
: (It may be available on one of: bintray mvn central)synapticloop:routemaster:2.3.0
: (It may be available on one of: bintray mvn central)
junit:junit:4.12
: (It may be available on one of: bintray mvn central)org.mockito:mockito-all:1.10.19
: (It may be available on one of: bintray mvn central)com.github.stefanbirkner:system-rules:1.16.1
: (It may be available on one of: bintray mvn central)commons-io:commons-io:2.5
: (It may be available on one of: bintray mvn central)com.mashape.unirest:unirest-java:1.4.9
: (It may be available on one of: bintray mvn central)
junit:junit:4.12
: (It may be available on one of: bintray mvn central)org.mockito:mockito-all:1.10.19
: (It may be available on one of: bintray mvn central)com.github.stefanbirkner:system-rules:1.16.1
: (It may be available on one of: bintray mvn central)mysql:mysql-connector-java:6.0.6
: (It may be available on one of: bintray mvn central)org.xerial:sqlite-jdbc:3.21.0.1
: (It may be available on one of: bintray mvn central)commons-io:commons-io:2.5
: (It may be available on one of: bintray mvn central)com.mashape.unirest:unirest-java:1.4.9
: (It may be available on one of: bintray mvn central)
NOTE: You may need to download any dependencies of the above dependencies in turn (i.e. the transitive dependencies)
--
This README.md file was hand-crafted with care utilising synapticloop
templar
->
documentr
--