|
Introduction
Most Web-based applications are three tier applications consisting of the presentation layer, business-logic layer, and data layer. The presentation layer interacts with business components for data. Generally, business components will have several methods exposed to implement different functionality, which take different sets of input parameters and return the values to the presentation layer. XML is used widely to exchange data. This article illustrates the interface between the presentation layer and business components. Instead of exposing several methods, we expose a single method to the interface and pass an ACTION variable to specify what kind of request is being made. The business component will internally call the individual function to perform the requested action.
Online Bookstore Example
For an "online bookstore" many methods will be required to implement the total functionality. Let us concentrate on the following methods:
GetBookAuthor()
GetBookTitle()
GetBookPrice()
Each method has the following input and output in XML format.
| Method | Input XML string | Output XML string |
| GetBookAuthor |
<Book>
<ISBN>6578890900</ ISBN>
< /Book >
|
<Book>
<Author>Ghouse</Author>
< /Book >
|
| GetBookTitle |
<Book>
<ISBN>6578890900</ ISBN>
< /Book >
|
<Book>
<Title>XML Made Easy</ Title >
< /Book >
|
| GetBookPrice |
<Book>
<ISBN>6578890900</ ISBN>
< /Book >
|
<Book>
<Price>$39.50</Price>
< /Book >
|
The proposed interface will have only one Method GetBookInfo
| Method | Input XML string | Output XML string |
| GetBookInfo |
<Book>
<Action>GetBookAuthor</Action>
<ISBN>6578890900</ ISBN>
< /Book > |
<Book>
<Author>Ghouse</Author>
< /Book > |
| GetBookInfo |
<Book>
<Action>GetBookTitle</Action>
<ISBN>6578890900</ ISBN>
< /Book > |
<Book>
<Title>XML Made Easy</ Title >
< /Book > |
| GetBookInfo |
<Book>
<Action>GetBookPrice</Action>
<ISBN>6578890900</ ISBN>
< /Book > |
<Book>
<Price>$39.50</Price>
< /Book > |
Advantages
1. Interface will now have only one method; very convenient to publish.
2. Presentation layer does not need to know all the methods, it only needs to pass "ACTION" so it is encapsulated.
3. Presentation layer is not affected by any name change of internal methods.
4. If new functionality needs to be added, just implement it in the business component. Presentation layer needs to only pass the new "ACTION" code for easy enhancements.
5. Effective code management and very good modularity; very conducive to reuse.
Sample Code: Business Component Code in C++ and GUI Code in VB
///////////////// IDL LOOKS LIKE THIS //////////////////////////
import "oaidl.idl";
import "ocidl.idl";
[
uuid(E8FE12B5-38A9-11D7-83A2-0050DAC9F0F5),
version(1.0),
helpstring("book 1.0 Type Library")
]
library BOOKLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
object,
uuid(E8FE12C1-38A9-11D7-83A2-0050DAC9F0F5),
dual,
helpstring("IBooks Interface"),
pointer_default(unique)
]
interface IBooks : IDispatch
{
[id(1), helpstring("method GetBookInfo")] HRESULT GetBookInfo([in]
BSTR bsInputStr, [out, retval] VARIANT *bsOutPutStr);
};
[
object,
uuid(50B1FB5B-38AA-11d7-83A2-0050DAC9F0F5),
dual,
helpstring("IProcessBooks Interface"),
pointer_default(unique)
]
interface IProcessBooks : IDispatch
{
[id(1), helpstring("method GetBookTitle")] HRESULT GetBookTitle
([in]BSTR bsInput, [out, retval] VARIANT *vntOutputXML);
[id(2), helpstring("method GetBookPrice")] HRESULT GetBookPrice
([in]BSTR bsInput, [out, retval] VARIANT *vntOutputXML);
[id(3), helpstring("method GetBookAuthor")] HRESULT GetBookAuthor
([in]BSTR bsInput, [out, retval] VARIANT *vntOutputXML);
};
[
uuid(E8FE12C2-38A9-11D7-83A2-0050DAC9F0F5),
helpstring("Books Class")
]
coclass Books
{
[default]interface IBooks;
interface IProcessBooks;
};
};
//////////////////////////////// IDL ENDS HERE //////////////////////////////////////
//////////////// COMPONENT IMPLEMENTATION START HERE ///////////////////////////////////
// Books.cpp : Implementation of CBooks
#include "stdafx.h"
#include "Book.h"
#include "Books.h"
#include<comdef.h>
using namespace MSXML2;
#define CHECKHR(x) {hr = x; if (FAILED(hr)) throw(hr);}
/////////////////////////////////////////////////////////////////////////////
// CBooks
STDMETHODIMP CBooks::GetBookInfo(BSTR bsInputStr, VARIANT *bsOutPutStr)
{
HRESULT hr;
long lngErrorCode;
IXMLDOMParseErrorPtr pXMLError = NULL;
IXMLDOMDocument2Ptr pXMLDoc2 = NULL;
CHECKHR(pXMLDoc2.CreateInstance("Msxml2.DOMDocument.4.0"));
IXMLDOMNodePtr pRequestElement = NULL, pRoot, pISBN = NULL;
CComBSTR bsNodeVal;
_bstr_t bsOutput;
VariantInit(bsOutPutStr);
bsOutPutStr->vt = VT_BSTR;
try
{
pXMLDoc2->async = false;
pXMLDoc2->resolveExternals = false;
pXMLDoc2->validateOnParse = true;
// IT VALIDATES WHEN IT LOADS XML DOC.
hr = pXMLDoc2->loadXML(_bstr_t(bsInputStr));
if(hr!=VARIANT_TRUE)
{
pXMLDoc2->get_parseError(&pXMLError);
pXMLError->get_errorCode(&lngErrorCode);
if (lngErrorCode != 0) throw( pXMLError );
}
CHECKHR(pRoot = pXMLDoc2->selectSingleNode(_bstr_t("BOOK")));
if(pRoot == NULL)
{
throw("Invalid XML Input");
}
CHECKHR(pRequestElement = pRoot->selectSingleNode
(_bstr_t("ACTION")));
CHECKHR(pISBN = pRoot->selectSingleNode(_bstr_t("ISBN")));
// GETTING THE FUNCTION NAME
CHECKHR(pRequestElement->get_text(&bsNodeVal));
CComPtr<ITypeInfo> pTypeInfo = NULL;
// Query the Inner Interface
CComQIPtr<IProcessBooks, &IID_IProcessBooks> pProcessBooks(this);
UINT dwIndex = 0;
CHECKHR(pProcessBooks->GetTypeInfo
((unsigned int) dwIndex, NULL, &pTypeInfo));
DISPID dispid;
OLECHAR FAR* szMember = bsNodeVal;
CHECKHR(pTypeInfo->GetIDsOfNames( &szMember, 1, &dispid));
BSTR names[2];
UINT pcNames = NULL;
CHECKHR( pTypeInfo->GetNames(dispid, names, 10, &pcNames) );
ATLASSERT(sizeof(names)/4 == pcNames);
// GETTING THE FUNCTION NAME
CHECKHR(pISBN->get_text(&bsNodeVal));
_variant_t pVarResult;
EXCEPINFO FAR *pExcepInfo = NULL;
unsigned int FAR *puArgErr = NULL;
_variant_t vntParams[1];
vntParams[0].vt = VT_BSTR;
vntParams[0].bstrVal = bsNodeVal;
DISPPARAMS dispparams;
dispparams.rgvarg = vntParams;
dispparams.cArgs = 1;
dispparams.cNamedArgs = 0;
CHECKHR( pProcessBooks->Invoke(
dispid,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
&dispparams, &pVarResult, pExcepInfo, puArgErr) );
bsOutput = pVarResult.bstrVal;
bsOutPutStr->bstrVal = bsOutput.copy();
}
catch( _com_error err )
{
}
catch(IXMLDOMParseErrorPtr spXmlError)
{
}
catch( ... )
{
}
return S_OK;
}
STDMETHODIMP CBooks::GetBookTitle(BSTR bsInput, VARIANT *vntOutputXML)
{
// Construct XML String to and fill vntOutputXML with Book Tittle
return S_OK;
}
STDMETHODIMP CBooks::GetBookPrice(BSTR bsInput, VARIANT *vntOutputXML)
{
// Construct XML String to and fill vntOutputXML with Book Price
return S_OK;
}
STDMETHODIMP CBooks::GetBookAuthor(BSTR bsInput, VARIANT *vntOutputXML)
{
// Construct XML String to and fill vntOutputXML with Book Author
return S_OK;
}
//////////////// COMPONENT IMPLEMENTATION ENDS HERE ///////////////////////////////////
//////////////// GUI IMPLEMENTATION START HERE ///////////////////////////////////
Dim x As New BOOKLib.Books
Dim y
Y=x.GetBookInfo("<BOOK><ACTION>GetBookTitle</ACTION>
<ISBN>12345678</ISBN></BOOK>")
//////////////// GUI IMPLEMENTATION END HERE ///////////////////////////////////
About the Author
Khadarabad Ghouse Mohiuddin presently works as Systems Architect in one of the leading Telecommunications Company in Dallas, TX, where he leads a team in developing Operations Support Systems. He likes to implement new innovative ideas using the latest technologies. He has in-depth knowledge of current and emerging technologies and leverages them to provide better solutions to the organization. He has more than 10 years of software development experience in variety of areas which include Image Processing, Satellite Simulators, Embedded Systems and Operations Support Systems. Ghouse can be reached at ghousem@yahoo.com.
|