Configures to add default member domain values only to email confirmed
users. - using spring domain event - add adapter layer - add EventListener - modulization account, member
This commit is contained in:
@@ -4,6 +4,7 @@ import com.yam.app.account.domain.AccountNotFoundException;
|
||||
import com.yam.app.account.domain.AccountReader;
|
||||
import com.yam.app.account.domain.ConfirmRegisterAccountProcessor;
|
||||
import com.yam.app.account.domain.LoginAccountProcessor;
|
||||
import com.yam.app.account.domain.RegisterAccountConfirmEvent;
|
||||
import com.yam.app.account.domain.RegisterAccountEvent;
|
||||
import com.yam.app.account.domain.RegisterAccountProcessor;
|
||||
import com.yam.app.account.presentation.AccountResponse;
|
||||
@@ -47,6 +48,7 @@ public class AccountFacade {
|
||||
@Transactional
|
||||
public void registerConfirm(ConfirmRegisterAccountCommand command) {
|
||||
confirmRegisterProcessor.registerConfirm(command.getToken(), command.getEmail());
|
||||
publisher.publishEvent(new RegisterAccountConfirmEvent(command.getEmail()));
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
|
||||
@@ -51,4 +51,8 @@ public final class Account {
|
||||
public boolean isValidToken(String token) {
|
||||
return this.emailCheckToken.equals(token);
|
||||
}
|
||||
|
||||
public void addMember(Long memberId) {
|
||||
this.memberId = memberId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.yam.app.account.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public final class GenerateMemberEvent {
|
||||
|
||||
private final Long memberId;
|
||||
private final String email;
|
||||
|
||||
public GenerateMemberEvent(Long memberId, String email) {
|
||||
this.memberId = memberId;
|
||||
this.email = email;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.yam.app.account.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public final class RegisterAccountConfirmEvent {
|
||||
|
||||
private final String email;
|
||||
|
||||
public RegisterAccountConfirmEvent(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.yam.app.account.infrastructure;
|
||||
|
||||
import com.yam.app.account.domain.AccountNotFoundException;
|
||||
import com.yam.app.account.domain.AccountReader;
|
||||
import com.yam.app.account.domain.AccountRepository;
|
||||
import com.yam.app.account.domain.GenerateMemberEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Component
|
||||
public class AccountEventListener {
|
||||
|
||||
private final AccountReader accountReader;
|
||||
private final AccountRepository accountRepository;
|
||||
|
||||
public AccountEventListener(AccountReader accountReader,
|
||||
AccountRepository accountRepository) {
|
||||
this.accountReader = accountReader;
|
||||
this.accountRepository = accountRepository;
|
||||
}
|
||||
|
||||
@EventListener
|
||||
@Transactional
|
||||
public void handle(GenerateMemberEvent event) {
|
||||
var account = accountReader.findByEmail(event.getEmail())
|
||||
.orElseThrow(() -> new AccountNotFoundException(event.getEmail()));
|
||||
account.addMember(event.getMemberId());
|
||||
accountRepository.update(account);
|
||||
}
|
||||
}
|
||||
34
src/main/java/com/yam/app/adapter/DomainEventTranslator.java
Normal file
34
src/main/java/com/yam/app/adapter/DomainEventTranslator.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.yam.app.adapter;
|
||||
|
||||
import com.yam.app.account.domain.RegisterAccountConfirmEvent;
|
||||
import com.yam.app.member.domain.GenerateMemberEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.event.TransactionalEventListener;
|
||||
|
||||
@Component
|
||||
class DomainEventTranslator {
|
||||
|
||||
private final ApplicationEventPublisher publisher;
|
||||
|
||||
public DomainEventTranslator(ApplicationEventPublisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@Async
|
||||
@TransactionalEventListener
|
||||
public void handle(RegisterAccountConfirmEvent event) {
|
||||
publisher.publishEvent(
|
||||
new com.yam.app.member.domain.RegisterAccountConfirmEvent(event.getEmail()));
|
||||
}
|
||||
|
||||
@Async
|
||||
@TransactionalEventListener
|
||||
public void handle(GenerateMemberEvent event) {
|
||||
publisher.publishEvent(
|
||||
new com.yam.app.account.domain.GenerateMemberEvent(event.getMemberId(),
|
||||
event.getEmail()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.yam.app.member.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public final class GenerateMemberEvent {
|
||||
|
||||
private final Long memberId;
|
||||
private final String email;
|
||||
|
||||
public GenerateMemberEvent(Long memberId, String email) {
|
||||
this.memberId = memberId;
|
||||
this.email = email;
|
||||
}
|
||||
}
|
||||
18
src/main/java/com/yam/app/member/domain/Member.java
Normal file
18
src/main/java/com/yam/app/member/domain/Member.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.yam.app.member.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
public final class Member {
|
||||
|
||||
private Long id;
|
||||
private String nickname;
|
||||
private String image;
|
||||
|
||||
public Member(String nickname, String image) {
|
||||
this.nickname = nickname;
|
||||
this.image = image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.yam.app.member.domain;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface MemberReader {
|
||||
|
||||
Optional<Member> findByNickname(String nickname);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.yam.app.member.domain;
|
||||
|
||||
public interface MemberRepository {
|
||||
|
||||
void save(Member entity);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package com.yam.app.member.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public final class RegisterAccountConfirmEvent {
|
||||
|
||||
private final String email;
|
||||
|
||||
public RegisterAccountConfirmEvent(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.yam.app.member.infrastructure;
|
||||
|
||||
import com.yam.app.member.domain.GenerateMemberEvent;
|
||||
import com.yam.app.member.domain.Member;
|
||||
import com.yam.app.member.domain.MemberReader;
|
||||
import com.yam.app.member.domain.MemberRepository;
|
||||
import com.yam.app.member.domain.RegisterAccountConfirmEvent;
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Component
|
||||
public class MemberEventListener {
|
||||
|
||||
private final MemberReader memberReader;
|
||||
private final MemberRepository memberRepository;
|
||||
private final ApplicationEventPublisher publisher;
|
||||
|
||||
public MemberEventListener(MemberReader memberReader,
|
||||
MemberRepository memberRepository,
|
||||
ApplicationEventPublisher publisher) {
|
||||
this.memberReader = memberReader;
|
||||
this.memberRepository = memberRepository;
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
@EventListener
|
||||
@Transactional
|
||||
public void handle(RegisterAccountConfirmEvent event) {
|
||||
var nickname = event.getEmail().split("@")[0];
|
||||
memberRepository.save(new Member(nickname, "temp.png"));
|
||||
var member = memberReader.findByNickname(nickname)
|
||||
.orElseThrow(IllegalArgumentException::new);
|
||||
publisher.publishEvent(new GenerateMemberEvent(member.getId(), event.getEmail()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.yam.app.member.infrastructure;
|
||||
|
||||
import com.yam.app.member.domain.MemberReader;
|
||||
import com.yam.app.member.domain.MemberRepository;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class MemberModuleConfiguration {
|
||||
|
||||
@Bean
|
||||
public MemberReader memberReader(SqlSessionTemplate template) {
|
||||
return new MybatisMemberRepository(template);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MemberRepository memberRepository(SqlSessionTemplate template) {
|
||||
return new MybatisMemberRepository(template);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.yam.app.member.infrastructure;
|
||||
|
||||
import com.yam.app.member.domain.Member;
|
||||
import com.yam.app.member.domain.MemberReader;
|
||||
import com.yam.app.member.domain.MemberRepository;
|
||||
import java.util.Optional;
|
||||
import org.mybatis.spring.SqlSessionTemplate;
|
||||
|
||||
public final class MybatisMemberRepository implements MemberRepository, MemberReader {
|
||||
|
||||
private final SqlSessionTemplate template;
|
||||
|
||||
private static final String SAVE_FQCN = "com.yam.app.member.domain.MemberRepository.save";
|
||||
|
||||
public MybatisMemberRepository(SqlSessionTemplate template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Member> findByNickname(String nickname) {
|
||||
return template.getMapper(MemberReader.class).findByNickname(nickname);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Member entity) {
|
||||
int result = template.insert(SAVE_FQCN, entity);
|
||||
if (result != 1) {
|
||||
throw new RuntimeException(
|
||||
String.format("There was a problem saving the object : %s", entity));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
withdraw = #{withdraw},
|
||||
joined_at = #{joinedAt},
|
||||
role = #{role},
|
||||
last_modified_at = NOW()
|
||||
last_modified_at = NOW(),
|
||||
member_id = #{memberId}
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
|
||||
12
src/main/resources/mapper/xml/MemberCommandMapper.xml
Normal file
12
src/main/resources/mapper/xml/MemberCommandMapper.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="com.yam.app.member.domain.MemberRepository">
|
||||
|
||||
<insert id="save" parameterType="com.yam.app.member.domain.Member">
|
||||
INSERT
|
||||
INTO MEMBER(nickname, image)
|
||||
VALUES (#{nickname}, #{image})
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
11
src/main/resources/mapper/xml/MemberQueryMapper.xml
Normal file
11
src/main/resources/mapper/xml/MemberQueryMapper.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="com.yam.app.member.domain.MemberReader">
|
||||
|
||||
<select id="findByNickname" parameterType="String"
|
||||
resultType="com.yam.app.member.domain.Member">
|
||||
SELECT * FROM member WHERE nickname = #{nickname}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -25,8 +25,5 @@ create table member(
|
||||
alter table account
|
||||
add constraint UK_q0uja26qgu1atulenwup9rxyr unique (email);
|
||||
|
||||
alter table member
|
||||
add constraint UK_hh9kg6jti4n1eoiertn2k6qsc unique (nickname);
|
||||
|
||||
alter table account
|
||||
add constraint FKr5j0huynd7nsv1s7e9vb8qvwo foreign key (member_id) references member;
|
||||
|
||||
@@ -21,10 +21,12 @@ final class ArchUnitTests {
|
||||
.layer("Presentation").definedBy("..presentation..")
|
||||
.layer("Infrastructure").definedBy("..infrastructure..")
|
||||
.layer("Integration").definedBy("..integration..")
|
||||
.layer("Adapter").definedBy("..adapter..")
|
||||
|
||||
.whereLayer("Presentation").mayOnlyBeAccessedByLayers("Application", "Integration")
|
||||
.whereLayer("Application").mayOnlyBeAccessedByLayers("Presentation", "Domain")
|
||||
.whereLayer("Domain").mayOnlyBeAccessedByLayers("Application", "Infrastructure")
|
||||
.whereLayer("Domain").mayOnlyBeAccessedByLayers("Application", "Infrastructure", "Adapter")
|
||||
.whereLayer("Infrastructure").mayOnlyBeAccessedByLayers("Presentation", "Integration")
|
||||
.whereLayer("Adapter").mayNotBeAccessedByAnyLayer()
|
||||
.whereLayer("Integration").mayNotBeAccessedByAnyLayer();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user