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

Adding detailed steps on adding a new plugin #5388

Merged
merged 2 commits into from
Jun 24, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Adding detailed steps on adding a new plugin
  • Loading branch information
mohanarpit committed Jun 24, 2021
commit 7c5a98e3421bbabcd619b7d76bb3ed86fdd2080b
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,246 @@

Please follow the given guidelines to make sure that your commit sails through the review process without any
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 = "043", id = "add-firestore-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
As much as possible, please try to abide by the following code design:
Expand All @@ -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)
between `editor.json` and the rendered web page.


### Package Dependency
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.
Expand Down