Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@
.gradle
build/
out/
.DS_Store
src/.DS_Store
src/main/.DS_Store
src/test/.DS_Store
35 changes: 23 additions & 12 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,44 +1,55 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.3.RELEASE")
}
}

group = 'org.springframework.samples'
version = '1.0.0.SNAPSHOT'

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply from: 'src/build/admin-tasks.gradle'
apply plugin: 'org.springframework.boot'
//apply from: 'src/build/admin-tasks.gradle'

repositories {
//mavenRepo urls: 'http://maven.springframework.org/milestone'
mavenCentral()
}

dependencies {
//compile 'org.springframework:spring-context:3.1.0.M1'
// https://mvnrepository.com/artifact/org.springframework/spring-context
// tag::jetty[]
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
// end::jetty[]
// tag::actuator[]
compile("org.springframework.boot:spring-boot-starter-actuator")
// end::actuator[]
compile group: 'org.springframework', name: 'spring-context', version: '3.1.0.RELEASE'
// https://mvnrepository.com/artifact/org.springframework/spring-jdbc
compile group: 'org.springframework', name: 'spring-jdbc', version: '3.1.0.RELEASE'

//compile 'org.springframework:spring-jdbc:3.1.0.M1'
compile 'cglib:cglib-nodep:2.2'
compile 'hsqldb:hsqldb:1.8.0.10'
compile 'commons-logging:commons-logging:1.1.1'
compile 'log4j:log4j:1.2.16'
//compile 'log4j:log4j:1.2.16'
compile 'javax.inject:javax.inject:1'
//testCompile 'org.springframework:spring-test:3.1.0.M1'
testCompile 'junit:junit:4.7'
}

[compileJava, compileTestJava]*.options*.compilerArgs = ['-Xlint:all']

sourceCompatibility = 1.6
targetCompatibility = 1.6
sourceCompatibility = 1.8
targetCompatibility = 1.8

task wee(type: Wrapper) {
gradleVersion = '2.10' //we want gradle 2.10 to run this project
}


// consolidate source directories for ease of browsing
sourceSets {
main {
java { srcDir 'src/main' }
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/com/bank/Application.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.bank;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import java.util.Arrays;

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {

System.out.println("Let's inspect the beans provided by Spring Boot:");

String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}

};
}

}
14 changes: 14 additions & 0 deletions src/main/java/com/bank/controller/TransferController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.bank.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TransferController {

@RequestMapping("/")
public String index() {
return "Greetings from Spring Boot!";
}

}
23 changes: 23 additions & 0 deletions src/main/java/com/bank/domain/DefaultTransferWindow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.bank.domain;

import java.time.LocalTime;

public class DefaultTransferWindow {
private LocalTime open;
private LocalTime close;
public DefaultTransferWindow(String open, String close) {
this.open = LocalTime.parse(open);
this.close = LocalTime.parse(close);
}

public boolean isValidTimeForTransferMoney(LocalTime transactionTime) {
return (transactionTime.isAfter(open))&&(transactionTime.isBefore(close));
}

public LocalTime getOpen() {
return this.open;
}
public LocalTime getClose() {
return this.close;
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/bank/domain/LocalTimeWrapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.bank.domain;

import org.omg.CORBA.Current;

import java.time.LocalTime;

public class LocalTimeWrapper {

private String specificTime = null;
public LocalTimeWrapper(String initial){
this.specificTime = initial;
}

public LocalTimeWrapper() {

}

public LocalTime getCurrentTime() {
if(this.specificTime != null)
return LocalTime.parse(this.specificTime);
return LocalTime.now();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package com.bank.domain;

import java.time.LocalTime;

import static java.lang.String.format;

public class TransferReceipt {
Expand All @@ -25,6 +27,12 @@ public class TransferReceipt {
private Account initialDestinationAccountCopy;
private Account finalSourceAccountCopy;
private Account finalDestinationAccountCopy;
private LocalTime transactionTime;


public TransferReceipt(LocalTime transactionTime) {
this.transactionTime = transactionTime;
}

public void setTransferAmount(double transferAmount) {
this.transferAmount = transferAmount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@

import com.bank.domain.InsufficientFundsException;
import com.bank.domain.TransferReceipt;
import com.bank.service.internal.InvalidTransferWindow;

public interface TransferService {

TransferReceipt transfer(double amount, String srcAcctId, String destAcctId)
throws InsufficientFundsException;
throws InsufficientFundsException, InvalidTransferWindow;

void setMinimumTransferAmount(double minimumTransferAmount);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,31 @@

import static java.lang.String.format;

import com.bank.domain.*;
import org.springframework.transaction.annotation.Transactional;

import com.bank.domain.Account;
import com.bank.domain.InsufficientFundsException;
import com.bank.domain.TransferReceipt;
import com.bank.repository.AccountRepository;
import com.bank.service.FeePolicy;
import com.bank.service.TransferService;

import java.time.LocalTime;

public class DefaultTransferService implements TransferService {

private final AccountRepository accountRepository;
private final FeePolicy feePolicy;
private double minimumTransferAmount = 1.00;
private LocalTimeWrapper localTimeWrapper;
private DefaultTransferWindow defaultTransferWindow;

public DefaultTransferService(AccountRepository accountRepository, FeePolicy feePolicy) {
public DefaultTransferService(AccountRepository accountRepository,
FeePolicy feePolicy,
LocalTimeWrapper localTimeWrapper,
DefaultTransferWindow transferWindow) {
this.accountRepository = accountRepository;
this.feePolicy = feePolicy;
this.localTimeWrapper = localTimeWrapper;
this.defaultTransferWindow = transferWindow;
}

@Override
Expand All @@ -44,36 +51,47 @@ public void setMinimumTransferAmount(double minimumTransferAmount) {

@Override
@Transactional
public TransferReceipt transfer(double amount, String srcAcctId, String dstAcctId) throws InsufficientFundsException {
if (amount < minimumTransferAmount) {
throw new IllegalArgumentException(format("transfer amount must be at least $%.2f", minimumTransferAmount));
}
public TransferReceipt transfer(double amount, String srcAcctId, String dstAcctId)
throws InsufficientFundsException, InvalidTransferWindow {

TransferReceipt receipt = new TransferReceipt();
LocalTime transactionTime = this.localTimeWrapper.getCurrentTime();
checkEligibility(amount, transactionTime);

Account srcAcct = accountRepository.findById(srcAcctId);
Account dstAcct = accountRepository.findById(dstAcctId);

receipt.setInitialSourceAccount(srcAcct);
receipt.setInitialDestinationAccount(dstAcct);

double fee = feePolicy.calculateFee(amount);
if (fee > 0) {
srcAcct.debit(fee);
}

receipt.setTransferAmount(amount);
receipt.setFeeAmount(fee);

srcAcct.debit(amount);
dstAcct.credit(amount);

accountRepository.updateBalance(srcAcct);
accountRepository.updateBalance(dstAcct);

return getTransferReceipt(amount, transactionTime, srcAcct, dstAcct, fee);
}

private TransferReceipt getTransferReceipt(double amount, LocalTime transactionTime, Account srcAcct, Account dstAcct, double fee) {
TransferReceipt receipt = new TransferReceipt(transactionTime);
receipt.setInitialSourceAccount(srcAcct);
receipt.setInitialDestinationAccount(dstAcct);
receipt.setTransferAmount(amount);
receipt.setFeeAmount(fee);
receipt.setFinalSourceAccount(srcAcct);
receipt.setFinalDestinationAccount(dstAcct);

return receipt;
}

private void checkEligibility(double amount, LocalTime transactionTime) throws InvalidTransferWindow {
if (amount < minimumTransferAmount) {
throw new IllegalArgumentException(format("transfer amount must be at least $%.2f", minimumTransferAmount));
}


if(!defaultTransferWindow.isValidTimeForTransferMoney(transactionTime)) {
throw new InvalidTransferWindow("We only allow to transfer between " + defaultTransferWindow.getOpen() + " and " + defaultTransferWindow.getClose());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.bank.service.internal;

public class InvalidTransferWindow extends Throwable {
public InvalidTransferWindow(String s) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
<bean id="transferService" class="com.bank.service.internal.DefaultTransferService">
<constructor-arg ref="accountRepository"/>
<constructor-arg ref="feePolicy"/>
<constructor-arg ref="localTimeWrapper"/>
<constructor-arg ref="defaultTransferWindow"/>
</bean>

<bean id="accountRepository" class="com.bank.repository.internal.JdbcAccountRepository">
Expand All @@ -18,10 +20,17 @@

<bean id="feePolicy" class="com.bank.service.internal.ZeroFeePolicy"/>

<bean id="localTimeWrapper" class="com.bank.domain.LocalTimeWrapper"/>

<bean id="defaultTransferWindow" class="com.bank.domain.DefaultTransferWindow">
<constructor-arg name="open" type="String" value="06:00:00"/>
<constructor-arg name="close" type="String" value="22:00:00"/>
</bean>

<beans profile="dev">
<jdbc:embedded-database id="dataSource">
<jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
<jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
<jdbc:script location="classpath:/sql/schema.sql"/>
<jdbc:script location="classpath:/sql/test-data.sql"/>
</jdbc:embedded-database>
</beans>

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.bank.config.xml;
package com.bank.integration;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

import com.bank.service.internal.InvalidTransferWindow;
import org.junit.Test;
import org.springframework.context.support.GenericXmlApplicationContext;

Expand All @@ -28,10 +29,10 @@
public class IntegrationTests {

@Test
public void transferTenDollars() throws InsufficientFundsException {
public void transferTenDollars() throws InsufficientFundsException, InvalidTransferWindow {
GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles("dev");
ctx.load("classpath:/com/bank/config/xml/transfer-service-config.xml");
ctx.load("classpath:/xml/transfer-service-config.xml");
ctx.refresh();

TransferService transferService = ctx.getBean(TransferService.class);
Expand Down
Loading