How to define Custom Components

by Ombretta Malinverno
8,148 views Published on Oct 24, 2017
Applies to: 7.2 or higher
Table of contents

Introduction

IFML, the modeling language of WebRatio Platform, is built on very few, highly composable concepts, which can be used to assemble complex Web applications for publishing or updating content. The key aspect of IFML is the capability of defining a Web Model consisting of pages, view components, and operations, linked to form a specification of the required content publishing or management functions.

However, the core components provided in IFML may not be sufficient for covering the entire spectrum of application requirements, and you may want to use your own software components in the development of your Web applications. WebRatio Platform includes the notion of custom components (also called plugin components), to this purpose. A Custom Component is a View Component or an Operation defined by the developer, and not included in the WebRatio Platform standard installation.

A Custom Component is both similar and different with respect to the standard components.

  1. Like standard component. You can place a custom component in a hypertext diagram, link it to other components, with input or output flows, define the component's properties using the Property View. If the component is a View Component, you can also place it in the grid using the Grid View, and choose a Component template to display its content.
  2. Unlike a standard component. A Custom Component has a behavior that is completely defined by the component designer. You can implement components that do virtually anything, from sending emails to publishing XML documents, to interacting with Web services.

Getting Started

The overall architecture of WebRatio distinguishes two major components:

  • WebRatio Development Environment. It supports the design-time activities of application development, including the specification of the application site views and the generation of the application code.
  • WebRatio Runtime. It enables the execution of Java Web applications generated by WebRatio Platform, by offering a feature-rich execution framework for page templates and business components.

The development of a custom component will take you through all the components of WebRatio Platform, because the definition and the execution of a component requires addressing both design-time and runtime issues. Add a Custom Component to WebRatio Platform require:

  1. Add a Component definition to the component library (mandatory). You need to edit the "Unit.xml" file using the tool provided editor, which instruct WebRatio Platform to build the proper commands for placing the custom component in the Web Model, linking it to other components, and defining the binding of input and output parameters.
  2. Add a set of rule for validating the usage of the custom component in the Web Model, and for producing error and warning reports. This means to create and edit the WebModel.template file, writing a fragment of Groovy code (optional).
  3. Add a set Groovy template files (Input.template, Output.template, Logic.template). They produce the runtime XML descriptors associated with the custom component (optional).
  4. Add one or more Component templates. It indicates how the component has to be rendered in a page (mandatory if the custom component is a View Component).
  5. Implement a runtime class. It performs the business service for which the component is designed.

In return of these activities, WebRatio Platform let you use your components in the Web Model of every Web Project and these components will cooperate perfectly with the standard components.

In the end, building a custom components boils down to write a few pieces of code and specifications, and so let's see how to create the place to store your work. Since also the pre-defined IFML components are implemented in the same way as your custom components, you can start familiarizing with the components of a custom component by looking at those of the standard components.

  1. Create a Components Project. Select the File > New > Components Project from the main menu, give a name for the project (e.g., "MyCustomComponents"), then press on the Finish button. This project is the container of your custom components. You can use different Components Project if you want.
  2. Add a Component. Select the File > New > Component from the main menu, give a name for the component (e.g., "MyFirstComponent"), then press on the Next button. Select "View Component" for the type of the component in the opening dialog; the tool also proposes a default name for the Component Service Java class. Feel free to change it. Then press on the Finish button.

After these two operations you should have a folder tree like the one shown in the image below. Each folder contains files associated with a different aspect of the component specification.

  • Unit.xml. It contains the Component Definition which is used by WebRatio Platform to allow the editing of the component in the Web Model, and to display its properties in the Property View.
  • Images. It contains the images used to represent the component in the Web Model.
  • Logic. It contains three files; two of them ("Output.template" and "Input.template") specify the component's input and output; one file (called "Logic.template") produces the runtime XML descriptor for the component's service.
  • Warning. It contains a file called WebModel.template used to show errors and warnings in the usage of the component.

The Unit.xml file

The "Unit.xml" file contains the entire custom component definition and configuration. WebRatio Platform provides a multi-page component editor that manages the entire lifecycle of a user-defined component and save it into this file. The pages of this editor are:

  • General.
  • Sub-Elements.
  • Logic.
  • Layout.
  • Documentation.

General Page

The General Page serves dual purpose:

  1. It contains a section to set the General Information of the custom component like the Name, the Type and the Views where it can be inserted.
  2. It specifies if the component can be source and target of one or more flows.

These are the properties that you can configure:

  • 16x16 Icon. The rendition of the component in the Outline tree. To change the 16x16 icon, a PNG file named 16.png must be inserted in the sub-folder Images of the component configuration folder.
  • 32x32 Icon. The rendition of the component in the Web Model Editor. To change the 32x32 icon, a PNG file named 32.png must be inserted in the sub-folder Images of the component configuration folder.
  • Name. The XML tag name given to the component, which corresponds to the component folder name.
  • Id Prefix. The prefix you want the component is identified by.
  • Name Prefix. The default name prefix of the component when it is added into the model.
  • Label. The label used to visualize the component in the Components view.

  • Type. The type of the component: View Component, Operation or Both.

  • Site View. The view(s) where you can insert the component. By default, the Site View option is on.

  • Flow Source. If checked, the component supports outgoing flows.
  • Flow Target. If checked, the component supports incoming flows.
  • Default Intra-Page Flow. It specifies the default flow type of intra-page flows exiting from the component. A flow between two view components is considered intrapage when the source and target components belong to the same page or to different pages that are displayed simultaneously: this occurs when the two pages are nested inside the same top level page and none of the two is part of an alternative element. The attribute is meaningful only for view components. The possible values are: Normale Navigation Flow, Automatic Navigation Flow and Data Flow.
  • Default Flow To Operation. It specifies the default flow type of flows exiting from the component that point to an operation. The attribute is meaningful only for view components. The possible values are: Normal Navigation Flow and Data Flow.

  • OK Flow Source. If checked, the component supports outgoing OK flows.
  • OK Flow Target. If checked, the component supports incoming OK flows.
  • Multiple OK Flows. If checked, the component supports multiple outgoing OK flows.
  • OK Flow Codes Script. If the component supports multiple OK Flows, it's possible to define a script to return the values to use in the code property of the OK Flow. The script returns a list of code values.

  • KO Flow Source. The component supports outgoing KO flows.
  • KO Flow Target. The component supports incoming KO flows.
  • Multiple KO Flows. The component supports multiple outgoing KO flows.
  • KO Flow Codes Script. If the component supports multiple KO Flows, it's possible to define a script to return the values to use in the code property of the KO Flow.

Sub-Elements Page

The Sub-Elements Page serves to add, delete or edit the component and sub component properties or sub components. For each component property, you can edit its options. The sub-elements have some common properties:

  • Label. It defines the label used to visualize the property in the Properties View. If the field label is void it is used the sub-element name as label.
  • Figure Order. It defines the order of elements to be drawn in the figure representing the component in the IFML model. If left blank, the property is not shown in the component figure.

Moreover each sub element has its own properties. You can find the list of sub elements and properties in the WebRatio User Guide. Here is the list of sub elements types.

  • Attributes Property. The property permits to select a set of entity attributes.
  • Attribute Property. The property permits to select an entity attribute.
  • Boolean Property. The property holds a true or false value.
  • Content Type Property. The property holds a content type property, which qualifies an existing type property.
  • Context Parameters Property. The property permits to select one or more context parameters.
  • Database Property. The property permits to select a database.
  • Entity Property. The property permits to select the entity from which the content of the component is drawn.
  • Enumeration Property. The property permits to select one of the proposed values.
  • File Property. The property permits to select a file that has to be associated to the component.
  • Float Property. The property permits to write a float value to associate to the property.
  • Integer Property. The property permits to write an integer value to associate to the property.
  • List Property. The property permits to create and manage a list of element children.
  • Ordering Property. The property permits to order the chidren of the element.
  • Password Property. The property permits to write a password.
  • Relationship Role Property. The property permits to select a domain model Relationship Role.
  • Site View Property. The property permits to select a site view.
  • SMTP Server Property. The property permits to select or create a SMTP Server.
  • Sort Attributes Property. The property permits to select the instances sorting attributes and the sorting algorithm (ascending or descending).
  • String Property. The property permits to write a string value to associate to the property.
  • Text Property. The property permits to write an arbitrary text or script.
  • Type Property. The property permits to select the type of the element.
  • XSD Type Property. The property permits to select the XSD type.

You can also add Sub Components to your custom component. A component can have several sub components that can be defined as the components properties. For each sub component you can define the same properties described above.

  1. Sub Component. The sub component option permits to define a new sub component and its properties. The properties of the element are:
    • Element Name. It is mandatory; it defines the tag name of the XML element designed to contain the sub component properties and sub-elements.
    • Id Prefix. It defines the prefix of the identifier of the sub component.
    • Name Prefix. It defines the prefix of the name of the element visualized when the sub component is added to the model.
    • Label. It defines the label of the element visualized in the Components View or Editor.
    • Max Card.. It defines if the parent component accepts more than one sub component. The possible values are 1 and many.
    • Enable Ajax Events. It enables the rise of AJAX events on the sub component.
    • Enable Ajax Auto-Complete. It enables the AJAX auto completion on the sub component.
    • Figure Order. It defines the order of element to be drawn in the figure representing the parent component in the IFML model. If left blank, the property is not shown in the component figure.
  2. Selector.The selector option is a shortcut for a special sub-component and permits to define a data selector and its properties. The properties of the element are:
    • Element Name. It is mandatory; it defines the tag name of the XML element designed to contain the selector properties.
    • Entity Id Expr. It is mandatory; it defines the XPath expression to reach the entity identifier defined in the entity property. The identifier allows to reach the Domain Model Entity.
    • Name Prefix. It defines the prefix of the name of the element visualized when the sub component is added to the model.
    • Default Policy. It defines if the selector default policy is enabled.
    • Automatic. It defines if the selector, with a key condition, has to be created at the parent component creation.
    • Label. It defines the label used to visualize the selector element in the Components View. If the label field is void it is used the sub component name as label.
    • Figure Order. It defines the order of the element to be drawn in the figure representing the parent component in the IFML model. If left blank, the property is not shown in the component figure.
  3. Sub Component Reference. The sub component reference option permits to define a sub component referencing an other sub component. You can see as example the Hierarchy Component, where a Level sub-component references itself through a sub-component reference.
    • Element Name. It is mandatory; it defines the tag name of the referenced sub component XML element.
    • Figure Order. It defines the order of the element to be drawn in the figure representing the parent component in the IFML model. If left blank, the property is not shown in the component figure.

Logic Page

The Logic Page permits the definition of logic scripts. The scripts are meaningful only for View Components because the scripts affect the computation order of the components in a page. As you can see in the image on the right there are different types of scripts:

  • Context Free Script. The script defines if the component computation depends on other components that brings parameters to it. If the component is context free, it has priority over the other page components during the page computation. The script must return true or false.
  • Multi Condition Script. The script defines if the component computation depends on other components that brings parameters to it through different flows. During the page propagation process the evaluation of Multi Condition components is post-poned with respect to the evaluation of other components. The script must return true or false.
  • History Script. The script defines if the component works with session parameters, i.e., the component is session aware. The script must return true or false. For instance the Get Component script is the following.
  • Auto Expand Script. At generation time, the component is auto expanded with the addition or cancellation of elements. As example see the Scroller Component script that shows how to add the five scroller flows and to add them the needed flow parameters. The script must not return a value.

Layout Page

The Layout Page serves to define the layout behaviour of the component. The layout behaviour can be defined only for the view components that can be layed out in the generated Web application. For instance the Selector Component is both an operation and a view component, but it can't be placed in in the layout grid. This means that the other options are disabled.

  • Form based. The component supports form-based data entry. For instance the Form Component is a form-based component used for gathering input employed to perform searches over the objects of an entity or to supply parameters to operations.
  • Can place individual layout attributes in grid. Activating this option, the layout attributes of the component can be placed in the grid without placing the entire layout component. For example the Details Component attributes can be placed individually.
  • Can place individual layout fields in grid. Activating this option, the layout fields of the component can be placed in the grid without placing the entire layout component. For example the Form Component fields can be placed individually.
  • Can place individual layout flows in grid. Activating this option, the layout flows of the component can be placed in the grid without placing the entire layout component. For example the Details Component flows can be placed individually.

Right-clicking on the structure root it appears a popup menu. Each option of the menu permits to add a specific script. The Groovy script includes a predefined variable named component which is the layout component DOM4J element.

  • Layout Attributes Script. The script defines which attributes are to be layed out. More specifically the script returns a list of attribute identifiers.
  • Layout Attributes Item Script.The script defines the name under which the component bean can be accessed at run-time. Usually, this script is not required because the most of components access their bean properties throughout a JSTL iteration declaring a context variable named current. If this does not happen, this script have the ability to produce the name under which the bean can be accessed.
  • Layout Fields Script.The script defines which fields are to be layed out. More specifically the script returns a list of fields identifiers.
  • Layout Flows Script.The script defines which flows are to be layed out. More specifically the script returns a list of flows identifiers.
  • Localization Keys Script.The script defines some predefined keys for the localization of the component elements, valid for all the instances of a specific component type. More specifically it returns a list of maps. Each map is formed of three entries: the id of the element, the key of the localization entry (usually, the name of the element) and the localized message to be displayed.

Documentation Page

The Documentation Page allows to give a brief description to each sub-element and to each input and output parameter. The sub-elements documentation consists of a brief description. The input and output parameters documentation consist, instead, of:

  • Parameter Name. The name of the input/output parameter.
  • Description. It describes the input/output parameter and defines the parameter purpose.

The Input.template

The "Input.template" file, located in the "Logic" sub-folder of the component root folder, specifies the component input parameters. Each input parameter has a name, a type and a label. The type attribute is very important because, if correctly used, allows you to enable the Automatic Binding feature when passing information on a flow incoming the custom component. The logic used in the Automatic Binding is that the type attribute of the input parameter of the component source of the flow and the output parameter of the component target of the flow have the same value (or at least one value equal from the pipe separated type list). As an example:

//example of component input parameter for automatic binding
<InputParameter name="<%= unitId%>.name" type="ent6.attr26.single" label="Name"/>

//example of component output parameter for automatic binding
<OutputParameter name="<%= unitId%>.name" type="ent6.attr26.single" label="First Name"/>

Here an example of "Input.template".

#?delimiters <%,%>,<%=,%>

<%
 setXMLOutput()
 def unitId = unit.valueOf("@id")
 def params = unit.selectNodes("Parameter")
%>

<InputParameters>
    <InputParameter name="<%= unitId%>.uri" type="" label="URI"/>
    <% for (param in params) { %>
        <InputParameter name="<%= unitId%>.<%= param["name"]%>" type="" label="<%= param["name"]%>"/>
    <% } %>        
</InputParameters>

The Output.template

The "Output.template" file, located in the "Logic" sub-folder of the component root folder, specifies the component output parameters. Each output parameter has a name, a type and a label. The type attribute is very important because, if correctly used, allows you to enable the Automatic Binding feature when passing information on a flow incoming the custom component. The logic used in the Automatic Binding is the same explained in the previous section.

Here is an example of "Output.template".

#?delimiters <%,%>,<%=,%>

<%
 setXMLOutput()
 def unitId = unit.valueOf("@id")
%>

<OutputParameters>
    <OutputParameter name="resultObject" type="" label="Result"/>
</OutputParameters>

The Logic.template structure

The "Logic.template" file, located in the "Logic" sub-folder of the component root folder, specifies the component behaviour and properties. It contains a <Descriptor> element, whose attributes describe several behaviour and appearance properties. The child elements of <Descriptor> specify the properties that will be available in the component's property frame. The <Descriptor> element is the root element of the component descriptor file, and specifies the runtime service Java class through the service attribute. You can simply specify only the Component Service or write a specific structure of your choice for the Descriptor.

Here are two examples of the "Logic.template" file showing both the choices.

#?delimiters <%,%>,<%=,%>

<Descriptor service="com.webratio.units.utility.rtx.PasswordUnitService">
    <% printRaw(serializeXML(unit, false)) %>
</Descriptor>

  • Line 3. It dDeclares the Java class "PasswordUnitService" as the Component Runtime Service.
  • Line 4. It prints all the XML related to the component.
#?delimiters <%,%>,<%=,%>

<%
 setXMLOutput()
 def unitId = unit["id"]
 def params = unit.selectNodes("Parameter")
%>

<Descriptor service="com.webratio.units.community.net.HttpClientComponentService">
    <Host><%= unit["host"]%></Host>
    <Port><%= unit["port"]%></Port>
    <Method><%= unit["method"]%></Method>
    <ResponseType><%= unit["responseType"]%></ResponseType>
    <Parameters>
        <% for (param in params) { %>
	     <Parameter><%= param["name"]%></Parameter>
        <% } %>  
    </Parameters>
</Descriptor>

  • Line 5. It extracts the component ID.
  • Line 6. It Extracts the component Parameters properties.
  • Line 9. It declares the Java class "HttpClientComponentService" as the Component Runtime Service.
  • Line 10. It retrieves the "host" attribute of the component and writes it into the Host node.
  • Line 11. It retrieves the "port" attribute of the component and writes it into the Host node.
  • Line 12. It retrieves the "method" attribute of the component and writes it into the Method node.
  • Line 13. It retrieves the "responseType" attribute of the component and writes it into the ResponseType node.
  • Lines 14-18. It writes a Parameter Node for each Parameter property.

The WebModel.template

The "WebModel.template" file, located in the "Warning" sub-folder of the component root folder, specifies the situation in which an error has to be shown to the WebRatio Platform user because the custom component is not used correctly. The definition of this file is not mandatory but it can be very useful if you are going to develope a complex custom component.

Here is an example.

#?delimiters <%,%>,<%=,%>

<%
    if (unit["host"] == "") {
        addWarning(unit, true, "Host is unspecified.")
    }

    if (unit["port"] == "") {
        addWarning(unit, true, "Port is unspecified.")
    }

    if (unit["method"] == "") {
        addWarning(unit, true, "Method is unspecified.")
    }

    if (unit["responseType"] == "") {
        addWarning(unit, true, "Response type  is unspecified.")
    }
%>

  • Lines 4-6. Create a warning when the "host" property is not defined.
  • Lines 8-10. Create a warning when the "port" property is not defined.
  • Lines 12-14. Create a warning when the "method" property is not defined.
  • Lines 16-18. Create a warning when the "method" property is not defined.

The Java class runtime component service

The Java class(es) defining the run-time behaviour of the component has a predefined structure that the Component Wizard prepare when you create the new component.

The constructor of a Component Service is the following:

public CustomComponentService(String id, RTXManager mgr, Element descr) throws RTXException {
    
    super(id, mgr, descr);

}

NOTE. The third argument of the constructor is a DOM4J element, associated with the root element of the component's logic descriptor (i.e. the <Descriptor> element). The code super(..) is required when the service class extends the predefined "com.webratio.rtx.core.AbstractService" class. The logic descriptor is accessed through the standard DOM4J APIs or with some utility methods provided by the "com.webratio.rtx.core.DescriptorHelper" class.

Here are some example to retrieve the <Host> element of the logic descriptor.

Element host = descr.selectSingleNode("Host");

Element Host = DescriptorHelper.getChild(descr, "Host", false, this);

Element Host = DescriptorHelper.getChild(descr, "Host", true, this);

List parameters = descr.selectNodes("Parameter");

List parameters = DescriptorHelper.getChildren(descr, "Parameter", false, this);

  • Line 1. Usage of the "selectSingleNode" method of the DOM4J APIs.
  • Line 3. Usage of the "getChild" DescriptorHelper utility method.
  • Line 5. Usage of the "getChild" DescriptorHelper utility method. The third parameter must be set to true if the element is required and an exception must be thrown.
  • Line 7. Usage of the "selectNodes" method of the DOM4J APIs.
  • Line 9. Usage of the "getChildren" DescriptorHelper utility method.

The "DescriptorHelper" provides methods to obtain the text values or the list of values of sibling children.

String host= DescriptorHelper.getChildValue(descr, "Host", true, this);         

List parameters = DescriptorHelper.getChildValues(descr, "Parameter", true, this);

The "execute" method is identical to the one exposed by the interface "com.webratio.rtx.RTXOperationUnitService". The only difference is on the structure of the JavaBean returned by the two methods, which is free for a view component, whereas for an operation must include a mandatory "resultCode" string property. In this method you may need to instantiate a Bean. There are two predefined class for the component Bean.

  1. BasicContentUnitBean. A base result bean for View Components. Services associated with View Components are encouraged to subclass this bean to provide their output parameters as bean's properties. It has two properties:
  • dataSize.The size of contained data.
  • data. The contained data (Object).
  1. ExtendedContentUnitBean. A map based result bean for View Components. This bean must be used when the View Component you are developing does not have a predefined structure and can return a list of elements.
  2. BasicOperationUnitBean. A base result bean for operations. Services associated with Operations are encouraged to subclass this bean to provide their output parameters as bean's properties. It has three properties:
  • resultCode. The result code of the operation (success or error).
  • errorMessage. The error message produced by the operation.
  • exception. The the exception produced by the operation.
  1. ExtendedOperationUnitBean. A map based result bean for operations. This bean must be used when the operation you are developing does not have a predefined structure and can return a list of elements.

Bean properties can be accessed through the "com.webratio.rtx.core.BeanHelper" class. The helper provides methods to retrieve and set the values of specific properties.

The BeanHelper.asString(obj) method gets the string value of an object. If the input object is a string, it is returned. If the input object is an array of strings, the first element (if any) is returned. If the input object is an array of objects, the toString() method is invoked over the first element (if any). Finally, the toString() method is invoked over the input object. A null value is returned if the input object is null.

String name = BeanHelper.asString(input)

Here is the code of the Java class for the HTTPClientComponent.

package com.webratio.units.community.net;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.lang.ObjectUtils;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.webratio.rtx.RTXConstants;
import com.webratio.rtx.RTXException;
import com.webratio.rtx.RTXManager;
import com.webratio.rtx.RTXOperationUnitService;
import com.webratio.rtx.beans.ExtendedOperationUnitBean;
import com.webratio.rtx.core.AbstractService;
import com.webratio.rtx.core.BeanHelper;
import com.webratio.rtx.core.DescriptorHelper;

public class HttpClientUnitService extends AbstractService implements RTXOperationUnitService {
    /** The host to connect */
    private String host;

    /** The port of the host */
    private String port;

    /** The method to use (GET/POST) */
    private String method;

    /** The type of response expected */
    private String responseType;

    /** The list of parameters */
    private List parameters;

    public HttpClientUnitService(String id, RTXManager mgr, Element descr) throws RTXException {

        super(id, mgr, descr);

        host = DescriptorHelper.getChildValue(descr, "Host", true, this);
        port = DescriptorHelper.getChildValue(descr, "Port", true, this);
        method = DescriptorHelper.getChildValue(descr, "Method", true, this);
        responseType = DescriptorHelper.getChildValue(descr, "ResponseType", true, this);
        Element parametersElement = DescriptorHelper.getChild(descr, "Parameters", true, this);
        parameters = DescriptorHelper.getChildValues(parametersElement, "Parameter", false, this);

    }

    public Object execute(Map operationContext, Map sessionContext) throws RTXException {

        ExtendedOperationUnitBean bean = new ExtendedOperationUnitBean();

        try {
            HttpClient client = createHttpClient(host, port);
            String uri = BeanHelper.asString(operationContext.get(getId() + ".uri"));
            if (!uri.startsWith("/")) {
                uri = "/" + uri;
            }
            Map params = new HashMap();
            for (Iterator iter = parameters.iterator(); iter.hasNext();) {
                String param = (String) iter.next();
                params.put(param, BeanHelper.asString(operationContext.get(getId() + "." + param)));
            }
            Object resultObject = executeMethod(method, client, uri, params, responseType);
            bean.put("resultObject", resultObject);
            bean.setResultCode(RTXConstants.SUCCESS_CODE);
        } catch (Exception e) {
            logError("Error in excuting http method", e);
            bean.setResultCode(RTXConstants.ERROR_CODE);
        }

        return bean;

    }

    private HttpClient createHttpClient(String ip, String port) {

        HttpClient client = new HttpClient();
        client.getHostConfiguration().setHost(ip, Integer.parseInt(port), "http");
        client.getParams().setCookiePolicy(CookiePolicy.DEFAULT);
        return client;

    }

    private Object executeMethod(String methodType, HttpClient client, String uri, Map params, String returnType) throws HttpException, IOException, DocumentException, RTXException {

        HttpMethod method = null;

        try {
            if (methodType.equals("get")) {
                method = new GetMethod(uri);
                NameValuePair[] pairs = new NameValuePair[params.size()];
                int index = 0;
                for (Iterator iter = params.entrySet().iterator(); iter.hasNext();) {
                    Entry entry = (Entry) iter.next();
                    pairs[index] = new NameValuePair(entry.getKey().toString(), entry.getValue().toString());
                    index++;
                }
                method.setQueryString(pairs);
            } else if (methodType.equals("post")) {
                method = new PostMethod(uri);
                for (Iterator iter = params.entrySet().iterator(); iter.hasNext();) {
                    Entry entry = (Entry) iter.next();
                    if (entry.getValue() instanceof List) {
                        for (Iterator iterator = ((List) entry.getValue()).iterator(); iterator.hasNext();) {
                            ((PostMethod) method).addParameter(entry.getKey().toString(), (String) iterator.next());
                        }
                    } else {
                        ((PostMethod) method).addParameter(entry.getKey().toString(), ObjectUtils.toString(entry.getValue()));
                    }
                }
            } else {
                throw new RTXException("The method '" + methodType + "' is not supported.");
            }
            client.executeMethod(method);
            if (returnType.equals("dom")) {
                return new SAXReader().read(method.getResponseBodyAsStream());
            } else if (returnType.equals("bytes")) {
                return method.getResponseBody();
            }
            return method.getResponseBodyAsString();
        } finally {
            if (method != null) {
                method.releaseConnection();
            }
        }
    }

    public void dispose() {

        host = null;
        port = null;
        method = null;
        responseType = null;
        parameters = null;

    }

}