PayMyBuddy is a Spring Boot-based web application that allows users to easily send money to their friends and manage transactions. The application enables users to create friend connections and make money transfers between them.
- Users can create accounts using their email and log in securely.
- Users can add other registered users as friends or remove them anytime.
- Users can select a friend, enter a description and amount, and send money instantly.
- All transfers are displayed in a transaction list, allowing users to track their payment history.
To access the application, users first need to register.
Signup:
- A new user can register by filling in their username, email, and password.
- The password is encrypted with BCrypt before being stored in the database.
- During signup, an account is automatically created for the user with an initial balance of 0.00.
Login:
- Registered users can log in with their email and password.
- Authentication is handled by Spring Security with a custom UserDetailsService. If the credentials are valid, the user is redirected to their dashboard.
After logging in, users can send money to their friends.
- The sender’s balance is verified before the transfer.
- If successful, balances are updated and the transaction is saved.
- All transactions can be viewed in the “My Transactions” section.
On the profile page, users can:
- View their registered information,
- Update their password
The contact page is used to manage friends inside the application.
Add a Friend:
- Users can add another user as a friend by entering their email address.
- The system checks in the database if this user exists and has an account.
- If the email does not exist → the user sees the message:
- “This user does not exist or has no account yet.”
- If the user tries to add themselves → the system displays:
- “You cannot add yourself as a friend.”
Remove a Friend:
- Users can also delete an existing friend from their list.
- The relationship is removed from the database, and the friend no longer appears in the contact and send money list.
In our application.properties file, we don’t write the database credentials directly. Instead, we use environment variables like this:
spring.application.name=demo
spring.datasource.url={DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
server.port=5000
- Security: We don’t want to expose sensitive data (like database username and password) inside the code or in GitHub.
- Flexibility: Each developer or server can have their own values without changing the code. For example:
- On your local machine, DB_USERNAME=root
- On production, DB_USERNAME=prod_user
We simply define these variables in the environment (for example in IntelliJ → Edit Configurations → Environment Variables), and Spring Boot automatically replaces ${DB_USERNAME} with the real value. This way, the application is portable, secure, and easy to configure in different environments (local, test, production).
This project includes unit tests to verify the behaviour of service classes in isolation. For example, we have a unit test for the sendMoney functionality to ensure that money transfers work correctly between accounts. This test checks:
- The sender's balance decreases by the transfer amount.
- The receiver's balance increases by the transfer amount.
- A transaction record is saved with the correct amount and description.
- Both sender and receiver accounts are updated in the database.
This ensures that the core logic of transferring funds behaves as expected without affecting the database directly (using mocked repositories).
@Test
void test_sendMoney_success(){
BigDecimal amount = BigDecimal.valueOf(30);
String description = "Payment";
when(accountRepository.findByUserId(sender.getId())).thenReturn(senderAccount);
when(accountRepository.findByUserId(receiver.getId())).thenReturn(receiverAccount);
transactionServiceImpl.sendMoney(sender, receiver, amount, description, "Euro");
assertEquals(new BigDecimal("70.00"), senderAccount.getBalance());
assertEquals(new BigDecimal("80.00"), receiverAccount.getBalance());
verify(transactionRepository).save(any(Transaction.class));
verify(accountRepository).save(senderAccount);
verify(accountRepository).save(receiverAccount);
}
This integration test ensures that the sendMoney feature works correctly with the actual database. It verifies:
- The sender's account balance decreases by the transfer amount.
- The receiver's account balance increases by the same amount.
- A transaction record is created and saved in the database.
- The transaction status is correctly set to SUCCESS.
By testing with the real repositories, we make sure that all parts of the money transfer process, updating accounts and storing transactions work together as expected.
@Test
public void createAPersonShouldReturnTrue() throws Exception {
Person person = new Person("Thomas", "Anderson", "15 Street John Kennedy",
"New York", "28000", "11-555-9999", "[email protected]");
MockHttpServletResponse response = mockMvc.perform(MockMvcRequestBuilders
.post("/person")
.content(objectMapper.writeValueAsString(person))
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isCreated())
.andReturn()
.getResponse();
assertEquals("true", response.getContentAsString(StandardCharsets.UTF_8));
}