GithubHelp home page GithubHelp logo

rajagopal28 / transaction-manager Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 1.0 1.23 MB

A Small, light-weight Rest API based Java application without any framework, which does not require any server or container runtime.

License: MIT License

Java 100.00%
java embedded-server jax-rs rest-api rest-assured integration-testing mockito powermockito sqlite3 javax-persistence

transaction-manager's Introduction

transaction-manager

Context

A Small, light-weight Rest API based Java application without any framework, which does not require any server.

Objectives

Following are the primary objectives this project is based on

  1. The REST API should be built on an embedded server which means there should be no server or container that helps these API end points run at a particular application endpoint
  2. TDD should be enforced at every stage of the implementation
  3. The Application implementation should be simple and scalable as if it has real time traffic with multiple users accessing the system simultaneously
  4. The Application is meant to be Light weight hence Heavy frameworks such as Spring could not considered while implementing
  5. Application could only rely on in memory datastores

The Approach

Based on the aforementioned objectives the system that is being built has been built based on the following approach:

  • Using Jersey-Server library to create a JAX-RS reliant REST API server which can run as a self contained, embedded server that can be started and stopped from a simple Java application.
  • Using Mockito and PowerMocktio frameworks the entire implementation is developed following the TDD strategy where fail tests -> refactor -> pass tests cycle was strictly carried on.
  • JAX-RS application are simple, fast, reliable at the same time scaled based on the underlying data access implementations
  • SQLite datastore is used to store the data without involving any sever runtime or containers to actively engage with data connections.
  • Hibernate-JPA library is used to leverage the advantages javax.persistence library which helps in efficient, simple and scaled database access approaches.

Schema

Schema Diagram

API System flow

Flow Diagram

API Flows

Endpoint info

Endpoint\HTTP METHOD POST GET
CRUD OP CREATE READ
/users Create new User List existing users
/users/1 -- Show Existing user
/users/1/accounts Create an account for user1 List All Accounts of user 1
/users/1/accounts/1 -- Show Existing User's Chosen Account
/users/1/accounts/1/transactions Post a transaction to the given account - payload varies Show Selected Account transactions
/users/1/accounts/1/transactions/1 -- Show Chosen Transaction detail

Response Status Codes

Following are the response status codes that are sent as part of the system

  • 200 - OK
  • 304 - Not Modified
  • 400 - Bad Request
  • 404 - Not Found
  • 500 - Internal Server Error
Endpoint Applicable status codes
/users 200, 304, 500
/users/1 200, 404
/users/1/accounts 200, 400, 500
/users/1/accounts/1 200, 400, 404
/users/1/accounts/1/transactions 200, 400, 404, 500
/users/1/accounts/1/transactions/1 200, 304, 400, 404, 500,

Endpoint details

/users

GET:

curl http://localhost:8080/users

HTTP STATUS: 200

[
    {
        "city": "Pasedena",
        "dob": "11/03/1980",
        "email": "[email protected]",
        "firstName": "Leonard",
        "gender": "male",
        "id": 1,
        "lastName": "Hofstader",
        "phoneNumber": "+811297983423"
    },
    {
        "city": "Pasedena",
        "dob": "12/12/1983",
        "email": "[email protected]",
        "firstName": "Penny",
        "gender": "female",
        "id": 2,
        "lastName": "Barrington",
        "phoneNumber": "+8242312213123"
    }
]

POST:

curl -d '{"city": "Pasedena","dob": "11/03/1980","email": "[email protected]","firstName": "Leonard","gender": "male","lastName": "Hofstader","phoneNumber": "+811297983423"}' -H "Content-Type: application/json" -X POST http://localhost:8080/users/

HTTP STATUS: 201

{
    "city": "Pasedena",
    "dob": "11/03/1980",
    "email": "[email protected]",
    "firstName": "Leonard",
    "gender": "male",
    "id": 1,
    "lastName": "Hofstader",
    "phoneNumber": "+811297983423"
}

Possible error messages:

  • Record Creation Failed!
  • Required Field(s) are Invalid! Field(s) :
  • Unable to Find Record with given data!
  • Internal Server Error! Please check Logs!

/users/{user-id}

GET:

curl http://localhost:8080/users/1

HTTP STATUS: 200

{
    "city": "Pasedena",
    "dob": "11/03/1980",
    "email": "[email protected]",
    "firstName": "Leonard",
    "gender": "male",
    "id": 1,
    "lastName": "Hofstader",
    "phoneNumber": "+811297983423"
}

/users/{user-id}/accounts

GET:

curl http://localhost:8080/users/1/accounts

HTTP STATUS: 200

[
    {
        "accountNumber": "2321342SFDS12",
        "accountType": "SAVINGS",
        "balance": 123.456,
        "currency": "USD",
        "id": 1,
        "timeCreated": 1561723026458,
        "user": {
            "city": "Pasedena",
            "dob": "12/12/2019",
            "email": "[email protected]",
            "firstName": "Leonard",
            "gender": "male",
            "id": 1,
            "lastName": "Hofstader",
            "phoneNumber": "+811297983423"
        }
    }
]

POST:

curl -d '{"accountNumber" : "2321342SFDS12","accountType" : "SAVINGS","currency" : "USD","balance" : 123.456}' -H "Content-Type: application/json" -X POST http://localhost:8080/users/1/accounts

HTTP STATUS: 201

{
    "accountNumber": "2321342SFDS12",
    "accountType": "SAVINGS",
    "balance": 123.456,
    "currency": "USD",
    "id": 1,
    "timeCreated": 1561723026458,
    "user": {
        "city": null,
        "dob": null,
        "email": null,
        "firstName": null,
        "gender": null,
        "id": 1,
        "lastName": null,
        "phoneNumber": null
    }
}

Possible error messages:

  • Record Creation Failed!
  • Required Field(s) are Invalid! Field(s) :
  • Unable to Find Record with given data!
  • Internal Server Error! Please check Logs!

/users/{user-id}/accounts/{account-id}

GET:

curl http://localhost:8080/users/1/accounts/1

HTTP STATUS: 200

{
    "accountNumber": "2321342SFDS12",
    "accountType": "SAVINGS",
    "balance": 123.456,
    "currency": "USD",
    "id": 1,
    "timeCreated": 1561723026458,
    "user": {
        "city": "Pasedena",
        "dob": "12/12/2019",
        "email": "[email protected]",
        "firstName": "Leonard",
        "gender": "male",
        "id": 1,
        "lastName": "Hofstader",
        "phoneNumber": "+811297983423"
    }
}

/users/{user-id}/accounts/{account-id}/transactions

GET:

curl http://localhost:8080/users/1/accounts

HTTP STATUS: 200

{
    "message": "Record Creation Failed!"
}

POST (DEPOSIT):

curl -d '{"transactionType" : "CHEQUE_DEPOSIT","amount" : 100.00,"currency" : "USD"}' -H "Content-Type: application/json" -X POST http://localhost:8080/users/1/accounts/1

HTTP STATUS: 304

{
    "amount": 100,
    "currency": "USD",
    "fromAccount": null,
    "id": 1,
    "timeCreated": 0,
    "toAccount": {
        "accountNumber": "2321342SFDS12",
        "accountType": "SAVINGS",
        "balance": 223.45600000000002,
        "currency": "USD",
        "id": 1,
        "timeCreated": 1561723026458,
        "user": {
            "city": "Pasedena",
            "dob": "12/12/2019",
            "email": "[email protected]",
            "firstName": "Leonard",
            "gender": "male",
            "id": 1,
            "lastName": "Hofstader",
            "phoneNumber": "+811297983423"
        }
    },
    "transactionType": "CHEQUE_DEPOSIT"
}

POST (TRANSFER):

curl -d '{"transactionType" : "TRANSFFER", "fromAccountId" : 2,"amount" : 10.00,"currency" : "USD"}' -H "Content-Type: application/json" -X POST http://localhost:8080/users/1/accounts/1

HTTP STATUS: 304

{
    "amount": 100,
    "currency": "USD",
    "fromAccount": {
        "accountNumber": "1211342SFDS12",
        "accountType": "SAVINGS",
        "balance": 23.456000000000003,
        "currency": "USD",
        "id": 2,
        "timeCreated": 1561731946466,
        "user": {
            "city": "Pasedena",
            "dob": "12/12/2019",
            "email": "[email protected]",
            "firstName": "Penny",
            "gender": "female",
            "id": 2,
            "lastName": "Hofstader",
            "phoneNumber": "+811297983423"
        }
    },
    "id": 1,
    "timeCreated": 1561732053415,
    "toAccount": {
        "accountNumber": "1211342SFDS12",
        "accountType": "SAVINGS",
        "balance": 223.45600000000002,
        "currency": "USD",
        "id": 1,
        "timeCreated": 1561731933733,
        "user": {
            "city": "Pasedena",
            "dob": "12/12/2019",
            "email": "[email protected]",
            "firstName": "Leonard",
            "gender": "male",
            "id": 1,
            "lastName": "Hofstader",
            "phoneNumber": "+811297983423"
        }
    },
    "transactionType": "TRANSFER"
}

Possible transaction types:

  • TRANSFER
  • CHEQUE_DEPOSIT
  • CASH_DEPOSIT

Possible error messages:

  • Record Creation Failed!
  • Unable to process transaction! Currency Conversion Not enabled
  • Unable to process transaction! Insufficient Balance in you Account!!
  • Required Field(s) are Invalid! Field(s) :
  • Unable to Find Record with given data!
  • Cannot transfer within the Same Account!
  • Internal Server Error! Please check Logs!

/users/{user-id}/accounts/{account-id}/transactions/{transaction-id}

GET:

curl http://localhost:8080/users/1/accounts/1/transactions/1

HTTP STATUS: 200

{
    "amount": 100,
    "currency": "USD",
    "fromAccount": null,
    "id": 1,
    "timeCreated": 0,
    "toAccount": {
        "accountNumber": "2321342SFDS12",
        "accountType": "SAVINGS",
        "balance": 223.45600000000002,
        "currency": "USD",
        "id": 1,
        "timeCreated": 1561723026458,
        "user": {
            "city": "Pasedena",
            "dob": "12/12/2019",
            "email": "[email protected]",
            "firstName": "Leonard",
            "gender": "male",
            "id": 1,
            "lastName": "Hofstader",
            "phoneNumber": "+811297983423"
        }
    },
    "transactionType": "CHEQUE_DEPOSIT"
}

Error handling

All the internal errors including runtime errors are handled at controller and sent as a valid response to user following is an example

curl -d '{"accountNumber" : "2321342SFDS12","accountType" : "SAVINGS","currency" : "USD","balance" : 123.456}' -H "Content-Type: application/json" -X POST http://localhost:8080/users/1/accounts

HTTP STATUS: 304

{
    "message": "Record Creation Failed!"
}

TDD - Red->Green->Refactor cycle

TDD Diagram

Unit test and Integration test coverage

Test Coverage

Setup and launch

installing the packages

With Tests:

$ mvn clean install -U

running tests

Unit tests:

$ mvn  test

Integration tests:

$ mvn integration-test

running server

$ java  com.revolut.assesment.project.server.EmbeddedJettyServer

Libraries Used

Following are the Libraries that are used as part of source and test cycles Dependency Diagram

    Developed in Jetbrain's IntelliJ IDE

Challenges

  • Had a lot of challenges in setting up environment first with maven as there was a certificate issue that was messing with my maven commands due to network provider issues
  • Had difficulty in choosing the embedded server library as the prime objective was to keep the application light weight
  • Initially started with H2 in-memory DB and found out the hard way that it cannot be alive without a server/container or a EJB environment like JBoss.
  • Faced quite a lot of difficulties when trying to adapt the JAX-RS framework over the jetty-server library provided by sun.net and not the glassfish one.
  • Chose SQLite as it was serving the purpose and lightweight but I had to write a lot of boilerplate code initially as I was not able to find any ORM support like JPA adapting to JAX-RS and embedded server format.
  • But after spending a lot of time researching I have found a way to make JPA from hibernate support SQLite which let me throw away all my code involving explicit connection handling.
  • Had issues trying to setup integration tests, tried glassfish-jersey-client and faced a lot of dependency mismatch issues but finally found the restassured.io that helped me adapt to the sun.net jersey-client library.

References

transaction-manager's People

Contributors

dependabot[bot] avatar rajagopal28 avatar

Stargazers

 avatar

Watchers

 avatar

Forkers

rajendramani

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.