DEV Community

Satyendra Pandey
Satyendra Pandey

Posted on

End-to-End System Design for a React + Java + Cosmos DB Application

In this guide, we’ll design a scalable React + Java application with Cosmos DB as the database. This setup is ideal for applications requiring high scalability, low latency, and multi-region availability. We'll cover everything from architecture to deployment, breaking it into actionable steps.


1. Planning and Requirement Analysis

Gather Requirements

  • Frontend Needs:
    • Dynamic UI.
    • Real-time updates.
    • Intuitive navigation.
  • Backend Needs:
    • Scalable APIs.
    • Complex data handling.
    • Secure data storage and processing.
  • Database Needs:
    • NoSQL structure for flexibility.
    • Low latency for global users.
    • Consistency levels for transactional operations.

Technology Stack

  • Frontend: React.js with TypeScript (optional), Redux for state management.
  • Backend: Java with Spring Boot.
  • Database: Azure Cosmos DB.
  • Communication: RESTful APIs.
  • Deployment: Docker + Kubernetes.

2. Architecture Design

High-Level Architecture

  • Frontend: React app for client-side rendering, API consumption, and dynamic UI.
  • Backend: Java Spring Boot for RESTful API development.
  • Database: Cosmos DB for highly available and partitioned data storage.
  • Communication: JSON-based REST APIs for interaction between the frontend and backend.

3. Frontend Development

Folder Structure

Organize the React project for scalability and maintainability:

src/
├── components/   # Reusable UI components
├── pages/        # Page-level components
├── hooks/        # Custom React hooks
├── context/      # Global state management using Context API
├── services/     # API calls
├── styles/       # CSS/SCSS files
├── App.js        # Root component
└── index.js      # Entry point
Enter fullscreen mode Exit fullscreen mode

Routing

Use react-router-dom for navigation:

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/users" element={<UserList />} />
      </Routes>
    </Router>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

State Management

Choose between Redux or Context API:

  • Use Redux for large applications needing centralized state management.
  • Use Context API for simpler state-sharing scenarios.

4. Backend Development

Spring Boot Setup

Set up a Spring Boot application with Maven or Gradle. Include the following dependencies:

<dependency>
    <groupId>com.azure.spring</groupId>
    <artifactId>spring-cloud-azure-starter-data-cosmos</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Project Structure

Organize your backend for scalability:

src/main/java/com/example/
├── controller/    # REST Controllers
├── service/       # Business logic
├── repository/    # Cosmos DB integration
├── model/         # Data models
└── application/   # Main application class
Enter fullscreen mode Exit fullscreen mode

Cosmos DB Configuration

Add the necessary configuration in application.properties:

spring.cloud.azure.cosmos.endpoint=<YOUR_COSMOS_DB_ENDPOINT>
spring.cloud.azure.cosmos.key=<YOUR_COSMOS_DB_KEY>
spring.cloud.azure.cosmos.database=<DATABASE_NAME>
spring.cloud.azure.cosmos.consistency-level=Session
Enter fullscreen mode Exit fullscreen mode

Define Models

Use annotations to map Java classes to Cosmos DB:

@Container(containerName = "users")
public class User {
    @Id
    private String id;
    private String name;
    private String email;

    // Getters and setters
}
Enter fullscreen mode Exit fullscreen mode

Repository

Create a repository interface for database operations:

@Repository
public interface UserRepository extends CosmosRepository<User, String> {}
Enter fullscreen mode Exit fullscreen mode

Service

Implement business logic in a service class:

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    public User createUser(User user) {
        return userRepository.save(user);
    }
}
Enter fullscreen mode Exit fullscreen mode

Controller

Expose APIs to interact with the database:

@RestController
@RequestMapping("/api/users")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping
    public List<User> getUsers() {
        return userService.getAllUsers();
    }

    @PostMapping
    public User createUser(@RequestBody User user) {
        return userService.createUser(user);
    }
}
Enter fullscreen mode Exit fullscreen mode

5. Database Design

Cosmos DB Features

  • Partitioning: Use a unique field like userId to optimize scalability.
  • Consistency Levels:
    • Use Session consistency for most scenarios.
    • Switch to Strong consistency for critical operations.
  • Indexing: Leverage Cosmos DB's automatic indexing for query optimization.

6. Integration

Connecting Frontend with Backend

Use Axios or Fetch in the React app:

import axios from "axios";

const API_URL = "http://localhost:8080/api/users";

export const fetchUsers = async () => {
  const response = await axios.get(API_URL);
  return response.data;
};

export const createUser = async (user) => {
  const response = await axios.post(API_URL, user);
  return response.data;
};
Enter fullscreen mode Exit fullscreen mode

Displaying Data in React

import React, { useState, useEffect } from "react";
import { fetchUsers, createUser } from "./services/userService";

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetchUsers().then(setUsers);
  }, []);

  return (
    <div>
      <h1>User List</h1>
      <ul>
        {users.map((user) => (
          <li key={user.id}>{user.name}</li>
        ))}
      </ul>
    </div>
  );
}

export default UserList;
Enter fullscreen mode Exit fullscreen mode

7. Testing

Frontend Testing

  • Use Jest and React Testing Library for unit tests.
  • Write integration tests for API calls.

Backend Testing

  • Use JUnit and Mockito for unit tests.
  • Test database operations with embedded Cosmos DB:
  <dependency>
      <groupId>com.azure</groupId>
      <artifactId>cosmosdb-emulator</artifactId>
  </dependency>
Enter fullscreen mode Exit fullscreen mode

8. Deployment

Containerization with Docker

Create Dockerfiles for both frontend and backend:

  • Frontend Dockerfile:
  FROM node:16
  WORKDIR /app
  COPY . .
  RUN npm install
  RUN npm run build
  EXPOSE 3000
  CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode
  • Backend Dockerfile:
  FROM openjdk:17
  WORKDIR /app
  COPY target/*.jar app.jar
  EXPOSE 8080
  ENTRYPOINT ["java", "-jar", "app.jar"]
Enter fullscreen mode Exit fullscreen mode

Orchestration with Kubernetes

Deploy services using Kubernetes manifests:

  • Define Deployment and Service for frontend and backend.
  • Use ConfigMaps and Secrets for storing Cosmos DB credentials.

9. Observability

Logging

  • Use Logback for backend logging.
  • Use browser developer tools for frontend debugging.

Monitoring

  • Set up Prometheus and Grafana for backend monitoring.
  • Use Azure Monitor for Cosmos DB insights.

10. Best Practices

  • Use environment variables to store sensitive information.
  • Optimize API calls with pagination and filtering.
  • Follow proper error-handling practices.

This guide ensures a robust and scalable design for a React + Java + Cosmos DB application. You can adapt this architecture to fit specific use cases, ensuring maintainability and performance for your project.

Top comments (0)