# Retrieving A Book By ID - Implementation

## 1 - Route Name

We will first add a route of `GET /api/v1/books/:id`_._

_File: src/routes/book.route.js_

```javascript
const express = require('express')
const router = express.Router()

const {
  getAllBooks,
  getBookById
} = require('../controllers/book')

router.get('/', getAllBooks)
router.get('/:id', getBookById) // This is our newly added route

module.exports = router
```

Followed by the controller setup.

_File: src/controllers/books/getABookById.js_

```javascript
const catchException = require('../utils/catchExceptions')

const getBookById = catchException(async (req, res, next) => {
  // our code goes here...
})
```

## 2 - Input Request

None.

## 3 - Middleware

None.

## 4 - Validation

None.

## 5 - Domain

The `getById()` method will look this, nice and simple.

_File: src/domain/services/bookRepository.js_

```javascript
// Retrieve - one
const getById = async (id) => {
  return await Model.findById(id)
}
```

Now for us to actually use the `bookRepository` in our `bookService`.

_File: src/domain/services/bookService.js_

```javascript
// Retrieve - one
const getBookById = async (bookId) => {
  const book = await bookRepository.getById(bookId)

  return book
}
```

## 6 - Events

None.

## 7 - Response

But wait! let's not forget the 404 validation we promised.

_File: src/domain/services/bookService.js_

```javascript
// Retrieve - one
const getBookById = async (bookId) => {
  if (!mongoose.Types.ObjectId.isValid(bookId)) {
    // the id is invalid
    throw new ApiException({
      message: `the book with that id: ${bookId} does not exist.`,
      status: 'failed',
      code: 404,
      data: null,
      errors: [`the book with that id: ${bookId} does not exist.`]
    })
  }

  const book = await bookRepository.getById(bookId)

  if (!book) {
    throw new ApiException({
      message: `the book with that id: ${bookId} does not exist.`,
      status: 'failed',
      code: 404,
      data: null,
      errors: [`the book with that id: ${bookId} does not exist.`]
    })
  }

  return book
}
```

As usual, here is our controller. Thanks to us doing the business logic validation in our domain layer, our controller is thin and free of clutter.

_File: src/controllers/book.controller.js_

```javascript
const getBookById = catchException(async (req, res, next) => {
  const book = await bookService.getBookById(req.params.id)

  return res.json(
    globalResponseDTO({
      status: 'success',
      code: 200,
      message: `Book with the specified id.`,
      data: book,
      errors: null
    })
  )
})
```
