Monday, October 21, 2013

Mule connector development pointers

This article will be helpful for the mule beginners.

ANNOTATIONS
  • Following are some annotation and its meaning
    • @Connector : To mark a class as a Connector.The following is a description of the attributes for this annotation:
      • name: The name of the connector. This is a simple string value which should not contain any spaces in it, it will be used to generate the namespace of the connector.
      • schemaVersion: The version of the generated schema. This usually should match Mule’s schema version, so for .3.1 use schemaVersion=”3.3.1″. Keep in mind that if you add or change methods marked as @Processors or add @Configurable fields the generated schema will change and you should bump the version to avoid compatibility issues.
      • friendlyName: This is the name of the connector and is meant to be used only in Studio. This name will appear as the module name in the palette. Contrary to the name parameter, this field can contain spaces.
      • Connector class
      • minMuleVersion: The minimum version of Mule that this connector supports. A check will be generated for runtime verification that the Mule version this connector is running on is the correct one.
    • @Configurable : To involve a field in configuration
    • Configurable Attribute
    • @Connect : To establish connection to the Service
      • ConnectionKey : annotated parameter is used as the key to the pool. Thus, the Connector can be invoked using a number of different credentials
      Connect method
    • @Start : An alternative to connect annotation.If you don’t want to exploit the connection pool facility you can use this.This will mean you can have a single instance per configuration.
      Start method
    • @Processor : To mark a method as an operation
      Documentation

    • @Disconnect :  Invoked when as part of the maintenance of the Connection Pool
      Disconnect and Validation Connection method
    • @ValidateConnection : Invoked before the invocation of an operatio

READING PROPERTY FILES

  • To read the property files keys you need to put the property file under the folder src/main/resources and then in the flow file you have to add an entry 
    • <context:property-placeholder location="fusionlive.properties"/>
    • xmlns:context="http://www.springframework.org/schema/context" 
  • You can read the attribute like ${host} in the flow file.

READING POST PARAM
  • To read the http POST parameter you have to have the following entry in the flow file.

Flow XML

COMPILATION COMMANDS

  • Connector Compilation : Go the the directory where the mule project is reside and run the following command to compile the connector. If the compilataion is success it will create a target folder under the mule project. This target folder intern have myconnector-1.0-javadoc.jar and UpdateSite.zip files which contains  the documentation and the connector to export. The first command will generate the document but there are some missing element. If you want to resove this you have to run the second command. Second command will generate the document in apidocs folder under the target folder and not in the myconnector-1.0-javadoc.jar file.

    • mvn3 clean package -Ddevkit.studio.package.skip=false -e

    • mvn3 javadoc:javadoc

  • Importing third party library : If you want to import the third party jar then you have to run the following commands

    •  mvn install:install-file -Dfile=/home/username/jdbc.jar -DgroupId=org.mule.modules -DartifactId=myconnector -Dversion=1.0 -Dpackaging=jar

    • mvn install:install-file -Dfile=/home/username/jdbc.jar -DgroupId=org.test -DartifactId=myconnector -Dversion=1.0 -Dpackaging=jar

DEPLOYING
  • Mule ESB / Mulesoft express deployment as Tomcat service

    • Download Mule standalone.
    • Unpack it in the server’s location of your desire. 
    • Place your zipped Mule application in the /mule-standalone/apps directory.
    • If you have any kind of connector .jar, place it in the /mule-standalone/lib/mule directory.
    • Now you’re ready to run your application, go to  /mule-standalone/bin and you can do ./mule
    • And stopping it using Crtl-C.
    • Or you can manipulate it as a daemon using instead mule start/stop/restart

Thursday, October 17, 2013

Mule Upload Example with custom connector

Following code shows how the upload can be done via mule custom connector.
  • Code for the custom upload connector :


import java.io.BufferedInputStream;
import java.io.IOException;
import org.mule.api.ConnectionException;
import org.mule.api.annotations.Configurable;
import org.mule.api.annotations.ConnectionIdentifier;
import org.mule.api.annotations.Connector;
import org.mule.api.annotations.Disconnect;
import org.mule.api.annotations.Processor;
import org.mule.api.annotations.ValidateConnection;
import org.mule.api.annotations.lifecycle.Start;
import org.mule.api.annotations.param.Payload;

/**
 * Upload Connector
 *
 * @author MuleSoft, Inc.
 */
@Connector(name="uploadconnector", schemaVersion="1.0", 
friendlyName="UploadConnector", description="Upload Functioanlity")
public class UploadConnector {
 
private String connectionIdentifier  = null;
private boolean isConnected = false;
 
/**
 * Specifies to which server to connect.
 */
 @Configurable
 private String host = null;
 
/**
  * @return the connectionIdentifier
  */
  @ConnectionIdentifier
 public String getConnectionIdentifier() {
    return connectionIdentifier;
 }
 
/**
 * @param connectionIdentifier the connectionIdentifier to set
 */
 public void setConnectionIdentifier(String connectionIdentifier) {
    this.connectionIdentifier = connectionIdentifier;
 }
 
 
/**
 * @return the host
 */
 public String getHost() {
    return host;
 }


/**
 * @param host the host to set
 */
 public void setHost(String host) {
    this.host = host;
 }

/**
 * Connects to server.
 * 
 * @throws ConnectionException, IOException
 */
 @Start
 public synchronized void connect()
    throws ConnectionException, IOException {
 }

/**
 * Disconnect
 */
 @Disconnect
 public synchronized void disconnect() {
    this.isConnected = false;
 }

/**
 * Are we connected
 */
 @ValidateConnection
 public boolean isConnected() {
    return this.isConnected;
 }
/**
 * Uploads the document
 * 
 * {@sample.xml ../../
 * ../doc/UploadConnector.xml.sample upload:publishdocument}
 *
 * @param payload File dat in the fromat of BufferedInputStream.
 * @param fileName File name of the file to upload.
 * 
 * @throws IOException If there is any exception while connecting 
 *         to the server.
 */
 @Processor
 public void publishdocument(@Payload BufferedInputStream payload, 
     String fileName) throws IOException {

     fileName = getFileName(fileName);
     //TODO Proceed with your client library.
 }
    
    
/**
 * Parse the content-dispposition parameter and get the file name 
 * out of it.
 * 
 * @param fileName content disposition parameter.
 */
 private String getFileName(String fileName) {
     String fileNameFinal = null;
     if(fileName != null){
         String filenameSplit[] = fileName.split(";");
         for (String fn : filenameSplit) {
             //filename="YT.jpg"
             if(fn.contains("filename=")){
                 fileNameFinal = fn.substring("filename=".length() + 2, 
                                 fn.length()-1);
             }
         }
     }
     return fileNameFinal;
 }
}


  • Code in the UploadConnector.xml.sample file
  1. Name of the method 'publishdocument' must be same as the name in the documentation file. i.e. UploadConnector.xml.sample
  2. Parameter name fileName must be same as specified in the function in the connector.


<!-- BEGIN_INCLUDE(uploadconnector:publishdocument) -->
    <uploadconnector:publishdocument 
        fileName="#[message.inboundProperties['content-disposition']]" 
        config-ref="uploadconnector"/>
<!-- END_INCLUDE(uploadconnector:publishdocument) -->


  • Entry in the UploadConnector.mflow file.
  1. Need to specify the host and port property in the properties file. Otherwise one can hard code it.
  2. Path attribute 'publishdocument' must be same as specified in the HTML form bellow. i.e. http://localhost:8081/publishdocument



<http:connector name="httpConnector" doc:name="HTTP\HTTPS">
  <service-overrides 
   messageFactory="org.mule.transport.http.HttpMultipartMuleMessageFactory" />
</http:connector>

<flow name="publishdocument" doc:name="publishdocument">

    <http:inbound-endpoint  connector-ref="httpConnector" 
        exchange-pattern="request-response"  host="${http.host}" 
        port="${http.port}" path="publishdocument" doc:name="HTTP"/>

    <fusionlive:publishdocument config-ref="uploadconnector" 
       fileName="#[message.inboundProperties['content-disposition']]" 
       doc:name="UploadCon"/>
</flow>



HTML Upload Form
  • Name of the file type element must be payload.
  • Method must be post and encrypt attribute must be 'multipart/form-data'


<html>
  <head>
    <title>UploadConnector</title>
  </head>
  <body>
    </br>
      Upload Form
      <form  action="http://localhost:8081/publishdocument" method="post" 
        enctype="multipart/form-data">
 <input type="file" name ="payload"/>
        <input type="submit" value="Upload" />
      </form>
  </body>
</html>