Plugins

The following article assumes the developer knows Java* & Maven. Download the seed project to get started with plugins.

Download Fork

Plugins allow the developer to write custom business logic for their API using Java. The use of plugins feature requires JDK 1.8 or greater to be installed on the system.

Creating Plugins

The user is required to upload a compressed .zip of a Maven project folder. The zip can be uploaded by click on New Project button in the Plugins section of the console.

Metamug Plugins Section

No other format except zip is supported for the project upload. Please do not upload .tar.gz, .rar or any other format.

Project Upload

The project should contain the following

  1. One or more classes implementing one of the Processable interfaces explained further in this article.
  2. One or more classes whose object is to be returned in the HTTP response. If custom objects are being returned.

The details of uploaded projects and information of processable classes is shown in the console

Metamug Plugins Section 2

Implementation

The following dependency must be provided in the pom.xml of the Maven project

<dependency>
    <groupId>com.metamug</groupId>
    <artifactId>mtg-api</artifactId>
    <version>1.1.4</version>
</dependency>

Metamug provides following two Java interfaces

  1. RequestProcessable
  2. ResultProcessable

The classes implementing either of these interfaces must be public and will have to Override the process() method. The code inside the process method gets executed and an Object is returned. The returned object is converted to XML or JSON as specified by the HTTP request header and is returned in the HTTP response.

Follow @metamug Star

Two types of plugins can be created for Metamug

  1. Request processors - Incoming HTTP requests can be directly processed upon.
  2. SQL result processors - The result set received by making SQL query to the database can be processed upon.

Request Processable

The RequestProcessable interface can be implemented to process HTTP request. The process() method provides access to the request parameters, the DataSource object and the request headers. The class implementing the interface should be public.

public interface RequestProcessable {
    public Object process(Map<String, String> requestParams, DataSource ds, Map<String, String> requestHeaders);
}

RequestExample.java

public class RequestExample implements RequestProcessable {

    @Override
    public Object process(Map<String, String> requestParams, DataSource ds, Map<String, String> requestHeaders) {
        //retrieve request parameters
        String name = requestParams.get("name");
        String email = requestParams.get("email");

        //get database connection
        try(Connection conn = ds.getConnection()){

            String insertSQL = "INSERT INTO users(name, email) VALUES (?,?)";
            PreparedStatement preparedStatement = conn.prepareStatement(insertTableSQL);
            preparedStatement.setString(1, name);
            preparedStatement.setString(2, email);
            // execute insert SQL stetement
            preparedStatement .executeUpdate();
        }

        return obj;
    }
}

The DataSource object is used to obtain the database connection. The connection is given to the database of the backend in which the Maven project is uploaded. The connection must be closed after the database operation is done.


Execute Tag

The Execute tag is used for invoking the RequestProcessable classes. The value of classname attribute has to be the full name of a RequestProcessable class (including package name) inside an uploaded maven project. When the HTTP request is made to the resource, the process() method inside the corresponding class will be executed. The HTTP request parameters will automatically be mapped inside the Map<String,String> of the process() method.

<Request method="GET">    
   <Execute classname="com.example.RequestExample" />
</Request>

Result Processable

This interface must be implemented to process SQL results. The process() method provides resultMap and columnNames to iterate through records and look up column names. The rowCount gives the number of records in the resultMap. This method is provided to override the XML/JSON output for SQL queries. This helps the user to customize the HTTP response body. The Content-Type header in this case will be text/plain and Content-Length will be the length of the output string.

interface ResultProcessable {
    public Object process(SortedMap[] rowMap, String[] columnNames, int rowCount);
}

ResultExample.java

public class ResultExample implements ResultProcessable {

    @Override
    public Object process(SortedMap[] results, String[] columnNames, int rowCount) {
        String id1 = results[0].get("id").toString();
        String name1 = results[0].get("name").toString();
        String id2 = results[1].get("id").toString();
        String name2 = results[1].get("name").toString();

        //do something with the result data
        //return {Object};
    }
}

The result map obtained inside the process() method of the ResultProcessable class can be used to obtain values from the database which can be used for further processing.

SQL Post-Processing

The result received by executing the SQL query can be processed upon by the developer using the ResultProcessable interface. The attribute "classname" is available for the <Query> element which is used for pointing to the ResultProcessable class. Let us consider the following resource file

...
<Request method="GET">
    <Query classname="com.metamug.urlshmvn.ResultExample" >

        SELECT id FROM urls WHERE url=$q

    </Query>
</Request>
...

In the above case, the given SQL will be executed when a GET request is made on the urls resource. The result obtained from the database on the execution of the SQL query will be handled by the com.metamug.urlshmvn.ResultExample class (included in an uploaded maven project) which implements the ResultProcessable interface.

*Oracle and Java are registered trademarks of Oracle and/or its affiliates. Other names may be trademarks of their respective owners.

Return Types of process() method

The process() method can return a simple String or a custom Java object.

Returning a String

A simple Java string returned by the process() method can be obtained directly as it is in the HTTP response.

public Object process(SortedMap[] results, String[] columnNames, int rowCount) {
    ...
    return "Hello World!";
}

Returning Java objects

The class of the object returned by the process() method should be annotated with JAXB annotations. At a minimum, the class has to be annotated with @XmlRootElement to automatically produce XML/JSON response depending on the Accept Header.

@XmlRootElement
public class Customer {

    String name;
    ...
}

This is the minimal configuration required to configure serialization of the object to json/xml. You can find the whole list of annotations on oracle's doc page.

Take a look at this example for more on returning objects.

Event Handlers

Event Handlers are invoked implicitly. They need not be referenced from resource xml.

Upload Event

When Upload is performed, the class implemented with the following interface is invoked. The uploaded file can be accessed from the event object also you will need to keep the param of the file object as "file".

Metamug Upload File

public CSVUploader implements UploadListener {

    public Object uploadPerformed(UploadEvent event, DataSource dataSource) {
        //TODO 
    }
}