Framework1/fw1 Singleton Bean example (coldfusion)

272 views
Skip to first unread message

Dejan Karan

unread,
Apr 5, 2019, 7:28:36 PM4/5/19
to framework-one
What I'm trying to achieve is to be able to save some data for each user that logs in to the app and use that data throughout the user session or until user browser is closed. I think Singleton Bean would do it but I'm having trouble with syntax. I'm using transient Bean just fine.

So far I've created the Bean in Application.cfc

getBeanFactory().addBean( "cart", createObject( "component" , "model.singletonbeans.cart" ) );

Next I've added the property in my controller (.cfc)

component accessors="true"
{
property beanFactory;

public void function cart( struct rc ) {

rc.mes = " Hello"
rc.cart = getBeanFactory().getBean('cart');
}

}
 
In the .cfm (cfdump) I'm getting the error:

Error: bean not found: cart

Does anyone have a simple example I can see how to create Singleton bean in framework 1 and reference it? 
Does Singleton bean means that every user (During their session) that connects to my Coldfusion server will be able to share data in this Bean or is this Singleton Bean only unique to each user session?

Richard Tugwell

unread,
Apr 6, 2019, 1:30:40 AM4/6/19
to framew...@googlegroups.com
You shouldn't need to manually add the bean - DI/1 will automatically do that if the bean is in the folder(s) specified in 'dilocations';

And in your controller you just need to specify the singleton as a property, not the bean factory, and DI1 will inject it for you

Richard Tugwell




--
FW/1 documentation: http://framework-one.github.io
FW/1 source code: http://github.com/framework-one/fw1
FW/1 chat / support: https://gitter.im/framework-one/fw1
FW/1 mailing list: http://groups.google.com/group/framework-one
---
You received this message because you are subscribed to the Google Groups "framework-one" group.
To unsubscribe from this group and stop receiving emails from it, send an email to framework-on...@googlegroups.com.
Visit this group at https://groups.google.com/group/framework-one.
For more options, visit https://groups.google.com/d/optout.

Richard Tugwell

unread,
Apr 6, 2019, 1:32:43 AM4/6/19
to framew...@googlegroups.com
NB CFML Slack is a better place to get help these days. There's a channel for FW1

Richard Tugwell

unread,
Apr 6, 2019, 1:59:17 AM4/6/19
to framew...@googlegroups.com
@Dejan - I misread your question in my haste! If you are wanting to store user sesson data, why not have a userService singleton that interacted with session (or something). Then you can inject that service and call e.g. userService.getCart()/setCart() etc?

Richard Tugwell



Nando Breiter

unread,
Apr 6, 2019, 7:12:31 AM4/6/19
to framew...@googlegroups.com
Dejan,

A few replies inline:


CarbonZero Sagl
+41 (0)76 303 4477 cell
skype: ariamedia


On Sat, Apr 6, 2019 at 1:28 AM Dejan Karan <kar...@umsl.edu> wrote:
What I'm trying to achieve is to be able to save some data for each user that logs in to the app and use that data throughout the user session or until user browser is closed. I think Singleton Bean would do it but I'm having trouble with syntax. I'm using transient Bean just fine.

So far I've created the Bean in Application.cfc

getBeanFactory().addBean( "cart", createObject( "component" , "model.singletonbeans.cart" ) );

What you may need in Application.cfc if you don't have it already, to conveniently create singletons, is the setting that tells FW1 where it can find beans, diLocations, and perhaps which injection engine to use. The default is di1.


variables.framework = {
  ....
diEngine = 'di1',
diLocations = 'model'
};


Next I've added the property in my controller (.cfc)

component accessors="true"
{
property beanFactory;

Ok, here you've injected beanFactory as a singleton that persists in application scope across all users in your controller. 


public void function cart( struct rc ) {

rc.mes = " Hello"

And here I believe rc.cart is a transient available to this request only. To be 100% sure, I'd read the docs again, but I won't do that because I think you're headed in the wrong direction here.

rc.cart = getBeanFactory().getBean('cart');
}

}
 
In the .cfm (cfdump) I'm getting the error:

I assume you are trying to dump cart instead of rc.cart from within the cart.cfm view? Since rc.cart is a transient, it should only be available in the cart view.

Error: bean not found: cart

Does anyone have a simple example I can see how to create Singleton bean in framework 1 and reference it? 

Wait a moment ...
 
Does Singleton bean means that every user (During their session) that connects to my Coldfusion server will be able to share data in this Bean or is this Singleton Bean only unique to each user session?

Singletons are stored in application scope and hence the data stored in a singleton would be shared across all users. So this isn't what you want for a cart. 

If you want to keep it simple, I'd suggest storing user data within your controller directly within session scope and dereferencing session scope in your view. So I think you'd want to use session.cart.??? for this rather than a bean. 

That said, if you prefer to encapsulate the data for the cart within a bean, then when the user initiates interaction with the cart, I think you'd want something like this:

if ( ! structkeyexists( session, 'cart' ) {
    session.cart = getBeanFactory().getBean('cart');
}

Just make sure from the docs that your getBean() call is creating a transient and not a singleton. There are options in there that I don't remember offhand. Keep in mind that once session.cart is created, whether it is a bean or data structure, you don't want to overwrite it, so you need to wrap the creation in a structkeyexists() call. 

I generally do not use singletons in my views unless I'm rendering something. In my case, I use a singleton to render a translation of a term in multiple languages in the view, but that's it. If I needed data from a singleton, I'd obtain it in the controller, set it to an rc scoped variable, and then it would be available in the view, rather than passing a singleton into the view via rc scope. 

Here's an example how I create singletons in my controllers using fw1's mechanism for injecting them.

variables.framework = {
....
diEngine = 'di1',
diLocations = 'services'
};



component accessors="true" {

property name="AppointmentService";
property name="ClientService";
property name="FinancialService";
property name="UtilsService";
property name="framework";
...
       public void function listAppointments( struct rc ) {
rc.qClients= variables.clientService.findGroupedClientsForSelect();
rc.minDate = variables.appointmentService.findMinDate();
rc.maxDate = variables.appointmentService.findMaxDate();

...

To make things clear, appointment.cfc is in my services directory, so the convention is that services/appointment.cfc is located and injected as a property named AppointmentService. diLocations can be a list of directories. 

Hope that helps.

Nando

Nando Breiter

unread,
Apr 6, 2019, 7:21:51 AM4/6/19
to framew...@googlegroups.com
By the way, I'd tend to use a simple data structure for the cart, session.cart.someArray or session.cart.someStruct. This would consume less memory on the server. It doesn't make sense to me that every user would need to have their own version of a function to add and remove items from the cart, create totals, perform a checkout, etc in memory. 



CarbonZero Sagl
+41 (0)76 303 4477 cell
skype: ariamedia

Nando Breiter

unread,
Apr 6, 2019, 7:18:32 PM4/6/19
to framew...@googlegroups.com
PS - Which brings things back to Richard's suggestion above. You could create a userService singleton that has functions in it to, for example, sum the total in session.cart, etc etc. All users would share a common userService, but it would not be used to store cart data. It would only be used to perform operations on session.cart so that each individual user retains their unique data set. 



CarbonZero Sagl
+41 (0)76 303 4477 cell
skype: ariamedia

Dejan Karan

unread,
Apr 6, 2019, 7:44:34 PM4/6/19
to framework-one
This is good info, thank you both.
Dejan
Reply all
Reply to author
Forward
0 new messages