TIL #5: Representing Response Object in REST API

I was thinking what is the best way to represent response object in REST API. So, I started thinking about all the things response object should provide to work effectively. Below is the list of things I want my response object to have:

  1. A single object structure to handle both successful and error scenarios
  2. Ability to handle multiple types of objects
  3. Ability to easily figure out if request failed or succeeded
  4. Store the error code and error message

The code in this post uses Java as the language of choice. As I use Spring Boot to build REST APIs so Jackson is the default JSON serialisation library.

The code below shows the ApiResponse object that captures both the success and error payload.

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;

public final class ApiResponse<T> {

    private ErrorResponse error;
    private T data;
    private Status status;

    private ApiResponse(Status status, ErrorResponse error) {
        this.error = error;
        this.status = status;
    }

    private ApiResponse(Status status, T data) {
        this.data = data;
        this.status = status;
    }

    @JsonCreator
    public static <T> ApiResponse<T> success(
            @JsonProperty("status") Status status,
            @JsonProperty("data") T data) {
        return new ApiResponse<>(status, data);
    }

    @JsonCreator
    public static <T> ApiResponse<T> error(
            @JsonProperty("status") Status status,
            @JsonProperty("error") ErrorResponse error) {
        return new ApiResponse<>(status, error);
    }

    public enum Status {
        SUCCESS("success"), ERROR("error");

        private final String status;

        Status(String status) {
            this.status = status;
        }

        @JsonValue
        public String getStatus() {
            return this.status;
        }
    }

    public ErrorResponse getError() {
        return this.error;
    }

    public T getData() {
        return this.data;
    }

    public Status getStatus() {
        return this.status;
    }
}

The key points in the class shown above are:

  1. Status enum will hold the status of the request. User can just look at this request to figure out whether request succeeded or failed.
  2. The class is generic so it can be used to store any type of object in the data.
  3. User can get more details about the error from the error object.

The ErrorResponse class is shown below.

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public final class ErrorResponse {
    public final String code;
    public final String message;

    @JsonCreator
    public ErrorResponse(
            @JsonProperty("code") String code,
            @JsonProperty("message") String message) {
        this.code = code;
        this.message = message;
    }
}

The ErrorResponse class has two fields code and message. The code can be HTTP code or any business specific code. The message variable gives details about the error.

I found the above response classes work great for the REST APIs that I recently built.

Example of successful response is shown below.

{
    "status": "success",
    "data": {
        "task": "Write a post",
        "taskStatus":"in_progress",
        "tags":["writing"]
    }
}

Example of failure response is show below.

{
    "status": "error",
    "error": {
        "code" "409",
         "message" : "User with username xyz already exists"
    }
}

One thing that you should ensure is that your JSON serialisation library exclude null values. For example, in case of error scenario you don’t want data field to be null. If you are using Spring Boot, you can instruct Jackson to exclude null fields by specifying a property shown below.

spring.jackson.default-property-inclusion=NON_NULL

If you are using Java 8 or Google’s Gauva and want to exclude Optional type as well then you should use NON_ABSENT value.

spring.jackson.default-property-inclusion=NON_ABSENT

TIL #4: Downloading a zip from S3 to local directory using AWS CLI

Today, I had a need to download a zip file from S3 . I quickly learnt that AWS CLI can do the job. The AWS CLI has aws s3 cp command that can be used to download a zip file from Amazon S3 to local directory as shown below.

 $ aws s3 cp s3://my_bucket/myzip.zip ./

If you want to download all files from a S3 bucket recursively then you can use the following command

$ aws s3 cp s3://my_bucket/  ./ -- recursive

You can specify your AWS profile using the profile option shown below.

$ aws s3 cp s3://my_bucket/myzip.zip ./ -- profile test

To download all the files from a folder you can use following command:

$ aws s3 cp s3://my_bucket/my_folder  ./ -- recursive

You can also use include and exclude options to filter files based on wildcards. For example, let’s suppose you only want to download files with zip extension from a S3 bucket my_bucket then you can use the following command.

$ aws s3 cp s3://pcl-caps ./ --recursive --exclude "*" --include "*.zip"

There is another great option dryrun that you can use to see the actions that will be performed without running the command. In the above command, if we add —dryrun flag then we can see which all files will be downloaded to local directory.

$ aws s3 cp s3://pcl-caps ./ --recursive --exclude "*" --include "*.zip" --dryrun

Issue #5: 10 Reads, A Handcrafted Weekly Newsletter for Humans

Welcome to the fifth  issue of 10 Reads weekly newsletter. Below are the 10 posts that I found good to read this week. Total time to read this newsletter is 145 minutes.

The only true wisdom is in knowing you know nothing – Socrates

  1. Stack Overflow Isn’t Very Welcoming. It’s Time for That to Change. : 10 mins read: Stack Overflow has realized that new users are not finding it welcoming so they are taking steps to improve it. I think for me the bigger lesson is that when an organization like Stack Overflow can work towards recognising mistakes and work on fixing them why can’t other companies do the same. In most oragnizations,  senior management try to hide problems under the carpet never recognising their wrong doings. I am not expecting organisations to go public with their problems but instead their should be open communication.
  2. Is There A Fix For Impostor Syndrome15 mins read. Reading this post I realized I also suffer from impostor syndrome. The post author describes 5 kinds of impostor and their behaviour that she learnt from book The Secret Thoughts of Successful Women: Why People Suffer from Impostor Syndrome and How to Thrive Inspite of it.
    1. The Expert: This manifests as a state of cringing denial when called an expert.
    2. The Perfectionist: Perfectionism underlies a feeling that one could have (and should have) done better.
    3. The Superwoman/man: Some people can’t stop working, taking on every task they can. Young argues that this kind of workaholism is the expression of a need for external validation and can be countered only by focusing on setting one’s own metrics for personal success.
    4. The Natural Genius: This behavior involves judging one’s worth on the basis of raw ability as opposed to effort.
    5. The Rugged Individualist: Rugged individualism demands that all tasks be performed alone, and little to no help is sought.
  3. How To Get Your Coworker To Agree With You : 30 mins read. This is not a long read but I spent a lot of time thinking about times when I behaved arrogantly and tried to force people to think my way. Many times it just doesn’t work. The key points for me in this post are:
    1. If you say someone that they are wrong, they will become defensive straightaway and try hard to prove why their decision is correct. It does not matter if your intentions were good other person will not be able to see the point. The author suggests that we should avoid arguments at all cost. In one of the books that I read recently, author suggests The only way to get best of an argument is to avoid it.
    2. Before you expect others to listen to you build a strong relationship and trust. People will only listen if they consider you worth listening to. There is no magic solution here. You have to work hard on yourself before you can expect people to agree with you.
    3. Don’t force your decisions on others. Give them options & let them choose the best based on their expertise.
    4. Don’t distrust expertise of your coworkers. The wisest people are the ones who always empty their cups.
  4. Tips for High Availability by Netflix15 mins  read. In this post, Netflix engineers share how they are able to keep their services up. Netflix has built a continuous integration and delivery tool called Spinnaker that imbibes all the best practices Netflix engineers have learnt over the year. Some of the best practices that we can use to make our systems highly available are:
    1. Prefer regional deploys over global deploys
    2. Use Red/Black deployment strategy  for production deploys
    3. Use deployment windows
    4. Enable Chaos Monkey
    5. Know how to roll back your deploy quickly
  5. Why Our Brains Fall for False Expertise, and How to Stop It 30 mins read. If the people who offer the most valuable contributions to your organization aren’t appropriately recognized for it, they won’t stay long. Or, possibly worse, they will stay and stop trying.
  6. Rust in production at Figma : 10 mins read. The author mentions a lot of compelling reasons why people should consider Rust for writing performance sensitive back-ends. The main benefits of Rust are Low memory usage, Awesome performance, and Solid toolchain. Rust is new so there are rough edges as well. Read the post to learn about the pros and cons of using Rust.
  7. Bitcoin is the greatest scam in history :10 mins read: I am glad someone finally put it. Every other day I hear people talking about Bitcoin and BlockChain without understanding what they are getting into. Cryptocurrency is a scam because:
    1. Bitcoins are accepted almost nowhere, and some cryptocurrencies nowhere at all. Even where accepted, a currency whose value can swing 10 percent or more in a single day is useless as a means of payment.
    2. Extreme price volatility also makes bitcoin undesirable as a store of value. And the storehouses — the cryptocurrency trading exchanges — are far less reliable and trustworthy than ordinary banks and brokers.
    3. A bitcoin has no intrinsic value. It only has value if people think other people will buy it for a higher price — the Greater Fool theory.
  8. PostgreSQL 11 will finally have procedures5 mins read. Many people have asked for this feature for years and PostgreSQL 11 will finally have it. I am of course talking about CREATE PROCEDURE. Traditionally PostgreSQL has provided all the means to write functions (which were often simply called “stored procedures”). However, in a function you cannot really run transactions – all you can do is to use exceptions, which are basically savepoints. Inside a function you cannot just commit a transaction or open a new one. CREATE PROCEDURE will change all that and provide you with the means to run transactions in procedural code.
  9. pg_wal is too big… what’s going on?15 mins read. Here are two ways to go about it: the first – is to take an emergency action, this is the last resort when there is only 2% or less of free disc space, lack of time to find the cause of the problem and the main goal of your actions is to avoid the risk of the database crash halt. The second – is set of actions directed to find out the cause of the space consumption – something you can only do when there is no risk of the database’s emergency stop.
  10. Keep The Degree Of Difficulty Down5 mins read: So the better approach is to pick something simple to execute, nail it, then build on it with another relatively simple move, nail that too, and keep going.

TIL #3: Exclude null fields in Spring Boot REST JSON API, Serializing Enum value with Jackson, and Change remote for a branch in Git

The three things that I learned today are mentioned below.

Learning 1: Exclude null fields in Spring Boot REST JSON API response

Spring Boot uses Jackson to convert to JSON. Spring Boot allows you to configure through a configuration property whether you want to include null values or not. By default, serialised JSON will include null values as well. To remove null values, you should use following property add it to your application.properties.

spring.jackson.default-property-inclusion=NON_NULL

If you are using Java 8 or Google’s Gauva and want to exclude Optional type as well then you should use NON_ABSENT value.

spring.jackson.default-property-inclusion=NON_ABSENT

To learn about all the values, you should look at Jackson’s com.fasterxml.jackson.annotation.JsonInclude.Include enumeration.

Learning 2: Serializing Enum value with Jackson

The second learning that I had today was around how to properly serialize enum values in Jackson. I had enum shown below

public enum Status {
    SUCCESS("success"), ERROR("error");

    private final String status;

    Status(String status) {
        this.status = status;
    }
}

I wanted my JSON structure to be as shown below.

{
  "status": "success"
}

To achieve that you have to Jackson’s @JsonCreator and @JsonValue annotation as shown below.

public enum Status {
    SUCCESS("success"), ERROR("error");

    private final String status;

    @JsonCreator
    Status(String status) {
        this.status = status;
    }

    @JsonValue
    public String getStatus() {
        return this.status;
    }
}

Learning 3: Change remote of a branch in Git

$ git branch develop --set-upstream-to=upstream/develop

You can view remote tracked by local branch using the following command.

$ git branch -lvv

Issue 4: 10 Reads, A Handcrafted Weekly Newsletter for Humans

Welcome to the fourth  issue of 10 Reads weekly newsletter. Below are the 10 posts that taught me something useful and unique that will help me become better software engineer. Total time to read this newsletter is 190 minutes. Continue reading “Issue 4: 10 Reads, A Handcrafted Weekly Newsletter for Humans”

20 Lessons Learned from Reading Rework Book

A couple of weeks back I re-read Rework book by Jason Fried and David Heinemeier Hansson. Following are the twenty lessons that I learned:

  1. Meetings are toxic. Either schedule meeting for 15 mins or 2 hours. The default duration of 1 hour is not the right duration for most meetings.

  2. Say no to feature requests. Keep your product minimal and coherent. This way you can build a product that is more useful for the client. Creativity is subtraction.
  3. Look at by-products of your work. Blogging, books, other ideas form from your base work. Don’t miss this opportunity. When you make something , you always make something else
  4. Hire a better writer. If you have to choose between two programmers then choose the one who is a better writer. Writing requires you to explain things clearly. A good writer knows the important of good communication.
  5. Embrace laziness. Wait till the right appropriate moment before building a feature.
  6. Learning from mistake is overrated. Build the smallest possible thing that is successful and then iterate on it. Success is the experience that actually counts.
  7. Small is not just a stepping-stone. Small is a great destination in itself. The best way to build things is Do things that don’t scale. Sometime small is the right size.
  8. Start making something. What you do is what matters, not what you think or say or plan.

  9. Embrace constraints. Constraints are advantages in disguise. Limited resources force you to make do with what you’ve got. There’s no room for waste. And that forces you to be creative.
  10. Start at the epicentre
  11. Ignore the details early on. The reason: Detail just don’t buy you anything in the early stages. Besides, you often can’t recognise the details that matter most unit after you start building. That’s when you see what needs more attention. You feel what’s missing. And that’s when you need to pay attention, not sooner. This is the reason I feel discovery sprints are useless. They give an illusion to client that you can magically figure out everything in 2 week without building stuff. The real questions arise once you start building. This is when you can validate your assumptions, clarify doubts, reason along, and try different approaches.
  12. Be a curator. There’s a lot of stuff off the walls than on the wall. The best is a sub-sub-subset of all the possibilities. Don’t be a hoarder. Be a collector. Creativity is subtraction.
  13. Focus on what won’t change
  14. Don’t get obsessed over tools. The content is what matters.
  15. Sleep 8 hours daily
  16. Say no by default. Customer is not always right.
  17. Don’t confuse enthusiasm with priority.
  18. Learn to say Sorry.
  19. If everything is high priority then nothing is high priority.
  20. Inspiration is perishable.

TIL #2 | IntelliJ Copy Constructor Refactoring

I wanted to learn what I wanted to know, but they wanted me to learn for the exam — Albert Einstein

Today, I spent most of my day in meetings, thinking, and preparing backlog so I couldn’t do much code.

Learning 1: IntelliJ Copy Constructor

Today, I was reviewing a piece of code where we had to create an object with 30 fields. The code had a constructor with 30 fields and then in the calling code we were passing those 30 fields. How error prone and tiring is this? A simple example is shown below.
Continue reading “TIL #2 | IntelliJ Copy Constructor Refactoring”

TIL #1 | PostgreSQL Gzip Dump, Docker-Compose, Change owner of PostgreSQL tables, and finding non-ascii characters in IntelliJ

Each day I learn something new while doing software development. From today, I have started documenting them. I will be posting/sharing tips and tricks that I discover.

Continue reading “TIL #1 | PostgreSQL Gzip Dump, Docker-Compose, Change owner of PostgreSQL tables, and finding non-ascii characters in IntelliJ”