Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/main/java/org/wise/portal/dao/newsitem/NewsItemDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,17 @@

import org.wise.portal.dao.SimpleDao;
import org.wise.portal.domain.newsitem.NewsItem;
import org.wise.portal.domain.newsitem.NewsType;

/**
* @author Patrick Lawler
*
*/
public interface NewsItemDao<T extends NewsItem> extends SimpleDao<NewsItem> {

List<NewsItem> getListByType(String type);
List<NewsItem> getNewsPageNews(NewsType type);

List<NewsItem> getHomePageNews(NewsType type);

List<NewsItem> getAllNews();
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.wise.portal.dao.impl.AbstractHibernateDao;
import org.wise.portal.dao.newsitem.NewsItemDao;
import org.wise.portal.domain.newsitem.NewsItem;
import org.wise.portal.domain.newsitem.NewsType;
import org.wise.portal.domain.newsitem.impl.NewsItemImpl;

/**
Expand All @@ -49,14 +50,36 @@ protected Class<NewsItemImpl> getDataObjectClass() {
}

@Override
public List<NewsItem> getNewsPageNews(NewsType type) {
return getLatestNews(false, type);
}

@Override
public List<NewsItem> getHomePageNews(NewsType type) {
return getLatestNews(true, type);
}

@Override
public List<NewsItem> getAllNews() {
return getLatestNews(false, NewsType.PUBLIC_AND_TEACHER);
}

@SuppressWarnings("unchecked")
public List<NewsItem> getListByType(String type) {
private List<NewsItem> getLatestNews(boolean limitQuery, NewsType type) {
CriteriaBuilder cb = getCriteriaBuilder();
CriteriaQuery<NewsItemImpl> cq = cb.createQuery(NewsItemImpl.class);
Root<NewsItemImpl> newsItemRoot = cq.from(NewsItemImpl.class);
cq.select(newsItemRoot).where(cb.equal(newsItemRoot.get("type"), type))
.orderBy(cb.desc(newsItemRoot.get("id")));

cq.select(newsItemRoot);
if (type.equals(NewsType.PUBLIC_ONLY)) {
cq.where(cb.equal(newsItemRoot.get("type"), "public"));
}
cq.orderBy(cb.desc(newsItemRoot.get("id")));

TypedQuery<NewsItemImpl> query = entityManager.createQuery(cq);
if (limitQuery) {
query.setMaxResults(3);
}
return (List<NewsItem>) (Object) query.getResultList();
}
}
13 changes: 13 additions & 0 deletions src/main/java/org/wise/portal/domain/newsitem/NewsType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.wise.portal.domain.newsitem;

public enum NewsType {
PUBLIC_ONLY, PUBLIC_AND_TEACHER;

public static NewsType stringToNewsType(String type) throws IllegalArgumentException {
return switch (type) {
case "publicOnly" -> PUBLIC_ONLY;
case "publicAndTeacher" -> PUBLIC_AND_TEACHER;
default -> throw new IllegalArgumentException("Invalid news type: " + type);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
*/
package org.wise.portal.domain.newsitem.impl;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Column;
Expand Down Expand Up @@ -52,7 +53,7 @@
@Table(name = NewsItemImpl.DATA_STORE_NAME)
@Getter
@Setter
public class NewsItemImpl implements NewsItem, Comparable<NewsItem> {
public class NewsItemImpl implements NewsItem, Comparable<NewsItem>, Serializable {

@Transient
public static final String DATA_STORE_NAME = "newsitem";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.wise.portal.domain.newsitem.NewsItem;
import org.wise.portal.domain.newsitem.NewsType;
import org.wise.portal.service.newsitem.NewsItemService;

import java.util.List;
Expand All @@ -19,19 +21,26 @@ public class NewsAPIController {
@Autowired
private NewsItemService newsItemService;

@RequestMapping(value = "", method = RequestMethod.GET)
protected String getNews() {
List<NewsItem> newsItems = newsItemService.retrieveAllNewsItem();
JSONArray newsItemsJSON = getNewsItemsJSON(newsItems);
return newsItemsJSON.toString();
@GetMapping()
protected String getNewsPageNews(@RequestParam String type) {
NewsType newsType = NewsType.stringToNewsType(type);
List<NewsItem> newsItems = this.newsItemService.retrieveNewsPageNews(newsType);
return this.getNewsItemsJSONString(newsItems);
}

@GetMapping("/home")
protected String getHomePageNews(@RequestParam String type) {
NewsType newsType = NewsType.stringToNewsType(type);
List<NewsItem> newsItems = this.newsItemService.retrieveAndCacheHomePageNews(newsType);
return this.getNewsItemsJSONString(newsItems);
}

private JSONArray getNewsItemsJSON(List<NewsItem> newsItems) {
private String getNewsItemsJSONString(List<NewsItem> newsItems) {
JSONArray newsItemsJSON = new JSONArray();
for (NewsItem newsItem: newsItems) {
newsItemsJSON.put(getNewsItemJSON(newsItem));
}
return newsItemsJSON;
return newsItemsJSON.toString();
}

private JSONObject getNewsItemJSON(NewsItem newsItem) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

import org.wise.portal.dao.ObjectNotFoundException;
import org.wise.portal.domain.newsitem.NewsItem;
import org.wise.portal.domain.newsitem.NewsType;
import org.wise.portal.domain.user.User;

/**
Expand All @@ -48,16 +49,23 @@ public interface NewsItemService {
NewsItem createNewsItem(Date date, User owner, String title, String news, String type);

/**
* Retrieves all NewsItem from the data store.
* Retrieves the latest NewsItems from the data store.
* @param type the type of news items to retrieve. Get all if type is not present.
* @return a Set of NewsItem
*/
List<NewsItem> retrieveAllNewsItem();
List<NewsItem> retrieveNewsPageNews(NewsType type);

/**
* Retrieves all NewsItem by specified type
* @return a Set of NewsItem of specified type
* Uses cached value or retrieves and caches the latest three NewsItems from the data store.
* @param type the type of news items to retrieve. Get all if type is not present.
* @return a Set of NewsItem
*/
List<NewsItem> retrieveAndCacheHomePageNews(NewsType type);

/** Retrieves all NewsItem from the data store.
* @return a Set of NewsItem
*/
List<NewsItem> retrieveByType(String type);
List<NewsItem> retrieveAllNewsItem();

/**
* Retrieves a NewsItem given an ID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,22 @@
package org.wise.portal.service.newsitem.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.wise.portal.dao.ObjectNotFoundException;
import org.wise.portal.dao.newsitem.NewsItemDao;
import org.wise.portal.domain.newsitem.NewsItem;
import org.wise.portal.domain.newsitem.NewsType;
import org.wise.portal.domain.newsitem.impl.NewsItemImpl;
import org.wise.portal.domain.user.User;
import org.wise.portal.service.newsitem.NewsItemService;

import java.util.Date;
import java.util.List;
import javax.management.timer.Timer;

/**
* @author Patrick Lawler
Expand All @@ -45,14 +50,23 @@ public class NewsItemServiceImpl implements NewsItemService {
@Autowired
private NewsItemDao<NewsItem> newsItemDao;

public List<NewsItem> retrieveAllNewsItem() {
return newsItemDao.getList();
@Override
public List<NewsItem> retrieveNewsPageNews(NewsType type) {
return newsItemDao.getNewsPageNews(type);
}

public List<NewsItem> retrieveByType(String type) {
return newsItemDao.getListByType(type);
@Override
@Cacheable(value = "newsItems", key = "#type")
public List<NewsItem> retrieveAndCacheHomePageNews(NewsType type) {
return newsItemDao.getHomePageNews(type);
}

@Override
public List<NewsItem> retrieveAllNewsItem() {
return newsItemDao.getAllNews();
}

@Override
public NewsItem retrieveById(Integer id) throws ObjectNotFoundException {
try {
return newsItemDao.getById(id);
Expand All @@ -62,6 +76,7 @@ public NewsItem retrieveById(Integer id) throws ObjectNotFoundException {
}

@Transactional
@CacheEvict(value = "newsItems", allEntries = true)
public NewsItem createNewsItem(Date date, User owner, String title, String news, String type) {
NewsItem newsItem = new NewsItemImpl();
newsItem.setDate(date);
Expand All @@ -74,6 +89,7 @@ public NewsItem createNewsItem(Date date, User owner, String title, String news,
}

@Transactional
@CacheEvict(value = "newsItems", allEntries = true)
public void updateNewsItem(Integer id, Date date, User owner, String title,
String news, String type) throws ObjectNotFoundException {
NewsItem newsItem = newsItemDao.getById(id);
Expand All @@ -86,8 +102,14 @@ public void updateNewsItem(Integer id, Date date, User owner, String title,
}

@Transactional
@CacheEvict(value = "newsItems", allEntries = true)
public void deleteNewsItem(Integer id) throws ObjectNotFoundException {
NewsItem newsItem = newsItemDao.getById(id);
newsItemDao.delete(newsItem);
}

@Scheduled(fixedRate = Timer.ONE_HOUR)
@CacheEvict(value = "newsItems", allEntries = true)
public void evictNewsItemsCache() {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@

import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.wise.portal.domain.authentication.Schoollevel;
import org.wise.portal.domain.newsitem.NewsItem;
import org.wise.portal.domain.newsitem.NewsType;
import org.wise.portal.domain.newsitem.impl.NewsItemImpl;
import org.wise.portal.domain.user.User;
import org.wise.portal.junit.AbstractTransactionalDbTests;
Expand All @@ -57,16 +59,39 @@ public void setUp() throws Exception {
}

@Test
public void getListByType_TypeThatDoesNotExist_ShouldReturnNone() {
List<NewsItem> newsItems = newsItemDao.getListByType("test");
assertEquals(0, newsItems.size());
public void getNewsPageNews_WithPublicOnlyType_ShouldReturnAllNewsItems() {
createNewsItem(teacher, new Date(), "public", "News Title 1", "news1");
createNewsItem(teacher, new Date(), "teacherOnly", "News Title 2", "news2");
List<NewsItem> newsItems = newsItemDao.getNewsPageNews(NewsType.PUBLIC_ONLY);
assertEquals(1, newsItems.size());
}

@Test
public void getListByType_TypeThatExists_ShouldReturnNewsItems() {
createNewsItem(teacher, new Date(), "public", "News Title", "news1");
List<NewsItem> newsItems = newsItemDao.getListByType("public");
assertEquals(1, newsItems.size());
public void getNewsPageNews_WithPublicAndTeacherType_ShouldReturnAllNewsItems() {
createNewsItem(teacher, new Date(), "public", "News Title 1", "news1");
createNewsItem(teacher, new Date(), "teacherOnly", "News Title 2", "news2");
List<NewsItem> newsItems = newsItemDao.getNewsPageNews(NewsType.PUBLIC_AND_TEACHER);
assertEquals(2, newsItems.size());
}

@Test
public void getHomePageNews_ShouldReturnThreeNewsItems() {
createNewsItem(teacher, new Date(), "public", "News Title 1", "news1");
createNewsItem(teacher, new Date(), "teacherOnly", "News Title 2", "news2");
createNewsItem(teacher, new Date(), "public", "News Title 3", "news3");
createNewsItem(teacher, new Date(), "teacherOnly", "News Title 4", "news4");
List<NewsItem> newsItems = newsItemDao.getHomePageNews(NewsType.PUBLIC_AND_TEACHER);
assertEquals(3, newsItems.size());
}

@Test
public void getAllNews_ShouldReturnAllNewsItems() {
createNewsItem(teacher, new Date(), "public", "News Title 1", "news1");
createNewsItem(teacher, new Date(), "teacherOnly", "News Title 2", "news2");
createNewsItem(teacher, new Date(), "public", "News Title 3", "news3");
createNewsItem(teacher, new Date(), "teacherOnly", "News Title 4", "news4");
List<NewsItem> newsItems = newsItemDao.getAllNews();
assertEquals(4, newsItems.size());
}

private NewsItem createNewsItem(User owner, Date date, String type, String title, String news) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Optional;

import org.easymock.EasyMockExtension;
import org.easymock.Mock;
Expand All @@ -47,6 +48,7 @@
import org.wise.portal.dao.ObjectNotFoundException;
import org.wise.portal.dao.newsitem.NewsItemDao;
import org.wise.portal.domain.newsitem.NewsItem;
import org.wise.portal.domain.newsitem.NewsType;
import org.wise.portal.domain.newsitem.impl.NewsItemImpl;
import org.wise.portal.domain.user.User;
import org.wise.portal.domain.user.impl.UserImpl;
Expand Down Expand Up @@ -158,14 +160,14 @@ public void deleteNewsItem_InvalidNewsItemID_ShouldThrowException()
}

@Test
public void retrieveAllNewsItem_TwoNewsItemsInDB_ShouldSucceed() {
public void retrieveNewsPageNews_TwoNewsItemsInDB_ShouldSucceed() {
List<NewsItem> newsItemsInDB = new ArrayList<NewsItem>();
newsItemsInDB.add(newsItem1);
newsItemsInDB.add(newsItem2);
expect(newsItemDao.getList()).andReturn(newsItemsInDB);
expect(newsItemDao.getNewsPageNews(NewsType.PUBLIC_AND_TEACHER)).andReturn(newsItemsInDB);
replay(newsItemDao);

List<NewsItem> newsItemsFromDB = newsItemServiceImpl.retrieveAllNewsItem();
List<NewsItem> newsItemsFromDB = newsItemServiceImpl.retrieveNewsPageNews(NewsType.PUBLIC_AND_TEACHER);
assertEquals(newsItemsFromDB.size(), 2);
assertTrue(newsItemsFromDB.get(0).equals(newsItem1));
assertTrue(newsItemsFromDB.get(1).equals(newsItem2));
Expand Down
Loading