Commit eea7e3f9 authored by Julien SADAOUI's avatar Julien SADAOUI
Browse files

feat: spring-reactor wording

parent 0526bdc6
<?xml version="1.0" encoding="UTF-8"?>
<testsuite name="fr.ippon.codingdojo.web.TransactionResourceTest" tests="3" skipped="0" failures="0" errors="0" timestamp="2018-12-09T19:28:46" hostname="mbp-de-julien.home" time="0.736">
<properties/>
<testcase name="should_create_credit_transaction()" classname="fr.ippon.codingdojo.web.TransactionResourceTest" time="0.649"/>
<testcase name="should_create_debit_transaction()" classname="fr.ippon.codingdojo.web.TransactionResourceTest" time="0.02"/>
<testcase name="should_get_all_transactions()" classname="fr.ippon.codingdojo.web.TransactionResourceTest" time="0.064"/>
<system-out><![CDATA[20:28:41.350 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating CacheAwareContextLoaderDelegate from class [org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate]
20:28:41.366 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating BootstrapContext using constructor [public org.springframework.test.context.support.DefaultBootstrapContext(java.lang.Class,org.springframework.test.context.CacheAwareContextLoaderDelegate)]
20:28:41.384 [Test worker] DEBUG org.springframework.test.context.BootstrapUtils - Instantiating TestContextBootstrapper for test class [fr.ippon.codingdojo.web.TransactionResourceTest] from class [org.springframework.boot.test.context.SpringBootTestContextBootstrapper]
20:28:41.390 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Neither @ContextConfiguration nor @ContextHierarchy found for test class [fr.ippon.codingdojo.web.TransactionResourceTest], using SpringBootContextLoader
20:28:41.393 [Test worker] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [fr.ippon.codingdojo.web.TransactionResourceTest]: class path resource [fr/ippon/codingdojo/web/TransactionResourceTest-context.xml] does not exist
20:28:41.393 [Test worker] DEBUG org.springframework.test.context.support.AbstractContextLoader - Did not detect default resource location for test class [fr.ippon.codingdojo.web.TransactionResourceTest]: class path resource [fr/ippon/codingdojo/web/TransactionResourceTestContext.groovy] does not exist
20:28:41.394 [Test worker] INFO org.springframework.test.context.support.AbstractContextLoader - Could not detect default resource locations for test class [fr.ippon.codingdojo.web.TransactionResourceTest]: no resource found for suffixes {-context.xml, Context.groovy}.
20:28:41.394 [Test worker] INFO org.springframework.test.context.support.AnnotationConfigContextLoaderUtils - Could not detect default configuration classes for test class [fr.ippon.codingdojo.web.TransactionResourceTest]: TransactionResourceTest does not declare any static, non-private, non-final, nested classes annotated with @Configuration.
20:28:41.423 [Test worker] DEBUG org.springframework.test.context.support.ActiveProfilesUtils - Could not find an 'annotation declaring class' for annotation type [org.springframework.test.context.ActiveProfiles] and class [fr.ippon.codingdojo.web.TransactionResourceTest]
20:28:41.489 [Test worker] DEBUG org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider - Identified candidate component class: file [/Users/julien/Development/coding-dojo/reactive-programming/reactive-programming/spring-reactor/build/classes/java/main/fr/ippon/codingdojo/Main.class]
20:28:41.491 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Found @SpringBootConfiguration fr.ippon.codingdojo.Main for test class fr.ippon.codingdojo.web.TransactionResourceTest
20:28:41.561 [Test worker] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - @TestExecutionListeners is not present for class [fr.ippon.codingdojo.web.TransactionResourceTest]: using defaults.
20:28:41.562 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Loaded default TestExecutionListener class names from location [META-INF/spring.factories]: [org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener, org.springframework.security.test.context.support.ReactorContextTestExecutionListener, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener, org.springframework.test.context.web.ServletTestExecutionListener, org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener, org.springframework.test.context.support.DependencyInjectionTestExecutionListener, org.springframework.test.context.support.DirtiesContextTestExecutionListener, org.springframework.test.context.transaction.TransactionalTestExecutionListener, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener]
20:28:41.570 [Test worker] DEBUG org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Skipping candidate TestExecutionListener [org.springframework.test.context.web.ServletTestExecutionListener] due to a missing dependency. Specify custom listener classes or make the default listener classes and their required dependencies available. Offending class: [javax/servlet/ServletContext]
20:28:41.576 [Test worker] INFO org.springframework.boot.test.context.SpringBootTestContextBootstrapper - Using TestExecutionListeners: [org.springframework.test.context.support.DirtiesContextBeforeModesTestExecutionListener@1c19b09d, org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener@3f10500a, org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener@1a6656e9, org.springframework.test.context.support.DirtiesContextTestExecutionListener@5813885f, org.springframework.test.context.transaction.TransactionalTestExecutionListener@95f4698, org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener@3472c7b9, org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener@1c8b0ec0, org.springframework.security.test.context.support.ReactorContextTestExecutionListener@581e2c7e, org.springframework.boot.test.autoconfigure.restdocs.RestDocsTestExecutionListener@2b06da63, org.springframework.boot.test.autoconfigure.web.client.MockRestServiceServerResetTestExecutionListener@9eb8fb5, org.springframework.boot.test.autoconfigure.web.servlet.MockMvcPrintOnlyOnFailureTestExecutionListener@4d527d46, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverTestExecutionListener@6406d54e, org.springframework.boot.test.mock.mockito.ResetMocksTestExecutionListener@794ece6f]
20:28:41.580 [Test worker] DEBUG org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener - Before test class: context [DefaultTestContext@69ce4d42 testClass = TransactionResourceTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [ReactiveWebMergedContextConfiguration@16bd9604 testClass = TransactionResourceTest, locations = '{}', classes = '{class fr.ippon.codingdojo.Main}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5bc75420, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@2a74cca1, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@1729f883, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@1d85c65f, org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizer@4dac38fc], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]], class annotated with @DirtiesContext [false] with mode [null].
20:28:41.586 [Test worker] DEBUG org.springframework.test.context.support.DependencyInjectionTestExecutionListener - Performing dependency injection for test context [[DefaultTestContext@69ce4d42 testClass = TransactionResourceTest, testInstance = fr.ippon.codingdojo.web.TransactionResourceTest@5909aa8f, testMethod = [null], testException = [null], mergedContextConfiguration = [ReactiveWebMergedContextConfiguration@16bd9604 testClass = TransactionResourceTest, locations = '{}', classes = '{class fr.ippon.codingdojo.Main}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true}', contextCustomizers = set[org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5bc75420, org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@2a74cca1, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@1729f883, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@1d85c65f, org.springframework.boot.test.web.reactive.server.WebTestClientContextCustomizer@4dac38fc], contextLoader = 'org.springframework.boot.test.context.SpringBootContextLoader', parent = [null]], attributes = map[[empty]]]].
20:28:41.602 [Test worker] DEBUG org.springframework.test.context.support.TestPropertySourceUtils - Adding inlined properties to environment: {spring.jmx.enabled=false, org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true, server.port=-1}
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.1.RELEASE)
2018-12-09 20:28:41.908 INFO 42889 --- [ Test worker] f.i.c.web.TransactionResourceTest : Starting TransactionResourceTest on mbp-de-julien.home with PID 42889 (started by julien in /Users/julien/Development/coding-dojo/reactive-programming/reactive-programming/spring-reactor)
2018-12-09 20:28:41.909 DEBUG 42889 --- [ Test worker] f.i.c.web.TransactionResourceTest : Running with Spring Boot v2.1.1.RELEASE, Spring v5.1.3.RELEASE
2018-12-09 20:28:41.910 INFO 42889 --- [ Test worker] f.i.c.web.TransactionResourceTest : No active profile set, falling back to default profiles: default
2018-12-09 20:28:45.009 DEBUG 42889 --- [ Test worker] f.i.c.config.DatabaseConfiguration : Configuring Mongobee
2018-12-09 20:28:45.555 WARN 42889 --- [ Test worker] o.s.security.core.userdetails.User : User.withDefaultPasswordEncoder() is considered unsafe for production and is only intended for sample applications.
2018-12-09 20:28:46.166 INFO 42889 --- [ Test worker] f.i.c.web.TransactionResourceTest : Started TransactionResourceTest in 4.558 seconds (JVM running for 5.997)
2018-12-09 20:28:46.684 DEBUG 42889 --- [ Test worker] f.i.codingdojo.web.TransactionResource : REST request to create Credit Operation : (Account Number=5c0d6ceeb4cd4ea7898c80b2/Amount=210)
2018-12-09 20:28:46.729 DEBUG 42889 --- [ntLoopGroup-2-2] f.i.c.service.impl.AccountServiceImpl : Account after transaction: Account(number=5c0d6ceeb4cd4ea7898c80b2, description=Checking Account, balance=310, transactions=[Transaction(amount=210, operation=CREDIT, date=2018-12-09)], customerId=customer@email.org)
2018-12-09 20:28:46.834 DEBUG 42889 --- [ Test worker] f.i.codingdojo.web.TransactionResource : REST request to create Debit Operation : (Account Number=5c0d6ceeb4cd4ea7898c80b3/Amount=150)
2018-12-09 20:28:46.842 DEBUG 42889 --- [ntLoopGroup-2-2] f.i.c.service.impl.AccountServiceImpl : Account after transaction: Account(number=5c0d6ceeb4cd4ea7898c80b3, description=Checking Account, balance=-50, transactions=[Transaction(amount=150, operation=DEBIT, date=2018-12-09)], customerId=customer@email.org)
2018-12-09 20:28:46.854 DEBUG 42889 --- [ Test worker] f.i.codingdojo.web.TransactionResource : REST request to create Credit Operation : (Account Number=5c0d6ceeb4cd4ea7898c80b4/Amount=20)
2018-12-09 20:28:46.861 DEBUG 42889 --- [ntLoopGroup-2-2] f.i.c.service.impl.AccountServiceImpl : Account after transaction: Account(number=5c0d6ceeb4cd4ea7898c80b4, description=Checking Account, balance=120, transactions=[Transaction(amount=20, operation=CREDIT, date=2018-12-09)], customerId=customer@email.org)
2018-12-09 20:28:46.866 DEBUG 42889 --- [ Test worker] f.i.codingdojo.web.TransactionResource : REST request to create Debit Operation : (Account Number=5c0d6ceeb4cd4ea7898c80b4/Amount=30)
2018-12-09 20:28:46.875 DEBUG 42889 --- [ntLoopGroup-2-2] f.i.c.service.impl.AccountServiceImpl : Account after transaction: Account(number=5c0d6ceeb4cd4ea7898c80b4, description=Checking Account, balance=90, transactions=[Transaction(amount=20, operation=CREDIT, date=2018-12-09), Transaction(amount=30, operation=DEBIT, date=2018-12-09)], customerId=customer@email.org)
]]></system-out>
<system-err><![CDATA[]]></system-err>
</testsuite>
Manifest-Version: 1.0
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: fr.ippon.codingdojo.Main
rootProject.name = "spring-reactor"
rootProject.name = "spring-reactor_solution"
package fr.ippon.codingdojo.web;
import fr.ippon.codingdojo.domain.Account;
import fr.ippon.codingdojo.service.AccountService;
import fr.ippon.codingdojo.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import javax.validation.Valid;
@RestController
@RequestMapping("/account")
public class AccountController {
private final UserService userService;
private final AccountService accountService;
public AccountController(UserService userService, AccountService accountService) {
this.userService = userService;
this.accountService = accountService;
}
@PostMapping
public Mono<ResponseEntity<Account>> create(@Valid @RequestBody Account account) {
return accountService.openAccount(account)
.map(createdAccount -> new ResponseEntity<>(createdAccount, HttpStatus.CREATED));
}
@DeleteMapping("/{number}")
public Mono<ResponseEntity<Void>> delete(@PathVariable("number") String accountNumber) {
return accountService.closeAccount(accountNumber)
.map(ResponseEntity::ok);
}
@GetMapping
public Flux<Account> getAll() {
return userService.getCurrentUser()
.flatMapMany(user -> accountService.getAccountsByCustomer(user.getEmail()));
}
@GetMapping("/{number}")
public Mono<ResponseEntity<Account>> get(@PathVariable("number") String accountNumber) {
return userService.getCurrentUser()
.flatMapMany(user -> accountService.getAccountsByCustomer(user.getEmail()))
.filter(account -> account.getNumber().equals(accountNumber))
.elementAt(0)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
}
\ No newline at end of file
package fr.ippon.codingdojo.web;
import fr.ippon.codingdojo.domain.Transaction;
import fr.ippon.codingdojo.service.AccountService;
import fr.ippon.codingdojo.service.UserService;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.math.BigDecimal;
@RestController
@RequestMapping("/account/{number}/transaction")
public class TransactionController {
private final AccountService accountService;
private final UserService userService;
public TransactionController(AccountService accountService, UserService userService) {
this.accountService = accountService;
this.userService = userService;
}
@GetMapping
public Flux<Transaction> getAll(@PathVariable("number") String accountNumber) {
return accountService.getTransactionsByAccount(accountNumber);
}
@PostMapping("/credit")
public Mono<ResponseEntity<Transaction>> credit(@PathVariable("number") String accountNumber, @RequestBody BigDecimal amount) {
return userService.getCurrentUser()
.flatMap(user -> accountService.creditAccount(user.getEmail(), accountNumber, amount))
.map(createdTransaction -> new ResponseEntity<>(createdTransaction, HttpStatus.CREATED))
.switchIfEmpty(Mono.just(ResponseEntity.notFound().build()));
}
@PostMapping("/debit")
public Mono<ResponseEntity<Transaction>> debit(@PathVariable("number") String accountNumber, @RequestBody BigDecimal amount) {
return userService.getCurrentUser()
.flatMap(user -> accountService.debitAccount(user.getEmail(), accountNumber, amount))
.map(createdTransaction -> new ResponseEntity<>(createdTransaction, HttpStatus.CREATED))
.switchIfEmpty(Mono.just(ResponseEntity.notFound().build()));
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<configuration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d [%thread] %-5level %class - %msg%n</pattern>
</encoder>
</appender>
<logger name="org.jsadaoui.demo" level="DEBUG"/>
<logger name="ch.qos.logback" level="WARN"/>
<logger name="org.springframework" level="WARN"/>
<root level="debug">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
......@@ -12,8 +12,8 @@ import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.server.SecurityWebFilterChain;
@Configuration
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
// TODO Activez la sécurité en mode réactif
// TODO Ajoutez la gestion des annotations de sécurité
public class SecurityConfiguration {
@Bean
......@@ -26,9 +26,6 @@ public class SecurityConfiguration {
.build();
}
@Bean
public ReactiveUserDetailsService userDetailsRepository(UserService userService) {
return new MongoReactiveUserDetailsService(userService, User.withDefaultPasswordEncoder());
}
// TODO Ajoutez un Bean UserDetailsService
}
......@@ -24,12 +24,12 @@ public class Account {
@Id
private String number;
@NotNull
private BigDecimal balance;
@Size(min = 1, max = 255)
private String description;
@NotNull
private BigDecimal balance;
@Builder.Default
private Set<Transaction> transactions = new HashSet<>();
......
......@@ -2,10 +2,10 @@ package fr.ippon.codingdojo.repository;
import fr.ippon.codingdojo.domain.Account;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface AccountRepository extends ReactiveMongoRepository<Account, String> {
Flux<Account> findByCustomerId(String customerId);
Mono<Account> findByCustomerIdAndNumber(String customerId, String number);
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment