![]() |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
For DevelopersRBT applications are designed to support customization of both the look and feel and the security implementation. In addition, the backend web services can be accessed directly to provide a flexible data access framework decoupled from the user interface. Application StylesheetsRBT applications are browser based DHTML with look and feel configured with CSS. You can customize the look and feel to better integrate with existing applications. CSS files can be found in the [webapp-root]/css directory and are separated into logical areas of the application:
Application ImagesAssociated with the stylesheets above are groups of images found in [webapp-root]/images:
Programmatic Document AccessProgrammatic access to RBT HTML, PDF, Excel and DataSet XML documents is provided via the RbtConnect object found in the rbtapi library. There are some limitations in the HTML document output when called from the API. When called from the API the HTML document will not display the toolbar and will not support drilldown documents. Example code is shown below: private void getRbtData() { InputStream inputStream = null; try { /** * the parameters to the RbtConnect constructor are as follows: * 1. String username * 2. String password * 3. String documentGroup * 4. String documentOwner * 5. String documentName * 6. String rbtServerUrl */ RbtConnect rconn = new RbtConnect("username", "password", "documentGroup", "documentOwner", "documentName", "http://myserver:8088"); /** * if runtime parameters are required you can add them using one of * the following addParameter methods: * * 1. addStringParameter(String fullyQualifiedColumnName, String value) * 2. addIntegerParameter(String fullyQualifiedColumnName, int value) * 3. addDoubleParameter(String fullyQualifiedColumnName, double value) * 4. addDateParameter(String fullyQualifiedColumnName, Date value) * 5. addDateParameter(String fullyQualifiedColumnName, Calendar value) * 6. addTimestampParameter(String fullyQualifiedColumnName, Date value) * 7. addTimestampParameter(String fullyQualifiedColumnName, Calendar value) * */ rconn.addIntegerParameter("HR.EMPLOYEES.EMPLOYEE_ID", 100); /** * RbtConnect provides 4 methods that return an InputStream providing * document data - remember to close the InputStream * * 1. getDataSet() - return xml document * 2. getExcel() - returns xls document * 3. getHtml() - returns html document * 4. getPdf() - return pdf document */ inputStream = rconn.getHtml(); int c = 0; while((c = inputStream.read()) > -1) { // do something with document input here } } catch (Exception ex) { ex.printStackTrace();; } finally { inputStream.close(); } } Open Access FrameworkRBT client access to configured datasources is provided open, synchronous, document-type web service built with JAX-WS 2.1 api. A set of XML objects provide data transport. Security and DataSet related XML objects will be discussed in greater detail below. The XML schemas to all RBT XML objects are found at the links below:
Security FrameworkThe RBT org.rbtdata.rbt.security.SecurityInterface class provides an interface to the role based security framework (covered later in this document). The majority of the objects passed to and from the SecurityInterface are of type SecurityObject. SecurityObject is a generic XML type providing data encapsulation for RBT application security entities. A SecurityObject can have child records defined by the XML type MemberType. For example, a role can have group members, a group can have user members, a user can have accessible table members and a table can have column members. The parent/child relationships extend to the MemberType. A MemberType object can have child records of type MemberType. For example, a user may have accessible table members and each table may contain column members. The XML schema containing SecurtyObject, MemberType and other associated XML types is shown below: <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xml.rbt.rbtdata.org/schemas" xmlns="http://xml.rbt.rbtdata.org/schemas" elementFormDefault="qualified"> <xsd:complexType name="SecurityObject"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="displayName" type="xsd:string" minOccurs="0"/> <xsd:element name="data" type="xsd:string" minOccurs="0"/> <xsd:element name="data2" type="xsd:string" minOccurs="0"/> <xsd:element name="lastModified" type="xsd:dateTime"/> <xsd:element name="memberOf" type="xsd:string" minOccurs="0"/> <xsd:element name="members" type="MembersType"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="MemberType"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="type" type="xsd:string"/> <xsd:element name="data" type="xsd:string"/> <xsd:element name="data2" type="xsd:string"/> <xsd:element name="displayName" type="xsd:string"/> <xsd:element name="members" type="MembersType" minOccurs="0"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="MembersType"> <xsd:sequence> <xsd:element name="member" type="MemberType" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="AvailableMembers"> <xsd:sequence> <xsd:element name="availableMember" type="AvailableMember" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="AvailableMember"> <xsd:sequence> <xsd:element name="selected" type="xsd:string"/> <xsd:element name="member" type="MemberType"/> <xsd:element name="availableMembers" type="AvailableMembers" minOccurs="0"/> </xsd:sequence> </xsd:complexType> </xsd:schema> A SecurityObject must represent one of the following security entities:
A SecurityObject can contain child members of type MemberType. The <type> tag must be be one of the following:
The AvailableMember type encapsulates a MemberType and has the additional <selected> tag. This object is used to provide data to the user interface and facilitates adding and removing object members. An AvailableMember type can also contain child types of AvailableMember paralleling the MemberType discussed above SecurityObject Field DescriptionsThe fields in the SecurityObject and MemberType objects have different meanings dependent on the object type. The tables below describe the field values associated with each object type.
MemberType Field Descriptions
Security InterfaceRBT provides an extendable security framework to allow security customization. The application security interface must be specified in the RBT configuration XML file and must implement the interface shown below: public interface SecurityInterface { /** * Used to pass configuration parameters to the specific SecurityInterface * implementation. * * @param map containing initialization parameters * @throws org.rbtdata.rbt.exceptions.BaseException */ public void init(Map initparams) throws BaseException; /** * evaluates incoming SOAP header to determine access * * @param sh * @return true if SOAP header credentials are granted access * @throws org.rbtdata.rbt.exceptions.BaseException */ public boolean authenticate(SOAPHeader sh) throws BaseException; /** * * @param userName * @return true if the input username is in the administrators group * @throws org.rbtdata.rbt.exceptions.BaseException */ public boolean isAdministrator(String userName) throws BaseException; /** * * @param userName * @return true if input username is member of the designers group * @throws org.rbtdata.rbt.exceptions.BaseException */ public boolean isDesigner(String userName) throws BaseException; /** * * @return the username of the currently logged in user */ public String getCurrentUserName(); /** * * @return SecurityObjects list of all RBT users * * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <SecurityObject> getAllUsers() throws BaseException; /** * * @return SecurityObject list of all RBT groups. * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <SecurityObject> getAllGroups() throws BaseException; /** * * @return SecurityObject list of all RBT roles. * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <SecurityObject> getAllRoles() throws BaseException; /** * * @return SecurityObject list of all custom-created foreign key relationships * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <SecurityObject> getAllForeignKeys() throws BaseException; /** * * @return SecuritObject list of all datasources available to the RBT application * - does not include the security datasource containing RBT security tables. * * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <SecurityObject> getAllDatasources() throws BaseException; /** * * @param jndiName - datasource JNDI name for RBT database connection * @param tableName - desired table name * @return MembersType object containing a MemberType list of column information. * @throws org.rbtdata.rbt.exceptions.BaseException */ public MembersType getTableColumns(String jndiName, String tableName) throws BaseException; /** * * @param userName * @return SecurityObject containing user record for input userName or null if no data found. * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject getUser(String userName) throws BaseException; /** * * @param userName * @return SecurityObject list of groups in which input user is a member. * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <SecurityObject> getUserGroups(String userName) throws BaseException; /** * * @param groupName * @return SecurityObject containing group record for input groupName or null if no data found * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject getGroup(String groupName) throws BaseException; /** * * @param groupName * @return SecurityObject list of roles in which input group is a member * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <SecurityObject> getGroupRoles(String groupName) throws BaseException; /** * * @param roleName * @return SecurityObject containing role record for input roleName or null if no data found * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject getRole(String roleName) throws BaseException; /** * * @param foreignKeyName * @return SecurityObject containing foreignKey record for input foreignKeyName or null if no data found * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject getForeignKey(String foreignKeyName) throws BaseException; /** * * @param jndiName * @return datasource record associated with input JNDI name * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject getDatasource(String jndiName) throws BaseException; /** * * @param jndiName * @param tableName * @return table record associated with input JNDI datasource and tableName * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject getTableSetup(String jndiName, String tableName) throws BaseException; /** * * @param parentType * @param parentName * @param memberType * @param memberName * @return true if entity defined by memberType (user, group, table etc) and * memberName is a child of the entity defined by parentType and parentName * @throws org.rbtdata.rbt.exceptions.BaseException */ public boolean isMember(String parentType, String parentName, String memberType, String memberName) throws BaseException; /** * * @param userData input user record * @return SecurityObject with updated user information after save. * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject saveUser(SecurityObject userData) throws BaseException; /** * * @param groupData * @return SecurityObject with updated group information after save. * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject saveGroup(SecurityObject groupData) throws BaseException; /** * * @param roleData * @return SecurityObject with updated role information after save. * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject saveRole(SecurityObject roleData) throws BaseException; /** * * @param foreignKeyData * @return SecurityObject with updated foreignKey information after save. * @throws org.rbtdata.rbt.exceptions.BaseException */ public SecurityObject saveForeignKey(SecurityObject foreignKeyData) throws BaseException; /** * * @param tableData MemberType record containing table and column display name setup * @throws org.rbtdata.rbt.exceptions.BaseException */ public void saveTableSetup(MemberType tableData) throws BaseException; /** * * @param userName user to delete * @throws org.rbtdata.rbt.exceptions.BaseException */ public void deleteUser(String userName) throws BaseException; /** * * @param groupName group to delete * @throws org.rbtdata.rbt.exceptions.BaseException */ public void deleteGroup(String groupName) throws BaseException; /** * * @param roleName role to delete * @throws org.rbtdata.rbt.exceptions.BaseException */ public void deleteRole(String roleName) throws BaseException; /** * * @param foreignKeyName foreign key to delete * @throws org.rbtdata.rbt.exceptions.BaseException */ public void deleteForeignKey(String foreignKeyName) throws BaseException; /** * * @param docGroup * @param docOwner * @param docName * @return * @throws org.rbtdata.rbt.exceptions.BaseException */ public RbtDocument getDocument(String docGroup, String docOwner, String docName) throws BaseException; /** * * @param userName * @return RbtDocument defined by key docGroup, docOwner and docName * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <UserDocument> getUserDocuments(String userName) throws BaseException; /** * * @param docGroup * @param docOwner * @param docName * @return UserDocument list containing documents that the current user can access * @throws org.rbtdata.rbt.exceptions.BaseException */ public void deleteDocument(String docGroup, String docOwner, String docName) throws BaseException; /** * * @param docData * @return save an RbtDocument * @throws org.rbtdata.rbt.exceptions.BaseException */ public RbtDocument saveDocument(RbtDocument docData) throws BaseException; /** * @param drillDownDocumentList * @param documentColumnValues * @return QueryParameter list containing available documents and their input parameters that are available for drilldown * @throws org.rbtdata.rbt.exceptions.BaseException */ public List <QueryParameters> getDrillDownDocumentConfig(String drillDownDocumentList, String documentColumnValues) throws BaseException; } As you can see, many of the methods are designed to work the SecurityObject that we described earlier. The other objects are defined can in the schemas noted earlier. To provide a fully customized a security implementation, implement the org.rbtdata.rbt.security.SecurityInterface shown above and ensure that the SecurityObject values are set as described earlier when processing. In many cases you may just want to implement custom handling of certain methods. In this case extend the defualt security implementation class org.rbtdata.rbt.security.JdbcSecurity and override the desired methods. Both the org.rbtdata.rbt.security.SecurityInterface and the org.rbtdata.rbt.security.JdbcSecurity classes are found in the provided rbtapi.jar library. It should be noted that the default authentication of RBT is plain text passwords passed in a SOAP message. To implement a more secure authentication scheme, you will want to extend JdbcSecurity and override the authenticate(SOAPHeader sh) method. The framework will pass the SOAP header element to this method and you can implement any SOAP supported authentication schema that passes credentials in the SOAP header. Security Interface ExampleThe RBT Admin web service call getAdminObjects <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:adm="http://admin.ws.rbt.rbtdata.org/"> <soapenv:Header> <wsse:Security xmlns:wsse='http://schemas.xmlsoap.org/ws/2003/06/secext'> <wsse:UsernameToken> <wsse:Username>admin</wsse:Username> <wsse:Password>admin</wsse:Password> </wsse:UsernameToken> </wsse:Security> </soapenv:Header> <soapenv:Body> <adm:getAdminObjects/> </soapenv:Body> </soapenv:Envelope> returns results similar to those shown in the file below: ![]() The RBT Admin web service call getTableColumns <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:adm="http://admin.ws.rbt.rbtdata.org/"> <soapenv:Header> <wsse:Security xmlns:wsse='http://schemas.xmlsoap.org/ws/2003/06/secext'> <wsse:UsernameToken><wsse:Username>admin</wsse:Username> <wsse:Password>admin</wsse:Password> </wsse:UsernameToken></wsse:Security> </soapenv:Header> <soapenv:Body> <adm:getTableColumns> <datasource>jdbc/MySQLDB</datasource> <schemaName>sakila</schemaName> <tableName>film</tableName> </adm:getTableColumns> </soapenv:Body> </soapenv:Envelope> returns results similar to those shown in the file below: ![]() he RBT Admin web service call getUser <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:adm="http://admin.ws.rbt.rbtdata.org/"> <soapenv:Header> <wsse:Security xmlns:wsse='http://schemas.xmlsoap.org/ws/2003/06/secext'> <wsse:UsernameToken><wsse:Username>admin</wsse:Username> <wsse:Password>admin</wsse:Password> </wsse:UsernameToken></wsse:Security> </soapenv:Header> <soapenv:Body> <adm:getUser> <userName>admin</userName> </adm:getUser> </soapenv:Body> </soapenv:Envelope> returns results similar to those shown in the file below: ![]() Web Service Query SupportQuery results RBT documents created in the designer can be retrieved programmatically using the the RBT Runner web service. query results are returned in a DataSet object which is defined in the XML schema shown below: <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xml.rbt.rbtdata.org/schemas" xmlns="http://xml.rbt.rbtdata.org/schemas" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" jaxb:version="1.0" elementFormDefault="qualified"> <xsd:annotation> <xsd:appinfo> <jaxb:globalBindings generateIsSetMethod="false"> <xjc:superClass name="org.rbtdata.rbt.util.XMLBase"/> </jaxb:globalBindings> </xsd:appinfo> </xsd:annotation> <xsd:complexType name="DataSet"> <xsd:sequence> <xsd:element name="name" type="xsd:string"/> <xsd:element name="requestor" type="xsd:string"/> <xsd:element name="createDate" type="xsd:dateTime"/> <xsd:element name="metaData" type="DataSetMetaData"/> <xsd:element name="row" type="RowData" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="DataSetMetaData"> <xsd:sequence> <xsd:element name="rowCount" type="xsd:int"/> <xsd:element name="columnCount" type="xsd:int"/> <xsd:element name="columnDef" type="ColumnDefinition" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="ColumnDefinition"> <xsd:sequence> <xsd:element name="index" type="xsd:int"/> <xsd:element name="name" type="xsd:string"/> <xsd:element name="type" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="RowData"> <xsd:sequence> <xsd:element name="col" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> </xsd:schema> DataSet DescriptionA DataSet object is a simple representation of tabular data similar to a JDBC ResultSet. DataSet elements are described in the tables below:
Example Web Service DataSet RequestThe example web service request below defines input parameters to load a document created by the RBT designer. The input parameters define the document we want to run
The DataSet web service request <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:run="http://runner.ws.rbt.rbtdata.org/" xmlns:sch="http://xml.rbt.rbtdata.org/schemas"> <soapenv:Header> <wsse:Security xmlns:wsse='http://schemas.xmlsoap.org/ws/2003/06/secext'> <wsse:UsernameToken><wsse:Username>admin</wsse:Username> <wsse:Password>admin</wsse:Password> </wsse:UsernameToken></wsse:Security> </soapenv:Header> <soapenv:Body> <run:getDataSet> <sch:QueryParameters> <sch:group>admin</sch:group> <sch:owner>admin</sch:owner> <sch:name>rbt employees</sch:name> </sch:QueryParameters> </run:getDataSet> </soapenv:Body> </soapenv:Envelope> returns results similar to those shown in the file below: ![]() If the document was designed to prompt for user input parameters, the request will include the QueryParameters record to encapsulate input parameters to pass along with the request. The QueryParameters schema is shown below: <?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://xml.rbt.rbtdata.org/schemas" xmlns="http://xml.rbt.rbtdata.org/schemas" elementFormDefault="qualified"> <xsd:complexType name="QueryParameters"> <xsd:sequence> <xsd:element name="group" type="xsd:string"/> <xsd:element name="owner" type="xsd:string"/> <xsd:element name="name" type="xsd:string"/> <xsd:element name="parameter" type="QueryParameter" maxOccurs="unbounded"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="QueryParameter"> <xsd:sequence> <xsd:element name="columnName" type="xsd:string"/> <xsd:element name="type" type="xsd:string"/> <xsd:element name="value" type="xsd:string"/> </xsd:sequence> </xsd:complexType> </xsd:schema> An example webservice request with input parameters is shown below. The individual elements are described in the table that follows. <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:run="http://runner.ws.rbt.rbtdata.org/" xmlns:sch="http://xml.rbt.rbtdata.org/schemas"> <soapenv:Header/> <soapenv:Body> <run:getDataSet> <sch:QueryParameters> <sch:group>admin</sch:group> <sch:owner>admin</sch:owner> <sch:name>rbt employe</sch:name> <!--1 or more repetitions:--> <sch:parameter> <sch:columnName>hr.employee.employee_id</sch:columnName> <sch:type>integer</sch:type> <sch:value>100</sch:value> </sch:parameter> </sch:QueryParameters> </run:getDataSet> </soapenv:Body> </soapenv:Envelope>
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|