Adventures with Docker

At work, we make heavy use of Docker containers for local development and I figured I should apply those learnings into my personal projects. I will say that this would be slightly harder if I didn’t have a reference project (i.e. work project setup) to reference.

My project is a Spring Boot Java application and requires a Postgresql database. Here’s how I built it up piece by piece:

  1. I started out learning to ‘dockerize’ the Java web service which is pretty straightforward (my sample Dockerfile which has links to sites that I referenced). With your Dockerfile, you can generate the image using the standard docker commands (docker build -t org/yourapp:latest .). However, I wanted to get more comfortable with gradle so I used the Transmode gradle plugin. This allows me to generate my image using a simple gradle task (my sample gradlew $dockerImageBuildTaskName).
  2. Then, I learned to configure the postgresql container (already present on the DockerHub registry) i.e. changing the port, setting my user/password, etc.
  3. Once I was able to individually build each image, I saw the need for ‘orchestrating’ the setup of the server + db which led me to docker-compose (my sample docker-compose file). Using this configuration-based approach takes the headache out of I’m also making use of env files since my application takes in api secrets and the like (aside, do NOT commit items like these to git. I have these env files located outside of my application folder and I use relative paths to access them)
  4. Dockerhub allows you to create a free repository to hold images and pushing your image is a straightforward two-step process: docker tag local-image:tagname reponame:tagname and docker push reponame:tagname. You can create your docker-compose file in a way that your image gets built every time you do ‘docker-compose up’ but I opted to separate out the build process from the startup.

Overall, I’m pretty pleased with my progress so far. I’m certain I haven’t followed all the best practices regarding Docker container configurations but that’s on my Trello to-do list!

Useful links:

  1. https://github.com/docker/labs/tree/master/developer-tools
  2. https://spring.io/guides/gs/spring-boot-docker/
  3. https://thepracticaldeveloper.com/2017/12/11/dockerize-spring-boot/#Dockerizing_Spring_Boot_or_any_executable_jar_file
  4. https://github.com/Transmode/gradle-docker
  5. https://docs.docker.com/get-started/
Advertisements

Signature calculation for AWS

I recently learned about ElasticSearch as a means of adding search to my android app which uses Firebase. From the android app, I am issuing a HTTP request (super easy thanks to Retrofit) to AWS ElasticSearch but this request has to be authenticated.

Amazon has some detailed documents on how to do this yourself but I’m waving the white flag after spending 3+ hrs debugging a mismatch between the signature I generated and what Amazon generated.

So, I’ll save you the trouble and share actual source code from Amazon that worked for me.

  1. http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-examples-using-sdks.html
  2. Source code showing a signed POST request: https://s3.amazonaws.com/aws-java-sdk/samples/AWSS3SigV4JavaSamples.jar. ‘Unzip’ this jar file if you have 7-zip. Otherwise, use the “jar xvf $file.jar” command
  3. The classes in the ‘auth’ & ‘util’ folders contain the classes of interest so copy them over to your project.
  4. A ‘runnable’ class you can inspect is PutS3ObjectSample.java which shows how it’s all put together.

Links

Did you know Let’s Encrypt offers free SSL certificates *and* hosting providers like DreamHost will assist you in ssl-ifying your websites?

If you’re collecting any sort of user sign up information, Google requires your form to be behind an SSL backed site. I’ve been getting warning emails from Google due to some relatively ancient personal projects I’ve done and I decided to bite the bullet and go through the process. So far, I’ve gone as far as simply ordering the free SSL cert via Dreamhost. Once I’ve properly setup my domains, the next step would be using .htacess to get all pages to load with https. *crossing fingers*

In my next post, I’d like to muse about passion projects and when to put things to pasture. 🙂

Binding a KendoUI ComboBox to a remote datasource

In .NET land, you can use WCF or Web API for making a web service. I went with WCF because it was “what I ‘knew’ but I will be experimenting with Web API just to become more knowledgeable. The biggest pain in the butt with WCF is figuring out the right items to put into the web.config file! It didn’t help matters that I wanted a REST-like setup which isn’t how WCF is set up to do out of the box. After a lot of trial and error, I got it working. Here’s how.

The Web Service Setup:

  • Add a WCF Service Application to your Visual Studio solution. My Visual Studio solution contains 3 projects: main .NET app, one project for unit testing, and the 3rd was the service application.
    • Add all necessary references to this new project. In my case, I had to add my .NET app’s DLL as a reference since I was making use of classes referenced there.
    • I also had to re-add System.Data.Entity to this new project but YMMV. Read the error output when you compile the new project and act accordingly.
    • If you added a WCF Service Library instead of a WCF Service application, you *might* need to change the project’s properties to make sure the target framework is set to (in my case) .NET 4.0 instead of the default .NET Client Profile.
  • If you want to be able to invoke your URLs via the browser (HTTP), you’ll have to make some changes to your interface & implementing class.
    • Add [WebGet] or [WebInvoke] decorations to your service implementation. I went with [WebInvoke] for flexibility.
    • Implement your interface and add the [WebInvoke] property as well but specify some additional attributes. Here’s what mine looked like: [WebInvoke(UrlTemplate = “Users/{id}”, Method=”Get”,ResponseFormat=WebMessageFormat.Json,BodyStyle = WebMessageBody.Bare)]
      • UriTemplate – allows you to specify the URL to invoke your method! So, I could do something like http://serviceUrl/Users/1. Make sure that the value inside the curly braces matches the parameter name exactly.
      • Method – I went with GET since I was primarily just retrieving data FROM the service. You can specify other types there e.g. “POST”, etc.
      • ResponseFormat – I went with JSON for flexibility. The only other option is XML.
      • BodyStyle – I went with bare becayse I wanted the returned data to be returned as-is.
    • Please note if you are expecting to pass parameters to your methods which will be invoked via HTTP, you will need to make those parameters of the string type. If you don’t, you’ll get an exception message. If you get this message,it’s actually a good sign that you’re on the right path! It was for me, anyway. 🙂
    • Open up your WCF Service Application’s web.config file and make the following changes
      • Create an <endpointBehaviors> tag like this: <endpointBehaviors><behavior name=”blah”><webHttp/></endpointBehaviors>and stick that into the <system.serviceModel> tag.
      • Inside the <system.serviceModel> tag, create a <services> tag like this: <services></services>
      • Inside the <services> tag, create a <service> tag like this: <service name=”NameSpace.ImplementingClassName” behaviorConfiguration=”MyServiceBehavior”></service> where ImplementingClassName means exactly that: the name of the class that implements your interface.
      • Inside the <service> tag, create an <endpoint> tag like this:<endpoint address=”” binding=”webHttpBinding” behaviorConfiguration=”blah” contract=”NameSpace.InterfaceName” /> where InterfaceName means exactly that: the name of the interface.
      • Make sure the <endpoint> behaviorConfiguration value matches the behavior name value put into the <endpointBehaviors> tag.
      • Inside the <serviceBehaviors> tag, add a “name” attribute to the <behavior> tag and make sure the value matches the behaviorConfiguration value specified in the <service> tag.
      • If you’re connecting to some DB, don’t forget to add your connection string inside the <configuration> tag.
      • At this point, you probably want to launch the service to give it a whirl. You should open up the service in a browser and be able to invoke your methods following the UriTemplate you specified.
    • I really hope my word salad makes sense. I will attempt to put up the web.config file so you can see what it looks like. Of course, you’re free to tell me how much I suck as writing tutorials as well. This is really more of a loosey goosey guide for my benefit mostly. 🙂

If you’ve come this far, you have a working service which you should test out by doing something like this: http://localhost:YYY/MyService.svc/Users/1 and since you specified the output of that method to be JSON, you should get a valid json response. You can verify the validity by pasting the output into JSONlint.com. Note that IE will try to download a file since it can’t display it. Use Firefox or Chrome to see the output directly in the browser.

The KendoUI ComboBox Setup:

Once I confirmed my web service was returning the correct data,I felt confident moving to this part of the problem. I’ve been used to working with the MVC wrappers for KendoUI widgets so there was a bit of a learning curve switching to the HTML/JS version. After much trial and error, I figured out the exact incantation which allowed me to use my remote datasource.

So, if you have a KendoUI combobox that needs a remote datasource and your remote datasource returns JSON, then your datasSource declaration should like similar to this:

dataSource: {
    type:"jsonp",
    transport:{
        read:{
            url: "http://serviceUrl/Service.svc/Users/All"
        }
    },
    error:function(e){
        console.log(e)
    }
}

Hope this helps someone.

Code quality

This developer’s work is never ‘done’. Despite sending off my project into Phase 1 of pilot testing, I am constantly worried that some showstopper will be discovered. To that end, I’ve taken it upon myself to test as much as I can; which is learned behavior from my coursework. I always worry about efficiency and as new features are added, I am making a conscious effort to not repeat myself and redactor where it makes sense.

As a relatively new C# developer, I’m constantly learning new ways of doing things. I recently got ReSharper installed on my workstation and I’ve already seen changes to how I code. In fact, thanks to ReSharper’s comforting presence, I was able to refactor some awful code I’d written in way less time. 🙂

Not sure where I was going with this lost but TL:DR –
(a) test, test, test your code.
(b) there’s always a better mousetrap. Replace yours if it makes sense to do so.