Skip to content

Commit ffc8842

Browse files
committed
feat: update
1 parent 3fc5c52 commit ffc8842

8 files changed

Lines changed: 108 additions & 91 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ gradle-app.setting
2121
.classpath
2222
/.settings/
2323
/.idea/
24+
/log/starter-webmvc-server.log

backend/build.gradle

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
*/
1313
plugins {
1414
id 'java'
15-
id 'org.springframework.boot' version '4.0.6'
15+
id 'org.springframework.boot' version '4.1.0'
1616
id 'io.spring.dependency-management' version '1.1.7'
1717
}
1818

@@ -29,31 +29,46 @@ repositories {
2929
mavenCentral()
3030
}
3131

32+
33+
ext {
34+
set('springAiVersion', "2.0.0-RC2")
35+
}
36+
3237
dependencies {
33-
implementation 'org.springframework.boot:spring-boot-starter-actuator'
34-
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
35-
implementation 'org.springframework.boot:spring-boot-starter-security'
36-
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
37-
implementation 'org.springframework.ai:spring-ai-starter-mcp-client:2.0.0-RC1'
38-
//implementation 'org.springframework.ai:spring-ai-starter-mcp-server-webmvc'
39-
implementation 'org.springframework.ai:spring-ai-tika-document-reader:2.0.0-RC1'
38+
implementation 'org.springframework.boot:spring-boot-starter-actuator'
39+
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
4040
implementation 'org.springframework.boot:spring-boot-starter-liquibase'
41+
implementation 'org.springframework.boot:spring-boot-starter-restclient'
42+
implementation 'org.springframework.boot:spring-boot-starter-security'
43+
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
44+
implementation 'org.springframework.ai:spring-ai-starter-mcp-client'
45+
implementation 'org.springframework.ai:spring-ai-starter-model-ollama'
46+
implementation 'org.springframework.ai:spring-ai-starter-model-transformers'
47+
implementation 'org.springframework.ai:spring-ai-starter-vector-store-pgvector'
48+
implementation 'org.springframework.ai:spring-ai-tika-document-reader'
49+
implementation 'org.springframework.ai:spring-ai-vector-store-advisor'
50+
4151
implementation 'net.javacrumbs.shedlock:shedlock-spring:6.0.1'
4252
implementation 'net.javacrumbs.shedlock:shedlock-provider-jdbc-template:6.0.1'
43-
implementation 'org.springframework.ai:spring-ai-starter-vector-store-pgvector:2.0.0-RC1'
44-
implementation 'org.springframework.ai:spring-ai-starter-model-transformers:2.0.0-RC1'
45-
implementation 'org.springframework.ai:spring-ai-starter-model-ollama:2.0.0-RC1'
4653
implementation 'tools.jackson.dataformat:jackson-dataformat-csv'
47-
testImplementation 'org.springframework.boot:spring-boot-starter-test'
48-
testImplementation 'org.springframework.security:spring-security-test'
49-
testImplementation 'org.springframework.boot:spring-boot-starter-liquibase-test'
50-
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
54+
5155
testImplementation 'org.springframework.boot:spring-boot-starter-actuator-test'
5256
testImplementation 'org.springframework.boot:spring-boot-starter-data-jpa-test'
57+
testImplementation 'org.springframework.boot:spring-boot-starter-liquibase-test'
58+
testImplementation 'org.springframework.boot:spring-boot-starter-restclient-test'
59+
testImplementation 'org.springframework.boot:spring-boot-starter-security-test'
60+
testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test'
61+
5362
testImplementation 'com.tngtech.archunit:archunit-junit5:1.4.2'
5463
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
5564
}
5665

66+
dependencyManagement {
67+
imports {
68+
mavenBom("org.springframework.ai:spring-ai-bom:${property("springAiVersion")}")
69+
}
70+
}
71+
5772
bootJar {
5873
archiveFileName = 'aidocumentlibrarychat.jar'
5974
}

backend/src/main/java/ch/xxx/aidoclibchat/adapter/controller/DocumentController.java

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@
2525
import org.springframework.web.bind.annotation.RestController;
2626
import org.springframework.web.multipart.MultipartFile;
2727

28-
import com.fasterxml.jackson.core.JsonProcessingException;
29-
import com.fasterxml.jackson.core.type.TypeReference;
30-
import com.fasterxml.jackson.databind.ObjectMapper;
31-
3228
import ch.xxx.aidoclibchat.domain.model.dto.BookDto;
3329
import ch.xxx.aidoclibchat.domain.model.dto.ChapterHeading;
3430
import ch.xxx.aidoclibchat.domain.model.dto.DocumentDto;
@@ -38,20 +34,22 @@
3834
import ch.xxx.aidoclibchat.usecase.mapping.BookMapper;
3935
import ch.xxx.aidoclibchat.usecase.mapping.DocumentMapper;
4036
import ch.xxx.aidoclibchat.usecase.service.DocumentService;
37+
import tools.jackson.core.type.TypeReference;
38+
import tools.jackson.databind.json.JsonMapper;
4139

4240
@RestController
4341
@RequestMapping("rest/document")
4442
public class DocumentController {
4543
private final DocumentMapper documentMapper;
4644
private final DocumentService documentService;
4745
private final BookMapper bookMapper;
48-
private final ObjectMapper objectMapper;
46+
private final JsonMapper jsonMapper;
4947

50-
public DocumentController(DocumentMapper documentMapper, DocumentService documentService, BookMapper bookMapper, ObjectMapper objectMapper) {
48+
public DocumentController(DocumentMapper documentMapper, DocumentService documentService, BookMapper bookMapper, JsonMapper jsonMapper) {
5149
this.documentMapper = documentMapper;
5250
this.documentService = documentService;
5351
this.bookMapper = bookMapper;
54-
this.objectMapper = objectMapper;
52+
this.jsonMapper = jsonMapper;
5553
}
5654

5755
@PostMapping("/upload")
@@ -64,11 +62,7 @@ public long handleDocumentUpload(@RequestParam("file") MultipartFile document) {
6462
public BookDto handleBookUpload(@RequestParam("book") MultipartFile bookFile,
6563
@RequestParam("chapters") String chaptersStr) {
6664
List<ChapterHeading> chapters;
67-
try {
68-
chapters = this.objectMapper.readValue(chaptersStr, new TypeReference<List<ChapterHeading>>() {});
69-
} catch (JsonProcessingException e) {
70-
throw new RuntimeException(e);
71-
}
65+
chapters = this.jsonMapper.readValue(chaptersStr, new TypeReference<List<ChapterHeading>>() {});
7266
var book = this.documentService.storeBook(this.bookMapper.toEntity(bookFile), chapters);
7367
this.documentService.addBookSummaries(book);
7468
return BookMapper.toDto(book);

backend/src/main/java/ch/xxx/aidoclibchat/adapter/repository/DocumentVSRepositoryBean.java

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,25 @@
3434
import org.springframework.stereotype.Repository;
3535

3636
import com.fasterxml.jackson.core.JsonProcessingException;
37-
import com.fasterxml.jackson.databind.ObjectMapper;
3837
import com.pgvector.PGvector;
3938

4039
import ch.xxx.aidoclibchat.domain.common.MetaData;
4140
import ch.xxx.aidoclibchat.domain.common.MetaData.DataType;
4241
import ch.xxx.aidoclibchat.domain.model.entity.DocumentVsRepository;
42+
import tools.jackson.databind.json.JsonMapper;
4343

4444
@Repository
4545
public class DocumentVSRepositoryBean implements DocumentVsRepository {
4646
private final String vectorTableName;
4747
private final VectorStore vectorStore;
4848
private final JdbcTemplate jdbcTemplate;
49-
private final ObjectMapper objectMapper;
49+
private final JsonMapper jsonMapper;
5050
private final FilterExpressionConverter filterExpressionConverter;
5151

5252
public DocumentVSRepositoryBean(JdbcTemplate jdbcTemplate, @Qualifier("embeddingModel") EmbeddingModel embeddingClient,
53-
ObjectMapper objectMapper) {
53+
JsonMapper jsonMapper) {
5454
this.jdbcTemplate = jdbcTemplate;
55-
this.objectMapper = objectMapper;
55+
this.jsonMapper = jsonMapper;
5656
this.vectorStore = PgVectorStore.builder(jdbcTemplate, embeddingClient).build();
5757
this.filterExpressionConverter = ((PgVectorStore) this.vectorStore).filterExpressionConverter;
5858
this.vectorTableName = PgVectorStore.DEFAULT_TABLE_NAME;
@@ -95,7 +95,7 @@ public List<Document> findAllTableDocuments() {
9595

9696
return this.jdbcTemplate.query(
9797
String.format("SELECT * FROM %s %s LIMIT ? ", this.vectorTableName, jsonPathFilter),
98-
new DocumentRowMapper(this.objectMapper), 100000);
98+
new DocumentRowMapper(this.jsonMapper), 100000);
9999
}
100100

101101
@Override
@@ -113,10 +113,10 @@ private static class DocumentRowMapper implements RowMapper<Document> {
113113

114114
private static final String COLUMN_CONTENT = "content";
115115

116-
private final ObjectMapper objectMapper;
116+
private final JsonMapper jsonMapper;
117117

118-
public DocumentRowMapper(ObjectMapper objectMapper) {
119-
this.objectMapper = objectMapper;
118+
public DocumentRowMapper(JsonMapper jsonMapper) {
119+
this.jsonMapper = jsonMapper;
120120
}
121121

122122
@Override
@@ -129,9 +129,7 @@ public Document mapRow(ResultSet rs, int rowNum) throws SQLException {
129129
Map<String, Object> metadata = toMap(pgMetadata);
130130
metadata.put(COLUMN_EMBEDDING, this.toDoubleArray(embedding));
131131

132-
Document document = new Document(id, content, metadata);
133-
134-
return document;
132+
return new Document(id, content, metadata);
135133
}
136134

137135
private float[] toDoubleArray(PGobject embedding) throws SQLException {
@@ -142,12 +140,8 @@ private float[] toDoubleArray(PGobject embedding) throws SQLException {
142140
private Map<String, Object> toMap(PGobject pgObject) {
143141

144142
String source = pgObject.getValue();
145-
try {
146-
return (Map<String, Object>) objectMapper.readValue(source, Map.class);
147-
} catch (JsonProcessingException e) {
148-
throw new RuntimeException(e);
149-
}
150-
}
143+
return (Map<String, Object>) jsonMapper.readValue(source, Map.class);
144+
}
151145
}
152146

153147
}

backend/src/main/java/ch/xxx/aidoclibchat/usecase/service/LocalMcpClient.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,14 @@
3131
public class LocalMcpClient {
3232
private final ChatClient chatClient;
3333

34-
public LocalMcpClient(Builder builder, ChatModel chatModel, ToolCallbackProvider tools) {
34+
public LocalMcpClient(Builder builder, ChatModel chatModel,
35+
//ToolCallbackProvider tools,
36+
List<McpSyncClient> mcpClients) {
3537
var advisor = ChatModelCallAdvisor.builder().chatModel(chatModel).build();
36-
this.chatClient = builder.defaultTools(tools).defaultAdvisors(List.of(advisor)).build();
38+
var mcpToolProvider = SyncMcpToolCallbackProvider.builder()
39+
.mcpClients(mcpClients)
40+
.build();
41+
this.chatClient = builder.defaultTools(mcpToolProvider).defaultAdvisors(List.of(advisor)).build();
3742
}
3843

3944
public McpResponseDto createResponse(McpRequestDto requestDto) {

backend/src/main/resources/application.properties

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ spring.servlet.multipart.resolve-lazily=true
2525

2626
spring.jackson.parser.allow-unquoted-control-chars=true
2727
spring.ai.openai.api-key=${OPENAI-API-KEY:23418pajkfdsadl\ufffda}
28-
spring.ai.embedding.transformer.enabled=false
29-
spring.ai.ollama.embedding.enabled=false
28+
spring.ai.model.embedding=transformers
3029

3130
management.health.livenessstate.enabled=true
3231
management.health.readinessstate.enabled=true
@@ -35,11 +34,12 @@ management.endpoint.health.status.http-mapping.down=500
3534
management.endpoint.health.status.http-mapping.out_of_service=503
3635
management.endpoint.health.show-details=always
3736

38-
spring.ai.mcp.client.sse.connections.server1.url=http://localhost:8081
39-
spring.ai.mcp.client.sse.connections.server1.name=my-book-movie-server
37+
# Der Name des Clients im System ist automatisch "my-book-movie-server"
38+
spring.ai.mcp.client.sse.connections.my-book-movie-server.url=http://localhost:8081/sse
4039
spring.ai.mcp.client.enabled=false
40+
spring.ai.mcp.client.toolcallback.enabled=true
4141
embedding-token-limit=2000
4242
document-token-limit=2000
4343
image.result-size=20
4444
openlibrary.result-size=5
45-
tmdb.api.key=${TMDB_API_KEY:}
45+
tmdb.api.key=${TMDB_API_KEY:}

frontend/build.gradle

Lines changed: 34 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,32 @@
1212
*/
1313
plugins {
1414
id 'java'
15+
id "com.github.node-gradle.node" version "7.0.2"
1516
}
1617

1718
group = 'ch.xxx'
1819
version = '0.0.1-SNAPSHOT'
1920

20-
task cleanAngular {
21+
node {
22+
version = '22.16.0'
23+
npmVersion = '10.9.2' // Gewünschte NPM Version
24+
download = true // Lädt Node/NPM automatisch herunter
25+
nodeProjectDir = file("${project.projectDir}/src/angular")
26+
}
27+
28+
tasks.register('npmInstallCustom', NpmTask) {
29+
onlyIf { project.hasProperty('withAngular') }
30+
31+
// Das Plugin weiß durch 'nodeProjectDir' bereits, wo es laufen muss.
32+
// Du musst hier nur noch die Argumente übergeben:
33+
args = ['install']
34+
35+
// Stellt sicher, dass Node/NPM vor der Ausführung heruntergeladen werden
36+
dependsOn 'nodeSetup', 'npmSetup'
37+
dependsOn 'cleanAngular'
38+
}
39+
40+
tasks.register('cleanAngular') {
2141
onlyIf {
2242
project.hasProperty('withAngular')
2343
}
@@ -27,7 +47,7 @@ task cleanAngular {
2747
}
2848
}
2949

30-
task cleanDist {
50+
tasks.register('cleanDist') {
3151
onlyIf {
3252
project.hasProperty('withAngular')
3353
}
@@ -36,7 +56,7 @@ task cleanDist {
3656
}
3757
}
3858

39-
task createDist {
59+
tasks.register('createDist') {
4060
onlyIf {
4161
project.hasProperty('withAngular')
4262
}
@@ -45,53 +65,30 @@ task createDist {
4565
}
4666
}
4767

48-
task npmInstall(type: Exec) {
68+
tasks.register('npmBuild', NpmTask) {
4969
onlyIf {
5070
project.hasProperty('withAngular')
5171
}
52-
workingDir = file('src/angular')
53-
if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")){
54-
commandLine 'npm.cmd', 'install'
55-
} else {
56-
commandLine 'npm', 'install'
57-
}
58-
dependsOn cleanAngular
59-
}
6072

61-
task npmBuild(type: Exec) {
62-
onlyIf {
63-
project.hasProperty('withAngular')
64-
}
65-
workingDir = file('src/angular')
66-
if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")){
67-
commandLine 'npm.cmd', 'run', 'build'
68-
} else {
69-
commandLine 'npm', 'run', 'build'
70-
}
71-
dependsOn npmInstall, cleanDist, createDist
73+
args = ['run', 'build']
74+
75+
dependsOn 'npmInstall', 'cleanDist', 'createDist'
7276
}
7377

74-
task testAngular(type: Exec) {
78+
tasks.register('testAngular', NpmTask) {
7579
onlyIf {
7680
project.hasProperty('withAngular')
7781
}
78-
workingDir = file('src/angular')
79-
if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")){
80-
commandLine 'npm.cmd', 'run', 'test'
82+
if (project.hasProperty("useChromium")) {
83+
args = ['run', 'test-chromium']
8184
} else {
82-
if(project.hasProperty("useChromium")) {
83-
commandLine 'npm', 'run', 'test-chromium'
84-
} else {
85-
commandLine 'npm', 'run', 'test'
86-
}
87-
}
88-
dependsOn npmInstall
89-
doFirst {
90-
println("Running ${commandLine.join(' ')}")
85+
args = ['run', 'test']
9186
}
87+
88+
dependsOn 'npmBuild'
9289
}
9390

94-
task buildAngular {
91+
tasks.register('buildAngular') {
9592
dependsOn npmBuild, testAngular
9693
}
9794

0 commit comments

Comments
 (0)