Adding detailed steps on adding a new plugin (#5388)

This commit is contained in:
Arpit Mohan 2021-06-24 17:22:04 +05:30 committed by GitHub
parent 6640a64fe4
commit 6ca1590d15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2,6 +2,246 @@
Please follow the given guidelines to make sure that your commit sails through the review process without any Please follow the given guidelines to make sure that your commit sails through the review process without any
hiccups. hiccups.
### Steps to create a new plugin
At this point, we assume that you have Appsmith's server code base setup locally. If not, please check out [the guide here](../ServerSetup.md).
1. Create a new maven module in the folder: `app/server/appsmith-plugins` via the command:
```
mvn archetype:generate \
-DgroupId=com.external.plugins \
-DartifactId=helloWorldPlugin \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
```
Replace the `artifactId` with your plugin name. This tutorial will use `helloWorldPlugin` as a place-holder.
This command will generate a folder called `helloWorldPlugin` with default source code in the `appsmith-plugins` directory.
2. Navigate to your plugin code with your favourite IDE.
3. Copy the required properties in the plugin's `pom.xml` file. Example:
```
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<plugin.id>hello-world-name</plugin.id>
<plugin.class>com.external.plugins.HelloWorldPlugin</plugin.class>
<plugin.version>1.0-SNAPSHOT</plugin.version>
<plugin.provider>tech@appsmith.com</plugin.provider>
<plugin.dependencies/>
</properties>
```
Replace the properties `plugin.id` and `plugin.class` with your plugin name.
4. Replace the default dependencies generated by maven with the following:
```
<dependencies>
<dependency>
<groupId>org.pf4j</groupId>
<artifactId>pf4j-spring</artifactId>
<version>0.7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.appsmith</groupId>
<artifactId>interfaces</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>provided</scope>
</dependency>
<!-- Test Dependencies -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<version>3.2.11.RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
```
5. Add the `build` command to `pom.xml`:
```
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<minimizeJar>false</minimizeJar>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Plugin-Id>${plugin.id}</Plugin-Id>
<Plugin-Class>${plugin.class}</Plugin-Class>
<Plugin-Version>${plugin.version}</Plugin-Version>
<Plugin-Provider>${plugin.provider}</Plugin-Provider>
</manifestEntries>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>runtime</includeScope>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
```
6. Add a file called `plugin.properties` with the following content:
```
plugin.id=hello-world-plugin
plugin.class=com.external.plugins.HelloWorldPlugin
plugin.version=1.0-SNAPSHOT
plugin.provider=tech@appsmith.com
plugin.dependencies=
```
Please remember that the `plugin.class` and `plugin.id` MUST be the same as the ones defined in your `pom.xml`.
7. Navigate to your plugin's Java source folder `src/` and create a new class file `HelloWorldPlugin.java`. This is the same name as defined in your `pom.xml` property `plugin.class`.
8. Ensure that the class has the following structure:
```
public class HelloWorldPlugin extends BasePlugin {
public HelloWorldPlugin(PluginWrapper wrapper) {
super(wrapper);
}
@Slf4j
@Extension
public static class HelloWorldPluginExecutor implements PluginExecutor<Object> {
}
}
```
The `BasePlugin` & `PluginExecutor` classes define the basic operations of plugin execution
9. Add the plugin to the DB so that the Appsmith platform understands that a new plugin has been created. This can be done via the `DatabaseChangelog.java` file. Eg:
```
@ChangeSet(order = "076", id = "add-hello-world-plugin", author = "")
public void addHelloWorldPlugin(MongoTemplate mongoTemplate) {
Plugin plugin = new Plugin();
plugin.setName("Hello World Plugin");
plugin.setType(PluginType.DB);
plugin.setPackageName("hello-world-plugin");
plugin.setUiComponent("DbEditorForm");
plugin.setResponseType(Plugin.ResponseType.JSON);
plugin.setIconLocation("https://your-plugin-icon-location.png");
plugin.setDocumentationLink("https://link-to-plugin-documentation.html");
plugin.setDefaultInstall(true);
try {
mongoTemplate.insert(plugin);
} catch (DuplicateKeyException e) {
log.warn(plugin.getPackageName() + " already present in database.");
}
installPluginToAllOrganizations(mongoTemplate, plugin.getId());
}
```
10. Add the files `editor.json` and `form.json` in the `src/main/resources` folder. These JSON files are required to render the UI for your plugin. Samples are given below:
```
# form.json
{
"form": [
{
"sectionName": "Details",
"id": 1,
"children": [
{
"label": "DB Username",
"configProperty": "datasourceConfiguration.authentication.username",
"controlType": "INPUT_TEXT",
"isRequired": true,
"placeholderText": "",
"initialValue": ""
},
{
"label": "DB Password",
"configProperty": "datasourceConfiguration.authentication.password",
"controlType": "INPUT_TEXT",
"dataType": "PASSWORD",
"initialValue": "",
"encrypted": true
}
]
}
]
}
# editor.json
{
"editor": [
{
"sectionName": "",
"id": 1,
"children": [
{
"label": "",
"configProperty": "actionConfiguration.body",
"controlType": "QUERY_DYNAMIC_TEXT"
}
]
}
]
}
```
11. Compile & run your code via the command:
```
cd app/server && ./build.sh && cd scripts && ./start-dev-server.sh
```
### Code Design ### Code Design
As much as possible, please try to abide by the following code design: As much as possible, please try to abide by the following code design:
@ -17,6 +257,7 @@ As much as possible, please try to abide by the following code design:
For details, please see [this mapping](https://github.com/appsmithorg/appsmith/tree/release/static/editor.png) For details, please see [this mapping](https://github.com/appsmithorg/appsmith/tree/release/static/editor.png)
between `editor.json` and the rendered web page. between `editor.json` and the rendered web page.
### Package Dependency ### Package Dependency
1. We use `Maven` to manage package dependencies, hence please add all your dependencies in `POM` file as shown in this 1. We use `Maven` to manage package dependencies, hence please add all your dependencies in `POM` file as shown in this
[pom.xml file](https://github.com/appsmithorg/appsmith/blob/release/app/server/appsmith-plugins/postgresPlugin/pom.xml) for postgreSQL plugin. [pom.xml file](https://github.com/appsmithorg/appsmith/blob/release/app/server/appsmith-plugins/postgresPlugin/pom.xml) for postgreSQL plugin.