Custom marshalling with Gson - part 1

Today, I’ll extend our project to add temporary storage of uploaded users in a HashMap<String,User> and allow retrieval of that HashMap as json. First, the new UserMap class. This class will be needed to register custom marshalling.

1
2
3
4
5
6
7
package com.ideoplex.tutorial;
import java.util.concurrent.ConcurrentHashMap;
public class UserMap extends ConcurrentHashMap<String,User> {
}

And three changes to the MyResource class. First, a static UserMap member to store the uploaded users. Second, a new getUserMap method to return the static member. And finally, an update to the postUser method to throw a WebApplicationException when uploading a duplicate email address and add the user to the static UserMap otherwise.

Read More

Jersey and Gson

Now that I have the project legwork out of the way, I can add Gson support to our web application. Our first step is adding gson as a project dependency. This will direct maven to include gson and its dependencies in the project.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ git diff
diff --git a/pom.xml b/pom.xml
index 0fe5b04..eedf81b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -70,6 +70,11 @@
<artifactId>jersey-media-moxy</artifactId>
</dependency>
-->
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.3</version>
+ </dependency>
</dependencies>
<properties>
<jersey.version>2.12</jersey.version>

Next, I’ll pull in some code from REST with Java in practice by Lars Michael. These two classes implement the javax.ws.rs.ext.MesssageBodyWriter and javax.ws.rs.ext.MessageBodyReader interfaces necessary to marshall objects to and from json. The @Provider annotation allows JAX-RS autodiscovery to automatically find and install our classes. First, the GsonWriter class:

Read More

Deploy to Tomcat with maven

Previously, I used maven to generate and package a jersey webapp. Today, I’ll extend our project to deploy the war file to Tomcat. This basically amounts to configuring Tomcat to accept connections from maven and configuring maven to use a specific Tomcat instance.

For our sample project, I’ll use a Tomcat instance on Nitrous.io. If you’re also using Nitrous, then you’ll probably need to start by installing tomcat on your instance:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ parts install tomcat
=> Extracting archive...
=> Installing...
=> Activating...
=> Installed tomcat 7.0.53
To start the Apache Tomcat server:
$ parts start tomcat
To stop the Apache Tomcat server:
$ parts stop tomcat
Apache Tomcat config is located at:
$ /home/action/.parts/packages/tomcat/7.0.53/conf
Default webapps at:
$ /home/action/.parts/packages/tomcat/7.0.53/webapps
Default port: 8080

Read More

Getting started with Maven

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project’s build, reporting and documentation from a central piece of information.

Ask ten developers about maven and you’ll probably get eleven opinions. The more experienced developers are apt to be on their 3rd or 4th opinion. My opinion of maven is similar to Churchill’s opinion of democracy:

democracy is the worst form of Government except for all those other forms that have been tried …

Churchill

Maven does everything — it will generate a template, download dependencies, build the project, run the tests and deploy the project. Let’s see how easy it is to build a jersey web application with maven.

Read More

AgileBits +1

Back last year after 1Password 4 for Mac was released we had an absolutely massive number of users who had emailed in with questions and it took us months to claw our way out of that. Unfortunately, you were one of the people we hadn’t been able to reply to. As an apology for that missed opportunity of ours to make you happy I just sent you a free copy of 1Password 4 for Windows and Mac

Kyle SwankAgilebits

The goal of any company is to keep their good customers loyal. It’s pretty clear that I’m a good customer (1Password, 1Password Pro, 1Password Family Upgrade, 1Password for Windows Family, 1Password 4 IOS, 1Password 4 Mac). And this is how AgileBits locks in my loyalty.

They didn’t need to gift me new licenses. But it’s nice to feel to feel appreciated.

Blogkeeping Update

For my readers in RSS-land, I’ve made some updates to the presentation here at Take the First Step.

Back to Landscape

I’ve returned to the default theme, landscape. I left because it took 27 minutes to generate the site. A little investigation led to the recent_posts widget as the guilty party — it was sorting the complete list of articles for every page. I removed the widget and generation time is under a minute.

This has also allowed me to change the format of my archive, category and tag pages from full text with pagination to date and title with no pagination. I think that it’s a lot easier skim over when you aren’t limited to 10 full text posts per page.

Theme Customization

I’ve made some changes to the underlying theme. The widgets now use theme properties to hide article counts and to change the archive list from monthly to annually. I also updated the CSS to use horizontal lists when displaying a bottom-bar rather than a sidebar.

I’m currently displaying the archive widget with annual links at the bottom of each page.

Theme in Github

Finally, I’m maintaining my theme in Github. This should make it easier for me to keep my theme up to date and allow me to make a pull request when I’m happy with my changes.

Net Neutrality +1

I’m not a believer in slippery slopes. But I’m going to make an exception today. Giving internet providers the right to sell preferential access to their users is a start of a slippery slope.

That’s why I’m joining the Internet Slowdown. Visitors to this weblog will see a symbolic “loading” icon to remind everyone what an internet without net neutrality would look like. If you allow cookies, then you will only see this once.

Healthcare Cheatsheets

The ideoplex household visited the emergency room last month. Healthcare costs are supposed to come down with the new high deductible health plans - we’re supposed to do a better job of comparison shopping once we have skin in the game. Based upon our experience, I think people are going to need some help.

The emergency room is the worst possible place for comparison shopping. You’re already under stress. You ping-pong between waiting to hear from the doctors and trying to understand what the doctors are talking about. It wasn’t easy to stay in-network, much less think about comparison shopping. We had access to wifi, but just about all the pages had disclaimers that you needed to confirm network coverage. And of course, I had go outside to get decent cell coverage.

I’m a believer in cheatsheets and checklists. Do standard thinking in advance, so you can focus on what’s actually different. I would think that there is money to be made by:

  1. Keeping insurance network listings up to date. So you didn’t have to call to confirm that a doctor was still in network.
  2. Keeping track of the on call specialists at hospital emergency rooms and what insurance networks they belonged to.
  3. Providing checklists of what questions to ask for various types of visits. Because most of us will only need to know this once.

Parking Page on Cloud Storage

Now that I’m using Google Domains, I thought that it only appropriate to have my parking page on Google Cloud Storage. It turned out to be pretty easy.

  1. Create a Google Cloud Storage bucket with your desired website name. You may need to prove that you control the domain before creating the bucket. In my case, Google knew that because they were the registrar.
  2. Build your static parking page. I started with the Grayscale template from Start Bootstrap and made my changes.
  3. Copy the static content up to Google Cloud Storage.
    1
    2
    3
    4
    gsutil cp -a public-read -R * gs://www.dwightshih.com
    # -a public-read gives the requester OWNER permission
    # and all other users READ permission
    # -R for recursive copy
  4. Update the bucket configuration to serve index.html when a bucket listing is requested via the CNAME alias.
    1
    2
    gsutil web set -m index.html gs://www.dwightshih.com
    # use -e <404.html> to specify an error page
  5. Update your DNS CNAME alias to c.storage.googleapis.com:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    $ dig www.dwightshih.com
    ; <<>> DiG 9.8.3-P1 <<>> www.dwightshih.com
    ;; global options: +cmd
    ;; Got answer:
    ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28866
    ;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0
    ;; QUESTION SECTION:
    ;www.dwightshih.com. IN A
    ;; ANSWER SECTION:
    www.dwightshih.com. 3600 IN CNAME c.storage.googleapis.com.
    c.storage.googleapis.com. 1055 IN CNAME storage.l.googleusercontent.com.
    storage.l.googleusercontent.com. 229 IN A 64.233.171.128
    ;; Query time: 58 msec
    ;; SERVER: 10.0.1.1#53(10.0.1.1)
    ;; WHEN: Mon Sep 1 16:48:08 2014
    ;; MSG SIZE rcvd: 129

And voilà, your static page should be up.