Front-Controller Framework Architecture and Services - frameworks

I am trying to use my service layer in my own front-controller style framework and I've always been taught to decouple the service layer from the controller layer.
This is causing me issues as I need to access important front-controller methods from my services, so I'm jumping through hoops to try and make this happen.
I noticed when looking at Coldbox however that the actual framework regularly passes the Coldbox controller through to its services.
Can and should this really be done?
The problem I have specifically that my controller/handler calls a service which gets a load of widgets for a page request, it then loops over each one and renders each widget, but each widget is itself a controller/handler and the controller/handler needs the front-controller.
How can this be done without passing in the front-controller or is my architecture all wrong?
CURRENT SERVICE CODE (shortened)
<cffunction name="renderWidgets" access="public" output="false" returntype="string" hint="I return an the prequested webpage URL.">
<cfargument name="source" type="string" default="" />
<cfargument name="templateId" type="string" default="" />
<cfargument name="webPageId" type="string" default="" />
<!--- set original template HTML --->
<cfset stuReturn.renderedHTML = arguments.source />
<!--- get assigned widgets and properties --->
<cfset stuReturn.qryTemplateObjects = findTemplateObjectAssignments({templateId=arguments.templateID}) />
<!--- if found --->
<cfif stuReturn.qryTemplateObjects.recordcount>
<!--- loop over assigned widgets --->
<cfloop query="stuReturn.qryTemplateObjects">
<!--- create struct --->
<cfset stuReturn.stuTemplateObjectAssignment = queryrowtostruct(stuReturn.qryTemplateObjects, stuReturn.qryTemplateObjects.currentrow) />
<!--- get the widget object --->
<cfset stuReturn.renderedHTML = stuReturn.renderedHTML & getFrontController().getWidget(stuReturn.stuTemplateObjectAssignment.objectId).render() /><!--- this is the problem, no access to getFrontController() --->
</cfloop>
</cfif>
<!--- return rendered HTML --->
<cfreturn stuReturn.renderedHTML />

Related

ColdFusion adding extensions to names of uploaded files?

So I was just working on some ColdFusion code to validate upload filename extensions, and I've noticed that when I delete the extension from a filename and then upload the file, the extension gets added back somehow I'm guessing based on the MIME type, however I'm not sure if ColdFusion is doing this, or the browser (MS Edge on Mac)? The extension appears inside the CLIENTFILE, CLIENTFILEEXT, CONTENTSUBTYPE, as well as the ATTEMPTEDSERVERFILE, SERVERFILE, and SERVERFILEEXT properties of the <cffile> result, even though the filename of the uploaded file didn't have an extension.
Anyone know what's going on?
This is the form input <input type="file" name="attachment1" style="width:100%"> and this is how it's being saved <cffile action="upload" filefield="attachment1" destination="#request.email_upload_folder#" nameconflict="overwrite" result="my_result1">. The extension also shows up when I use this function to get the client file name (I admit to copy-pasting this code without understanding how it works):
<cffunction name="getClientFileName" access="public" returntype="string" output="false" hint="">
<cfargument name="fieldName" required="true" type="string" hint="Name of the Form field" />
<cfset var tmpPartsArray = Form.getPartsArray() />
<cfif IsDefined("tmpPartsArray")>
<cfloop array="#tmpPartsArray#" index="local.tmpPart">
<cfif local.tmpPart.isFile() AND local.tmpPart.getName() EQ arguments.fieldName>
<cfreturn local.tmpPart.getFileName() />
</cfif>
</cfloop>
</cfif>
<cfreturn "" />
</cffunction>

Does ColdFusion support REST API URIs with a dynamic token in the middle of the URI?

I've been playing with ColdFusion 11's REST API support and am wondering if it's possible to have it support a URI with a dynamic token in the middle of the URI instead of only at the end. That is, it very easily supports URIs like:
/rest/users/12345
where the 12345 is dynamic (in this case, the user's userID). But I haven't been able to find a way (without a tremendous amount of URI hacking) to support URIs like:
/rest/users/12345/emailAddresses
So, is it possible to do this in ColdFusion (11 or 2016)? If not, is it supported in Taffy (I didn't see where it is but I could be wrong)?
TIA
It's been a while and I wanted to provide the answer in case anyone else has this same question...
ColdFusion, when defining a CFC for a REST endpoint, allows you to specify wildcards/variable names in the restpath attribute to both the <cfcomponent> and <cffunction> tags. You would then define <cfargument> tags for each one of these variables so that you can access them within your function. For example:
<cfcomponent rest="true" restpath="/users/{userId}/pets" ... >
<cffunction name="getPets" access="remote" httpMethod="GET">
<cfargument name="userId" type="numeric" required="true" restargsource="Path" />
<!--- Called with a path like /users/123/pets/ --->
<!--- do stuff using the arguments.userId (123) variables --->
</cffunction>
<cffunction name="getPet" access="remote" httpMethod="GET" restpath="{petId}">
<cfargument name="userId" type="numeric" required="true" restargsource="Path" />
<cfargument name="petId" type="numeric" required="true" restargsource="Path" />
<!--- Called with a path like /users/123/pets/456/ --->
<!--- do stuff using the arguments.userId (123) and/or arguments.petId (456) variables --->
</cffunction>
</cfcomponent>
The keys here are using the restpath attribute with the variable defined as a variable name in curly braces and then defining those variables as arguments to the function with a restargsource attribute set to "Path".
I hope this helps.

REST services in ColdFusion 11

I am trying to create a new rest service in coldfusion and I wanted to try not passing in some parameters if I don't have a value for them but I am getting a 'not found' response from my function.
REST Service CFC:
<cfcomponent rest="true" restpath="/crudService">
<cffunction name="getHandlerJSON" access="remote" httpmethod="GET" restpath="{customerID}" returntype="query" produces="application/json">
<cfargument name="customerID" required="false" restargsource="Path" type="numeric" default=-1/>
<cfset myQuery = queryNew("id,name","Integer,varchar",[[1, "Sagar"], [2, "Ganatra"]])>
<cfquery dbtype="query" name="resultQuery">
select * from myQuery where 1=1
<cfif arguments.customerID neq -1>
and id = #arguments.customerID#
</cfif>
</cfquery>
<cfreturn resultQuery>
</cffunction>
</cfcomponent>
And this is how I am calling it:
<cfhttp url="http://dev.test.com/rest/api/crudService/2" result="restResult" method="GET" />
<cfdump var="#deserializeJSON(restResult.filecontent,false)#">
And the outcome:
{"COLUMNS":["ID","NAME"],"DATA":[[2,"Ganatra"]]}
What I want to do is to be able to call my service without an id and get all of the results back. Do I need to create a separate function for this? What is the best practice?
When passing parameters to a REST service CFC via PATH those params must exist in the URL. If not, then the path CF is looking at is not correct.
I believe you will need a separate function to return all results...OR, pass a huge number like 1000000.

<h:form action="#{bean.method()}"> gets called twice

I am writing a Java EE application for changing password. For taking old and new password inputs I am using a jsf form.
<h:form method="post" action="#{changePass.updatePassword()}" >
<h:inputText id="username" value = "#{changePass.username}" readonly="true" required="true"/>
<h:inputSecret id="oldPassword" value = "#{changePass.oldPassword}" required="true" />
<h:inputSecret id="newPassword" value = "#{changePass.newPassword}" required="true" />
<h:inputSecret id="confirmPassword" value = "#{changePass.confirmPassword}" required="true" />
<button id="update" type="submit"></button>
</h:form>
My intention is to call updatePassword() function in changePass bean class when user clicks on the button. But this fuction gets called twice in this form.
when the form loads
When the user clocks on the button
How can I avoid this calling during the form load?
Your xhtml should look like this:
<h:form>
<h:inputSecret id="newPassword" value = "#{changePass.newPassword}" required="true" />
<h:commandButton value="submit" action="#{changePass.updatePassword}" />
</h:form>
If that still doesn't work then there is smtg wrong with your bean. Also you might want to follow some tutorials. I'm not entirely sure the syntax you used is wrong but it's the first time I've seen it though.

Usage of Float and Integer in DynaActionForm properties and retrieving them with struts-html.tld tags

I have a DynaActionForm element in my struts-config.xml like:
<form-bean name="myActionForm" type="org.apache.struts.action.DynaActionForm">
<!-- Control Params -->
<form-property name="action" type="java.lang.String" />
<form-property name="list" type="java.lang.String" initial="master_document_list.data"/>
<!-- Business params -->
<form-property name="code" type="java.lang.String"/>
<form-property name="name" type="java.lang.String"/>
<form-property name="description" type="java.lang.String"/>
<form-property name="sequenceNumber" type="java.lang.Float"/>
</form-bean>
And the jsp page where I am trying to use it:
<!-- struts-html.tld imported with prefix html -->
<html:form>
<table>
<tr>
<td>Sequence No.</td>
<td><html:text property="sequenceNumber" maxlength="15" style="width:75%"/></td>
</tr>
<table>
</html:form>
but when i do this I am getting a JspException saying "No getter method for property sequenceNumber. I am quite sure that the name is correct. Is it the type that is not getting accepted then? I thought the DynaActionForm allowed types are all major java types including the Thread-Safe Wrappers (e.g. Float, Integer, Short, Long, etc.).
N.B. I am using struts1
After digging apache documentation, i figured out that
<html:text> tag has got the following settings:
name= Name of the form bean
property= Name of the property associated to the form-property tag for the bean above
Althernatively, using ${myBean.map.myProp} will point me to the right direction.
Thanks all,