Tuesday, December 6, 2016

What Code Belongs in an MVC Controller

The purpose of a controller is to act as a conduit between each user interaction and system response. Typically this involves three steps:

  • readRequest(). For a web server this means reading the inbound HTTP request, analyzing the headers, taking care of authorization.
  • doSomething(). Now that the server knows what it's being asked to do, the server can go ahead and do something useful.
  • writeResponse(). After the server has finished its job or kicked off a long-running process, it should write a response back to the user to let the user know how things went.

In a different sense, a controller's action method is just a wrapper for a function that executes actual business logic, a wrapper that translates an HTTP request into function args.

This setup makes sense to me, but what other approaches are there to writing good controllers? Please share your comments.

Wednesday, November 9, 2016

Install Anaconda 2 to /opt/anaconda2

By default, Anaconda 4.2 for Python 2 will install itself to the user's home directory on Linux. This is great for local development, but for server-side deployment and testing it's better to install to a shared location.

The install docs are pretty vague about how to set this up, saying simply, "Install Anaconda as a user unless root privileges are required." The way I've made this work easily on an Amazon EC2 running Ubuntu 16.04 LTS is as follows.

  1. Download the appropriate installer
  2. Install as a superuser with sudo bash Anaconda2-4.2.0-Linux-x86_64.sh
  3. Install to /opt/anaconda2 and prepend the install location to PATH in ~/.bashrc
  4. Change the target directory's group ownership to ubuntu and grant g+w permission for the directory and all its subdirectories

In short, something like this will work beautifully, allowing packages to still be installed simply using conda install or pip install.

Wednesday, July 27, 2016

caffe.io.load_image vs. cv2.imdecode

Interesting note to self... the following code produces the same results, one using a chain of OpenCV methods and the other using a concise Caffe method.

Thursday, May 12, 2016

Mix Groovy and Java in STS 3.7.3.RELEASE

To mix Java and Groovy together in the same Spring Starter project, a few changes can be made to the project's properties and paths. By default, when a Java project is created it only looks for source files and test files in the src/main/java and src/test/java directories.

Add src/main/groovy to Java Build Path


  1. Create the src/main/groovy directory
  2. Right-click the project in Package Explorer, then click Properties
  3. Click Java Build Path in the left sidebar
  4. Click Add Folder... to add src/main/groovy


Add Groovy libraries to classpath


  1. Right-click the project in Package Explorer
  2. Expand Groovy, then click Add Groovy libraries to classpath


Only include groovy-all


At this point, trying to run the Spring Boot app will generate errors that look like this.

...
org.apache.catalina.core.ContainerBase : A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]
...


The errors can be resolved by removing the extra libraries STS automatically added in the previous step.
  1. Right-click Groovy Libraries in the project
  2. Click Properties
  3. Select "No, only include groovy-all" in the first panel that asks, "Should all jars in the groovy-eclipse lib folder be included on the classpath?"

Monday, May 9, 2016

Mix Groovy and Java in IntellJ IDEA

To mix Java and Groovy together in the same IntelliJ IDEA project, a simple change can be made to the project's .iml file. By default, when the project is created it only looks for source files and test files in the src/main/java directory.
By adding two sourceFolder elements IntellJ will automatically find and compile .groovy files in the Groovy directory.

Wednesday, May 4, 2016

Go to Assembla Ticket

Here's a simple JS code that can be converted into a bookmarklet to quickly open an Assembla ticket.

Saturday, April 30, 2016

HTTP/REST API Specifications

Now that I have the pleasure of designing new APIs to support both B2C and B2B use cases, my first thought is to standardize. In the case of APIs, I believe standards reduce the burden of maintenance and improve the ease of integration.

To that end, I sought to define guidelines for all operations. These are not new or novel, but I need these to set shared expectations with my team. And we start with a few core principles:

  1. Follow REST conventions for CRUD operations
  2. Use JSON in all request and response bodies (Content-Type: application/json)...
  3. Except where binary content is involved (Content-Type: multipart/form-data)

REST conventions


Striving to KISS:

Error response body


Success responses will contain appropriate data for the request, but all error response bodies look alike. At least structurally, having only one field.

  • Array<Error> errors - An array of any errors encountered while executing the operation. This field is always present for an error state (any non-200 HTTP status).


Each errors element has the following fields:

  • int code - "for programmatic consumption" (ref Braintree)
  • String message - "for human consumption" (ref Braintree)
  • String component - Whatever we're blaming for the error