Skip to content

Commit 5df1ea0

Browse files
author
I750911
committed
Merge remote-tracking branch 'origin/main' into update-available-model-list
2 parents 4a656fb + 97bc3b5 commit 5df1ea0

File tree

6 files changed

+116
-10
lines changed

6 files changed

+116
-10
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ The following table lists the required versions, based on the latest release:
4747

4848
See [an example `pom.xml` in our Spring Boot application](sample-code/spring-app/pom.xml).
4949

50+
> [!WARNING]
51+
> All classes under any of the `...model` packages are generated from an OpenAPI specification and marked as `@Beta`.
52+
> This means that these model classes are not guaranteed to be stable and may change with future releases.
53+
> They are safe to use, but may require updates even in minor releases.
54+
5055
## Getting Started
5156

5257
### What You'll Build
@@ -130,6 +135,8 @@ For more detailed information and advanced usage, please refer to the following:
130135
- [OpenAI Chat Completion](docs/guides/OPENAI_CHAT_COMPLETION.md)
131136
- [AI Core Deployment](docs/guides/AI_CORE_DEPLOYMENT.md)
132137

138+
For updating versions, please refer to the [**Release Notes**](docs/release-notes/release-notes-0-to-14.md).
139+
133140
## FAQs
134141

135142
### _"How to add a custom header to AI Core requests?"_

core/pom.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@
3030
</developers>
3131
<properties>
3232
<project.rootdir>${project.basedir}/../</project.rootdir>
33-
<coverage.complexity>52%</coverage.complexity>
34-
<coverage.line>64%</coverage.line>
35-
<coverage.instruction>62%</coverage.instruction>
36-
<coverage.branch>47%</coverage.branch>
37-
<coverage.method>65%</coverage.method>
38-
<coverage.class>80%</coverage.class>
33+
<coverage.complexity>62%</coverage.complexity>
34+
<coverage.line>76%</coverage.line>
35+
<coverage.instruction>76%</coverage.instruction>
36+
<coverage.branch>60%</coverage.branch>
37+
<coverage.method>74%</coverage.method>
38+
<coverage.class>90%</coverage.class>
3939
</properties>
4040

4141
<dependencies>
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.sap.ai.sdk.core.common;
2+
3+
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4+
import static org.mockito.ArgumentMatchers.any;
5+
import static org.mockito.Mockito.doThrow;
6+
import static org.mockito.Mockito.spy;
7+
import static org.mockito.Mockito.when;
8+
9+
import com.fasterxml.jackson.annotation.JsonProperty;
10+
import java.io.IOException;
11+
import lombok.Data;
12+
import lombok.SneakyThrows;
13+
import lombok.experimental.StandardException;
14+
import org.apache.hc.core5.http.ContentType;
15+
import org.apache.hc.core5.http.HttpEntity;
16+
import org.apache.hc.core5.http.io.entity.StringEntity;
17+
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
18+
import org.junit.jupiter.api.Test;
19+
20+
class ClientResponseHandlerTest {
21+
22+
static class MyResponse {}
23+
24+
@Data
25+
static class MyError implements ClientError {
26+
@JsonProperty("message")
27+
private String message;
28+
}
29+
30+
@StandardException
31+
static class MyException extends ClientException {}
32+
33+
@Test
34+
public void testParseErrorAndThrow() {
35+
var sut = new ClientResponseHandler<>(MyResponse.class, MyError.class, MyException::new);
36+
37+
MyException cause = new MyException("Something wrong");
38+
39+
assertThatThrownBy(() -> sut.parseErrorAndThrow("{\"message\":\"foobar\"}", cause))
40+
.isInstanceOf(MyException.class)
41+
.hasMessage("Something wrong and error message: 'foobar'")
42+
.hasCause(cause);
43+
44+
assertThatThrownBy(() -> sut.parseErrorAndThrow("{\"foo\":\"bar\"}", cause))
45+
.isInstanceOf(MyException.class)
46+
.hasMessage("Something wrong and error message: ''")
47+
.hasCause(cause);
48+
49+
assertThatThrownBy(() -> sut.parseErrorAndThrow("<message>foobar</message>", cause))
50+
.isEqualTo(cause);
51+
}
52+
53+
@SneakyThrows
54+
@Test
55+
public void testBuildExceptionAndThrow() {
56+
var sut = new ClientResponseHandler<>(MyResponse.class, MyError.class, MyException::new);
57+
58+
HttpEntity entityWithNetworkIssues = spy(new StringEntity(""));
59+
doThrow(new IOException("Network issues")).when(entityWithNetworkIssues).writeTo(any());
60+
doThrow(new IOException("Network issues")).when(entityWithNetworkIssues).getContent();
61+
62+
var response = spy(new BasicClassicHttpResponse(400, "Bad Request"));
63+
when(response.getEntity())
64+
.thenReturn(null)
65+
.thenReturn(entityWithNetworkIssues)
66+
.thenReturn(new StringEntity("", ContentType.APPLICATION_JSON))
67+
.thenReturn(new StringEntity("<html>oh", ContentType.TEXT_HTML))
68+
.thenReturn(new StringEntity("{\"message\":\"foobar\"}", ContentType.APPLICATION_JSON));
69+
70+
assertThatThrownBy(() -> sut.buildExceptionAndThrow(response))
71+
.isInstanceOf(MyException.class)
72+
.hasMessage("Request failed with status 400 Bad Request")
73+
.hasNoCause();
74+
assertThatThrownBy(() -> sut.buildExceptionAndThrow(response))
75+
.isInstanceOf(MyException.class)
76+
.hasMessage("Request failed with status 400 Bad Request")
77+
.hasNoCause();
78+
assertThatThrownBy(() -> sut.buildExceptionAndThrow(response))
79+
.isInstanceOf(MyException.class)
80+
.hasMessage("Request failed with status 400 Bad Request")
81+
.hasNoCause();
82+
assertThatThrownBy(() -> sut.buildExceptionAndThrow(response))
83+
.isInstanceOf(MyException.class)
84+
.hasMessage("Request failed with status 400 Bad Request")
85+
.hasNoCause();
86+
assertThatThrownBy(() -> sut.buildExceptionAndThrow(response))
87+
.isInstanceOf(MyException.class)
88+
.hasMessage("Request failed with status 400 Bad Request and error message: 'foobar'")
89+
.hasCause(new MyException("Request failed with status 400 Bad Request"));
90+
}
91+
}

docs/guides/AI_CORE_DEPLOYMENT.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313

1414
This guide provides examples on how to create and manage deployments in SAP AI Core using the SAP AI SDK for Java.
1515

16+
> [!WARNING]
17+
> The below examples rely on generated model classes.
18+
> Please be aware of the [implications described here](/README.md#general-requirements).
19+
1620
## Prerequisites
1721

1822
Before using the AI Core module, ensure that you have met all the general requirements outlined in the [README.md](../../README.md#general-requirements).

docs/guides/CONNECTING_TO_AICORE.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,18 @@ You can define a destination in the BTP Destination Service and use that to conn
116116
- **Client ID**: `[clientid]`
117117
- **Client Secret**: `[clientsecret]`
118118
- **Token Service URL Type**: `Dedicated`
119-
- **Token Service URL**: `[url]`
119+
- **Token Service URL**: `[url]/oauth/token`
120120
121121
Fill in the values for URL, client ID, client secret, and token service URL from the service key JSON.
122+
Make sure to add `/oauth/token` in the token service URL.
122123
123124
</details>
124125
125126
To use the destination, ensure you have created an instance of the BTP Destination Service and bound it to your application.
126127
128+
> [!Tip]
129+
> If you are using CAP, you can again use Hybrid Testing to bind the destination service to your application when running **locally**.
130+
127131
```java
128132
Destination destination = DestinationAccessor.getDestination("my-aicore").asHttp();
129133
AiCoreService aiCoreService = new AiCoreService().withBaseDestination(destination);

sample-code/spring-app/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ Before you can run the sample app, you need to install the AI SDK into your loca
1313

1414
> [!NOTE]
1515
> The sample app uses the latest state of the SDK, so make sure to install the SDK after pulling a new version via Git.
16-
> Alternatively, you check out one of the release tags of the repository, e.g. `git fetch --all --tags && git checkout rel/0.1.0`.
16+
> Alternatively, you check out one of the release tags of the repository, e.g. `git fetch --all --tags && git checkout rel/1.1.0`.
1717
1818
Next, you'll need to set up credentials for the AI Core service:
1919

20-
* Follow [these instructions](../../README.md#option-1-set-ai-core-credentials) to create a service key for the AI Core service.
20+
* Follow [these instructions](/docs/guides/CONNECTING_TO_AICORE.md) to create a service key for the AI Core service.
2121

2222
⚠️ Put the `.env` file in the sample app directory.
2323

@@ -29,4 +29,4 @@ Head to http://localhost:8080 in your browser to see all available endpoints.
2929

3030
## Run the E2E Test
3131

32-
Trigger the [GitHub Action](https://github.com/SAP/ai-sdk-java/actions/workflows/e2e-test.yml).
32+
Trigger the [GitHub Action](https://github.com/SAP/ai-sdk-java/actions/workflows/e2e-test.yaml).

0 commit comments

Comments
 (0)