Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: GraphQL connector template #202

Merged
merged 20 commits into from
Feb 10, 2023

Conversation

markfarkas-camunda
Copy link
Contributor

@markfarkas-camunda markfarkas-camunda commented Jan 11, 2023

Description

Created the template and skeleton for GraphQL connector.

UPDATE

The code is ready for an early MVP use-case testing. Please test and provide feedback here under this ticket.

Steps to run it locally:

  1. set up zeebe locally (e.g. with docker compose)
  2. check out this branch
  3. navigate to connectors-common-library folder(/connectors/connectors-common-library), and build this module by executing:
mvn clean install
  1. navigate to graphql folder(/connectors/graphql), and build the graphql connector by executing:
mvn clean install
  1. go back to the main folder and build the whole bundle by executing:
mvn clean package

and start the application with:

java -jar ./bundle/mvn/default-bundle/target/connector-runtime-bundle-0.16.0-SNAPSHOT-with-dependencies.jar  "-Dexec.mainClass=io.camunda.connector.bundle.LocalConnectorRuntime"

This should start the application

  1. Add this element template to the Desktop modeler.

  2. Test with the bpmns below (updated):
    bpmns.zip

  3. Validate the result in Operate
    image

  4. Visit the https://studio.apollographql.com/public/star-wars-swapi/home?variant=current site to see the GraphQL DB structure, and explore other properties for the queries.

Related issues

#153

https://github.com/camunda/product-hub/issues/784

bpmn-io/bpmn-js-properties-panel#866

Copy link

@bastiankoerber bastiankoerber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add variable input field and link to documentation how to use it :-)
Rest looks good for me

},
{
"label": "Query Parameters",
"description": "Map of query parameters to add to the request URL",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we link here to a documentation, where we are showing how it will work?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am missing the variable input view. Have i overseen it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for noticing, I missed that. I added to the template rn. Please find the updated template in my PR in web modeler where you can instantly see it in the modeler by clicking one of the deployments. https://github.com/camunda/web-modeler/pull/3530

@MaxTru
Copy link
Contributor

MaxTru commented Jan 16, 2023

Note: the deploy branch can be found here (e.g., for testing)

Copy link
Contributor

@MaxTru MaxTru left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I miss something, but:

  • Where would I put the GraphQL query ?
  • Where would I put the GraphQL variables?

Can you please add a usage example (e.g., a screenshot of a typical GraphQL examples using this connector)

"id": "io.camunda.connectors.GraphQL.v1",
"description": "Execute GraphQL query",
"version": 1,
"documentationRef": "https://docs.camunda.io/docs/components/modeler/web-modeler/connectors/available-connectors/template/",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This link is dead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I missed the variables, thank you for noticing. Fixed it, and the link also. See https://github.com/camunda/web-modeler/pull/3530

@MaxTru
Copy link
Contributor

MaxTru commented Jan 16, 2023

Consider example by @christian-konrad , @bastiankoerber :

image

@MaxTru
Copy link
Contributor

MaxTru commented Jan 17, 2023

Hey @markfarkas-camunda ,

is this ready for re-review? If so, please press the "request re-review" button:

image

This way @bastiankoerber and I know when we should look at this again.

@markfarkas-camunda
Copy link
Contributor Author

@MaxTru I re-requested review here: https://github.com/camunda/web-modeler/pull/3530 now, thank you for reminding me, I had issues with the automatic deployment, I resolved that, so now you should be able to see the fixed template. I won't re-request the review here, my other PR should be the one to review.

@markfarkas-camunda markfarkas-camunda self-assigned this Jan 23, 2023
@@ -0,0 +1,3 @@
name: HTTPJSON
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be GraphQL maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Obviously. Thank you for noticing. 👍

Copy link
Member

@chillleader chillleader left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested the basic functionality - looks great!
Left a couple of generic comments for discussion.

Comment on lines 30 to 37
inputVariables = {
"url",
"method",
"authentication",
"query",
"variables",
"connectionTimeoutInSeconds"
},
Copy link
Member

@chillleader chillleader Jan 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A side comment: I think we might want to consider changing the naming pattern to connectorName.variableName, e.g. graphql.url here, because the current behavior of input mappings of variables with the same name is sometimes surprising. I have a feeling it may lead to a conflict between different connectors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know about this, good catch. I will modify the input variables.

import com.google.api.client.http.HttpHeaders;
import com.google.common.base.Objects;

public abstract class Authentication {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many of the data classes are identical here and in REST connector. Should we move the common data classes into a separate module, e.g. connectors-common-library?

@nikku
Copy link
Member

nikku commented Jan 27, 2023

Looks good overall template UI wise 👍.

Nitty-gritty: It feels like we can further simplify our descriptions. I like the usage of links to external resources though.

image

I personally prefer call to actions like Learn how to <define variables> or <Configure variables> to send with the query over Variables to add to the query or mutation. See <Documentation>.

@nikku
Copy link
Member

nikku commented Jan 27, 2023

Nit-pick: Swap Method and URL (URL is important, method should be pre-filled with the most reasonable option (POST?):

image

@markfarkas-camunda
Copy link
Contributor Author

Nit-pick: Swap Method and URL (URL is important, method should be pre-filled with the most reasonable option (POST?):

image

Make sense, but I would still choose GET as a pre-filled option. It is possible to execute a mutation with GET, although according to the official doc "by convention it's suggested that one doesn't use GET requests to modify data".
It is the customer's responsibility to use the right option here.
What we can do maybe is recognize that the query is a mutation(start with the keyword "mutation"), and automatically set the method to post, or make the field red if its value is GET. @nikku do you think something like this is possible on the frontend?

@nikku
Copy link
Member

nikku commented Jan 27, 2023

Make sense, but I would still choose GET as a pre-filled option.

Is it also a convention that queries are executed via GET? If that is the case I agree with you.

@markfarkas-camunda
Copy link
Contributor Author

markfarkas-camunda commented Jan 27, 2023

Is it also a convention that queries are executed via GET? If that is the case I agree with you.

If we follow the REST conventions GET should be the right choice for queries, although there are no rules regarding this in the docs. Theoretically there can be a limitation on the length of a url, hence on the query parameter, but that is very unlikely we will ever encounter this limitation. For example for a Windows IIS WebServer the default value for max length of query string is 2048 bytes according to the docs
I would still vote for GET as pre-filled option.

@christian-konrad
Copy link

@bastiankoerber do you want us building syntax highlighting for the GraphQL query/mutation part? I could at least open an issue for that in the core modeling team

@nikku
Copy link
Member

nikku commented Jan 27, 2023

@christian-konrad Please open an issue and link it.

I opened an issue: bpmn-io/bpmn-js-properties-panel#858.


We'd need to fix the GraphQL embedding one way or the other:

  • A proper GraphQL editor OR
  • A monospace textarea that resizes to a decent size (so contents are not hidden)

It leaves a bad impression to edit / view GraphQL queries in a non-monospace apperance:

image

@markfarkas-camunda markfarkas-camunda marked this pull request as ready for review February 9, 2023 16:04
Comment on lines 1 to 6
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* under one or more contributor license agreements. Licensed under a proprietary license.
* See the License.txt file for more information. You may not use this file
* except in compliance with the proprietary license.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A question regarding a licensing. With a common library we apply Camunda OSS license, while HTTP REST connector was Apache 2.0. How is it resolved now? Is the HTTP REST still under Apache 2.0 despite few components being under under Camunda OSS?

@markfarkas-camunda @bastiankoerber @chillleader WDYT?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I also have the same question. I think at least the common-library should definitely be Apache 2.0.

Comment on lines +1 to +5
Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under one or more contributor license agreements and licensed to you under a proprietary license.
You may not use this file except in compliance with the proprietary license.
The proprietary license can be either the Camunda Platform Self-Managed Free Edition license (available on Camunda’s website) or the Camunda Platform Self-Managed Enterprise Edition license (a copy you obtain when you contact Camunda).
The Camunda Platform Self-Managed Free Edition comes for free but only allows for usage of the software (file) in non-production environments.
If you want to use the software (file) in production, you need to purchase the Camunda Platform Self-Managed Enterprise Edition.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have REST connector under Apache 2.0, does it make sense to make GraphQL Apache 2.0 as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct


public class GraphQLRequestWrapper {
@NotBlank private GraphQLRequest graphql;
private Authentication authentication;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't it be marked as @Secret?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily, we do not want to replace any secrets in these two attributes. This is just a helper class to handle the graphql namespace. (graphql.url, graphql.method, etc.)

@@ -6,7 +6,7 @@
<parent>
<groupId>io.camunda.connector</groupId>
<artifactId>connector-parent</artifactId>
<version>0.6.0-SNAPSHOT</version>
<version>0.6.0-alpha3</version>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it be still SNAPSHOT in PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs to use the latest release with the relevant commit to handle secrets in inherited classes.

Copy link
Member

@chillleader chillleader left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really like it - nicely done!
I just have a minor concern about licensing.

#camunda.connector.webhook.enabled=true
##spring.main.web-application-type=none

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: don't forget to remove these 😄

Comment on lines 2 to 5
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. Camunda licenses this file to you under the Apache License,
* Version 2.0; you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* under one or more contributor license agreements. Licensed under a proprietary license.
* See the License.txt file for more information. You may not use this file
* except in compliance with the proprietary license.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to license the GraphQL connector and the common library under proprietary license or Apache 2.0?

REST Connector is licensed under Apache 2.0, so I believe it makes sense to also have an open source license at least for common-library. And we can keep the GraphQL connector proprietary.

setTimeout(request, httpRequest);
HttpHeaders headers = new HttpHeaders();

if (authentication.getClientAuthentication().equals(Constants.BASIC_AUTH_HEADER)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still worse to maintain null-safety.

Suggested change
if (authentication.getClientAuthentication().equals(Constants.BASIC_AUTH_HEADER)) {
if (Constants.BASIC_AUTH_HEADER).equals(authentication.getClientAuthentication()) {

data.put(Constants.AUDIENCE, authentication.getAudience());
data.put(Constants.SCOPE, authentication.getScopes());

if (authentication.getClientAuthentication().equals(Constants.CREDENTIALS_BODY)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here regarding null-safety

errorCode = errorContent.getErrorCode();
errorMessage = errorContent.getError();
} catch (Exception e) {
// cannot be loaded as JSON, ignore and use plain message
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put a log statement here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARN should be sufficient.

context.validate(connectorRequest);
context.replaceSecrets(connectorRequest);

return proxyFunctionUrl == null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we have Apache Commons lib here, consider StringUtils.isBlank(proxyFunctionUrl)

Copy link
Member

@chillleader chillleader Feb 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or String::isBlank since we're using Java 11 here. But this would still require a null check.

Copy link
Contributor

@igpetrov igpetrov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No critical issues found, thus approving.
Minor suggestions.

Please make sure you talk about licensing issues with @bastiankoerber before release.

Thank you.

@markfarkas-camunda
Copy link
Contributor Author

I fixed the issues and suggestions, I am waiting for Bastian's decision about licensing.

@igpetrov igpetrov self-requested a review February 10, 2023 14:17
Comment on lines +18 to +33
<properties>
<license.inlineheader>Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
under one or more contributor license agreements. See the NOTICE file
distributed with this work for additional information regarding copyright
ownership. Camunda licenses this file to you under the Apache License,
Version 2.0; you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.</license.inlineheader>
</properties>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, should be this one

Suggested change
<properties>
<license.inlineheader>Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
under one or more contributor license agreements. See the NOTICE file
distributed with this work for additional information regarding copyright
ownership. Camunda licenses this file to you under the Apache License,
Version 2.0; you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.</license.inlineheader>
</properties>
<licenses>
<license>
<name>Camunda Platform Self-Managed Free Edition license</name>
<url>https://camunda.com/legal/terms/cloud-terms-and-conditions/camunda-cloud-self-managed-free-edition-terms/</url>
</license>
<license>
<name>Camunda Platform Self-Managed Enterprise Edition license</name>
</license>
</licenses>
<properties>
<license.inlineheader>Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH
under one or more contributor license agreements. Licensed under a proprietary license.
See the License.txt file for more information. You may not use this file
except in compliance with the proprietary license.</license.inlineheader>
</properties>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, disregard this comment. I think, it's okay to keep it as Apache 2.0 since it's a common lib.

Comment on lines +18 to +26
<licenses>
<license>
<name>Camunda Platform Self-Managed Free Edition license</name>
<url>https://camunda.com/legal/terms/cloud-terms-and-conditions/camunda-cloud-self-managed-free-edition-terms/</url>
</license>
<license>
<name>Camunda Platform Self-Managed Enterprise Edition license</name>
</license>
</licenses>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one is correct.

Copy link
Contributor

@igpetrov igpetrov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants