abidinberkay
abidinberkay

Reputation: 2025

How to design "delete user flow" in monolith application with Spring Boot?

I have a monolith spring boot application and I have a user for the program. I want to make an endpoint to delete user, but my problem is there are so many entities and Jpa repository interfaces related to the user. When I want to delete a user, I need to inject so many repository interface into the related deletion service like:

    @Service
    public class DeletionService {
    
        private static final int S3_DELETION_KEY_LIMIT = 1000;
    
        private final OfficeRepository officeRepository;
        private final AdvertRepository advertRepository;
        private final UserRepository userRepository;
        private final AdvertSearchRepository advertSearchRepository;
        private final AdvertPricesRepository advertPricesRepository;
        private final AdvertFacilityRepository advertFacilityRepository;
        private final AdvertVirtualPackagesRepository advertVirtualPackagesRepository;
        private final BookingRepository bookingRepository;
        private final AdvertMediasRepository advertMediasRepository;
        private final MediaRepository mediaRepository;
        private final AmazonS3Service amazonS3Service;
        private final OfficeBuildingSecurityRepository officeBuildingSecurityRepository;
        private final OfficeCyberSecurityRepository officeCyberSecurityRepository;
        private final OfficeFacilityRepository officeFacilityRepository;
        private final OfficeMediasRepository officeMediasRepository;
        private final OfficeNotificationsRepository officeNotificationsRepository;
        private final OfficePropertiesRepository officePropertiesRepository;
        private final OfficeRoomsRepository officeRoomsRepository;
        private final OfficeViewsRepository officeViewsRepository;
        private final OwnerCompanyRepository ownerCompanyRepository;
        private final PushNotificationTokenRepository pushNotificationTokenRepository;
... and so many other repositories and 


//CONSTRUCTOR etc.

Everything in the program is related to the user and If I delete the user then everything goes off. I am not sure it is correct style or flow, how can I do this with a better approach if there is any other option in monolith app? Do I have to inject all related repository interfaces into the current service ?

Note: I am not using any queue service like Kafka, Sqs, RabbitMq etc.

Upvotes: 0

Views: 66

Answers (1)

Andrey B. Panfilov
Andrey B. Panfilov

Reputation: 6111

That does not really matter what is you architecture, monolithic or microservices - patterns remain the same.

Basic idea: decompose that large delete operation into individual steps, for example:

public interface DeleteStep<E> {

    void delete(E entity);

}

@Component
public class DeleteFiles implements DeleteStep<User> {

    @Autowired
    AmazonS3Service amazonS3Service

    @Override
    public void delete(User user) {
         amazonS3Service.deleteUserFiles(user);
    }

}


@Component
public class DeleteNotifications implements DeleteStep<User> {

    @Autowired
    OfficeNotificationsRepository officeNotificationsRepository;

    @Override
    public void delete(DmUser user) {
        officeNotificationsRepository.deleteUserNotifications(user);
    }

}

Now the body of our DeletionService would look like:

@Autowired
ObjectProvider<DeleteStep<User>> userDeletionSteps;

public void deleteUser(User user) {
    userDeletionSteps.forEach(s -> s.delete(user));
}

Now we may actually improve that basic idea via taking advantage of application events, for example:

public class UserDeleteEvent {

    private final User user;

    public UserDeleteEvent(User user) {
        this.user = user;
    }

    public User getUser() {
        return user;
    }
    
}


interface OfficeNotificationsRepository extends ... {

    @EventListener(UserDeleteEvent.class)
    default void onUserDeleted(UserDeleteEvent event) {
        deleteUserNotifications(event.getUser());
    }

}

class AmazonS3Service ... {

    @EventListener(UserDeleteEvent.class)
    void onUserDeleted(UserDeleteEvent event) {
        deteteUserFiles(event.getUser());
    }

}

and now our DeletionService turns into:

@Autowired
ApplicationEventPublisher eventPublisher;

public void deleteUser(User user) {
    eventPublisher.publishEvent(new UserDeleteEvent(user));
}

Moreover, we may take advantage of @DomainEvents and get rid of DeletionService - UserRepository may dispatch application events.

Upvotes: 0

Related Questions