I have several DTO objects.
public class MovieRequest {}
public class OtherTitle extends MovieRequest {}
public class ReleaseDate extends MovieRequest {}
These objects are uploaded using a generic contribution(DTO object)
public class ContributionNew<T extends MovieRequest> {} to the methods
void createOtherTitleContribution(
        final ContributionNew<OtherTitle> contribution,
        ...
);
void updateOtherTitleContribution(
        final ContributionUpdate<OtherTitle> contribution,
        ...
);
 void createReleaseDateContribution(
        final ContributionNew<ReleaseDate> contribution,
        ...
);
void updateReleaseDateContribution(
        final ContributionUpdate<ReleaseDate> contribution,
        ...
);
Information for films is more and these methods will be duplicated about 30 times f. e. createBoxOfficeContribution e.t.c
For example, the method of updating contributions looks like this
@Override
public void updateOtherTitleContribution(
        ContributionUpdate<OtherTitle> contribution,
        Long contributionId,
        Long userId
) throws ResourceNotFoundException {
    log.info("Called with contribution {}, contributionId {}, userId {}",
            contribution, contributionId, userId);
    final UserEntity user = this.findUser(userId);
    final ContributionEntity contributionEntity = this.findContribution(contributionId, EditStatus.WAITING, user, MovieField.OTHER_TITLE);
    this.validIds(contributionEntity.getIdsToAdd(), contribution.getElementsToAdd().keySet());
    this.validIds(contributionEntity.getIdsToUpdate().keySet(), contribution.getElementsToUpdate().keySet());
    this.validIds(contributionEntity.getIdsToDelete(), contribution.getIdsToDelete());
    this.cleanUpIdsToAdd(contributionEntity.getIdsToAdd(), contribution.getElementsToAdd().keySet(), contributionEntity.getMovie().getOtherTitles());
    this.cleanUpIdsToUpdate(contributionEntity.getIdsToUpdate(), contribution.getElementsToUpdate().keySet());
    this.cleanUpIdsToDelete(contributionEntity.getIdsToDelete(), contribution.getIdsToDelete());
    contribution.getElementsToAdd().forEach((key, value) -> {
        this.moviePersistenceService.updateOtherTitle(value, key, contributionEntity.getMovie());
    });
    contribution.getElementsToUpdate().forEach((key, value) -> {
        this.moviePersistenceService.updateOtherTitle(value, key, contributionEntity.getMovie());
    });
    contribution.getNewElementsToAdd()
            .forEach(otherTitle -> {
                final Long id = this.moviePersistenceService.createOtherTitle(otherTitle, contributionEntity.getMovie(), user);
                contributionEntity.getIdsToAdd().add(id);
            });
    contributionEntity.setSources(contribution.getSources());
    Optional.ofNullable(contribution.getComment()).ifPresent(contributionEntity::setUserComment);
}
As you can see, the only difference in these methods is to call the method
this.moviePersistenceService.updateOtherTitle(...)
And the method updateReleaseDateContribution calls
this.moviePersistenceService.updateReleaseDate(...)
As you can see the difference is only a few lines, and the old way the current code will have several thousand lines. Do you have any idea for a universal generic method? How to do it better?
