Application architecture using AbstractGateway

100 views
Skip to first unread message

Gavin Baumanis

unread,
Jan 26, 2012, 7:07:55 PM1/26/12
to coldspri...@googlegroups.com
Hi Everyone,
I have recently had a discussion on the CFAUSSIE mailing list about application architecture and the merit of having a service layer in addition to the data access layer.
 
The summation of that thread was that I was questioning what value the service layer provided to me, in the REAL WORLD - since whenever I used a service layer - it was 99% of the time used as a "proxy" to the data access layer.
I was hand writing all the SQL in the Gateways, and then repeating the method signatures (manually) in the service layer, as a public API.
It seemed like an awful lot of duplication to me.
 
During that discussion, Mark M. put me onto using the onMissingMethod functionality and the AbstractGateway cfc from ColdSpring.
(He was actually even nice enough to give me a hand with a sample app - BIG thanks!)
 
For thos not yet using it, the AnbstractGateway dynamically creates CRUD functions for properties in the "base" objects.
Eg. if you have a user object with XXX properties (username, password, firstname, surname.....)
Then AbstractGateway will create;
getXXX, deleteXXX, listXXX etc methods for you.
Machine generated, human-error free and repeatable.... nice!
 
 
Anyway,
I have managed to start a new application using his ideas.
Despite previously using onMissingMethod for a "trial" of SOA  - I haven't used it in anger so to speak - and it is definitely the first time I have used the AbstractGateway.cfc
 
So ultimately, I just wanted to confirm that I was doing things correctly - before I got too far into it.
As is always the case, please feel free to share any ideas / thoughts you might have.
All the code is below - And thanks!
 
 
 
So assuming that I have a User class with a dozen properties, I have the following,
 
User.cfc
----------------------
 - extends nothing,
 - contains no methods,
      - just the user properties
 
component persistent="true" table="User"  schema="dbo" output="false"
{
 /* properties */
 property name="userName" column="userName" type="string" ormtype="string" fieldtype="id";
 property name="password" column="password" type="string" ormtype="string";
 ...
 
 
UserGateway.cfc
--------------------------
 - extends AbstractGateway for dynamic creation of CRUD methods
 - contains no methods
      - is an empty CFC
 
component
 extends="AbstractGateway"
 displayname="UserGateway"
 hint="I am responsible for all databaase / persistence operations for the User Class.
   I extend the AbstractGateway Class to dynamically create getter / setter methods for the User Class."
{
}
 
 
UserService.cfc
-----------------------
 - extends AbstractService.cfc
 - contains a single method for linking the gateway to the AbstractService
    - (The AbstractService contains the onMissingMethod function...)
 
component
 extends="AbstractService"
 displayname="rsUser Service Manager"
 hint="I am the Service Manager / Public API for the User Gateway class."
{
 public function init()
 {
  super.init(data=new UserGateway());
 }
}
 
 
AbstractService.cfc
------------------------------------
component
 accessors="true"
 displyname="AbstractService Class"
 hint="I am extended by other SERVICE objects so that they might inherit my onMissingMethod function"
{
 property data;
 
 public function init(data)
 {
  setData(data);
 }

 public function onMissingMethod(string missingMethodName, struct missingMethodArguments)
 {
  return evaluate("getData().#missingMethodName#(argumentCollection=missingMethodArguments)");
 }
}
 
 
 

Mark Mandel

unread,
Jan 26, 2012, 10:57:45 PM1/26/12
to coldspri...@googlegroups.com
Looks good to me - assuming it is doing what I think you want it to.

Ultimate question - is it working for you? :)

Mark

 
 
 

--
You received this message because you are subscribed to the Google Groups "ColdSpring-Users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/coldspring-users/-/HoVLeM_sySwJ.
To post to this group, send email to coldspri...@googlegroups.com.
To unsubscribe from this group, send email to coldspring-use...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/coldspring-users?hl=en.



--
E: mark....@gmail.com
T: http://www.twitter.com/neurotic
W: www.compoundtheory.com

2 Devs from Down Under Podcast

Tony Nelson

unread,
Jan 26, 2012, 11:21:36 PM1/26/12
to ColdSpring-Users
Wouldn't it be better to inject a UserGateway into your UserService
rather than create one inside UserService.init()?

This is the ColdSpring user group and all...

Mark Mandel

unread,
Jan 26, 2012, 11:22:40 PM1/26/12
to coldspri...@googlegroups.com
Oh yeah, I missed that. +1 to what Tony said.

Mark

--
You received this message because you are subscribed to the Google Groups "ColdSpring-Users" group.
To post to this group, send email to coldspri...@googlegroups.com.
To unsubscribe from this group, send email to coldspring-use...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/coldspring-users?hl=en.

Gavin Baumanis

unread,
Feb 20, 2012, 9:52:51 PM2/20/12
to coldspri...@googlegroups.com
Hi there,

After working in a different problem space for a little while I am back to getting on with the new part of our application.

The code in the CFCs, hasn't changed, though we have rearchitected the application since I was last here talking about it.
(So I "do" assume it is something that we have done)

None the less I have come across an error that doesn't appear via a Google search or a group search, so I figured I would ask for some help - and hope that it is something silly....

Anyway, when creating a Service - using;
<cfset testService = createObject("component", "com.cogstate.qms.dcTestService").init() />

<cfdump var="#testService#" />

 I now get the following ;

Detail[empty string]
ErrNumber0
MessageElement SINGLETON.INSTANCE is undefined in a Java object of type class coldfusion.runtime.AttributeCollection referenced as ''
Resolvedname[empty string]
StackTracecoldfusion.runtime.UndefinedElementException: Element SINGLETON.INSTANCE is undefined in a Java object of type class coldfusion.runtime.AttributeCollection referenced as '' at coldfusion.runtime.DotResolver.resolveSplitNameInMap(DotResolver.java:109) at coldfusion.runtime.CfJspPage._resolve(CfJspPage.java:1578) at coldfusion.runtime.CfJspPage._resolveAndAutoscalarize(CfJspPage.java:1796) at coldfusion.runtime.CfJspPage._resolveAndAutoscalarize(CfJspPage.java:1788) at cfAbstractGateway2ecfc347768562$funcINIT.runFunction(C:\DataPoint\com\coldspring\orm\hibernate\AbstractGateway.cfc:51) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472) at coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:654) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:443) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:413) at coldfusion.runtime.CFPage.___createObjectInternal(CFPage.java:10266) at coldfusion.runtime.CFPage._createObject(CFPage.java:10232) at cfdcTestService2ecfc608659344$funcINIT.runFunction(C:\DataPoint\com\cogstate\qms\dcTestService.cfc:27) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:654) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:443) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:413) at coldfusion.runtime.CfJspPage._invoke(CfJspPage.java:2431) at cfscribble2ecfm1191294066.runPage(C:\DataPoint\www\scribble.cfm:12) at coldfusion.runtime.CfJspPage.invoke(CfJspPage.java:235) at coldfusion.tagext.lang.IncludeTag.doStartTag(IncludeTag.java:429) at coldfusion.runtime.CfJspPage._emptyTcfTag(CfJspPage.java:2798) at cfapplication2ecfc1007700339$funcONREQUEST.runFunction(C:\DataPoint\www\application.cfc:145) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:472) at coldfusion.runtime.UDFMethod$ReturnTypeFilter.invoke(UDFMethod.java:405) at coldfusion.runtime.UDFMethod$ArgumentCollectionFilter.invoke(UDFMethod.java:368) at coldfusion.filter.FunctionAccessFilter.invoke(FunctionAccessFilter.java:55) at coldfusion.runtime.UDFMethod.runFilterChain(UDFMethod.java:321) at coldfusion.runtime.UDFMethod.invoke(UDFMethod.java:220) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:654) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:443) at coldfusion.runtime.TemplateProxy.invoke(TemplateProxy.java:413) at coldfusion.runtime.AppEventInvoker.invoke(AppEventInvoker.java:104) at coldfusion.runtime.AppEventInvoker.onRequest(AppEventInvoker.java:296) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:406) at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40) at coldfusion.filter.PathFilter.invoke(PathFilter.java:112) at coldfusion.filter.LicenseFilter.invoke(LicenseFilter.java:30) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:75) at coldfusion.filter.BrowserDebugFilter.invoke(BrowserDebugFilter.java:79) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:46) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.filter.CachingFilter.invoke(CachingFilter.java:62) at coldfusion.CfmServlet.service(CfmServlet.java:204) at coldfusion.bootstrap.BootstrapServlet.service(BootstrapServlet.java:89) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at coldfusion.monitor.event.MonitoringServletFilter.doFilter(MonitoringServletFilter.java:42) at coldfusion.bootstrap.BootstrapFilter.doFilter(BootstrapFilter.java:46) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:414) at org.apache.coyote.ajp.AjpProcessor.process(AjpProcessor.java:203) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:298) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662)
TagContext
array
1
struct
COLUMN0
IDCF_DOTRESOLVER
LINE51
RAW_TRACEat cfAbstractGateway2ecfc347768562$funcINIT.runFunction(C:\DataPoint\com\coldspring\orm\hibernate\AbstractGateway.cfc:51)
TEMPLATEC:\DataPoint\com\coldspring\orm\hibernate\AbstractGateway.cfc
TYPECFML
2
struct
COLUMN0
IDCF_CFPAGE
LINE27
RAW_TRACEat cfdcTestService2ecfc608659344$funcINIT.runFunction(C:\DataPoint\com\cogstate\qms\dcTestService.cfc:27)
TEMPLATEC:\DataPoint\com\cogstate\qms\dcTestService.cfc
TYPECFML
3
struct
COLUMN0
IDCF_TEMPLATEPROXY
LINE12
RAW_TRACEat cfscribble2ecfm1191294066.runPage(C:\DataPoint\www\scribble.cfm:12)
TEMPLATEC:\DataPoint\www\scribble.cfm
TYPECFML
4
struct
COLUMN0
IDCFINCLUDE
LINE145
RAW_TRACEat cfapplication2ecfc1007700339$funcONREQUEST.runFunction(C:\DataPoint\www\application.cfc:145)
TEMPLATEC:\DataPoint\www\application.cfc
TYPECFML



To try and help a little, here is the code of relevance;
scribble.cfm @12
<cfset testService = createObject("component", "com.cogstate.qms.dcTestService").init() />

dcTestService.cfc
component
extends="com.cogstate.AbstractService"
displayname="dcTest Service Manager"
hint="I am the Service Manager / Public API for the dcTest Gateway class."

{
public function init()
{
super.init(data=new dcTestGateway());
}
}


dcTestGateway.cfc
component
extends="com.coldspring.orm.hibernate.AbstractGateway"
displayname="dcTestGateway"
hint="I am responsible for all databaase / persistence operations for the dcTest Class.
I extend the AbstractGateway Class to dynamically create getter / setter methods for the dcTest Class."
{
}

dcTest.cfc
Has no methods, only properties.

If anyone has any ideas component
extends="com.cogstate.AbstractService"
displayname="dcTest Service Manager"
hint="I am the Service Manager / Public API for the dcTest Gateway class."

{
public function init()
{
super.init(data=new dcTestGateway());
}
}



As always - thanks in advance for any help!


Mark Mandel

unread,
Feb 20, 2012, 10:11:59 PM2/20/12
to coldspri...@googlegroups.com
Have you got an instance of ColdSpring running?

Mark

--
You received this message because you are subscribed to the Google Groups "ColdSpring-Users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/coldspring-users/-/9MeD7P6l2esJ.

To post to this group, send email to coldspri...@googlegroups.com.
To unsubscribe from this group, send email to coldspring-use...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/coldspring-users?hl=en.

Gavin Baumanis

unread,
Feb 20, 2012, 10:41:16 PM2/20/12
to coldspri...@googlegroups.com
As always - thanks Mark, I knew it was going to be something simple!
The code to instantiate CS, wasn't committed when I was "playing" around earlier - and as a result of the application rearchitecture, I checked out an entirely new working copy - certain that I would remember all the local changes...!

Just while I think of it, Any chance of a better error message?


Thanks again!

Gavin Baumanis

unread,
May 10, 2012, 9:54:44 AM5/10/12
to coldspri...@googlegroups.com
HI Everyone,

I need to reopen this thread as I am still having an error that I can;t seem to solve for myself.

I still have the AbstractService, AbstractGateway and the specific object service layer classes.


AbstractService
--------------------
component
accessors = "true"
displayname = "AbstractService Class"
hint = "I am extended by other SERVICE objects so that they might inherit my onMissingMethod function"
{
property data;

public function init(data)
{
setData(data);
}

public function onMissingMethod(string missingMethodName, struct missingMethodArguments)
{
return evaluate("getData().#missingMethodName#(argumentCollection=missingMethodArguments)");
}
}


commentsService
-----------------------
component
extends = "com.myProject.AbstractService"
displayname = "Comments Service Manager"
hint = "I am the Service Manager / Public API for the CommentsGateway class."

{
public function init()
{
super.init(data=new CommentsGateway());

return this;
}
}


I have a very simple "junk" template that I am trying to run - but it is producing a weird error for me.
The code and the error follows.
Hopefully, I am just missing something really simple  - but i'll be damned if I can work it out for myself.

Index.cfm
-------------
<cfscript>
    CommentsServiceCFC= createObject("component", "com.projectDir.Comments.CommentsService");
    myNewComment = CommentsServiceCFC.getComments();
</cfscript>


Error;

Type


java.lang.NullPointerException

array

1

struct

COLUMN

0

ID

??

LINE

1

RAW_TRACE

at Statement27.evaluate(<generated>:1)

TEMPLATE

<generated>

TYPE

CFML

2

struct

COLUMN

0

ID

CF_CFPAGE

LINE

69

RAW_TRACE

at cfAbstractService2ecfc55306172$funcONMISSINGMETHOD.runFunction(C:\inetpub\wwwroot\projectDir\trunk\com\projectDir\AbstractService.cfc:69)

TEMPLATE

C:\inetpub\wwwroot\projectDir\trunk\com\projectDir\AbstractService.cfc

TYPE

CFML

3

struct

COLUMN

0

ID

CF_TEMPLATEPROXY

LINE

48

RAW_TRACE

at cfindex2ecfm1327402007.runPage(C:\inetpub\wwwroot\projectDir\trunk\index.cfm:48)

TEMPLATE

C:\inetpub\wwwroot\projectDir\trunk\index.cfm

TYPE

CFML

4

struct

COLUMN

0

ID

CFINCLUDE

LINE

266

RAW_TRACE

at cfApplication2ecfc498167235$funcONREQUEST.runFunction(C:\inetpub\wwwroot\projectDir\trunk\Application.cfc:266)

TEMPLATE

C:\inetpub\wwwroot\projectDir\trunk\Application.cfc

TYPE

CFML



As is always the case - a very big thanks !

Gavin.


Tony Nelson

unread,
May 10, 2012, 10:22:37 AM5/10/12
to coldspri...@googlegroups.com
I don't think createObject() calls init() by default. Try changing your code to:

CommentsServiceCFC = new com.projectDir.Comments.CommentsService();

Gavin Baumanis

unread,
May 10, 2012, 5:00:18 PM5/10/12
to coldspri...@googlegroups.com
Hi Tony,

Thanks! 
Slight;y embarrassing - in the sense that I recently gave a presentation / code review of the new architecture that I am using to the rest of the IT team and specifically mentioned to everyone exactly your point!

Thanks again!

Gavin. 
Reply all
Reply to author
Forward
0 new messages