I found a code of basic inmemory account transaction from
https://anonsvn.springframework.org/svn/spring-samples . I just tried Serialization on that code instead of table usage. I wish to share that part with you all.
The first attachment is original code downloaded from the link mentioned above. The second attachment in this page is modified with serialization code by me to enhance the code and see the transactions with serialization without table transaction.
The classes available are as follows:
1) mypack.config.basic.account.AppConfig.java
2) mypack.config.basic.account.domain.Account.java
3) mypack.config.basic.account.domain.repository.AccountRepository.java
4) mypack.config.basic.account.domain.repository.InMemoryAccountRepository.java
5) mypack.config.basic.account.domain.service.TransferService.java
6) mypack.config.basic.account.domain.service.TransferServiceImpl.java
7) mypack.config.basic.account.domain.service.TransferServiceTest.java
Steps to create and compile and run are same as Spring3HelloWorld sample.
Now we see the classes structure below:
1) AppConfig.java
package mypack.config.basic.account;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import mypack.config.basic.account.repository.AccountRepository;
import mypack.config.basic.account.repository.InMemoryAccountRepository;
import mypack.config.basic.account.service.TransferService;
import mypack.config.basic.account.service.TransferServiceImpl;
@Configuration
public class AppConfig {
/**
* Bean definition
* @return TransferServiceImpl
* @throws Exception
*/
public @Bean TransferService transferService() throws Exception {
return new TransferServiceImpl(accountRepository());
}
/**
* Bean definition
* @return InMemoryAccountRepository
* @throws Exception
*/
public @Bean AccountRepository accountRepository() throws Exception {
return new InMemoryAccountRepository();
}
}
2) Account.java
package mypack.config.basic.account.domain;
import static java.lang.String.format;
import java.io.Serializable;
public class Account implements Serializable {
private final String id;
private double balance;
/**
* Constructor of Account
* @param id
* @param initialBalance
*/
public Account(String id, double initialBalance) {
this.id = id;
this.balance = initialBalance;
}
/**
* get id of an account
* @return id
*/
public String getId() {
return id;
}
/**
* get balance of an account
* @return balance
*/
public double getBalance() {
return balance;
}
/**
* debit from an account
* @param amount
*/
public void debit(double amount) {
balance -= amount;
}
/**
* credit to an account
* @param amount
*/
public void credit(double amount) {
balance += amount;
}
/**
* copy of an account
* @param src
* @return Account
*/
public static Account copy(Account src) {
return new Account(src.getId(), src.getBalance());
}
/**
* Returns Account details of an id
*/
@Override
public String toString() {
return format("Account: id=%s, balance=%.2f", getId(), getBalance());
}
}
3) AccountRepository.java
package mypack.config.basic.account.repository;
import java.util.Set;
import mypack.config.basic.account.domain.Account;
public interface AccountRepository {
/**
* find an account of a given id
* @param acctId
* @return Account
*/
Account findById(String acctId);
/**
* update an account for a given id
* @param account
*/
boolean update(Account account);
/**
* Add a new account to InMemory
* @param account
*/
boolean add(Account account);
/**
* remove account
* @param accId
*/
boolean remove(String accId);
/**
* Find all accounts from InMemory
* @return Set<Account>
*/
Set<Account> findAll();
/**
* Find all accounts from InMemory
* @return Set<String>
*/
Set<String> findAllIds();
/**
* serialize inmemory object
* @throws Exception
*/
void serialize() throws Exception;
/**
* Deserialize stored object
* @throws Exception
*/
void deSerialize() throws Exception;
}
4) InMemoryAccountRepository.java
package mypack.config.basic.account.repository;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import mypack.config.basic.account.domain.Account;
public class InMemoryAccountRepository implements AccountRepository {
private Map<String, Account> accountsById;
/**
* Constructor of InMemoryAccountRepository
* @throws Exception
*/
public InMemoryAccountRepository() throws Exception {
if ( ( new File( "account_repository.sfe" ) ).exists() && ( new File( "account_repository.sfe" ) ).isFile() )
deSerialize();
else
accountsById = new HashMap<String, Account>();
}
/**
* find account of an id
* @return Account
*/
public Account findById(String acctId) {
if ( !accountsById.containsKey(acctId) )
return null;
else
return Account.copy(accountsById.get(acctId));
}
/**
* update of an existing account
*/
public boolean update(Account account) {
if (!accountsById.containsKey(account.getId()))
return false;
else {
accountsById.put(account.getId(), Account.copy(account));
return true;
}
}
/**
* add a new account
*/
public boolean add(Account account) {
if (accountsById.containsKey(account.getId()))
return false;
else {
accountsById.put(account.getId(), Account.copy(account));
return true;
}
}
public boolean remove(String id) {
Account account = (Account) accountsById.get(id);
if ( account != null) {
accountsById.remove(account.getId());
return true;
}
return false;
}
/**
* find all accounts
* @return Set<Account>
*/
public Set<Account> findAll() {
HashSet<Account> allAccounts = new HashSet<Account>();
for (Account account : accountsById.values())
allAccounts.add(Account.copy(account));
return allAccounts;
}
/**
* find all accounts
* @return Set<String>
*/
public Set<String> findAllIds() {
HashSet<String> allAccounts = new HashSet<String>();
for (String Id : accountsById.keySet())
allAccounts.add(Id);
return allAccounts;
}
/**
* serialize inmemory object
* @throws Exception
*/
public void serialize() throws Exception {
ObjectOutputStream accRepObject = new ObjectOutputStream( new FileOutputStream("account_repository.sfe"));
accRepObject.writeObject(findAll());
accRepObject.flush();
accRepObject.close();
}
/**
* Deserialize stored object
* @throws Exception
*/
public void deSerialize() throws Exception {
ObjectInputStream accRepReadObject = new ObjectInputStream( new FileInputStream("account_repository.sfe"));
HashSet<Account> allAccounts = (HashSet<Account>)accRepReadObject.readObject();
accRepReadObject.close();
accountsById = new HashMap<String, Account>();
for ( Account account: allAccounts)
{
accountsById.put(account.getId(),account);
}
}
}
5) TransferService.java
package
mypack.config.basic.account.service;
public
interface TransferService {
/**
* Transfer balance of srcAcctId to destAcctId
* @param amount
* @param srcAcctId
* @param destAcctId
*/
void transfer(double amount, String srcAcctId, String destAcctId);
}
6) TransferServiceImpl.java
package mypack.config.basic.account.service;
import mypack.config.basic.account.domain.Account;
import mypack.config.basic.account.repository.AccountRepository;
public class TransferServiceImpl implements TransferService {
private final AccountRepository accountRepository;
/**
* Constructor of TransferServiceImpl
* @param accountRepository
*/
public TransferServiceImpl(AccountRepository accountRepository) {
this.accountRepository = accountRepository;
}
/**
* Transfer balance of srcAcctId to destAcctId
* @param amount
* @param srcAcctId
* @param destAcctId
*/
public void transfer(double amount, String srcAcctId, String destAcctId) {
Account srcAcct = accountRepository.findById(srcAcctId);
Account destAcct = accountRepository.findById(destAcctId);
srcAcct.debit(amount);
destAcct.credit(amount);
accountRepository.update(srcAcct);
accountRepository.update(destAcct);
}
}
7) TransferServiceTest.java
package mypack.config.basic.account.service;
import java.io.DataInputStream;
import java.util.HashSet;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import mypack.config.basic.account.AppConfig;
import mypack.config.basic.account.domain.Account;
import mypack.config.basic.account.repository.AccountRepository;
import mypack.config.basic.account.service.TransferService;
public class TransferServiceTest {
//Declaration
ApplicationContext ctx;
AccountRepository accountRepository;
TransferService transferService;
/**
* Constructor of TransferServiceTest
* Initialize ApplicationContext, AccountRepository, TransferService
*/
public TransferServiceTest()
{
// create the spring container using the AppConfig @Configuration class
ctx = new AnnotationConfigApplicationContext(AppConfig.class);
// retrieve the beans we'll use during testing
accountRepository = ctx.getBean(AccountRepository.class);
transferService = ctx.getBean(TransferService.class);
}
/**
* Do add/update/find/findall/transfer/remove/commit to accounts
* @throws Exception
*/
public void doTransactions() throws Exception {
HashSet<String> Ids;
String input = null;
String id;
String amount = null;
String decisionString = null;
boolean flag = false;
do
{
System.out.println("Enter either of these add|update|find|findall|transfer|remove|commit|exit");
DataInputStream accountInputStream = new DataInputStream(System.in);
input = accountInputStream.readLine();
if (input.equalsIgnoreCase("add")) {
System.out.println("Please enter necessary data to create a new account; Please confirm the id you specify is not available already.");
Ids = (HashSet<String>) accountRepository.findAllIds();
if ( Ids != null && !Ids.isEmpty())
System.out.println("Existing Account Numbers:\t" + Ids);
else
System.out.println("There are no accounts created yet. Welcome to open an account here!!!");
System.out.println("Enter new Account Number:\t");
id = accountInputStream.readLine();
accountInputStream = new DataInputStream(System.in);
System.out.println("Enter amount you wish to deposit:\t");
amount = accountInputStream.readLine();
flag = accountRepository.add(new Account( id, Double.parseDouble(amount) ));
if ( flag )
{
System.out.println("Account added, but not commited!!! Do you want to commit? Say Yes|No :");
decisionString = accountInputStream.readLine();
if ( decisionString.equalsIgnoreCase("yes")) {
accountRepository.serialize();
System.out.println("New account created has been commited!!!");
} else
System.out.println("Your new account will not be available until you commit!!! Thank you!!!");
} else
System.out.println("The account number specified is already available. Please try some other account number!");
}
else if(input.equalsIgnoreCase("update")) {
Ids = (HashSet<String>) accountRepository.findAllIds();
System.out.println("Existing Account Numbers:\t" + Ids);
System.out.println("Enter Account Number to be updated from the account numbers listed above:\t");
id = accountInputStream.readLine();
System.out.println("Enter amount:\t");
amount = accountInputStream.readLine();
flag = accountRepository.update(new Account(id, Double.parseDouble(amount)));
if (flag) {
System.out.println("Account has been updated, but not commited!!! Do you want to commit? Yes|No :");
decisionString = accountInputStream.readLine();
if ( decisionString.equalsIgnoreCase("yes")) {
accountRepository.serialize();
System.out.println("updation to the account has been commited!!!");
} else
System.out.println("Your updation to the account will not be available until you commit!!! Thank you!!!");
}else
System.out.println("The account number requested to update does not exist!!!");
}
else if(input.equalsIgnoreCase("find")) {
System.out.println("Enter Account Number:\t");
String acctId = accountInputStream.readLine();
Account account = accountRepository.findById(acctId);
if ( account != null ) {
System.out.println("Account requested is below!!!\n");
System.out.println("Account Number:\t"+ account.getId());
System.out.println("Account Balance:\t"+account.getBalance());
}else
System.out.println("The account number requested does not exist!!!");
}
else if(input.equalsIgnoreCase("findall")) {
HashSet<Account> allAccounts = (HashSet<Account>) accountRepository.findAll();
System.out.println("All accounts are shown below!!!");
if ( allAccounts != null && !allAccounts.isEmpty() )
{
for (Account account : allAccounts)
{
System.out.println("Account Number:\t" + account.getId());
System.out.println("Account Balance:\t" + account.getBalance());
System.out.println("\n");
}
} else {
System.out.println("There are no accounts availeble with us. Sorry!!!");
}
}
else if(input.equalsIgnoreCase("transfer")) {
System.out.println("Please enter source and destination account numbers and amount to be transfered!!!");
Ids = (HashSet<String>) accountRepository.findAllIds();
System.out.println("Existing Account Numbers:\t" + Ids);
System.out.println("Enter source account number from the account numbers listed above:\t");
String srcAcctId = accountInputStream.readLine();
System.out.println("Enter destination account number from the account numbers listed above:\t");
String destAcctId = accountInputStream.readLine();
Account srcAccount = accountRepository.findById(srcAcctId);
System.out.println("The account Number "+ srcAcctId + "has account balance Rs."+ srcAccount.getBalance());
System.out.println("Please enter the amount specified or less than that!");
System.out.println("Enter amount to be transfered:\t");
amount = accountInputStream.readLine();
if ( Double.parseDouble(amount) <= srcAccount.getBalance()) {
transferService.transfer(Double.parseDouble(amount), srcAcctId, destAcctId);
System.out.println("Amount has been transfered, but not commited!!! Do you want to commit? Yes|No :");
decisionString = accountInputStream.readLine();
if ( decisionString.equalsIgnoreCase("yes")) {
accountRepository.serialize();
System.out.println("updation to the account has been commited!!!");
} else
System.out.println("Your transaction changes will not be available until you commit!!! Thank you!!!");
} else
System.out.println("The transaction requested cannot be performed as the amount exceeds the balance available!!!");
}
else if(input.equalsIgnoreCase("remove")) {
Ids = (HashSet<String>) accountRepository.findAllIds();
System.out.println("Existing Account Numbers:\t" + Ids);
System.out.println("Please enter account number to be deleted from the account numbers listed above:\t");
id = accountInputStream.readLine();
flag = accountRepository.remove(id);
if (flag) {
System.out.println("Acount has been removed, but not commited!!! Do you want to commit? Yes|No :");
decisionString = accountInputStream.readLine();
if ( decisionString.equalsIgnoreCase("yes")) {
accountRepository.serialize();
System.out.println("Deletion to the account has been commited!!!");
} else
System.out.println("Deletion of account will not be deleted until you commit!!! Thank you!!!");
} else
System.out.println("The account number specified for deletion does not exist!!!");
}
else if(input.equalsIgnoreCase("commit")) {
accountRepository.serialize();
System.out.println("Addition/Modification/Removal of accounts has been commited!!!");
}
} while (!input.equals("exit"));
}
/**
* Commit changes done to accounts
* @throws Exception
*
*/
public void doCommit() throws Exception {
accountRepository.serialize();
}
/**
* main method
*/
public static void main(String[] args) throws Exception {
TransferServiceTest transferServiceTest = new TransferServiceTest();
transferServiceTest.doTransactions();
}
}
Now we see addition for the sample:
Output:
Feb 15, 2011 12:22:45 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1cd8669: startup date [Tue Feb 15 12:22:45 IST 2011]; root of context hierarchy
Feb 15, 2011 12:22:45 PM org.springframework.context.annotation.ConfigurationClassEnhancer enhance
INFO: Successfully enhanced mypack.config.basic.account.AppConfig; enhanced class name is: mypack.config.basic.account.AppConfig$$EnhancerByCGLIB$$794e7021
Feb 15, 2011 12:22:45 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@5224ee: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,appConfig,accountRepository,transferService]; root of factory hierarchy
Enter either of these add|update|find|findall|transfer|remove|commit|exit
Please enter necessary data to create a new account; Please confirm the id you specify is not available already.
Existing Account Numbers: [345, 123, 789, 567, 456, 678, 234]
Enter new Account Number:
Enter amount you wish to deposit:
Account added, but not commited!!! Do you want to commit? Say Yes|No :
New account created has been commited!!!
Enter either of these add|update|find|findall|transfer|remove|commit|exit
Enter Account Number:
Account requested is below!!!
Account Number: 890
Account Balance: 5000.0
Enter either of these add|update|find|findall|transfer|remove|commit|exit
Please try other options!!! Thank you!!!
add
890
5000
yes
find
890
exit