...
If using one of the three recommended methods for creating new components, the methods below are the BI Component methods that need to be customized to provide your needed functionality. The methods are listed in the order that they are typically called during normal processing. Depending on the option used to create your component, not all of these methods are required. See above sections for more details.
getLogger()
This method creates a Log object that will be use to log messages from your component. It has to be created by your component (instead of a superclass) so that the log correctly records the class name of your object.
This method is implemented with a single line.
Code Block |
---|
public Log getLogger() {
return LogFactory.getLog(this.class);
}
|
validateSystemSettings()
This method allows your component to verify that any its required system settings it needs in order to operate are set correctly. For examples, the Kettle component (org.pentaho.plugin.kettle.KettleComponent) checks it system settings to see if it is configured for a file-based or RBDMS-based repository, and the email component (org.pentaho.plugin.email.EmailComponent) uses its system settings to connect to your email server.
System-wide settings for components should be stored in XML documents in the 'system' folder in the Pentaho solution root folder. System settings are ones that will be the same for every instance of your component and that won't change while the server or application is running (unless manually changed by an administrator).
In the system folder you will see subdirectories such as 'kettle', 'quartz', and 'smtp-email'. If your component needs system settings you can create a directory to store your settings in and place an XML file in the directory. The XML file can be named anything that you like. Within the XML document you can arrange the settings in any format that you like. The settings file for the email component provides a good example of a settings file. Within the root solution folder the path to the email settings file is 'system/smtp-email/email_config.xml'.
...
<email-smtp>
<!-- The values within <properties> are passed directly to the JavaMail API.
For a list of valid properties see
http://java.sun.com/products/javamail/javadocs/index.html -->
<properties>
<!-- This is the address of your SMTP email server for sending email. e.g.
smtp.pentaho.org -->
<mail.smtp.host></mail.smtp.host>
<!-- This is the port of your SMTP email server. Usually this is 25.
For GMail this is 587 -->
<mail.smtp.port>25</mail.smtp.port>
<!-- The transport for accessing the email server. Usually this is smtp.
For GMail this is smtps -->
<mail.transport.protocol>smtp</mail.transport.protocol>
<!-- Usually this is 'false'. For GMail it is 'true' -->
<mail.smtp.starttls.enable>false</mail.smtp.starttls.enable>
<!-- Set to true if the email server requires the sender to authenticate -->
<mail.smtp.auth>true</mail.smtp.auth>
<!-- This is true if the email server requires an SSL connection.
Usually 'false'. For GMail this is 'true' -->
<mail.smtp.ssl>false</mail.smtp.ssl>
<!-- Output debug information from the JavaMail API -->
<mail.debug>false</mail.debug>
</properties>
<!-- This is the default 'from' address that emails from the Pentaho BI Suite
will appear to come from e.g. joe.pentaho@pentaho.org -->
<mail.from.default>joe.pentaho@pentaho.org</mail.from.default>
<!-- This is the user id used to connect to the email server for sending email
It is only required if email-authenticate is set to true
This is never sent or shown to anyone -->
<mail.userid></mail.userid>
<!-- This is the password used to connect to the email server for sending email
It is only required if email-authenticate is set to true
This is never sent or shown to anyone -->
<mail.password></mail.password>
</email-smtp>
The email component accesses these settings by calling PentahoSystem.getSystemSetting(). For example:
String mailhost = PentahoSystem.getSystemSetting("smtp-email/email_config.xml", "mail.smtp.host", null);
The getSystemSetting() method finds an entry in a system setting file and returns it to the component. The component does not need to know where the system settings files are located. See the 'Utility' section below for more information on the method PentahoSystem.getSystemSetting().
validateAction()
This method is called to give your component the chance to verify that it has the inputs and resources that it needs to complete successfully. If you return 'false' from this method execution of the action sequence will terminate.
This method should only be used to check that the inputs are available it should not check the values of inputs because they are not guaranteed to be available at this point during execution. If your component needs resources such as a template file referred to in the action sequence as "new-employee-greeting", you can check that the resource is available by calling isDefinedResource("new-employee-greeting").
If your component needs an input called 'employee-id', you can check that it has been defined in the action sequence by calling isDefinedInput("employee-id").
If your component needs an output called "employee-greeting-email-text", you can check that it has been defined in the action sequence by calling isDefinedOutput("employee-greeting-email-text").
Your validateAction() method would now look like this
Code Block |
---|
public boolean validateAction() {
if (!isDefinedResource("new-employee-greeting")) {
error( "A template called 'new-employee-greeting' has not been defined" );
return false;
}
if (!isDefinedInput("employee-id")) {
error( "An employee id is needed" );
return false;
}
if (!isDefinedOutput("employee-greeting-email-text") ) {
error("An output called 'employee-greeting-email-text' has not been defined" );
return false;
}
return true;
}
|
Notice that we are only checking to see if the input has been defined and we are not trying to get the input value.
The validateAction() of the EmailComponent looks like this:
Code Block |
---|
public boolean validateAction() {
// make sure that we can get a 'to' email address
if (!isDefinedInput("to")) {
error(Messages.getErrorString("Email.ERROR_0001_TO_NOT_DEFINED",
getActionName()));
return false;
}
// make sure that we can get a subject for the email
if (!isDefinedInput("subject")) {
error(Messages.getErrorString("Email.ERROR_0002_SUBJECT_NOT_DEFINED",
getActionName()));
return false;
}
// make sure that we have either a plain text or html message for the email
if (!isDefinedInput("message-plain") && !isDefinedInput("message-html")) {
error(Messages.getErrorString("Email.ERROR_0003_BODY_NOT_DEFINED",
getActionName()));
return false;
}
return true;
}
|
Notice that this method does not check for the optional parameters such as 'cc', 'bcc', or email attachments but only checks for the minimum parameters that are required for the component to execute successfully.
You do not have to call for each individual resource, input, or output. If you prefer, you can work with java.util.Set objects that contain the names of the available items. These sets can be obtained by calling getResourceNames(), getInputNames(), and getOutputNames(). For example
Code Block |
---|
Set inputNames = getInputNames();
if( !inputNames.contains( "param1" ) && !inputNames.contains( "param2" ) ) {
error( "I need both param1 and param2" );
return false;
}
|
init()
This method is called to allow the component to perform any initialization operations that are required before the executeAction() is called.
executeAction()
This method is called to cause the component to perform its function. Within this method you can call other internal API methods to get the values of inputs, to get resources, to ask users for parameters, and to get output streams. Typically, during the execute method a component will:
- Gather input values. These might be parameters or component settings. If the input values are not complete, the component can stop executing or prompt the user for additional information.
- Gather resources. These might be templates or definition files.
- Get an output pipe of some kind (e.g. an output stream).
- Create output contents.
- Return the status of the execution.
See 'Internal API' below for descriptions of the methods available for the component to use. We will use the executeAction() of the PrintComponent (org.pentaho.plugin.print.PrintComponent) as an example (minor modifications have been made for clarity).
Code Block |
---|
protected boolean executeAction() {
String printFileName = null;
IActionResource printFileResource = null;
// see if we are printing a file
if (isDefinedInput("print-file")) {
// get the name of the file to print
printFileName = getInputStringValue("print-file");
}
InputStream inStream = null;
// Get the name of the printer to use
if (isDefinedInput("printer-name")) {
printerName = getInputStringValue("printer-name");
}
// try to find the requested printer
PrintService printer = getPrinterInternal(printerName);
if (printer == null) {
// the requested printer is not available
if (!feedbackAllowed()) {
// we are not allowed to prompt the user for a printer, we have to fail
error( "The requested printer "+printerName+" is not available" );
return false;
}
// prompt the user for an available printer
// get a list of available print services
PrintService[] services = PrinterJob.lookupPrintServices();
ArrayList values = new ArrayList();
// add each print service to our list of printers
for (int i = 0; i < services.length; i++) {
String value = services[i].getName();
values.add(value);
}
// create a parameter for the user to select from
createFeedbackParameter("printer-name",
"select a printer", "", null, values, null, "select");
return null;
}
promptNeeded();
return true;
}
// Get the number of copies
int copies = 1;
if (isDefinedInput("copies")) {
copies = Integer.valueOf(getInputStringValue("copies")).intValue();
}
// Check for a valid printFileName or printFile Resource
if (printFileName != null) {
try {
inStream = new FileInputStream(printFileName);
} catch (FileNotFoundException fnfe) {
error(fnfe.toString(), fnfe);
return false;
}
// Set the input source for sending to the driver.
InputSource source = new InputSource(inStream);
try {
Driver driver = new Driver(source, null);
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintService(printer);
PrintRenderer renderer = new PrintRenderer(pj, copies);
driver.setRenderer(renderer);
driver.run();
} catch (Exception ex) {
error( "Could not print the document", ex);
return false;
}
return true;
}
|
done()
...
Child pages (Children Display) |
---|