Sub-application with ColdSpring doesn't have access to package methods

190 Views Asked by At

I'm having trouble creating a sub-application using ColdSpring to instantiate my objects.

In my parent application, I have a ColdSpring config file which is instantiating a bunch of components with no problems. One of them is a 'Categories' (CategoryGateway) component, which has another component for the table (NestedSetTreeTable) injected into it. The injected component contains a package method, 'GetDatasource' which is called by the CategoryGateway component.

This works with no problems in my parent app, however when I try to instantiate the component in my sub-app, it seems that the package method is inaccessible to the CategoryGateway component.

Now, I'm very new to ColdSpring - and also to the concept of creating a sub-application from a parent app - so I'm not sure I'm doing things correctly.

Here's my set up:

Parent app contains a mapped version of ColdSpring and its own coldspring.xml. The coldspring.xml contains the following to instantiate the categories component:

<!-- Categories CFC -->
<bean id="categories" parent="config" class="com.categories.categoryGateway">
    <constructor-arg name="sCategoriesTable">
        <value>${sCategoriesTable}</value>
    </constructor-arg>
    <constructor-arg name="sNSTTable">
        <value>${sNSTTable}</value>
    </constructor-arg>      
    <constructor-arg name="NST">
        <ref bean="categoriesNST" />
    </constructor-arg>      
</bean>

<!-- Categories NST Table CFC -->
<bean id="categoriesNST" parent="config" class="com.categories.NestedSetTreeTable">
    <constructor-arg name="datasourceName">
        <value>${sDSN}</value>
    </constructor-arg>
    <constructor-arg name="table">
        <value>${sNSTTable}</value>
    </constructor-arg>
</bean> 

In my parent's Application.cfc, I instantiate the component thus:

Application.com.categories = beanFactory.getBean('categories');

All works correctly. Now, in my sub Application, I have another mapped version of ColdSpring, and a separate coldspring.xml so that I can use it to instantiate components specific to the sub app. I've checked that the correct coldspring.xml is being run.

I'm not instantiating the base components in my sub-app's Application.cfc, but am calling Super.onApplicationStart to get the parent's method to run. The parent's contains the instantiating code, however it's using the child's Coldspring.xml to find the components - therefore I've created a mapping to the parent app, and adjusted the child's Coldspring.xml accordingly - so this reads:

<!-- Categories CFC -->
<bean id="categories" parent="config" class="core.com.categories.categoryGateway">
    <constructor-arg name="sCategoriesTable">
        <value>${sCategoriesTable}</value>
    </constructor-arg>
    <constructor-arg name="sNSTTable">
        <value>${sNSTTable}</value>
    </constructor-arg>      
    <constructor-arg name="NST">
        <ref bean="categoriesNST" />
    </constructor-arg>      
</bean>

<!-- Categories NST Table CFC -->
<bean id="categoriesNST" parent="config" class="core.com.categories.NestedSetTreeTable">
    <constructor-arg name="datasourceName">
        <value>${sDSN}</value>
    </constructor-arg>
    <constructor-arg name="table">
        <value>${sNSTTable}</value>
    </constructor-arg>
</bean> 

There are several other core components that are loaded in this way before the categories one throws an error - so the technique appears to be working and I have access to my core components without explicitly instantiating them in the child's Application.cfc. However, when it gets to the categories component, I recieve the following error:

Bean creation exception during init() of core.com.categories.categoryGateway

component [core.com.categories.NestedSetTreeTable] has no function with name [getDatasource]:

If I make the getDatasource method public, it seems to work - however this doesn't seem right, since it works as is in the parent app.

Add to the list of things that I'm new to, OOP and inheritance... so if I'm going about this totally the wrong way then please let me know. What I'm attempting is the separation of core functionality (user management, error handling, validation and a bunch of stuff I tend to reuse in every app) from specific app functionality (an e-commerce site may have a cart component not required by a CMS, for instance) in such a way that as I develop a new feature, I can decide to put it in the core and make it available to all my apps, or in the specific app. So in this example, I'm attempting to load core functionality in the parent's Application.cfc and have the child automatically be able to use it. Ideally the child shouldn't have to specify the core functionality in the Coldspring.xml, but I've not found a way of running both the parent's and the child's.

Any help, much appreciated!

1

There are 1 best solutions below

7
On

The injected component contains a private method, 'GetDatasource' which is called by the CategoryGateway component.

You are mistaken here. If GetDatasource is private to NestedSetTreeTable, then CategoryGateway has no access to it. Fullstop.

One can only call private methods from within the component itself, or in a situation where ComponentChild extends ComponentParent, ComponentChild can call private methods from ComponentParent.

It is irrelevant that CategoryGateway takes a NestedSetTreeTable as an argument: that does not confer any special access for CateoryGateway to NestedSetTreeTable's methods.

Coldspring is also irrelevant here: it is just a mechanism for marshalling the instantiation of objects, it does not confer any special powers, nor break the rules of method access.

So this being the case - and I don't doubt you are seeing disparate situations between your environments - you are omitting some key information from your question.