Skip to content

Commit

Permalink
up to jpa-search-helper 3.2.2
Browse files Browse the repository at this point in the history
  • Loading branch information
biagio committed Nov 14, 2024
1 parent 29c3475 commit ac5d418
Show file tree
Hide file tree
Showing 12 changed files with 151 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Start the application and try it:
```

- OpenAPI/Swagger: http://localhost:8080/swagger-ui/index.html
- GraphiQL: http://localhost:8080/graphiql
- Grafana: http://localhost:3000
- Spring Boot dashboard: http://localhost:3000/dashboards
- Prometheus & Tempo: http://localhost:3000/explore
Expand Down
6 changes: 5 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ dependencyManagement {

dependencies {
// jpa-search-helper
implementation 'app.tozzi:jpa-search-helper:3.2.1'
implementation 'app.tozzi:jpa-search-helper:3.2.2'

// Spring Boot dependencies
implementation 'org.springframework.boot:spring-boot-starter-actuator'
Expand All @@ -47,6 +47,9 @@ dependencies {
implementation 'io.micrometer:micrometer-tracing-bridge-otel'
implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
runtimeOnly 'io.micrometer:micrometer-registry-prometheus'
runtimeOnly 'com.netflix.graphql.dgs:graphql-dgs-spring-boot-micrometer'

// Dev
developmentOnly 'org.springframework.boot:spring-boot-docker-compose'

// DB
Expand All @@ -55,6 +58,7 @@ dependencies {
// Test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation 'com.netflix.graphql.dgs:graphql-dgs-spring-graphql-starter-test'
}

tasks.named('test') {
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/app/tozzi/manager/BookManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import io.micrometer.observation.annotation.Observed;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
Expand All @@ -18,10 +19,12 @@ public class BookManager {
@Autowired
private BookRepository bookRepository;

@Transactional(readOnly = true)
public List<Book> findBooks(Map<String, String> filters) {
return bookRepository.findAllWithPaginationAndSorting(filters, Book.class).map(BookUtils::toBook).toList();
}

@Transactional(readOnly = true)
public List<Book> findBooks(JPASearchInput input) {
return bookRepository.findAllWithPaginationAndSorting(input, Book.class).map(BookUtils::toBook).toList();
}
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/app/tozzi/repository/entity/AuthorEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.Setter;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Entity
Expand Down Expand Up @@ -32,4 +33,17 @@ public class AuthorEntity {
@ManyToMany(mappedBy = "authors")
private Set<BookEntity> books = new HashSet<>();

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

var that = (AuthorEntity) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
return Objects.hashCode(id);
}
}
14 changes: 14 additions & 0 deletions src/main/java/app/tozzi/repository/entity/BookEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Entity
Expand Down Expand Up @@ -52,4 +53,17 @@ public class BookEntity {
@Formula("(SELECT AVG(s.PRICE) FROM SALES s WHERE s.book_id = id)")
private BigDecimal avgPrice;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

var that = (BookEntity) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
return Objects.hashCode(id);
}
}
15 changes: 15 additions & 0 deletions src/main/java/app/tozzi/repository/entity/GenresEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.Setter;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

@Entity
Expand All @@ -23,4 +24,18 @@ public class GenresEntity {

@ManyToMany(mappedBy = "genres")
private Set<AuthorEntity> authors = new HashSet<>();

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

var that = (GenresEntity) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
return Objects.hashCode(id);
}
}
15 changes: 15 additions & 0 deletions src/main/java/app/tozzi/repository/entity/SalesEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.Setter;

import java.math.BigDecimal;
import java.util.Objects;

@Entity
@Getter
Expand All @@ -26,4 +27,18 @@ public class SalesEntity {

@Column(name = "CHANNEL")
private String channel;

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

var that = (SalesEntity) o;
return Objects.equals(id, that.id);
}

@Override
public int hashCode() {
return Objects.hashCode(id);
}
}
15 changes: 15 additions & 0 deletions src/main/resources/application.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,18 @@ logging:
org:
hibernate: DEBUG

dgs:
graphql:
virtualthreads:
enabled: true

server:
compression:
enabled: true
min-response-size: 10KB
servlet:
encoding:
charset: UTF-8
force-request: true
force-response: true
shutdown: graceful
1 change: 1 addition & 0 deletions src/main/resources/schema/schema.graphql
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
type Query {

# Advanced search with projection
projection(filters: [Filter]): [Book]

}
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void mode1_success() throws Exception {
mvc.perform(get(PATH + "?isbn_eq=1234567891234567")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().is(200))
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE));
.andExpect(content().contentType("application/json;charset=UTF-8"));
verify(bookManager, times(1)).findBooks(anyMap());
}

Expand All @@ -122,7 +122,7 @@ public void mode2_success() throws Exception {
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().is(200))
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE));
.andExpect(content().contentType("application/json;charset=UTF-8"));
verify(bookManager, times(1)).findBooks(any(JPASearchInput.class));
}

Expand Down
65 changes: 65 additions & 0 deletions src/test/java/app/tozzi/controller/GraphQLTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package app.tozzi.controller;

import app.tozzi.datafetcher.BookDataFetcher;
import app.tozzi.model.Book;
import app.tozzi.repository.BookRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;

import java.util.List;
import java.util.Map;

import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
public class GraphQLTest {

@Autowired
private MockMvc mockMvc;

@MockBean
private BookDataFetcher bookDataFetcher;

@MockBean
private BookRepository bookRepository;

@Test
public void test_ok() throws Exception {
var book = Book.builder()
.isbn("1234567891234567")
.build();

when(bookRepository.projection(anyMap(), any(), any())).thenReturn(List.of(Map.of("isbn", "1234567890123456")));
when(bookDataFetcher.projection(any(), any())).thenReturn(List.of(book));

mockMvc.perform(MockMvcRequestBuilders.post("/graphql")
.contentType("application/json")
.content("{\"query\":\"query {\\n\\tprojection(\\n\\t\\tfilters: [{ key: \\\"isbn_in\\\", value: \\\"1234567890123456,2234567890123456\\\" }]\\n\\t) {\\n\\t\\tisbn\\n\\t}\\n}\\n\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.data.projection[0].isbn").exists());

verify(bookDataFetcher, times(1)).projection(any(), any());
}

@Test
public void test_ko() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/graphql")
.contentType("application/json")
.content("{\"query\":\"{\\n projection(filters : [\\n { key: \\\"isbn_in\\\", value: \\\"1234567890123456,2234567890123456\\\" }\\n ]) {\\n isbna\\n }\\n }\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.errors").exists())
.andExpect(jsonPath("$.data").doesNotExist());

verify(bookDataFetcher, times(0)).projection(any(), any());
}

}
2 changes: 1 addition & 1 deletion src/test/java/app/tozzi/util/BookUtilsUnitTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void toBook() {
g1.setDescription("Fantasy");

GenresEntity g2 = new GenresEntity();
g2.setId(1L);
g2.setId(2L);
g2.setDescription("Horror");

a1.getGenres().add(g1);
Expand Down

0 comments on commit ac5d418

Please sign in to comment.