Skip to content

Commit 9672f8c

Browse files
fix: Removed Javascript from Spring application (#306)
* fix: Removed Javascript from Spring application * Added form * Added JSON/Message form back * Fix * forgor
1 parent b209da7 commit 9672f8c

14 files changed

+275
-711
lines changed

docs/guides/OPENAI_CHAT_COMPLETION.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ var result = OpenAiClient.forModel(GPT_35_TURBO).chatCompletion(request);
122122
String resultMessage = result.getContent();
123123
```
124124

125-
See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OpenAiController.java)
125+
See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OpenAiService.java)
126126

127127
## Chat Completion with Specific Model Version
128128

@@ -205,7 +205,7 @@ Integer tokensUsed = totalOutput.getUsage().getCompletionTokens();
205205
System.out.println("Tokens used: " + tokensUsed);
206206
```
207207

208-
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OpenAiController.java). It shows the usage of Spring
208+
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OpenAiService.java). It shows the usage of Spring
209209
Boot's `ResponseBodyEmitter` to stream the chat completion delta messages to the frontend in real-time.
210210

211211
## Embedding
@@ -218,4 +218,4 @@ var request = new OpenAiEmbeddingParameters().setInput("Hello World");
218218
OpenAiEmbeddingOutput embedding = OpenAiClient.forModel(TEXT_EMBEDDING_ADA_002).embedding(request);
219219
```
220220

221-
See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OpenAiController.java)
221+
See [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OpenAiService.java)

docs/guides/ORCHESTRATION_CHAT_COMPLETION.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ var config = new OrchestrationModuleConfig()
8383
.withLlmConfig(OrchestrationAiModel.GPT_4O);
8484
```
8585

86-
Please also refer to [our sample code](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) for this and all following code examples.
86+
Please also refer to [our sample code](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java) for this and all following code examples.
8787

8888
## Chat Completion
8989

@@ -176,7 +176,7 @@ var result =
176176
The convenience method `getContent()` on the resulting object will throw an `OrchestrationClientException` upon invocation.
177177
The low level API under `getOriginalResponse()` will not throw an exception.
178178

179-
You will find [some examples](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java) in our Spring Boot application demonstrating response handling with filters.
179+
You will find [some examples](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java) in our Spring Boot application demonstrating response handling with filters.
180180

181181
## Data masking
182182

@@ -253,7 +253,7 @@ try (Stream<String> stream = client.streamChatCompletion(prompt, config)) {
253253
}
254254
```
255255

256-
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/OrchestrationController.java).
256+
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/OrchestrationService.java).
257257
It shows the usage of Spring Boot's `ResponseBodyEmitter` to stream the chat completion delta messages to the frontend in real-time.
258258

259259
## Set model parameters

docs/guides/SPRING_AI_INTEGRATION.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Prompt prompt = new Prompt("What is the capital of France?", opts);
5050
ChatResponse response = client.call(prompt);
5151
```
5252

53-
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationController.java).
53+
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/SpringAiOrchestrationService.java).
5454

5555
## Orchestration Masking
5656

@@ -74,7 +74,7 @@ ChatResponse response = client.call(prompt);
7474
```
7575

7676
Please
77-
find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationController.java).
77+
find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/SpringAiOrchestrationService.java).
7878

7979
## Stream chat completion
8080

@@ -98,4 +98,4 @@ Flux<String> responseFlux =
9898

9999
_Note: A Spring endpoint can return `Flux` instead of `ResponseEntity`._
100100

101-
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/SpringAiOrchestrationController.java).
101+
Please find [an example in our Spring Boot application](../../sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/services/SpringAiOrchestrationService.java).

sample-code/spring-app/pom.xml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,6 @@
118118
<groupId>com.fasterxml.jackson.core</groupId>
119119
<artifactId>jackson-core</artifactId>
120120
</dependency>
121-
<dependency>
122-
<groupId>com.fasterxml.jackson.core</groupId>
123-
<artifactId>jackson-annotations</artifactId>
124-
</dependency>
125121
<!-- scope "runtime" -->
126122
<dependency>
127123
<groupId>ch.qos.logback</groupId>

sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/Application.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,34 @@
11
package com.sap.ai.sdk.app;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import com.sap.ai.sdk.orchestration.OrchestrationJacksonConfiguration;
5+
import javax.annotation.Nonnull;
36
import org.springframework.boot.SpringApplication;
47
import org.springframework.boot.autoconfigure.SpringBootApplication;
58
import org.springframework.boot.web.servlet.ServletComponentScan;
9+
import org.springframework.context.annotation.Bean;
610
import org.springframework.context.annotation.ComponentScan;
11+
import org.springframework.context.annotation.Primary;
712

813
/** Main class to start the Spring Boot application. */
914
@SpringBootApplication
1015
@ComponentScan({"com.sap.cloud.sdk", "com.sap.ai.sdk.app"})
1116
@ServletComponentScan({"com.sap.cloud.sdk", "com.sap.ai.sdk.app"})
1217
public class Application {
18+
19+
/**
20+
* Temporary workaround to fix the issue with the Orchestration spec.
21+
*
22+
* @return a modified object mapper that works for Orchestration.
23+
*/
24+
@Bean
25+
@Primary
26+
@SuppressWarnings("unused")
27+
@Nonnull
28+
public ObjectMapper objectMapper() {
29+
return OrchestrationJacksonConfiguration.getOrchestrationObjectMapper();
30+
}
31+
1332
/**
1433
* Main method to start the Spring Boot application.
1534
*

sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/ControllerExceptionHandler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
class ControllerExceptionHandler {
1515
/** Exceptions thrown by the Spring Boot controllers are turned into a readable text response. */
1616
@ExceptionHandler(Exception.class)
17-
ResponseEntity<String> handleError(final Exception ex) {
17+
Object handleError(final Exception ex) {
1818
final var headers = new HttpHeaders();
1919
headers.setContentType(MediaType.TEXT_PLAIN);
2020

sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/ConfigurationController.java

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
import com.sap.ai.sdk.core.model.AiConfiguration;
55
import java.util.stream.Collectors;
66
import javax.annotation.Nullable;
7-
import org.springframework.http.ResponseEntity;
87
import org.springframework.web.bind.annotation.GetMapping;
9-
import org.springframework.web.bind.annotation.RequestHeader;
8+
import org.springframework.web.bind.annotation.RequestParam;
109
import org.springframework.web.bind.annotation.RestController;
1110

1211
/** Endpoint for Configuration operations */
@@ -16,23 +15,17 @@ class ConfigurationController {
1615

1716
private static final ConfigurationApi CLIENT = new ConfigurationApi();
1817

19-
/**
20-
* Get the list of configurations.
21-
*
22-
* @param accept the accept header
23-
* @return a response entity with a string representation of the list of configurations
24-
*/
2518
@GetMapping("/configurations")
26-
ResponseEntity<Object> getConfigurations(
27-
@Nullable @RequestHeader(value = "accept", required = false) final String accept) {
19+
Object getConfigurations(
20+
@Nullable @RequestParam(value = "format", required = false) final String format) {
2821
final var configList = CLIENT.query("default");
29-
if ("application/json".equals(accept)) {
30-
return ResponseEntity.ok().body(configList);
22+
if ("json".equals(format)) {
23+
return configList;
3124
}
3225
final var items =
3326
configList.getResources().stream()
3427
.map(AiConfiguration::getName)
3528
.collect(Collectors.joining(", "));
36-
return ResponseEntity.ok("The following configurations are available: %s.".formatted(items));
29+
return "The following configurations are available: %s.".formatted(items);
3730
}
3831
}

sample-code/spring-app/src/main/java/com/sap/ai/sdk/app/controllers/DeploymentController.java

Lines changed: 30 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222
import org.springframework.http.ResponseEntity;
2323
import org.springframework.web.bind.annotation.GetMapping;
2424
import org.springframework.web.bind.annotation.PathVariable;
25-
import org.springframework.web.bind.annotation.RequestHeader;
2625
import org.springframework.web.bind.annotation.RequestMapping;
26+
import org.springframework.web.bind.annotation.RequestParam;
2727
import org.springframework.web.bind.annotation.RestController;
2828

2929
/** Endpoints for AI Core AiDeployment operations */
@@ -36,12 +36,7 @@ class DeploymentController {
3636
private static final DeploymentApi CLIENT = new DeploymentApi();
3737
private static final String RESOURCE_GROUP = "default";
3838

39-
/**
40-
* Create and delete a deployment with the Java specific configuration ID.
41-
*
42-
* @param configId The configuration id.
43-
* @return the deployment deletion response
44-
*/
39+
/** Create and delete a deployment with the Java specific configuration ID. */
4540
@Nullable
4641
AiDeploymentDeletionResponse createAndDeleteDeploymentByConfigId(final String configId) {
4742
final var deployment =
@@ -53,20 +48,14 @@ AiDeploymentDeletionResponse createAndDeleteDeploymentByConfigId(final String co
5348
return CLIENT.delete(RESOURCE_GROUP, deployment.getId());
5449
}
5550

56-
/**
57-
* Create and delete a deployment with the Java specific configuration ID.
58-
*
59-
* @param configId The configuration id.
60-
* @param accept The accept header.
61-
* @return a response entity with a string representation of the deployment creation response
62-
*/
51+
/** Create and delete a deployment with the Java specific configuration ID. */
6352
@GetMapping("/by-config/{id}/createDelete")
64-
ResponseEntity<Object> createAndDeleteDeploymentByConfigId(
53+
Object createAndDeleteDeploymentByConfigId(
6554
@Nonnull @PathVariable("id") final String configId,
66-
@Nullable @RequestHeader(value = "accept", required = false) final String accept) {
55+
@Nullable @RequestParam(value = "format", required = false) final String format) {
6756
final var response = createAndDeleteDeploymentByConfigId(configId);
68-
if ("application/json".equals(accept)) {
69-
return ResponseEntity.ok().body(response);
57+
if ("json".equals(format)) {
58+
return response;
7059
}
7160
return ResponseEntity.ok("Deployment created and will be deleted.");
7261
}
@@ -75,16 +64,11 @@ ResponseEntity<Object> createAndDeleteDeploymentByConfigId(
7564
* Stop all deployments with the Java specific configuration ID.
7665
*
7766
* <p>Only RUNNING deployments can be STOPPED
78-
*
79-
* @param configId The configuration id.
80-
* @param accept The accept header.
81-
* @return a response entity with a string representation of the deployment modification response
8267
*/
8368
@GetMapping("/by-config/{id}/stop")
84-
@Nonnull
85-
ResponseEntity<Object> stopByConfigId(
69+
Object stopByConfigId(
8670
@Nonnull @PathVariable("id") final String configId,
87-
@Nullable @RequestHeader(value = "accept", required = false) final String accept) {
71+
@Nullable @RequestParam(value = "format", required = false) final String format) {
8872
final List<AiDeployment> myDeployments = getAllByConfigId(configId);
8973
log.info("Found {} deployments to STOP", myDeployments.size());
9074

@@ -96,26 +80,21 @@ ResponseEntity<Object> stopByConfigId(
9680
.map(id -> CLIENT.modify(RESOURCE_GROUP, id, modificationRequest))
9781
.toList();
9882

99-
if ("application/json".equals(accept)) {
100-
return ResponseEntity.ok().body(stoppedDeployments);
83+
if ("json".equals(format)) {
84+
return stoppedDeployments;
10185
}
102-
return ResponseEntity.ok("Deployments under the given config ID stopped.");
86+
return "Deployments under the given config ID stopped.";
10387
}
10488

10589
/**
10690
* Delete all deployments with the Java specific configuration ID.
10791
*
10892
* <p>Only UNKNOWN and STOPPED deployments can be DELETED
109-
*
110-
* @param configId The configuration id.
111-
* @param accept The accept header.
112-
* @return a response entity with a string representation of the deployment deletion response
11393
*/
11494
@GetMapping("/by-config/{id}/delete")
115-
@Nonnull
116-
ResponseEntity<Object> deleteByConfigId(
95+
Object deleteByConfigId(
11796
@Nonnull @PathVariable("id") final String configId,
118-
@Nullable @RequestHeader(value = "accept", required = false) final String accept) {
97+
@Nullable @RequestParam(value = "format", required = false) final String format) {
11998
final List<AiDeployment> myDeployments = getAllByConfigId(configId);
12099
log.info("Found {} deployments to DELETE", myDeployments.size());
121100

@@ -124,40 +103,27 @@ ResponseEntity<Object> deleteByConfigId(
124103
myDeployments.stream()
125104
.map(deployment -> CLIENT.delete(RESOURCE_GROUP, deployment.getId()))
126105
.toList();
127-
if ("application/json".equals(accept)) {
128-
return ResponseEntity.ok().body(responseList);
106+
if ("json".equals(format)) {
107+
return responseList;
129108
}
130-
return ResponseEntity.ok("Deployments under the given config ID deleted.");
109+
return "Deployments under the given config ID deleted.";
131110
}
132111

133-
/**
134-
* Get all deployments with the Java specific configuration ID.
135-
*
136-
* @param configId The configuration id.
137-
* @param accept The accept header.
138-
* @return a response entity with a string representation of the Java specific deployments
139-
*/
112+
/** Get all deployments with the Java specific configuration ID. */
140113
@GetMapping("/by-config/{id}/getAll")
141-
ResponseEntity<Object> getAllByConfigId(
114+
Object getAllByConfigId(
142115
@Nonnull @PathVariable("id") final String configId,
143-
@Nullable @RequestHeader(value = "accept", required = false) final String accept) {
116+
@Nullable @RequestParam(value = "format", required = false) final String format) {
144117
final var deployments = getAllByConfigId(configId);
145-
if ("application/json".equals(accept)) {
146-
return ResponseEntity.ok().body(deployments);
118+
if ("json".equals(format)) {
119+
return deployments;
147120
}
148121
final var items =
149122
deployments.stream().map(AiDeployment::getId).collect(Collectors.joining(", "));
150-
return ResponseEntity.ok(
151-
"The following Java-specific deployments are available: %s.".formatted(items));
123+
return "The following Java-specific deployments are available: %s.".formatted(items);
152124
}
153125

154-
/**
155-
* Get all deployments with the Java specific configuration ID.
156-
*
157-
* @param configId The configuration id.
158-
* @return the Java specific deployments
159-
*/
160-
@Nonnull
126+
/** Get all deployments with the Java specific configuration ID. */
161127
List<AiDeployment> getAllByConfigId(@Nonnull @PathVariable("id") final String configId) {
162128
final AiDeploymentList deploymentList = CLIENT.query(RESOURCE_GROUP);
163129

@@ -166,34 +132,23 @@ List<AiDeployment> getAllByConfigId(@Nonnull @PathVariable("id") final String co
166132
.toList();
167133
}
168134

169-
/**
170-
* Get all deployments, including non-Java specific deployments
171-
*
172-
* @param accept The accept header.
173-
* @return a response entity with a string representation of the Java specific deployments
174-
*/
135+
/** Get all deployments, including non-Java specific deployments */
175136
@GetMapping("/getAll")
176-
@Nonnull
177-
ResponseEntity<Object> getAll(
178-
@Nullable @RequestHeader(value = "accept", required = false) final String accept) {
137+
Object getAll(@Nullable @RequestParam(value = "format", required = false) final String format) {
179138
final var deployments = getAll();
180-
if ("application/json".equals(accept)) {
181-
return ResponseEntity.ok().body(deployments);
139+
if ("json".equals(format)) {
140+
return deployments;
182141
}
183142
final var items =
184143
deployments != null
185144
? deployments.getResources().stream()
186145
.map(AiDeployment::getId)
187146
.collect(Collectors.joining(", "))
188147
: "";
189-
return ResponseEntity.ok("The following deployments are available: %s.".formatted(items));
148+
return "The following deployments are available: %s.".formatted(items);
190149
}
191150

192-
/**
193-
* Get all deployments
194-
*
195-
* @return all deployments
196-
*/
151+
/** Get all deployments */
197152
@Nullable
198153
AiDeploymentList getAll() {
199154
return CLIENT.query(RESOURCE_GROUP);
@@ -203,9 +158,6 @@ AiDeploymentList getAll() {
203158
* Create a configuration, and deploy it.
204159
*
205160
* <p>This is to be invoked from a unit test.
206-
*
207-
* @param model The OpenAI model to deploy
208-
* @return the deployment creation response
209161
*/
210162
@Nonnull
211163
@SuppressWarnings("unused") // debug method that doesn't need to be tested

0 commit comments

Comments
 (0)