Skip to content

Commit 6f38258

Browse files
authored
Merge pull request #231 from nanotaboada/copilot/add-books-search-endpoint
Add /books/search endpoint for description-based search
2 parents cdc3194 + 52cb909 commit 6f38258

File tree

9 files changed

+397
-14
lines changed

9 files changed

+397
-14
lines changed

.java-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
21

src/main/java/ar/com/nanotaboada/java/samples/spring/boot/controllers/BooksController.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
import java.net.URI;
66
import java.util.List;
77

8-
import jakarta.validation.Valid;
9-
108
import org.hibernate.validator.constraints.ISBN;
119
import org.springframework.http.HttpStatus;
1210
import org.springframework.http.ResponseEntity;
@@ -16,9 +14,12 @@
1614
import org.springframework.web.bind.annotation.PostMapping;
1715
import org.springframework.web.bind.annotation.PutMapping;
1816
import org.springframework.web.bind.annotation.RequestBody;
17+
import org.springframework.web.bind.annotation.RequestParam;
1918
import org.springframework.web.bind.annotation.RestController;
2019
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;
2120

21+
import ar.com.nanotaboada.java.samples.spring.boot.models.BookDTO;
22+
import ar.com.nanotaboada.java.samples.spring.boot.services.BooksService;
2223
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
2324
import io.swagger.v3.oas.annotations.Operation;
2425
import io.swagger.v3.oas.annotations.info.Contact;
@@ -29,9 +30,8 @@
2930
import io.swagger.v3.oas.annotations.responses.ApiResponse;
3031
import io.swagger.v3.oas.annotations.responses.ApiResponses;
3132
import io.swagger.v3.oas.annotations.tags.Tag;
32-
33-
import ar.com.nanotaboada.java.samples.spring.boot.models.BookDTO;
34-
import ar.com.nanotaboada.java.samples.spring.boot.services.BooksService;
33+
import jakarta.validation.Valid;
34+
import jakarta.validation.constraints.NotBlank;
3535

3636
@RestController
3737
@Tag(name = "Books")
@@ -100,6 +100,18 @@ public ResponseEntity<List<BookDTO>> getAll() {
100100
return ResponseEntity.status(HttpStatus.OK).body(books);
101101
}
102102

103+
@GetMapping("/books/search")
104+
@Operation(summary = "Searches books by description keyword")
105+
@ApiResponses(value = {
106+
@ApiResponse(responseCode = "200", description = "OK - Returns matching books (or empty array if none found)", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BookDTO[].class))),
107+
@ApiResponse(responseCode = "400", description = "Bad Request - Missing or blank description parameter", content = @Content)
108+
})
109+
public ResponseEntity<List<BookDTO>> searchByDescription(
110+
@RequestParam @NotBlank(message = "Description parameter must not be blank") String description) {
111+
List<BookDTO> books = booksService.searchByDescription(description);
112+
return ResponseEntity.status(HttpStatus.OK).body(books);
113+
}
114+
103115
/*
104116
* -------------------------------------------------------------------------
105117
* HTTP PUT

src/main/java/ar/com/nanotaboada/java/samples/spring/boot/models/BooksDataInitializer.java

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,171 @@ public static List<Book> seed() {
116116
definitions and measures of productivity.""");
117117
book9781484242216.setWebsite("https://link.springer.com/book/10.1007/978-1-4842-4221-6");
118118
books.add(book9781484242216);
119+
Book book9781642002232 = new Book();
120+
book9781642002232.setIsbn("9781642002232");
121+
book9781642002232.setTitle("Database Design Succinctly");
122+
book9781642002232.setAuthor("Joseph D. Booth");
123+
book9781642002232.setPublisher("Syncfusion");
124+
book9781642002232.setPublished(LocalDate.of(2022, 5, 25));
125+
book9781642002232.setPages(87);
126+
book9781642002232.setDescription(
127+
"""
128+
The way a user might perceive and use data and the optimal way a computer \
129+
system might store it are often very different. In this Database Design \
130+
Succinctly®, learn how to model the user's information into data in a computer \
131+
database system in such a way as to allow the system to produce useful results \
132+
for the end user. Joseph D. Booth will cover how to design a database system to \
133+
allow businesses to get better reporting and control over their information, as \
134+
well as how to improve their data to make sure it is as accurate as possible.""");
135+
book9781642002232.setWebsite("https://www.syncfusion.com/succinctly-free-ebooks/database-design-succinctly");
136+
books.add(book9781642002232);
137+
Book book9781642001174 = new Book();
138+
book9781642001174.setIsbn("9781642001174");
139+
book9781642001174.setTitle("SOLID Principles Succinctly");
140+
book9781642001174.setAuthor("Gaurav Kumar Arora");
141+
book9781642001174.setPublisher("Syncfusion");
142+
book9781642001174.setPublished(LocalDate.of(2016, 10, 31));
143+
book9781642001174.setPages(78);
144+
book9781642001174.setDescription(
145+
"""
146+
There is always room for improving one's coding ability, and SOLID design \
147+
principles offer one way to see marked improvements in final output. With SOLID \
148+
Principles Succinctly®, author Gaurav Kumar Arora will instruct you in how to \
149+
use SOLID principles to take your programming skills to the next level.""");
150+
book9781642001174.setWebsite("https://www.syncfusion.com/succinctly-free-ebooks/solidprinciplessuccinctly");
151+
books.add(book9781642001174);
152+
Book book9781642001440 = new Book();
153+
book9781642001440.setIsbn("9781642001440");
154+
book9781642001440.setTitle("Java Succinctly Part 1");
155+
book9781642001440.setAuthor("Christopher Rose");
156+
book9781642001440.setPublisher("Syncfusion");
157+
book9781642001440.setPublished(LocalDate.of(2017, 8, 29));
158+
book9781642001440.setPages(125);
159+
book9781642001440.setDescription(
160+
"""
161+
Java is a high-level, cross-platform, object-oriented programming language that \
162+
allows applications to be written once and run on a multitude of different \
163+
devices. Java applications are ubiquitous, and the language is consistently \
164+
ranked as one of the most popular and dominant in the world. Christopher Rose's \
165+
Java Succinctly® Part 1 describes the foundations of Java—from printing a line \
166+
of text to the console, to inheritance hierarchies in object-oriented \
167+
programming. The e-book covers practical aspects of programming, such as \
168+
debugging and using an IDE, as well as the core mechanics of the language.""");
169+
book9781642001440.setWebsite("https://www.syncfusion.com/succinctly-free-ebooks/java-succinctly-part-1");
170+
books.add(book9781642001440);
171+
Book book9781642001457 = new Book();
172+
book9781642001457.setIsbn("9781642001457");
173+
book9781642001457.setTitle("Java Succinctly Part 2");
174+
book9781642001457.setAuthor("Christopher Rose");
175+
book9781642001457.setPublisher("Syncfusion");
176+
book9781642001457.setPublished(LocalDate.of(2017, 9, 5));
177+
book9781642001457.setPages(134);
178+
book9781642001457.setDescription(
179+
"""
180+
In this second e-book on Java, Christopher Rose takes readers through some of \
181+
the more advanced features of the language. Java Succinctly® Part 2 explores \
182+
powerful and practical features of Java, such as multithreading, building GUI \
183+
applications, and 2-D graphics and game programming. Then learn techniques for \
184+
using these mechanisms in coherent projects by building a calculator app and a \
185+
simple game with the author.""");
186+
book9781642001457.setWebsite("https://www.syncfusion.com/succinctly-free-ebooks/java-succinctly-part-2");
187+
books.add(book9781642001457);
188+
Book book9781642001495 = new Book();
189+
book9781642001495.setIsbn("9781642001495");
190+
book9781642001495.setTitle("Scala Succinctly");
191+
book9781642001495.setAuthor("Chris Rose");
192+
book9781642001495.setPublisher("Syncfusion");
193+
book9781642001495.setPublished(LocalDate.of(2017, 10, 16));
194+
book9781642001495.setPages(110);
195+
book9781642001495.setDescription(
196+
"""
197+
Learning a new programming language can be a daunting task, but Scala \
198+
Succinctly® makes it a simple matter. Author Chris Rose guides readers through \
199+
the basics of Scala, from installation to syntax shorthand, so that they can \
200+
get up and running quickly.""");
201+
book9781642001495.setWebsite("https://www.syncfusion.com/succinctly-free-ebooks/scala-succinctly");
202+
books.add(book9781642001495);
203+
Book book9781642001242 = new Book();
204+
book9781642001242.setIsbn("9781642001242");
205+
book9781642001242.setTitle("SQL Queries Succinctly");
206+
book9781642001242.setAuthor("Nick Harrison");
207+
book9781642001242.setPublisher("Syncfusion");
208+
book9781642001242.setPublished(LocalDate.of(2017, 2, 4));
209+
book9781642001242.setPages(102);
210+
book9781642001242.setDescription(
211+
"""
212+
SQL is the language of data, and therefore the intermediary language for those \
213+
who straddle the line between technology and business. Every business \
214+
application needs a database and SQL is the key to working with these databases. \
215+
Nick Harrison's SQL Queries Succinctly® will show you how to craft queries in \
216+
SQL, from basic CRUD statements and slicing and dicing the data, to applying \
217+
filters and using aggregate functions to summarize the data. You will look at \
218+
solving common problems, navigating hierarchical data, and exploring the data \
219+
dictionary.""");
220+
book9781642001242.setWebsite("https://www.syncfusion.com/succinctly-free-ebooks/sql-queries-succinctly");
221+
books.add(book9781642001242);
222+
Book book9781642001563 = new Book();
223+
book9781642001563.setIsbn("9781642001563");
224+
book9781642001563.setTitle("Docker Succinctly");
225+
book9781642001563.setAuthor("Elton Stoneman");
226+
book9781642001563.setPublisher("Syncfusion");
227+
book9781642001563.setPublished(LocalDate.of(2018, 1, 16));
228+
book9781642001563.setPages(98);
229+
book9781642001563.setDescription(
230+
"""
231+
Containers have revolutionized software development, allowing developers to \
232+
bundle their applications with everything they need, from the operating system \
233+
up, into a single package. Docker is one of the most popular platforms for \
234+
containers, allowing them to be hosted on-premises or on the cloud, and to run \
235+
on Linux, Windows, and Mac machines. With Docker Succinctly® by Elton Stoneman, \
236+
learn the basics of building Docker images, sharing them on the Docker Hub, \
237+
orchestrating containers to deliver large applications, and much more.""");
238+
book9781642001563.setWebsite("https://www.syncfusion.com/succinctly-free-ebooks/docker-succinctly");
239+
books.add(book9781642001563);
240+
Book book9781642001792 = new Book();
241+
book9781642001792.setIsbn("9781642001792");
242+
book9781642001792.setTitle("Kubernetes Succinctly");
243+
book9781642001792.setAuthor("Rahul Rai, Tarun Pabbi");
244+
book9781642001792.setPublisher("Syncfusion");
245+
book9781642001792.setPublished(LocalDate.of(2019, 3, 1));
246+
book9781642001792.setPages(121);
247+
book9781642001792.setDescription(
248+
"""
249+
With excellent orchestration and routing capabilities, Kubernetes is an \
250+
enterprise-grade platform for building microservices applications. Kubernetes is \
251+
evolving as the de facto container management tool used by organizations and \
252+
cloud vendors all over the world. Kubernetes Succinctly® by Rahul Rai and Tarun \
253+
Pabbi is your guide to learning Kubernetes and leveraging its many capabilities \
254+
for developing, validating, and maintaining your applications.""");
255+
book9781642001792.setWebsite("https://www.syncfusion.com/succinctly-free-ebooks/kubernetes-succinctly");
256+
books.add(book9781642001792);
257+
Book book9781838820756 = new Book();
258+
book9781838820756.setIsbn("9781838820756");
259+
book9781838820756.setTitle("The Kubernetes Workshop");
260+
book9781838820756
261+
.setAuthor("Zachary Arnold, Sahil Dua, Wei Huang, Faisal Masood, Mélony Qin, Mohammed Abu Taleb");
262+
book9781838820756.setPublisher("Packt");
263+
book9781838820756.setPublished(LocalDate.of(2020, 9, 1));
264+
book9781838820756.setPages(780);
265+
book9781838820756.setDescription(
266+
"""
267+
Thanks to its extensive support for managing hundreds of containers that run \
268+
cloud-native applications, Kubernetes is the most popular open source container \
269+
orchestration platform that makes cluster management easy. This workshop adopts a \
270+
practical approach to get you acquainted with the Kubernetes environment and its \
271+
applications. Starting with an introduction to the fundamentals of Kubernetes, \
272+
you'll install and set up your Kubernetes environment. You'll understand how to \
273+
write YAML files and deploy your first simple web application container using \
274+
Pod. You'll then assign human-friendly names to Pods, explore various Kubernetes \
275+
entities and functions, and discover when to use them. As you work through the \
276+
chapters, this Kubernetes book will show you how you can make full-scale use of \
277+
Kubernetes by applying a variety of techniques for designing components and \
278+
deploying clusters. You'll also get to grips with security policies for limiting \
279+
access to certain functions inside the cluster. Toward the end of the book, \
280+
you'll get a rundown of Kubernetes advanced features for building your own \
281+
controller and upgrading to a Kubernetes cluster without downtime.""");
282+
book9781838820756.setWebsite("https://www.packtpub.com/free-ebook/the-kubernetes-workshop/9781838820756");
283+
books.add(book9781838820756);
119284
return books;
120285
}
121286
}

src/main/java/ar/com/nanotaboada/java/samples/spring/boot/repositories/BooksRepository.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package ar.com.nanotaboada.java.samples.spring.boot.repositories;
22

3+
import org.springframework.data.jpa.repository.Query;
34
import org.springframework.data.repository.CrudRepository;
5+
import org.springframework.data.repository.query.Param;
46
import org.springframework.stereotype.Repository;
57

68
import ar.com.nanotaboada.java.samples.spring.boot.models.Book;
79

10+
import java.util.List;
811
import java.util.Optional;
912

1013
@Repository
@@ -16,4 +19,14 @@ public interface BooksRepository extends CrudRepository<Book, String> {
1619
// Non-default methods in interfaces are not shown in coverage reports
1720
// https://www.jacoco.org/jacoco/trunk/doc/faq.html
1821
Optional<Book> findByIsbn(String isbn);
22+
23+
/**
24+
* Finds books whose description contains the given keyword (case-insensitive).
25+
* Uses JPQL with CAST to handle CLOB description field.
26+
*
27+
* @param keyword the keyword to search for in the description
28+
* @return a list of books matching the search criteria
29+
*/
30+
@Query("SELECT b FROM Book b WHERE LOWER(CAST(b.description AS string)) LIKE LOWER(CONCAT('%', :keyword, '%'))")
31+
List<Book> findByDescriptionContainingIgnoreCase(@Param("keyword") String keyword);
1932
}

src/main/java/ar/com/nanotaboada/java/samples/spring/boot/services/BooksService.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ public List<BookDTO> retrieveAll() {
6060
.toList();
6161
}
6262

63+
/*
64+
* -------------------------------------------------------------------------
65+
* Search
66+
* -------------------------------------------------------------------------
67+
*/
68+
69+
public List<BookDTO> searchByDescription(String keyword) {
70+
return booksRepository.findByDescriptionContainingIgnoreCase(keyword)
71+
.stream()
72+
.map(this::mapFrom)
73+
.toList();
74+
}
75+
6376
/*
6477
* -------------------------------------------------------------------------
6578
* Update

src/test/java/ar/com/nanotaboada/java/samples/spring/boot/test/BookFakes.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,22 @@ public static Book createOneValid() {
1616
Book book = new Book();
1717
book.setIsbn("9781484200773");
1818
book.setTitle("Pro Git");
19-
book.setSubtitle("Everything you neeed to know about Git");
20-
book.setAuthor("Scott Chacon and Ben Straub");
21-
book.setPublisher("lulu.com; First Edition");
19+
book.setSubtitle("Everything You Need to Know About Git");
20+
book.setAuthor("Scott Chacon, Ben Straub");
21+
book.setPublisher("Apress");
2222
book.setPublished(LocalDate.of(2014, 11, 18));
23-
book.setPages(458);
23+
book.setPages(456);
2424
book.setDescription(
2525
"""
26-
Pro Git (Second Edition) is your fully-updated guide to Git and its \
27-
usage in the modern world. Git has come a long way since it was first developed by \
28-
Linus Torvalds for Linux kernel development. It has taken the open source world by \
29-
storm since its inception in 2005, and this book teaches you how to use it like a \
30-
pro.""");
26+
Pro Git is your fully-updated guide to Git and its usage in the modern world. \
27+
Git has come a long way since it was first developed by Linus Torvalds for Linux \
28+
kernel development. It has taken the open source world by storm since its \
29+
inception in 2005, and this book teaches you how to use it like a pro. Effective \
30+
and well-implemented version control is a necessity for successful web projects, \
31+
whether large or small. This book will help you master the fundamentals of Git, \
32+
including branching and merging, creating and managing repositories, customizing \
33+
your workflow, and using Git in a team environment. You'll also learn advanced \
34+
topics such as Git internals, debugging, automation, and customization.""");
3135
book.setWebsite("https://git-scm.com/book/en/v2");
3236
return book;
3337
}

0 commit comments

Comments
 (0)