Skip to content

Latest commit

 

History

History
457 lines (383 loc) · 10.4 KB

README.adoc

File metadata and controls

457 lines (383 loc) · 10.4 KB

Shopping list backend

Introduction

This document describes a system which allows users to manage shopping lists on their mobile phone. The system has the two main parts - the mobile application (frontend) and server (backend). According to the code challenge task this project implements only server-backend.

Prerequisites

To compile and run this project you need any operating system with bash interpreter or Windows 2000 or newest. Also you need Oracle JDK or OpenJDK version 8.

How to build

In the project folder type the following command:

Windows:

shopping-list> mvnw.cmd clean install

Linux / MacOS:

$ ./mvnv clean install

How to run

In the project folder type the following command:

For all operating systems:

java -jar ./target/shopping-list*.jar

System design description

Use cases

The backend solution enables mobile app to synchronize lists and its items across devices and accounts. The system can be in use cases shown on the diagram:

use cases

User registration

The process of user registration is shown on the following diagram:

user registration

Invite a friend

The friend invitation process is shown on this diagram:

invite collaborator

Add new shopping list

Look at the next diagram to see how the adding new list process is happening:

add new list

Edit existing shopping lists

The next diagram shows how users edit shopping lists and how the system helps to resolve conflicts:

edit list

Implementation

Tools

This project written in Java 8 and uses and the following tools:

  • Spring Boot - provides the ability to create uber-jar, all-in-one file

  • Spring Data JPA - a convenient way to operate data

  • Hibernate - the ORM engine

  • Spring security - to protect private user date from unauthorized access

  • Jersey - JAX-RS implementation for creating RESTful services

  • H2 - SQL-compatible in-memory database

  • HikariCP - a connection pool for optimal database connections using

  • Junit - testing framework

  • Lombok - a library to reduce boilerplate code

  • Maven - a compile tool

Project structure

The project contains following packages:

  • entities - contains entities that are serialized to json structures

  • exceptions - contains specific exceptions

  • repository - contains interfaces to manage data in database

  • rest - contains /lists and /users (not implemented in current version) endpoint with data-classes and jersey config

  • security - security config classes

  • services - contains the application main logic to process users (not implemented in current version), shopping lists, and list items.

The file application.properties contains app settings.

The test folder contains tests for all implemented in the main code use cases.

data.sql contains test data imported into database on tests start.

Network interface

The backend solution built as RESTful web-service and has the following endpoints:

  • /users - used for manage users (not implemented in current version)

  • /lists - used for manage shopping lists

    • GET /lists - returns all lists with items for an authorized user and 200 "ok" response code.

    • GET /list/{id} - returns specific list with items by given id. Returns 200 "ok" response code in case of success or 404 not found if the list doesn’t exist or doesn’t belong to the authorized user.

    • POST /list- stores a new list with items. Returns 200 "ok" response code and URL to the new list in case of success. If the list is not correct, returns 400 "bad request" response code. Doesn’t return a body.

    • POST /list/{id} - replaces an existing list with given id by modified one. Returns response code 200 "ok" if no errors or 400 "bad request" if incoming data is not correct. Returns 404 not found if the list doesn’t exist or doesn’t belong to the authorized user. In the body returns information about conflicts if they were happening.

    • DELETE /list/{id} - removes a shopping list with given id from the database. Returns 200 "ok" if success or 404 not found if the list doesn’t exist or doesn’t belong to the authorized user. Response has no body.

Commands to the server

Get all user’s shopping lists

Method: GET

URI: /lists/

Request body: <ignored>

Response body example:

[
  {
    "id": 1,
    "name": "CPUs",
    "description": "Processors for servers #1, #6, #11",
    "owner": {
      "id": 1,
      "login": "mark.johnson@yahoo.com",
      "name": "Mark Johnson"
    },
    "listItems": [
      {
        "id": 1,
        "version": 0,
        "name": "Core i5",
        "description": "CPU Intel Core i5",
        "checked": true,
        "quantity": 2,
        "isDeleted": false,
        "author": {
          "id": 1,
          "login": "mark.johnson@yahoo.com",
          "name": "Mark Johnson"
        },
        "device": {
          "id": 1,
          "name": "Samsung Galaxy S8"
        }
      },
      {
        "id": 2,
        "version": 0,
        "name": "Core i7",
        "description": "CPU Intel Core i7",
        "checked": true,
        "quantity": 1,
        "isDeleted": false,
        "author": {
          "id": 1,
          "login": "mark.johnson@yahoo.com",
          "name": "Mark Johnson"
        },
        "device": {
          "id": 1,
          "name": "Samsung Galaxy S8"
        }
      }
    ]
  },
  {
    "id": 5,
    "name": "RAMs",
    "description": "Memory for servers",
    "owner": {
      "id": 1,
      "login": "mark.johnson@yahoo.com",
      "name": "Mark Johnson"
    },
    "listItems": []
  }
]
Get specific shopping list

Method: GET

URI example: /lists/1

Basic authorization: Required

Request body: <ignored>

Response body example:

{
  "id": 1,
  "name": "CPUs",
  "description": "Processors for servers #1, #6, #11",
  "owner": {
    "id": 1,
    "login": "mark.johnson@yahoo.com",
    "name": "Mark Johnson"
  },
  "listItems": [
    {
      "id": 1,
      "version": 0,
      "name": "Core i5",
      "description": "CPU Intel Core i5",
      "checked": true,
      "quantity": 2,
      "isDeleted": false,
      "author": {
        "id": 1,
        "login": "mark.johnson@yahoo.com",
        "name": "Mark Johnson"
      },
      "device": {
        "id": 1,
        "name": "Samsung Galaxy S8"
      }
    },
    {
      "id": 2,
      "version": 0,
      "name": "Core i7",
      "description": "CPU Intel Core i7",
      "checked": true,
      "quantity": 1,
      "author": {
        "id": 1,
        "login": "mark.johnson@yahoo.com",
        "name": "Mark Johnson"
      },
      "device": {
        "id": 1,
        "name": "Samsung Galaxy S8"
      }
    }
  ]
}
Store new shopping list

Method: POST

URI: /lists/

Basic authorization: Required

Request body example:

{
  "name": "CPUs",
  "description": "Processors for servers #1, #6, #11",
  "author": {
    "id": 1,
    "login": "mark.johnson@yahoo.com",
    "name": "Mark Johnson"
  },
  "device": {
    "id": 1,
    "name": "Samsung Galaxy S8"
  },
  "listItems": [
    {
      "version": 0,
      "name": "Core i5",
      "description": "CPU Intel Core i5",
      "checked": true,
      "quantity": 2
    },
    {
      "version": 0,
      "name": "Core i7",
      "description": "CPU Intel Core i7",
      "checked": true,
      "quantity": 1
    }
  ]
}

Response body: <empty>

Update existing shopping list

Method: POST

URI example: /lists/1

Basic authorization: Required

Request body example (no info about conflicts):

{
  "id": 1,
  "name": "CPUs",
  "description": "Processors for servers #1, #6, #11",
  "author": {
    "id": 1,
    "login": "mark.johnson@yahoo.com",
    "name": "Mark Johnson"
  },
  "device": {
    "id": 1,
    "name": "Samsung Galaxy S8"
  },
  "listItems": [
    {
      "id": 1,
      "version": 0,
      "name": "Core i5",
      "description": "CPU Intel Core i5",
      "checked": true,
      "quantity": 2
    },
    {
      "id": 2,
      "version": 1,
      "isDeleted": true
    }
  ]
}

Response body (no conflicts):

{
  "conflictedItems": [],
  "newRemoteItems": []
}

Response body (has 1 conflict):

{
  "conflictedItems": [
    {
      "id": 1,
      "version": 2,
      "name": "AMD",
      "description": "CPU AMD",
      "checked": true,
      "quantity": 1,
      "author": {
        "id": 2,
        "login": "miranda.johnson@yahoo.com",
        "name": "Miranda Johnson"
      },
      "device": {
        "id": 3,
        "name": "Apple iPhone"
      },
    }
  ],
  "newRemoteItems": []
}

Response body (has 1 new remote item):

{
  "conflictedItems": [],
  "newRemoteItems": [
    {
      "id": 10,
      "version": 1,
      "name": "Ciryx",
      "description": "Antique Cityx CPU",
      "checked": false,
      "quantity": 5,
      "author": {
        "id": 2,
        "login": "miranda.johnson@yahoo.com",
        "name": "Miranda Johnson"
      },
      "device": {
        "id": 3,
        "name": "Apple iPhone"
      },
    }
  ]
}

Request body example (with fixed conflicted items):

{
  "id": 1,
  "name": "CPUs",
  "description": "Processors for servers #1, #6, #11",
  "author": {
    "id": 1,
    "login": "mark.johnson@yahoo.com",
    "name": "Mark Johnson"
  },
  "device": {
    "id": 1,
    "name": "Samsung Galaxy S8"
  },
  "listItems": [
    {
      "id": 1,
      "version": 0,
      "name": "Core i5",
      "description": "CPU Intel Core i5",
      "checked": true,
      "quantity": 2,
      "force": true
    },
    {
      "id": 2,
      "version": 1,
      "isDeleted": true,
      "force": true
    },
    {
      "id": 10,
      "version": 1,
      "name": "Ciryx",
      "description": "Antique Cityx CPU",
      "checked": false,
      "quantity": 5,
      "force": true
    }
  ]
}

Response body: no conflicts.

Limitations

In the current version the following functions are implemented particularly:

  • working with shopping list collaborators - supported authorship of editings, conflict resolving with providing info about editors, owners mangement; not supported storing collaborators in the database.

  • security - no integration with an external user log in system. Basic authorization with no user roles is used.