20
20
import java .util .function .Consumer ;
21
21
22
22
import com .ibm .cloud .sdk .core .security .IamAuthenticator ;
23
+ import com .ibm .cloud .sdk .core .security .IamToken ;
23
24
import org .apache .commons .logging .Log ;
24
25
import org .apache .commons .logging .LogFactory ;
26
+ import org .springframework .retry .annotation .Backoff ;
27
+ import org .springframework .retry .annotation .Retryable ;
25
28
import reactor .core .publisher .Flux ;
26
29
27
30
import org .springframework .ai .retry .RetryUtils ;
@@ -50,6 +53,7 @@ public class WatsonxAiApi {
50
53
private final String streamEndpoint ;
51
54
private final String textEndpoint ;
52
55
private final String projectId ;
56
+ private IamToken token ;
53
57
54
58
/**
55
59
* Create a new chat api.
@@ -72,6 +76,7 @@ public WatsonxAiApi(
72
76
this .textEndpoint = textEndpoint ;
73
77
this .projectId = projectId ;
74
78
this .iamAuthenticator = IamAuthenticator .fromConfiguration (Map .of ("APIKEY" , IAMToken ));
79
+ this .token = this .iamAuthenticator .requestToken ();
75
80
76
81
Consumer <HttpHeaders > defaultHeaders = headers -> {
77
82
headers .setContentType (MediaType .APPLICATION_JSON );
@@ -88,27 +93,33 @@ public WatsonxAiApi(
88
93
.build ();
89
94
}
90
95
96
+ @ Retryable (retryFor = Exception .class , maxAttempts = 3 , backoff = @ Backoff (random = true , delay = 1200 , maxDelay = 7000 , multiplier = 2.5 ))
91
97
public ResponseEntity <WatsonxAiResponse > generate (WatsonxAiRequest watsonxAiRequest ) {
92
98
Assert .notNull (watsonxAiRequest , WATSONX_REQUEST_CANNOT_BE_NULL );
93
99
94
- String bearer = this .iamAuthenticator .requestToken ().getAccessToken ();
100
+ if (this .token .needsRefresh ()) {
101
+ this .token = this .iamAuthenticator .requestToken ();
102
+ }
95
103
96
104
return this .restClient .post ()
97
105
.uri (this .textEndpoint )
98
- .header (HttpHeaders .AUTHORIZATION , "Bearer " + bearer )
106
+ .header (HttpHeaders .AUTHORIZATION , "Bearer " + this . token . getAccessToken () )
99
107
.body (watsonxAiRequest .withProjectId (projectId ))
100
108
.retrieve ()
101
109
.toEntity (WatsonxAiResponse .class );
102
110
}
103
111
112
+ @ Retryable (retryFor = Exception .class , maxAttempts = 3 , backoff = @ Backoff (random = true , delay = 1200 , maxDelay = 7000 , multiplier = 2.5 ))
104
113
public Flux <WatsonxAiResponse > generateStreaming (WatsonxAiRequest watsonxAiRequest ) {
105
114
Assert .notNull (watsonxAiRequest , WATSONX_REQUEST_CANNOT_BE_NULL );
106
115
107
- String bearer = this .iamAuthenticator .requestToken ().getAccessToken ();
116
+ if (this .token .needsRefresh ()) {
117
+ this .token = this .iamAuthenticator .requestToken ();
118
+ }
108
119
109
120
return this .webClient .post ()
110
121
.uri (this .streamEndpoint )
111
- .header (HttpHeaders .AUTHORIZATION , "Bearer " + bearer )
122
+ .header (HttpHeaders .AUTHORIZATION , "Bearer " + this . token . getAccessToken () )
112
123
.bodyValue (watsonxAiRequest .withProjectId (this .projectId ))
113
124
.retrieve ()
114
125
.bodyToFlux (WatsonxAiResponse .class )
0 commit comments