Commit 747f9b62 authored by Daniel Gerhardt's avatar Daniel Gerhardt

Introduce new abstractions for services and repositories

Repositories now implement Spring Data interfaces. Basic CouchDB
operations are now implemented once by `CouchDbCrudRepository` instead
of having redundant methods to handle each design document.
parent 39790f9c
......@@ -143,6 +143,10 @@
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mail</artifactId>
......
......@@ -21,10 +21,11 @@ import de.thm.arsnova.entities.Answer;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.User;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface AnswerRepository {
public interface AnswerRepository extends CrudRepository<Answer, String> {
Answer get(String id);
Answer getMyAnswer(User me, String questionId, int piRound);
List<Answer> getAnswers(String contentId, int piRound);
......
......@@ -3,10 +3,11 @@ package de.thm.arsnova.persistance;
import de.thm.arsnova.entities.Comment;
import de.thm.arsnova.entities.CommentReadingCount;
import de.thm.arsnova.entities.User;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface CommentRepository {
public interface CommentRepository extends CrudRepository<Comment, String> {
int getInterposedCount(String sessionKey);
CommentReadingCount getInterposedReadingCount(String sessionId);
CommentReadingCount getInterposedReadingCount(String sessionId, User user);
......
......@@ -2,10 +2,11 @@ package de.thm.arsnova.persistance;
import de.thm.arsnova.entities.Content;
import de.thm.arsnova.entities.User;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface ContentRepository {
public interface ContentRepository extends CrudRepository<Content, String> {
List<Content> getQuestions(Object... keys);
Content getQuestion(String id);
Content saveQuestion(String sessionId, Content content);
......
......@@ -18,10 +18,11 @@
package de.thm.arsnova.persistance;
import de.thm.arsnova.entities.Motd;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface MotdRepository {
public interface MotdRepository extends CrudRepository<Motd, String> {
List<Motd> getAdminMotds();
List<Motd> getMotdsForAll();
List<Motd> getMotdsForLoggedIn();
......
......@@ -23,10 +23,11 @@ import de.thm.arsnova.entities.Session;
import de.thm.arsnova.entities.SessionInfo;
import de.thm.arsnova.entities.User;
import de.thm.arsnova.entities.transport.ImportExportSession;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface SessionRepository {
public interface SessionRepository extends CrudRepository<Session, String> {
Session getSessionFromId(String sessionId);
Session getSessionFromKeyword(String keyword);
Session saveSession(User user, Session session);
......
......@@ -18,10 +18,9 @@
package de.thm.arsnova.persistance;
import de.thm.arsnova.entities.DbUser;
import org.springframework.data.repository.CrudRepository;
public interface UserRepository {
DbUser findUserByUsername(String username);
DbUser createOrUpdateUser(DbUser user);
boolean deleteUser(DbUser user);
public interface UserRepository extends CrudRepository<DbUser, String> {
DbUser findByUsername(String username);
int deleteInactiveUsers(long lastActivityBefore);
}
......@@ -20,7 +20,6 @@ import org.ektorp.DbAccessException;
import org.ektorp.DocumentOperationResult;
import org.ektorp.UpdateConflictException;
import org.ektorp.ViewResult;
import org.ektorp.support.CouchDbRepositorySupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -35,7 +34,7 @@ import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Collectors;
public class CouchDbAnswerRepository extends CouchDbRepositorySupport<Answer> implements AnswerRepository, ApplicationEventPublisherAware {
public class CouchDbAnswerRepository extends CouchDbCrudRepository<Answer> implements AnswerRepository, ApplicationEventPublisherAware {
private static final int BULK_PARTITION_SIZE = 500;
private static final Logger logger = LoggerFactory.getLogger(CouchDbAnswerRepository.class);
......@@ -53,7 +52,7 @@ public class CouchDbAnswerRepository extends CouchDbRepositorySupport<Answer> im
private ApplicationEventPublisher publisher;
public CouchDbAnswerRepository(final CouchDbConnector db, final boolean createIfNotExists) {
super(Answer.class, db, createIfNotExists);
super(Answer.class, db, "by_sessionid", createIfNotExists);
}
@Scheduled(fixedDelay = 5000)
......
......@@ -14,14 +14,13 @@ import org.ektorp.CouchDbConnector;
import org.ektorp.DocumentNotFoundException;
import org.ektorp.UpdateConflictException;
import org.ektorp.ViewResult;
import org.ektorp.support.CouchDbRepositorySupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
public class CouchDbCommentRepository extends CouchDbRepositorySupport<Comment> implements CommentRepository {
public class CouchDbCommentRepository extends CouchDbCrudRepository<Comment> implements CommentRepository {
private static final Logger logger = LoggerFactory.getLogger(CouchDbCommentRepository.class);
@Autowired
......@@ -31,7 +30,7 @@ public class CouchDbCommentRepository extends CouchDbRepositorySupport<Comment>
private SessionRepository sessionRepository;
public CouchDbCommentRepository(final CouchDbConnector db, final boolean createIfNotExists) {
super(Comment.class, db, createIfNotExists);
super(Comment.class, db, "by_sessionid", createIfNotExists);
}
@Override
......
......@@ -12,7 +12,6 @@ import org.ektorp.DocumentNotFoundException;
import org.ektorp.UpdateConflictException;
import org.ektorp.ViewQuery;
import org.ektorp.ViewResult;
import org.ektorp.support.CouchDbRepositorySupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -29,7 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
public class CouchDbContentRepository extends CouchDbRepositorySupport<Content> implements ContentRepository {
public class CouchDbContentRepository extends CouchDbCrudRepository<Content> implements ContentRepository {
private static final Logger logger = LoggerFactory.getLogger(CouchDbContentRepository.class);
@Autowired
......@@ -39,7 +38,7 @@ public class CouchDbContentRepository extends CouchDbRepositorySupport<Content>
private AnswerRepository answerRepository;
public CouchDbContentRepository(final CouchDbConnector db, final boolean createIfNotExists) {
super(Content.class, db, createIfNotExists);
super(Content.class, db, "by_sessionid", createIfNotExists);
}
@Cacheable("skillquestions")
......
package de.thm.arsnova.persistance.couchdb;
import de.thm.arsnova.entities.Entity;
import org.ektorp.BulkDeleteDocument;
import org.ektorp.CouchDbConnector;
import org.ektorp.support.CouchDbRepositorySupport;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.NoRepositoryBean;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
@NoRepositoryBean
abstract class CouchDbCrudRepository<T extends Entity> extends CouchDbRepositorySupport<T> implements CrudRepository<T, String> {
private String countableAllViewName;
protected CouchDbCrudRepository(
final Class<T> type,
final CouchDbConnector db,
final String designDocName,
final String countableAllViewName,
final boolean createIfNotExists) {
super(type, db, designDocName, createIfNotExists);
this.countableAllViewName = countableAllViewName;
}
protected CouchDbCrudRepository(
final Class<T> type,
final CouchDbConnector db,
final String countableAllViewName,
final boolean createIfNotExists) {
super(type, db, createIfNotExists);
this.countableAllViewName = countableAllViewName;
}
protected String getCountableAllViewName() {
return countableAllViewName;
}
@Override
public <S extends T> S save(final S entity) {
final String id = entity.getId();
if (id != null) {
db.update(entity);
} else {
db.create(entity);
}
return entity;
}
@Override
public <S extends T> Iterable<S> save(final Iterable<S> entities) {
if (!(entities instanceof Collection)) {
throw new IllegalArgumentException("Implementation only supports Collections.");
}
db.executeBulk((Collection<S>) entities);
return entities;
}
@Override
public T findOne(final String id) {
return get(id);
}
@Override
public boolean exists(final String id) {
return contains(id);
}
@Override
public Iterable<T> findAll() {
return db.queryView(createQuery(countableAllViewName).includeDocs(true), type);
}
@Override
public Iterable<T> findAll(final Iterable<String> strings) {
if (!(strings instanceof Collection)) {
throw new IllegalArgumentException("Implementation only supports Collections.");
}
return db.queryView(createQuery(countableAllViewName)
.keys((Collection<String>) strings)
.includeDocs(true),
type);
}
@Override
public long count() {
return db.queryView(createQuery(countableAllViewName).reduce(true)).getRows().get(0).getValueAsInt();
}
@Override
public void delete(final String id) {
T entity = get(id);
db.delete(id, entity.getRevision());
}
@Override
public void delete(final T entity) {
db.delete(entity);
}
@Override
public void delete(final Iterable<? extends T> entities) {
if (!(entities instanceof Collection)) {
throw new IllegalArgumentException("Implementation only supports Collections.");
}
final List<BulkDeleteDocument> docs = ((Collection<? extends T>) entities).stream()
.map(entity -> new BulkDeleteDocument(entity.getId(), entity.getRevision()))
.collect(Collectors.toList());
db.executeBulk(docs);
}
@Override
public void deleteAll() {
throw new UnsupportedOperationException("Deletion of all entities is not supported for security reasons.");
}
}
......@@ -21,7 +21,6 @@ import de.thm.arsnova.entities.Motd;
import de.thm.arsnova.persistance.MotdRepository;
import de.thm.arsnova.services.SessionService;
import org.ektorp.CouchDbConnector;
import org.ektorp.support.CouchDbRepositorySupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -31,14 +30,14 @@ import org.springframework.cache.annotation.Cacheable;
import java.util.ArrayList;
import java.util.List;
public class CouchDbMotdRepository extends CouchDbRepositorySupport<Motd> implements MotdRepository {
public class CouchDbMotdRepository extends CouchDbCrudRepository<Motd> implements MotdRepository {
private static final Logger logger = LoggerFactory.getLogger(CouchDbMotdRepository.class);
@Autowired
private SessionService sessionService;
public CouchDbMotdRepository(final CouchDbConnector db, final boolean createIfNotExists) {
super(Motd.class, db, createIfNotExists);
super(Motd.class, db, "by_sessionkey", createIfNotExists);
}
@Override
......
......@@ -36,7 +36,6 @@ import org.ektorp.DocumentNotFoundException;
import org.ektorp.UpdateConflictException;
import org.ektorp.ViewQuery;
import org.ektorp.ViewResult;
import org.ektorp.support.CouchDbRepositorySupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -55,7 +54,7 @@ import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class CouchDbSessionRepository extends CouchDbRepositorySupport<Session> implements SessionRepository {
public class CouchDbSessionRepository extends CouchDbCrudRepository<Session> implements SessionRepository {
private static final Logger logger = LoggerFactory.getLogger(CouchDbSessionRepository.class);
@Autowired
......@@ -68,7 +67,7 @@ public class CouchDbSessionRepository extends CouchDbRepositorySupport<Session>
private MotdRepository motdRepository;
public CouchDbSessionRepository(final CouchDbConnector db, final boolean createIfNotExists) {
super(Session.class, db, createIfNotExists);
super(Session.class, db, "by_keyword", createIfNotExists);
}
@Override
......
......@@ -22,23 +22,23 @@ import de.thm.arsnova.entities.DbUser;
import de.thm.arsnova.persistance.UserRepository;
import org.ektorp.BulkDeleteDocument;
import org.ektorp.CouchDbConnector;
import org.ektorp.DbAccessException;
import org.ektorp.DocumentOperationResult;
import org.ektorp.ViewQuery;
import org.ektorp.ViewResult;
import org.ektorp.support.CouchDbRepositorySupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class CouchDbUserRepository extends CouchDbRepositorySupport<DbUser> implements UserRepository {
public class CouchDbUserRepository extends CouchDbCrudRepository<DbUser> implements UserRepository {
private static final int BULK_PARTITION_SIZE = 500;
private static final Logger logger = LoggerFactory.getLogger(CouchDbUserRepository.class);
public CouchDbUserRepository(final CouchDbConnector db, final boolean createIfNotExists) {
super(DbUser.class, db, createIfNotExists);
super(DbUser.class, db, "by_username", createIfNotExists);
}
private void log(Object... strings) {
......@@ -46,7 +46,7 @@ public class CouchDbUserRepository extends CouchDbRepositorySupport<DbUser> impl
}
@Override
public DbUser createOrUpdateUser(final DbUser user) {
public DbUser save(final DbUser user) {
final String id = user.getId();
if (null != id) {
......@@ -59,20 +59,19 @@ public class CouchDbUserRepository extends CouchDbRepositorySupport<DbUser> impl
}
@Override
public DbUser findUserByUsername(final String username) {
public DbUser findByUsername(final String username) {
final List<DbUser> users = queryView("by_username", username);
return !users.isEmpty() ? users.get(0) : null;
}
@Override
public boolean deleteUser(final DbUser user) {
public void delete(final DbUser user) {
if (db.delete(user) != null) {
log("delete", "type", "user", "id", user.getId());
return true;
} else {
logger.error("Could not delete user {}", user.getId());
return false;
throw new DbAccessException("Could not delete document.");
}
}
......
......@@ -48,7 +48,7 @@ public class DbUserDetailsService implements UserDetailsService {
public UserDetails loadUserByUsername(String username) {
String uid = username.toLowerCase();
logger.debug("Load user: " + uid);
DbUser dbUser = userRepository.findUserByUsername(uid);
DbUser dbUser = userRepository.findByUsername(uid);
if (null == dbUser) {
throw new UsernameNotFoundException("User does not exist.");
}
......
......@@ -339,7 +339,7 @@ public class UserServiceImpl implements UserService {
@Override
public DbUser getDbUser(String username) {
return userRepository.findUserByUsername(username.toLowerCase());
return userRepository.findByUsername(username.toLowerCase());
}
@Override
......@@ -360,7 +360,7 @@ public class UserServiceImpl implements UserService {
return null;
}
if (null != userRepository.findUserByUsername(lcUsername)) {
if (null != userRepository.findByUsername(lcUsername)) {
logger.info("User registration failed. {} already exists.", lcUsername);
return null;
......@@ -372,7 +372,7 @@ public class UserServiceImpl implements UserService {
dbUser.setActivationKey(RandomStringUtils.randomAlphanumeric(32));
dbUser.setCreation(System.currentTimeMillis());
DbUser result = userRepository.createOrUpdateUser(dbUser);
DbUser result = userRepository.save(dbUser);
if (null != result) {
sendActivationEmail(result);
} else {
......@@ -436,7 +436,7 @@ public class UserServiceImpl implements UserService {
@Override
public DbUser updateDbUser(DbUser dbUser) {
if (null != dbUser.getId()) {
return userRepository.createOrUpdateUser(dbUser);
return userRepository.save(dbUser);
}
return null;
......@@ -456,7 +456,7 @@ public class UserServiceImpl implements UserService {
throw new NotFoundException();
}
userRepository.deleteUser(dbUser);
userRepository.delete(dbUser);
return dbUser;
}
......@@ -478,7 +478,7 @@ public class UserServiceImpl implements UserService {
dbUser.setPasswordResetKey(RandomStringUtils.randomAlphanumeric(32));
dbUser.setPasswordResetTime(System.currentTimeMillis());
if (null == userRepository.createOrUpdateUser(dbUser)) {
if (null == userRepository.save(dbUser)) {
logger.error("Password reset failed. {} could not be updated.", username);
}
......
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