valentinacupac / banking-kata-java Goto Github PK
View Code? Open in Web Editor NEWBanking Kata (Java)
License: MIT License
Banking Kata (Java)
License: MIT License
A reality we can often observe in real world applications, and even more so in microservices architectures, is communication with multiple services in order to achieve a task.
For example, in case of opening a new account, checking that a person exists and is registered in the country.
It would be useful to add an example of communication with a fictional external system to demonstrate the implementation with hexagonal architecture (hint: basically a repository).
User has requested to withdraw more than the funds that they have available
Account score is calculated as follows:
NameFactor => count the total number of characters in the account holder's first name and last name (let's call it "n"). If that is <= 5 then the NameFactor is 3, if it's > 5 and <= 10 then the NameFactor is "n", and if it's > 10 then the NameFactor is 3 x "n".
BalanceFactor => the balance factor is the value of the balance + 5.
TimeFactor => the time factor is calculated as the number of days since the account was created
Then the score is:
In the class RandomAccountIdGenerator, currently GENERATOR_ID is hardcoded but it needs to be made configurable
How can you map between your domain entities and a entity managed by Hibernate for example?
Consider configuring multiple environments. For example, different database connection strings per environment.
Internally record AccountId in the repository
DB tests are passing locally, but failing on GitHub Actions after changes in a69b455
GitHub Actions log https://github.com/valentinacupac/banking-kata-java/actions/runs/3788279403/jobs/6440898243#step:8:86
`BankingApplicationTests > contextLoads() FAILED
java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
Caused by: java.lang.IllegalStateException at SpringBootCondition.java:60
Caused by: java.lang.IllegalArgumentException at PropertyPlaceholderHelper.java:180
JpaBankAccountStorageTest > should_return_empty_given_non_existent_account_number() FAILED
org.junit.jupiter.api.extension.ParameterResolutionException at ExecutableInvoker.java:239
Caused by: java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
Caused by: java.lang.IllegalStateException at SpringBootCondition.java:60
Caused by: java.lang.IllegalArgumentException at PropertyPlaceholderHelper.java:180
JpaBankAccountStorageTest > should_return_added_bank_account() FAILED
org.junit.jupiter.api.extension.ParameterResolutionException at ExecutableInvoker.java:239
Caused by: java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
Caused by: java.lang.IllegalStateException at SpringBootCondition.java:60
Caused by: java.lang.IllegalArgumentException at PropertyPlaceholderHelper.java:180
JpaBankAccountStorageTest > should_find_multiple_added_bank_accounts() FAILED
org.junit.jupiter.api.extension.ParameterResolutionException at ExecutableInvoker.java:239
Caused by: java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
Caused by: java.lang.IllegalStateException at SpringBootCondition.java:60
Caused by: java.lang.IllegalArgumentException at PropertyPlaceholderHelper.java:180
BankAccountControllerSystemTest > should_open_account_given_valid_request() FAILED
org.junit.jupiter.api.extension.ParameterResolutionException at ExecutableInvoker.java:239
Caused by: java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
Caused by: java.lang.IllegalStateException at SpringBootCondition.java:60
Caused by: java.lang.IllegalArgumentException at PropertyPlaceholderHelper.java:180
108 tests completed, 5 failed`
Pending to see if this is caused due to Postgres password change? Aside from that, there weren't any other changes related to Postgres.
Locally, the tests pass (when Postgres environment variables are configured), the issue started appearing on GitHub Actions only.
When a new account is opened, the event AccountOpened should be published.
The idea it's to add Cucumber to demonstrate OutsideIn TDD way. It would most probably showed in the 23 Nov 2022 meetup.
Job to be done :
Update instructions regarding Keycloak since currently the only version that works is the docker instructions.
In order to use an admin panel for database i suggest to include adminer
Also the docker-compose file has an invalid POSTGRES_PASSWORD variable due to README
User has provided a non-existent bank account number, so the system returns an error
PROBLEM DESCRIPTION
BankAccountControllerSystemTest test fails after the changeset with Keycloak addition a69b455
I executed the instructions as per running_with_docker.md.
I get this response:
> Task :test
BankAccountControllerSystemTest > should_open_account_given_valid_request() FAILED
org.springframework.web.reactive.function.client.WebClientRequestException at ExchangeFunctions.java:141
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException
Caused by: java.net.ConnectException at Net.java:-2
2022-12-27 17:56:02.448 INFO 29688 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-12-27 17:56:02.449 INFO 29688 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2022-12-27 17:56:02.452 INFO 29688 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
2022-12-27 17:56:02.462 INFO 29688 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-12-27 17:56:02.464 INFO 29688 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Shutdown initiated...
2022-12-27 17:56:02.465 INFO 29688 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Shutdown completed.
2022-12-27 17:56:02.472 INFO 29688 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-12-27 17:56:02.473 INFO 29688 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-3 - Shutdown initiated...
2022-12-27 17:56:02.474 INFO 29688 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-3 - Shutdown completed.
108 tests completed, 1 failed
> Task :test FAILED
FAILURE: Build failed with an exception.
Reviewing the more detailed stack trace
org.springframework.web.reactive.function.client.WebClientRequestException: Connection refused: no further information: localhost/127.0.0.1:10000; nested exception is io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:10000
at app//org.springframework.web.reactive.function.client.ExchangeFunctions$DefaultExchangeFunction.lambda$wrapException$9(ExchangeFunctions.java:141)
at app//reactor.core.publisher.MonoErrorSupplied.subscribe(MonoErrorSupplied.java:55)
at app//reactor.core.publisher.Mono.subscribe(Mono.java:4400)
at app//reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103)
at app//reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222)
at app//reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222)
at app//reactor.core.publisher.FluxMap$MapSubscriber.onError(FluxMap.java:132)
at app//reactor.core.publisher.FluxPeek$PeekSubscriber.onError(FluxPeek.java:222)
at app//reactor.core.publisher.MonoNext$NextSubscriber.onError(MonoNext.java:93)
at app//reactor.core.publisher.MonoFlatMapMany$FlatMapManyMain.onError(MonoFlatMapMany.java:204)
at app//reactor.core.publisher.SerializedSubscriber.onError(SerializedSubscriber.java:124)
at app//reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.whenError(FluxRetryWhen.java:225)
at app//reactor.core.publisher.FluxRetryWhen$RetryWhenOtherSubscriber.onError(FluxRetryWhen.java:274)
at app//reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.drain(FluxConcatMap.java:415)
at app//reactor.core.publisher.FluxConcatMap$ConcatMapImmediate.onNext(FluxConcatMap.java:251)
at app//reactor.core.publisher.EmitterProcessor.drain(EmitterProcessor.java:491)
at app//reactor.core.publisher.EmitterProcessor.tryEmitNext(EmitterProcessor.java:299)
at app//reactor.core.publisher.SinkManySerialized.tryEmitNext(SinkManySerialized.java:100)
at app//reactor.core.publisher.InternalManySink.emitNext(InternalManySink.java:27)
at app//reactor.core.publisher.FluxRetryWhen$RetryWhenMainSubscriber.onError(FluxRetryWhen.java:190)
at app//reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:194)
at app//reactor.netty.http.client.HttpClientConnect$MonoHttpConnect$ClientTransportSubscriber.onError(HttpClientConnect.java:304)
at app//reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:194)
at app//reactor.netty.resources.DefaultPooledConnectionProvider$DisposableAcquire.onError(DefaultPooledConnectionProvider.java:155)
at app//reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121)
at app//reactor.netty.internal.shaded.reactor.pool.AbstractPool$Borrower.fail(AbstractPool.java:477)
at app//reactor.netty.internal.shaded.reactor.pool.SimpleDequePool.lambda$drainLoop$9(SimpleDequePool.java:431)
at app//reactor.core.publisher.FluxDoOnEach$DoOnEachSubscriber.onError(FluxDoOnEach.java:186)
at app//reactor.core.publisher.MonoCreate$DefaultMonoSink.error(MonoCreate.java:194)
at app//reactor.netty.resources.DefaultPooledConnectionProvider$PooledConnectionAllocator$PooledConnectionInitializer.onError(DefaultPooledConnectionProvider.java:538)
at app//reactor.core.publisher.MonoFlatMap$FlatMapMain.secondError(MonoFlatMap.java:192)
at app//reactor.core.publisher.MonoFlatMap$FlatMapInner.onError(MonoFlatMap.java:259)
at app//reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:106)
at app//reactor.core.publisher.Operators.error(Operators.java:198)
at app//reactor.core.publisher.MonoError.subscribe(MonoError.java:53)
at app//reactor.core.publisher.Mono.subscribe(Mono.java:4400)
at app//reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103)
at app//reactor.netty.transport.TransportConnector$MonoChannelPromise.tryFailure(TransportConnector.java:534)
at app//reactor.netty.transport.TransportConnector$MonoChannelPromise.setFailure(TransportConnector.java:488)
at app//reactor.netty.transport.TransportConnector.lambda$doConnect$7(TransportConnector.java:223)
at app//io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578)
at app//io.netty.util.concurrent.DefaultPromise.notifyListeners0(DefaultPromise.java:571)
at app//io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:550)
at app//io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:491)
at app//io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:616)
at app//io.netty.util.concurrent.DefaultPromise.setFailure0(DefaultPromise.java:609)
at app//io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:117)
at app//io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.fulfillConnectPromise(AbstractNioChannel.java:321)
at app//io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:337)
at app//io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:710)
at app//io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
at app//io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
at app//io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
at app//io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
at app//io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at app//io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at [email protected]/java.lang.Thread.run(Thread.java:833)
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:139)
at reactor.core.publisher.Mono.block(Mono.java:1731)
at org.springframework.test.web.reactive.server.DefaultWebTestClient$DefaultRequestBodyUriSpec.exchange(DefaultWebTestClient.java:361)
at com.optivem.kata.banking.system.BankAccountControllerSystemTest.getToken(BankAccountControllerSystemTest.java:52)
at com.optivem.kata.banking.system.BankAccountControllerSystemTest.should_open_account_given_valid_request(BankAccountControllerSystemTest.java:67)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy2/jdk.proxy2.$Proxy5.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: no further information: localhost/127.0.0.1:10000
Caused by: java.net.ConnectException: Connection refused: no further information
at java.base/sun.nio.ch.Net.pollConnect(Native Method)
at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672)
at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:946)
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:330)
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:710)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
Similar failure currently occurs on GitHub Actions too https://github.com/valentinacupac/banking-kata-java/actions/runs/3788816924/jobs/6441972612
BankAccountControllerSystemTest > should_open_account_given_valid_request() FAILED
org.springframework.web.reactive.function.client.WebClientRequestException at ExchangeFunctions.java:1[41](https://github.com/valentinacupac/banking-kata-java/actions/runs/3788816924/jobs/6441972612#step:8:42)
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException
Caused by: java.net.ConnectException at Errors.java:155
2022-12-27 16:54:10.0[47](https://github.com/valentinacupac/banking-kata-java/actions/runs/3788816924/jobs/6441972612#step:8:48) INFO 3365 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-12-27 16:54:10.0[49](https://github.com/valentinacupac/banking-kata-java/actions/runs/3788816924/jobs/6441972612#step:8:50) INFO 3365 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2022-12-27 16:54:10.0[53](https://github.com/valentinacupac/banking-kata-java/actions/runs/3788816924/jobs/6441972612#step:8:54) INFO 3365 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
108 tests completed, 1 failed
2022-12-27 16:[54](https://github.com/valentinacupac/banking-kata-java/actions/runs/3788816924/jobs/6441972612#step:8:55):10.070 INFO 3365 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-12-27 16:54:10.071 INFO 3365 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Shutdown initiated...
2022-12-27 16:54:10.073 INFO 3365 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Shutdown completed.
2022-12-27 16:54:10.081 INFO 3365 --- [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2022-12-27 16:54:10.081 INFO 3365 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-3 - Shutdown initiated...
2022-12-27 16:54:10.085 INFO 3365 --- [ionShutdownHook] com.zaxxer.hikari.HikariDataSource : HikariPool-3 - Shutdown completed.
HOTFIX
I have temporarily commented out the security-related code (see commit ef5ba9c) because BankAccountControllerSystemTest.should_open_account_given_valid_request was failing both locally & on GitHub Actions. That code could be brought back later, after we find out how to fix this issue to make the test pass.
Adding a secondary implementation for BankAccountRepository with MongoDB.
Make it configurable so that we can switch between them.
Evaluate pros and cons of Flyway vs Liquibase and implement one of these for our project
Hello,
Last weekend I tried to add on the project a plugin in order to banned some imports according to some packages. This can be very useful to check at the build step if we violated boundaries of the hexagonal architecture. For example thanks to this plugin, I can ensure that we can't have imports from infrastructure in domain package.
On top of that, if it's the case, we can add some exclusions to make explicit the todo list of what should be shift and ensure that no new banned imports will be added.
Maven Plugin:
Little problem, when I opened the banking-cata-java project, I was surprised because it is not a maven project but a gradle project.
And for gradle I don't know how I can use this useful plugin.
So if you have an idea on how we can have a similar check by using gradle I will be happy to talk with you :)
see below a maven sample to exclude infra imports in domain package :
<execution>
<id>check-imports</id>
<phase>process-sources</phase>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<RestrictImports>
<groups>
<group>
<reason>Forbid to depend to infrastructure/application (adapters primary/secondary) or external lib in domain</reason>
<basePackages>
<basePackage>com.example.demo.domain.**</basePackage>
</basePackages>
<bannedImports>
<bannedImport>com.example.demo.adapters.primaries.**</bannedImport>
<bannedImport>com.example.demo.adapters.secondaries.**</bannedImport>
<bannedImport>com.fasterxml.jackson.**</bannedImport>
<bannedImport>org.springframework.**</bannedImport>
<bannedImport>io.swagger.**</bannedImport>
<bannedImport>lombok.**</bannedImport>
</bannedImports>
<exclusions>
</exclusions>
</group>
<group>
<reason>Forbid to depend to infrastructure (secondary) in application (primary)</reason>
<basePackages>
<basePackage>com.example.demo.adapters.primaries.**</basePackage>
</basePackages>
<bannedImports>
<bannedImport>com.example.demo.adapters.secondaries.**</bannedImport>
</bannedImports>
<exclusions>
</exclusions>
</group>
<group>
<reason>Limit dependency of demo to the other domains (useful in case of modular monolith)</reason>
<basePackages>
<basePackage>com.example.demo.**</basePackage>
</basePackages>
<bannedImports>
<bannedImport>com.example.business.**</bannedImport>
</bannedImports>
</group>
</groups>
</RestrictImports>
<!-- You could have another rule instance here for restricting further imports -->
</rules>
</configuration>
</execution>
Mutation testing used to work, but stopped working after the addition of environment variables
The error is:
`
4:46:45 PM PIT >> SEVERE : Tests failing without mutation:
Description [testClass=com.optivem.kata.banking.BankingApplicationTests, name=[engine:junit-jupiter]/[class:com.optivem.kata.banking.BankingApplicationTests]/[method:contextLoads()]]
Exception in thread "main" org.pitest.help.PitHelpError: 1 tests did not pass without mutation when calculating line coverage. Mutation testing requires a green suite.
See http://pitest.org for more details.
at org.pitest.coverage.execute.DefaultCoverageGenerator.verifyBuildSuitableForMutationTesting(DefaultCoverageGenerator.java:115)
at org.pitest.coverage.execute.DefaultCoverageGenerator.calculateCoverage(DefaultCoverageGenerator.java:97)
at org.pitest.coverage.execute.DefaultCoverageGenerator.calculateCoverage(DefaultCoverageGenerator.java:52)
at org.pitest.mutationtest.tooling.MutationCoverage.runAnalysis(MutationCoverage.java:149)
at org.pitest.mutationtest.tooling.MutationCoverage.runReport(MutationCoverage.java:139)
at org.pitest.mutationtest.tooling.EntryPoint.execute(EntryPoint.java:123)
at org.pitest.mutationtest.tooling.EntryPoint.execute(EntryPoint.java:54)
at org.pitest.mutationtest.commandline.MutationCoverageReport.runReport(MutationCoverageReport.java:98)
at org.pitest.mutationtest.commandline.MutationCoverageReport.main(MutationCoverageReport.java:45)
`
I was searching for "Gradle Pitest Plugin Environment Variables"
I tried to set the environment variables, based on this https://stackoverflow.com/questions/56159077/set-environment-variables-in-gradle-pitest-plugin
tasks.named('pitest') { environment('env:POSTGRES_URL', 'jdbc:postgresql://localhost:5432/banking_kata') environment('$POSTGRES_USER', 'postgres') environment('POSTGRES_PASSWORD', 'admin') }
But still doesn't work.
Plan to continue further search.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.