Highlighted

Implementing a service layer to call gateways and DAOs

New Here ,
May 13, 2015

Copy link to clipboard

Copied

I am using CF11. In addition to the Datasource component, I created a package of four components ( 1 x Bean, 1 x DAO, 1 x Gateway, 1 x Service) that deals with grapes...

The datasource object and the service object have been persisted in Application.cfc as follows:

<cffunction name="onApplicationStart" output="false">

  <!--- Instantiate the Datasource object --->

  <cfset var objDatasource = createObject ('component','components.beans.Datasource').init(

  DSName='dns', username='abc',

  password='pass') />


  <!--- Instantiate and persist the Grape service in the application scope  --->

  <cfset Application.GrapeSVC = createObject('component','components.dataAccess.GrapeSVC').init(

  datasource = objDatasource) />

</cffunction>

The service object (GrapeSVC.cfc) acts as a façade pattern to the other inner components: a Bean (Grape.cfc), a DAO (GrapeDAO.cfc) and a Gateway (GrapesGW.cfc).

Now, I have below a CFM template that instantiates the above service object (GrapeSVC) to simply call a method - getAllGrapes() from the gateway - that lists all the grapes in the database:

ListGrapes.cfm

<!--- Instantiate the Datasource object --->

  <cfset objDatasource = createObject ('component','components.beans.Datasource').init(

  DSName='dns', username='abc',

  password='pass') />

  <!--- Instantiate the Grape service object and pass in the datasource object --->

  <cfset objGrapeSVC = createObject('component','components.dataAccess.GrapeSVC').init(

  datasource = objDatasource) />

  <!--- Pull out all grapes from the database --->

  <cfset qResults = objGrapeSVC.getAllGrapes() /> 

    <!--- Dump the results --->

    <cfdump var="#qResults#" label="getAllGrapes results" />


The code above works fine as long as I keep instantiating the datasource object within the above CFM template. If I take it out, the code breaks. This does not make sense to me since I have already persisted the datasource object in Application.cfc above and mostly because the objective is to avoid repeats. My question therefore is:

What is wrong in the above approach and is there a way to NOT re-instantiate the datasource object in every CFM template?

TOPICS
Advanced techniques

Views

492

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

Implementing a service layer to call gateways and DAOs

New Here ,
May 13, 2015

Copy link to clipboard

Copied

I am using CF11. In addition to the Datasource component, I created a package of four components ( 1 x Bean, 1 x DAO, 1 x Gateway, 1 x Service) that deals with grapes...

The datasource object and the service object have been persisted in Application.cfc as follows:

<cffunction name="onApplicationStart" output="false">

  <!--- Instantiate the Datasource object --->

  <cfset var objDatasource = createObject ('component','components.beans.Datasource').init(

  DSName='dns', username='abc',

  password='pass') />


  <!--- Instantiate and persist the Grape service in the application scope  --->

  <cfset Application.GrapeSVC = createObject('component','components.dataAccess.GrapeSVC').init(

  datasource = objDatasource) />

</cffunction>

The service object (GrapeSVC.cfc) acts as a façade pattern to the other inner components: a Bean (Grape.cfc), a DAO (GrapeDAO.cfc) and a Gateway (GrapesGW.cfc).

Now, I have below a CFM template that instantiates the above service object (GrapeSVC) to simply call a method - getAllGrapes() from the gateway - that lists all the grapes in the database:

ListGrapes.cfm

<!--- Instantiate the Datasource object --->

  <cfset objDatasource = createObject ('component','components.beans.Datasource').init(

  DSName='dns', username='abc',

  password='pass') />

  <!--- Instantiate the Grape service object and pass in the datasource object --->

  <cfset objGrapeSVC = createObject('component','components.dataAccess.GrapeSVC').init(

  datasource = objDatasource) />

  <!--- Pull out all grapes from the database --->

  <cfset qResults = objGrapeSVC.getAllGrapes() /> 

    <!--- Dump the results --->

    <cfdump var="#qResults#" label="getAllGrapes results" />


The code above works fine as long as I keep instantiating the datasource object within the above CFM template. If I take it out, the code breaks. This does not make sense to me since I have already persisted the datasource object in Application.cfc above and mostly because the objective is to avoid repeats. My question therefore is:

What is wrong in the above approach and is there a way to NOT re-instantiate the datasource object in every CFM template?

TOPICS
Advanced techniques

Views

493

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
May 13, 2015 0
New Here ,
May 14, 2015

Copy link to clipboard

Copied

After a more careful reading of Matt Gifford's OO Programming in ColdFusion, I could re-factor the code as follows:

Application.cfc:

<cffunction name="onApplicationStart" output="false">

  <!--- Instantiate the Datasource object --->

  <cfset var objDatasource = createObject ('component','components.beans.Datasource') />

  <!--- Instantiate and persist the Grape service in the application scope  --->

  <cfset Application.GrapeSVC = createObject('component','components.dataAccess.GrapeSVC').init(

  datasource = objDatasource) />

  </cffunction>

dropping the init() that contained the datasource login credentials. Those have been set once as default properties in the Datasource bean instead, and nowhere repeated.

Same thing in the Listgrapes.cfm template:

<!--- Instantiate the Datasource object --->

  <cfset objDatasource = createObject('component','components.beans.Datasource') />

  <!--- Instantiate the Grape service object and pass in the datasource object --->

  <cfset objGrapeSVC = createObject('component','components.dataAccess.GrapeSVC').init(

  datasource = objDatasource) />

  <!--- Pull out all grapes from the database --->

  <cfset qResults = objGrapeSVC.getAllGrapes() /> 

    <!--- Dump the results --->

    <cfdump var="#qResults#" label="getAllGrapes results" />


Still not sure whether this code is optimised, but it works. Not sure whether setting the default Datasource bean properties with its access credentials is secure as well.

However I encountered an interesting problem accessing a private method in the underlying gateway component. The method getAllGrapes() is public both in the service component and the gateway component. Within the gateway component this public method getAllGrapes() calls a private method filterAllGrapes() that implements a search filter. I had to set the access to the method filterAllGrapes() in the gateway object from private to package in order to make the call from the service layer possible. Leaving the access method to private triggers an error. I had no such problem when calling the same method from the gateway directly (i.e not implementing the service layer). I am not really sure what caused this issue.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
May 14, 2015 0
BKBK LATEST
Adobe Community Professional ,
May 17, 2015

Copy link to clipboard

Copied

That is so by design. In ColdFusion, private access means that the function will only be accessible to the component within which it is defined, or to any components that extend it.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
May 17, 2015 0