Skip to content

Commit 25eb8c8

Browse files
author
Anand Rajneesh
committed
[#25] MongoDB Custom Repositories
1 parent 233fe46 commit 25eb8c8

File tree

10 files changed

+289
-17
lines changed

10 files changed

+289
-17
lines changed

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@
7777
<dependency>
7878
<groupId>com.github.fakemongo</groupId>
7979
<artifactId>fongo</artifactId>
80-
<version>2.0.6</version>
80+
<version>2.1.0</version>
8181
<scope>test</scope>
8282
</dependency>
8383
<dependency>

src/main/java/org/gluecoders/library/dao/BookDao.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Created by Anand_Rajneesh on 6/14/2017.
99
*/
1010
@Repository
11-
public interface BookDao extends MongoRepository<Book, String> {
11+
public interface BookDao extends MongoRepository<Book, String>, BookDaoCustom {
1212

1313
Book findDistinctByIsbnCode(long isbnCode);
1414
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.gluecoders.library.dao;
2+
3+
import org.gluecoders.library.models.Book;
4+
5+
import java.util.List;
6+
7+
/**
8+
* Created by Anand_Rajneesh on 6/17/2017.
9+
*/
10+
public interface BookDaoCustom {
11+
12+
public List<Book> findBooks(List<String> categories, String author, String title, String publishedYear);
13+
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
package org.gluecoders.library.dao.impl;
2+
3+
import com.sun.org.apache.xml.internal.resolver.readers.TextCatalogReader;
4+
import org.gluecoders.library.dao.BookDaoCustom;
5+
import org.gluecoders.library.models.Book;
6+
import org.slf4j.Logger;
7+
import org.slf4j.LoggerFactory;
8+
import org.springframework.beans.factory.annotation.Autowired;
9+
import org.springframework.data.mongodb.core.MongoTemplate;
10+
import org.springframework.data.mongodb.core.query.*;
11+
import org.springframework.stereotype.Component;
12+
import org.springframework.util.StringUtils;
13+
14+
import java.util.List;
15+
16+
/**
17+
* Created by Anand_Rajneesh on 6/17/2017.
18+
*/
19+
@Component
20+
public class BookDaoImpl implements BookDaoCustom {
21+
22+
private static final Logger LOGGER = LoggerFactory.getLogger(BookDaoImpl.class);
23+
24+
private final MongoTemplate mongoTemplate;
25+
26+
@Autowired
27+
public BookDaoImpl(MongoTemplate mongoTemplate) {
28+
this.mongoTemplate = mongoTemplate;
29+
}
30+
31+
@Override
32+
public List<Book> findBooks(List<String> categories, String author, String title, String publishedYear) {
33+
Query query = buildSearchQuery(categories, author, title, publishedYear);
34+
LOGGER.debug("Query built for findBooks {}", query);
35+
return mongoTemplate.find(query, Book.class);
36+
}
37+
38+
private Query buildSearchQuery(List<String> categories, String author, String title, String publishedYear) {
39+
TextCriteria textCriteria = TextCriteria.forDefaultLanguage().matchingAny(author, title);
40+
Criteria criteria = new Criteria();
41+
if (categories != null && categories.size() > 0) {
42+
criteria.and("categories").in(categories);
43+
}
44+
if (StringUtils.hasText(publishedYear)) {
45+
criteria.and("publishedYear.year").is(Integer.parseInt(publishedYear));
46+
}
47+
if(author != null || title != null){
48+
return TextQuery.queryText(textCriteria).addCriteria(criteria);
49+
}else {
50+
return Query.query(criteria);
51+
}
52+
}
53+
54+
}

src/main/java/org/gluecoders/library/rest/Books.java

+9-6
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,23 @@ public class Books {
3333
private Validator validator;
3434

3535
@GetMapping
36-
public ResponseEntity<List<Book>> getAllBooks() {
37-
LOGGER.info("getAllBooks invoked");
38-
List<Book> list = bookService.getAllBooks();
36+
public ResponseEntity<List<Book>> getAllBooks(@RequestParam(value = "category", required = false) List<String> categories,
37+
@RequestParam(value = "title", required = false) String title,
38+
@RequestParam(value = "author", required = false) String author,
39+
@RequestParam(value = "year", required = false) String year) {
40+
LOGGER.info("getAllBooks invoked with search criteria {} , {}, {}, {}", categories, title, author, year);
41+
List<Book> list = bookService.getAllBooks(categories, title, author, year);
3942
return new ResponseEntity<>(list, HttpStatus.OK);
4043
}
4144

4245
@GetMapping("/{isbn}")
4346
public ResponseEntity<Book> getBook(@PathVariable("isbn") long isbnCode) {
4447
LOGGER.info("getBook invoked for ISBN code {}", isbnCode);
4548
Book book = bookService.getBookByISBN(isbnCode);
46-
if(book == null) {
49+
if (book == null) {
4750
LOGGER.debug("Book not found for ISBN code {}", isbnCode);
4851
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
49-
}else{
52+
} else {
5053
LOGGER.debug("Book found for ISBN code {} {}", isbnCode, book);
5154
return new ResponseEntity<>(book, HttpStatus.OK);
5255
}
@@ -55,7 +58,7 @@ public ResponseEntity<Book> getBook(@PathVariable("isbn") long isbnCode) {
5558
@PostMapping
5659
public ResponseEntity<Book> addBook(@RequestBody Book book) {
5760
List<ConstraintViolation> violations = validator.validate(book);
58-
if(!violations.isEmpty()) {
61+
if (!violations.isEmpty()) {
5962
LOGGER.info("violations {} for request payload {}", violations, book);
6063
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
6164
}

src/main/java/org/gluecoders/library/services/BookService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010
public interface BookService {
1111

12-
List<Book> getAllBooks();
12+
List<Book> getAllBooks(List<String> categories, String title, String author, String year);
1313

1414
Book addBook(Book book);
1515

src/main/java/org/gluecoders/library/services/DefaultBookService.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ public class DefaultBookService implements BookService {
2121
private BookDao bookDao;
2222

2323
@Override
24-
public List<Book> getAllBooks() {
25-
LOGGER.info("getAllBooks() invoked");
26-
return bookDao.findAll();
24+
public List<Book> getAllBooks(List<String> categories, String title, String author, String year) {
25+
LOGGER.info("getAllBooks() invoked with search criteria {} , {}, {}, {}", categories, title, author, year);
26+
return bookDao.findBooks(categories, title, author, year);
2727
}
2828

2929
@Override

src/test/java/org/gluecoders/library/dao/BookDaoTest.java

+173
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import org.gluecoders.library.config.Database;
88
import org.gluecoders.library.dao.config.FakeMongo;
99
import org.gluecoders.library.models.Book;
10+
import org.junit.Ignore;
1011
import org.junit.Rule;
1112
import org.junit.Test;
1213
import org.junit.runner.RunWith;
@@ -17,13 +18,18 @@
1718
import org.springframework.test.context.junit4.SpringRunner;
1819

1920
import java.time.Month;
21+
import java.util.ArrayList;
22+
import java.util.Arrays;
2023
import java.util.List;
24+
import java.util.Optional;
25+
import java.util.function.Supplier;
2126

2227
import static com.lordofthejars.nosqlunit.mongodb.MongoDbRule.MongoDbRuleBuilder.newMongoDbRule;
2328
import static org.junit.Assert.*;
2429

2530
/**
2631
* Created by Anand_Rajneesh on 6/14/2017.
32+
* TODO FIXME - Text based search queries are not working in test mode, Fongo not able to set up text index ?
2733
*/
2834
@RunWith(SpringRunner.class)
2935
@Import(value = {FakeMongo.class, Database.class})
@@ -114,4 +120,171 @@ public void deleteBook_IdNotPresent(){
114120
bookDao.delete(book);
115121
}
116122

123+
@Test
124+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/empty.json")
125+
public void findBooks_NoBooksAvailable(){
126+
List<Book> books = FindTester.test(bookDao).noArgs().get();
127+
assertTrue(books.isEmpty());
128+
}
129+
130+
@Test
131+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
132+
public void findBooks_BooksAvailableMatchingCategory1(){
133+
List<Book> books = FindTester.test(bookDao).category("Technology").get();
134+
assertTrue(books.size() == 1);
135+
assertTrue(books.get(0).getIsbnCode() == 9780471019947L);
136+
}
137+
138+
@Test
139+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
140+
public void findBooks_BooksAvailableMatchingCategory2(){
141+
List<Book> books = FindTester.test(bookDao).category("Science", "Java").get();
142+
assertTrue(books.size() == 6);
143+
}
144+
145+
@Test
146+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
147+
public void findBooks_BooksAvailableNoneMatchingCategory(){
148+
List<Book> books = FindTester.test(bookDao).category("NeverMatching").get();
149+
assertTrue(books.size() == 0);
150+
}
151+
152+
@Test @Ignore
153+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
154+
public void findBooks_BooksAvailableMatchingAuthor(){
155+
List<Book> books = FindTester.test(bookDao).author("Moss").get();
156+
assertTrue(books.size() == 1);
157+
assertTrue(books.get(0).getIsbnCode() == 9780412104909L);
158+
}
159+
160+
@Test @Ignore
161+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
162+
public void findBooks_BooksAvailableNotMatchingAuthor(){
163+
List<Book> books = FindTester.test(bookDao).author("MossXYZ").get();
164+
assertTrue(books.size() == 0);
165+
}
166+
167+
@Test @Ignore
168+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
169+
public void findBooks_BooksAvailableMatchingTitle(){
170+
List<Book> books = FindTester.test(bookDao).title("Advanced").get();
171+
assertTrue(books.size() == 4);
172+
}
173+
174+
@Test @Ignore
175+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
176+
public void findBooks_BooksAvailableNotMatchingTitle(){
177+
List<Book> books = FindTester.test(bookDao).title("AdvancedSuper").get();
178+
assertTrue(books.size() == 0);
179+
}
180+
181+
@Test
182+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
183+
public void findBooks_BooksAvailableMatchingYear(){
184+
List<Book> books = FindTester.test(bookDao).publishedYear("2001").get();
185+
assertTrue(books.size() == 2);
186+
}
187+
188+
@Test(expected = NumberFormatException.class)
189+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
190+
public void findBooks_BooksAvailableMatchingYear_UnhandledError(){
191+
List<Book> books = FindTester.test(bookDao).publishedYear("2001s").get();
192+
assertTrue(books.size() == 0);
193+
}
194+
195+
@Test @Ignore
196+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
197+
public void findBooks_BooksAvailableCustom1(){
198+
List<Book> books = FindTester.test(bookDao).title("Java").publishedYear("2001").get();
199+
assertTrue(books.size() == 2);
200+
}
201+
202+
@Test @Ignore
203+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
204+
public void findBooks_BooksAvailableCustom2(){
205+
List<Book> books = FindTester.test(bookDao).category("Science").title("Java").publishedYear("2001").get();
206+
assertTrue(books.size() == 0);
207+
}
208+
209+
@Test @Ignore
210+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
211+
public void findBooks_BooksAvailableCustom3(){
212+
List<Book> books = FindTester.test(bookDao).category("Science", "Java").title("Java").publishedYear("2001").get();
213+
assertTrue(books.size() == 2);
214+
}
215+
216+
@Test @Ignore
217+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
218+
public void findBooks_BooksAvailableCustom4(){
219+
List<Book> books = FindTester.test(bookDao).title("Advanced").publishedYear("1996").get();
220+
assertTrue(books.size() == 2);
221+
}
222+
223+
@Test @Ignore
224+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
225+
public void findBooks_BooksAvailableCustom5(){
226+
List<Book> books = FindTester.test(bookDao).title("Advanced").publishedYear("1999").get();
227+
assertTrue(books.size() == 1);
228+
}
229+
230+
@Test @Ignore
231+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
232+
public void findBooks_BooksAvailableCustom6(){
233+
List<Book> books = FindTester.test(bookDao).author("William Harvey").get();
234+
assertTrue(books.size() == 2);
235+
}
236+
237+
238+
@Test @Ignore
239+
@UsingDataSet(loadStrategy = LoadStrategyEnum.CLEAN_INSERT, locations="/books/manybooks.json")
240+
public void findBooks_BooksAvailableCustom7(){
241+
List<Book> books = FindTester.test(bookDao).author("William Harvey").category("Java").get();
242+
assertTrue(books.size() == 1);
243+
}
244+
245+
private static class FindTester{
246+
247+
private BookDao testObject;
248+
private List<String> categories = null;
249+
private String author = null;
250+
private String title = null;
251+
private String publishedYear = null;
252+
private List<Book> books = null;
253+
public static FindTester test(BookDao bookDao){
254+
FindTester t = new FindTester();
255+
t.testObject = bookDao;
256+
return t;
257+
}
258+
259+
public Supplier<List<Book>> noArgs(){
260+
return () -> testObject.findBooks(null,null,null,null);
261+
}
262+
263+
public FindTester category(String ... category){
264+
this.categories = Optional.ofNullable(this.categories).orElseGet(ArrayList::new);
265+
this.categories.addAll(Arrays.asList(category));
266+
return this;
267+
}
268+
269+
public FindTester author(String author){
270+
this.author = author;
271+
return this;
272+
}
273+
274+
public FindTester title(String title){
275+
this.title = title;
276+
return this;
277+
}
278+
279+
public FindTester publishedYear(String publishedYear){
280+
this.publishedYear = publishedYear;
281+
return this;
282+
}
283+
284+
public List<Book> get(){
285+
return testObject.findBooks(categories, author, title, publishedYear);
286+
}
287+
288+
}
289+
117290
}

0 commit comments

Comments
 (0)