2424import io .serverlessworkflow .impl .TaskContext ;
2525import io .serverlessworkflow .impl .WorkflowApplication ;
2626import io .serverlessworkflow .impl .WorkflowContext ;
27+ import io .serverlessworkflow .impl .WorkflowError ;
28+ import io .serverlessworkflow .impl .WorkflowException ;
2729import io .serverlessworkflow .impl .WorkflowModel ;
2830import io .serverlessworkflow .impl .resources .ResourceLoader ;
2931import io .swagger .v3 .oas .models .OpenAPI ;
3032import io .swagger .v3 .parser .OpenAPIV3Parser ;
33+ import jakarta .ws .rs .WebApplicationException ;
3134import jakarta .ws .rs .client .Client ;
3235import jakarta .ws .rs .client .ClientBuilder ;
3336import jakarta .ws .rs .client .Invocation ;
3437import jakarta .ws .rs .client .WebTarget ;
3538import jakarta .ws .rs .core .MultivaluedMap ;
39+ import jakarta .ws .rs .core .Response ;
3640import java .net .URI ;
41+ import java .util .List ;
42+ import java .util .Map ;
43+ import java .util .Optional ;
3744import java .util .concurrent .CompletableFuture ;
38- import java .util .concurrent .atomic .AtomicReference ;
3945
4046public class OpenAPIExecutor implements CallableTask <CallOpenAPI > {
4147
4248 private static final Client client = ClientBuilder .newClient ();
4349 private WebTargetSupplier webTargetSupplier ;
4450 private RequestSupplier requestSupplier ;
45- private final OpenAPIModelConverter converter = new OpenAPIModelConverter () {};
51+ private OpenAPIModelConverter converter = new OpenAPIModelConverter () {};
4652
4753 @ FunctionalInterface
4854 private interface WebTargetSupplier {
@@ -59,7 +65,6 @@ WorkflowModel apply(
5965 public void init (
6066 CallOpenAPI task , Workflow workflow , WorkflowApplication application , ResourceLoader loader ) {
6167 OpenAPIArguments args = task .getWith ();
62- WithOpenAPIParameters withParams = args .getParameters ();
6368
6469 URI uri = getOpenAPIDocumentURI (args .getDocument ().getEndpoint ().getUriTemplate ());
6570
@@ -69,33 +74,75 @@ public void init(
6974
7075 OpenAPIOperationContext ctx = generateContext (openAPI , args , uri );
7176
72- this .webTargetSupplier =
73- () -> {
74- final AtomicReference <WebTarget > webTarget =
75- new AtomicReference <>(
76- client
77- .target (openAPI .getServers ().get (0 ).getUrl ())
78- .path (ctx .buildPath (withParams .getAdditionalProperties ())));
79-
80- MultivaluedMap <String , Object > queryParams =
81- ctx .buildQueryParams (withParams .getAdditionalProperties ());
82- queryParams .forEach (
83- (key , value ) -> {
84- for (Object o : value ) {
85- webTarget .set (webTarget .get ().queryParam (key , o ));
86- }
87- });
88-
89- return webTarget .get ();
90- };
77+ WithOpenAPIParameters withParams =
78+ Optional .ofNullable (args .getParameters ()).orElse (new WithOpenAPIParameters ());
79+
80+ this .webTargetSupplier = getTargetSupplier (openAPI , ctx , withParams );
9181
9282 this .requestSupplier =
9383 (request , w , taskContext , node ) -> {
94- Object response = request .method (ctx .httpMethodName (), node .objectClass ());
95- return converter .toModel (application .modelFactory (), node , response );
84+ try {
85+ Response response = request .method (ctx .httpMethodName (), Response .class );
86+
87+ if (!args .isRedirect () && !is2xx (response )) {
88+ throw new WorkflowException (
89+ WorkflowError .communication (
90+ response .getStatus (),
91+ taskContext ,
92+ "Received a non-2xx nor 3xx response but redirects are enabled" )
93+ .build ());
94+ }
95+
96+ if (args .isRedirect () && isNot2xxNor3xx (response )) {
97+ throw new WorkflowException (
98+ WorkflowError .communication (
99+ response .getStatus (),
100+ taskContext ,
101+ "Received a non-2xx nor 3xx response but redirects are enabled" )
102+ .build ());
103+ }
104+
105+ return converter .toModel (
106+ application .modelFactory (), node , response .readEntity (node .objectClass ()));
107+ } catch (WebApplicationException exception ) {
108+ throw new WorkflowException (
109+ WorkflowError .communication (
110+ exception .getResponse ().getStatus (), taskContext , exception )
111+ .build ());
112+ }
96113 };
97114 }
98115
116+ private static WebTargetSupplier getTargetSupplier (
117+ OpenAPI openAPI , OpenAPIOperationContext ctx , WithOpenAPIParameters withParams ) {
118+ return () -> {
119+ WebTarget webTarget =
120+ client
121+ .target (openAPI .getServers ().get (0 ).getUrl ())
122+ .path (ctx .buildPath (withParams .getAdditionalProperties ()));
123+
124+ MultivaluedMap <String , Object > queryParams =
125+ ctx .buildQueryParams (withParams .getAdditionalProperties ());
126+
127+ for (Map .Entry <String , List <Object >> queryParam : queryParams .entrySet ()) {
128+ for (Object value : queryParam .getValue ()) {
129+ webTarget = webTarget .queryParam (queryParam .getKey (), value );
130+ }
131+ }
132+
133+ return webTarget ;
134+ };
135+ }
136+
137+ private static boolean is2xx (Response response ) {
138+ return response .getStatusInfo ().getFamily ().equals (Response .Status .Family .SUCCESSFUL );
139+ }
140+
141+ private static boolean isNot2xxNor3xx (Response response ) {
142+ return !(response .getStatusInfo ().getFamily ().equals (Response .Status .Family .SUCCESSFUL )
143+ || response .getStatusInfo ().getFamily ().equals (Response .Status .Family .REDIRECTION ));
144+ }
145+
99146 private static OpenAPIOperationContext generateContext (
100147 OpenAPI openAPI , OpenAPIArguments args , URI uri ) {
101148 return openAPI .getPaths ().entrySet ().stream ()
@@ -142,7 +189,6 @@ private static URI getOpenAPIDocumentURI(UriTemplate template) {
142189 if (template .getLiteralUri () != null ) {
143190 return template .getLiteralUri ();
144191 } else if (template .getLiteralUriTemplate () != null ) {
145- // TODO: Support
146192 // https://github.com/serverlessworkflow/specification/blob/main/dsl-reference.md#uri-template
147193 throw new UnsupportedOperationException (
148194 "URI templates with parameters are not supported yet" );
0 commit comments