Yun Zhi Lin
Yunspace.com +YunZhiLin @YunZhiLin
End to end prototype of a Bill Aggregator that mimics vendor API. See below for detail specifications.
FK: List(Subscriptions)
FK: List(Subscriptions)
FK: Provider.id, Premise.id, Bill.accountNumber, List(Bill.id, Status)
FK: Provider.id, Subscription.referenceNumber
FK: Provider, Premise, Subscription
Due to the time contraint, it's important to decide on the approach taken to plan out a successfull prototype:
PUT /subscription/
GET /subscription/trigger/{subscriptoinID}/{billID}/
GET /bill/?billID={billID}
Gradle combines the best of Ant and Maven
repositories {
mavenLocal()
mavenCentral()
}
project.ext {
dropwizardVersion = '0.7.0-SNAPSHOT'
mongojackVersion = '2.0.0-RC5'
dropWizardConfig = './src/main/resources/billproto.yml'
}
dependencies {
compile 'io.dropwizard:dropwizard-core:' + dropwizardVersion
compile 'org.mongojack:mongojack:' + mongojackVersion
testCompile group: 'junit', name: 'junit', version: '4.11'
}
run {
args 'server', dropWizardConfig
}
mongo:
host: ds039487.mongolab.com
port: 39487
db: tycoon-mongo
user: ####
password: ####
public class MongoConfiguration {
@NotNull
public String host;
@Min(1)
@Max(65535)
@NotNull
public int port;
@NotNull
public String db;
@NotNull
public String user;
@NotNull
public String password;
}
mongo = new Mongo(mongoConfig.host, mongoConfig.port);
db = mongo.getDB(mongoConfig.db);
db.authenticate(mongoConfig.user, mongoConfig.password.toCharArray());
bills = wrap(db.getCollection("bill"), Bill.class, String.class);
dbCursor = bills.find().is("_id", billID);
if (dbCursor.hasNext()) { Bill result = cursor.next();}
mongoimport --host --username --password --db --collection --file
@Override
protected Result check() throws Exception {
mongo.getDB(dbname).getCollectionNames();
return Result.healthy();
}
{"MongoHealthCheck":{"healthy":true},"deadlocks":{"healthy":true}}
{"MongoHealthCheck":{"healthy":false,
"message":"not authorized for query on tycoon-mongo.system.namespaces",
"error":{"message":"not authorized for query on tycoon-mongo.system.namespaces",
"stack":[...]
"deadlocks":{"healthy":true}}
Use http://www.jsonschema2pojo.org/. Then apply simple annotations for Jackson and Hibernate Validatior.
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Notification {
@Id
public String notificationID;
@NotNull
public String subscriptionID;
@NotNull
public String notificationURLForBillDataRetrival;
@NotNull
public String notificationURLForBillImageRetrival;
}
NOTE: Use @Id for UUID, not @ObjectId
Annotate opertion, metrics, url path and output format.
Jackson automatically parse POJO into specified mediaType.
@GET
@Timed
@Path("trigger/{subscriptionID}/{billID}")
@Produces(MediaType.APPLICATION_JSON)
public Notification triggerNotification(
@PathParam("subscriptionID") String subscriptionID,
@PathParam("billID") String billID) {
...
notification = new Notification();
notification.notificationID = UUID.randomUUID().toString();
notification.subscriptionID = subscriptionID;
notification.notificationURLForBillDataRetrival =
subscription.subscriptionCallBackURL + "?billID=" + billID;
return notification;
}
Putting all of the above together
@Override
public void run(
BillprotoConfiguration configuration,
Environment environment) throws Exception {
MongoManaged mongoManaged =
new MongoManaged(configuration.mongo);
environment.lifecycle().manage(mongoManaged);
environment.healthChecks().register(
"MongoHealthCheck", new MongoHealthCheck(mongoManaged));
environment.jersey().register(new SubscriptionResource(mongoManaged));
environment.jersey().register(new BillResource(mongoManaged));
}
sudo apt-get install java7-runtime-headless
gcutil addfirewall rest --description="http" --allowed="tcp:8080
gcutil addfirewall admin --description="Iadmin" --allowed="tcp:8081"
gcutil --project={project-id} push {instance-name} {local-file} {remote-target-path}
java -jar billproto-0.2-fat.jar server billproto.yml
By building just the bare minimum operations in each components that work well together, we were able to cover the core user story and better assess our API feasibility.
We also managed to test out a new framework and built a template that can be fleshed out for future applications.