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

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