• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Error on Components package and ACCESS="PACKAGE" in function

Community Beginner ,
Apr 16, 2023 Apr 16, 2023

Copy link to clipboard

Copied

Hi all,

 

I test the use of access="package" in a cfc function and it doesn't work, although I do exactly what the documentation says. It says that

1) cfcs in the same folder are considered a package and

2) a func having access="package" can be accessed by the functions of the all the other components of the same package (folder).

 

Please see the simple code below. All 3 files are in the same folder.

When I call  index.cfm  I get the message "Variable CFC2FUNC is undefined"

 

<!--- index.cfm --->

<cfobject name="oX" component="cfc1">
<cfset x = oX.cfc1func()>
<cfoutput>#x#</cfoutput>

 

<!--- cfc1.cfc --->

<cfcomponent>
<cffunction name="cfc1func" access="public" returntype="string">
    <cfset local.ret = cfc2func()>
    <cfreturn Ret>
</cffunction>
</cfcomponent>

 

<!--- cfc2.cfc --->

<cfcomponent>
<cffunction name="cfc2func" access="package" returntype="string">
    <cfreturn "ABC">
</cffunction>
 </cfcomponent>

 

What is not correct in the code above?

 

Thanks in advance for your help

Kostas

 

TOPICS
Advanced techniques , Documentation , Security

Views

388

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
community guidelines

correct answers 1 Correct answer

Community Expert , Apr 16, 2023 Apr 16, 2023

You've misconstrued how things work there, but you're very close. You still need to create an instance of cfc2 (in cfc1) in order to call a method in it from within cfc1 (or from within any cfml template).

 

To be clear, the access control doesn't change HOW you call methods, only WHO (what template) can call it, once the cfc is instantiated. With public, any can; with private, no other can; with package, others can but only if in the same package/folder; while remote is like public but the meth

...

Votes

Translate

Translate
Community Expert ,
Apr 16, 2023 Apr 16, 2023

Copy link to clipboard

Copied

You've misconstrued how things work there, but you're very close. You still need to create an instance of cfc2 (in cfc1) in order to call a method in it from within cfc1 (or from within any cfml template).

 

To be clear, the access control doesn't change HOW you call methods, only WHO (what template) can call it, once the cfc is instantiated. With public, any can; with private, no other can; with package, others can but only if in the same package/folder; while remote is like public but the method can be called from outside of cfml. 

 

See  https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-f/cffunction.html


/Charlie (troubleshooter, carehart.org)

Votes

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
community guidelines
Community Expert ,
Apr 16, 2023 Apr 16, 2023

Copy link to clipboard

Copied

In my first writing of this, I mistakenly typed public in the 2nd paragraph where I clearly meant package, while distinguishing the 4 types. I've since corrected that. 


/Charlie (troubleshooter, carehart.org)

Votes

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
community guidelines
Community Beginner ,
Apr 21, 2023 Apr 21, 2023

Copy link to clipboard

Copied

Charlie,

thank you for your reply. I guess your suggestion is the one below

<!--- cfc1.cfc --->

<cfcomponent>
 <cfobject name="oCFC2" component="CFC2">
<cffunction name="cfc1func" access="public" returntype="string">
<cfreturn oCFC2.cfc2func()>
</cffunction>
</cfcomponent>

 

I did it and it works. I thought that as "extends=.." connects two CFCs without making any instance in one of another, in the same way acess="package" would connect CFCs of the same folder without needing instance.

 

Thank you very much

Kostas

Votes

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
community guidelines
Community Expert ,
Apr 21, 2023 Apr 21, 2023

Copy link to clipboard

Copied

Glad to have helped. And there are indeed many ways to have instantiated the cfc of course, and whether in that pseudo-constructor of the calling cfc or within the method making the call. I wasn't recommending any particular way or place, just that it would need to be done somehow. 🙂 

 

Finally, you somehow marked as " the answer" my second reply--which merely pointed out a mistake in my first. I have swapped those as "the answer" for the sake of future readers. 


/Charlie (troubleshooter, carehart.org)

Votes

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
community guidelines
Community Expert ,
Apr 22, 2023 Apr 22, 2023

Copy link to clipboard

Copied

LATEST
quote

 

<!--- cfc1.cfc --->

<cfcomponent>
 <cfobject name="oCFC2" component="CFC2">
<cffunction name="cfc1func" access="public" returntype="string">
<cfreturn oCFC2.cfc2func()>
</cffunction>
</cfcomponent>

 

Kostas


By @Kostas

 

That works, of course. But, as Charlie has hinted, there are at least 3 caveats:

  1.  You've defined the object oCFC2 in the so-called pseudo-constructor area. That imples that every function in the component CFC1 will have access to the same object oCFC2. However, that could turn out to be a code smell.

    Firstly, it makes CFC1 and CFC2 to be tightly coupled. Secondly, simultaneous access to oCFC2 by different CFC1 functions might lead to thread-contention issues.  
  2.  The same consideration applies when you define the object within the function cfc1func instead. In that case, the object oCFC2 would still be available to any other function in the component cfc1, say, cfc1funcX. Provided the call

    oX.cfc1funcX()

    follows the call 

    oX.cfc1func()

    within the same request.

  3.  Suppose then that the object oCFC2 needs to be used only within the function cfc1func. To guarantee scalable, loosely-coupled code, you should use the VAR or LOCAL scope. For example, as follows:
    <cffunction name="cfc1func" access="public" returntype="string">
    	<!---
    	The instance oCFC2 is only available within this function.
    	The object no longer exists after cfc1func returns.
    	Advantages:
    	    Loose coupling;
    	    Avoidance of thread contention;
    	    Code that is less complex, hence easier to maintain
    	 --->
    	<cfset local.oCFC2="">
    	<cfobject name="oCFC2" component="CFC2">
        <cfset local.ret = oCFC2.cfc2func()>
        <cfreturn ret>
    </cffunction>​

    We are one on the subject that unnecessarily applying inheritance can be a bad thing. But not paying attention to the above caveats can lead to more serious problems than wrongly applying inheritance.

Votes

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
community guidelines
Community Expert ,
Apr 17, 2023 Apr 17, 2023

Copy link to clipboard

Copied

Charlie has given you one suggestion for a solution. Namely, to create an instance of cfc2, and use it to make the cfc2func() call. Pretty much as you've done in index.cfm.

 

A second suggestion is to use the current code, but with cfc1 extending cfc2. That is:

 

<!--- cfc1.cfc --->
<cfcomponent extends="cfc2">
<cffunction name="cfc1func" access="public" returntype="string">
    <cfset local.ret = cfc2func()>
    <cfreturn Ret>
</cffunction>
</cfcomponent>

 

However, you shouldn't do that just for convenience. It is poor design to have ArbitraryComponent.cfc to extend AnotherArbitraryComponent.cfc.

 

There should be a reason in your design for using extension. Examples:

  • Dog.cfc extends Animal.cfc;
  • Employee.cfc extends Person.cfc;

 

 

Votes

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
community guidelines
Community Beginner ,
Apr 21, 2023 Apr 21, 2023

Copy link to clipboard

Copied

BKBK

thank you for your reply. Your comment is alsolutely right. Extending whatever from wherever to whatever else wherever it is, is poor design and in case of middle and up size projects it leads to a mess "OOP".

 

Kostas

 

Votes

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
community guidelines
Resources
Documentation