[ColdBox 4.1] Interceptor not setting session bean

I am trying to set a bean with some values from a new interceptor which I created. At first I placed the sets in the preProcess of the security interceptor (security module interceptor) and everything was working fine and values get set and stick in session. When I created a custom interceptor and copied the code from the preProcess in the security interceptor the values no longer get set. I dump the projectBean.getThis() and I can see them set but when I dump the it is all blank. Any ideas why it works fine in one interceptor but not another?? Thanks!

My interceptor settings in ColdBox.cfc:

//Register interceptors as an array, we need order
interceptors = [
// SES
{class=“coldbox.system.interceptors.SES”},
// User interceptor
{class=“interceptors.userSession”},
// Security - handles PKI and NONPKI logon
{class=“cbsecurity.interceptors.Security”,
name=“CBSecurity”,
properties = {
// please add the properties you want here to configure the security interceptor
rulesFile = “/cbsecurity/config/security.json.cfm”,
rulesSource = “json”
}
}
];

My Bean:

component accessors=“true” scope=“session” singleton {

property name=“projects”;
property name=“projTitle”;
property name=“projId”;
property name=“parentProjId”;
property name=“bannerImage”;
property name=“defaultPhase”;
property name=“dsn”;
property name=“editDuration”;
property name=“myKey”;
property name=“parentDsn”;
property name=“phase”;
property name=“phaseTitle”;
property name=“prjEngName”;
property name=“projectLogo”;

/**

  • Constructor
    */
    function init(){
    return this;
    }

/* Utils */
function getThis(){
return this;
}

}

preProcess code:

var rc = event.getCollection(); var oSession = getInstance('SessionStorage@cbstorages');

if (StructKeyExists(rc, “project”) and rc.project neq projectBean.getProjId()) {
// Set user info for this project/phase
userBean.setUsername(oSession.getVar(“username”));

// Set project settings
var qry = proj.getProjectSettings(rc.project);

projectBean.setProjId(qry.projId);
projectBean.setProjTitle(qry.title);
projectBean.setParentProjId(qry.parentProjId);
projectBean.setBannerImage(qry.bannerImage);
projectBean.setDefaultPhase(qry.defaultPhase);
projectBean.setDsn(qry.dsn);
projectBean.setEditDuration(qry.editDuration);
projectBean.setMyKey(qry.myKey);
projectBean.setParentDsn(qry.parentDsn);
projectBean.setPhase(qry.phase);
projectBean.setPhaseTitle(qry.phaseTitle);
projectBean.setPrjEngName(qry.prjEngName);
projectBean.setProjectLogo(qry.projectLogo);

(dump you see below)
writedump(projectBean.getThis());
writedump(session);
abort;
}

Bean dump after setting:

component models.beans.projectBean
$MIXED true
PROPERTIES
projects [empty string]
projTitle PROJECT1
projId 7
parentProjId [empty string]
bannerImage [empty string]
defaultPhase [empty string]
dsn PROJECT1

editDuration 90
myKey PROJECT1

parentDsn PROJECT1

phase [empty string]
phaseTitle [empty string]
prjEngName [empty string]
projectLogo [empty string]

METHODS

Session dump w empty values:

struct
cbox_flash_scope
struct [empty]

cbstorage
struct

sessionid E8034E3470215F75654809CF1F44703D.cfusion
urltoken CFID=21307&CFTOKEN=bfbd95ea2e9f2ccf-0806BFA4-5C26-0A61-9CA62637760D20B5&jsessionid=E8034E3470215F75654809CF1F44703D.cfusion
wirebox:projectbean
component models.beans.projectBean
$MIXED true
PROPERTIES
projects [empty string]
projTitle [empty string]
projId [empty string]
parentProjId [empty string]
bannerImage [empty string]
defaultPhase [empty string]
dsn [empty string]
editDuration [empty string]
myKey [empty string]
parentDsn [empty string]
phase [empty string]
phaseTitle [empty string]
prjEngName [empty string]
projectLogo [empty string]

METHODS

You have reinit the framework when you make these changes right?

Yes, I even restarted the CF11 service

  • Why are you setting session data in preProcess? That runs every request and session data presumable only needs to be set once per session. Can the project be reset on every request?
  • scope=“session” singleton Why is this bean set to the singleton scope and the session scope? That doesn’t make any sense. I think you just want session
  • Where is projectBean coming from in your preprocess code? If it is session scoped, do NOT inject it into your interceptor since it is a transient. This is called scope widening injection and it’s bad. Instead, call wirebox.getInstance( ‘mySessionScopedObject’ ) every time.
    Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

  • Why are you setting session data in preProcess? That runs every request and session data presumable only needs to be set once per session. Can the project be reset on every request? - Yes, we deal with numerous projects with multiple sub projects which could each have multiple phases with their own settings and user roles. So depending on where the user navigated, they could be jumping around from project to project. The data would only get reset in preProcess if “if (StructKeyExists(rc, “project”) and rc.project neq projectBean.getProjId())” is true.
  • scope=“session” singleton Why is this bean set to the singleton scope and the session scope? That doesn’t make any sense. I think you just want session Yes, I have removed singleton.
  • Where is projectBean coming from in your preprocess code? If it is session scoped, do NOT inject it into your interceptor since it is a transient. This is called scope widening injection and it’s bad. Yes, I was injecting it there and in some models (removed all injections of it now everywhere). Instead, call wirebox.getInstance( ‘mySessionScopedObject’ ) every time.
  • OK, I added “var projectBean = wirebox.getInstance(‘beans.projectBean’);” to my preProcess function to use for my sets (Everything is working now!)
  • I also removed “map(“projectBean”).to(“models.beans.projectBean”);” from my WireBox config file. I added "prc.projectBean = thewirebox.getInstance(‘beans.projectBean’); to my request decorator. Is this a good solution or am I missing something else that I could do in the WireBox config file like any other type of injections or mapping??
    Thanks for all the help!

Chad

I think we’re making progress Chad :slight_smile:

  • I also removed “map(“projectBean”).to(“models.beans.projectBean”);” from my WireBox config file. I added "prc.projectBean = thewirebox.getInstance(‘beans.projectBean’); to my request decorator. Is this a good solution or am I missing something else that I could do in the WireBox config file like any other type of injections or mapping??

This is totally up to your preference. I prefer to only request a bean by it’s name and not the full path. Of course, I also take care not to have more than one bean with the same name in different folders so the name is unique. I don’t like to map each of my CFCs separately though, so I use mapDirectory() to recursively map all the CFCs in one directory at once.

mapDirectory( ‘models’ );

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

So with scope=“session” it is safe to still have mappings in the WireBox config and inject into the models? Just not safe to inject into interceptors?

Thanks,
Chad

Chad… consider what happens when a session expires. Everything in it dies. If you have added a session.value to one of your persistent models (singletons)…what will happen when you try to use it if that session has expired? It’ll be a “dead stick”, maybe a NULL pointer because the source object has been purged. If you are are using it as an argument to a function, that’s different.

The mappings don’t actually create instances of objects, they just define the objects for Wirebox. Basically, when you create a mapping you’re telling Wirebox about an object called “foo” that you might ask for in the future and giving WireBox the recipe it needs to create “foo” when the time comes. ALL objects WireBox creates have a mapping whether you create it or not. (WireBox will make one the first time if necessary).

Scope widening injection comes into play once you are dealing with actual object instances. The rule of thumb is never put a hard reference to another objects whose lifespan is shorter than the object you’re injecting into. Interceptors are singletons by default-- a single instance is created and persisted for the life of the application and shared by every thread. Therefore, only other singletons should ever be injected directly into an interceptor. Same for handlers. Otherwise, the injection will be “widening” the scope of the transient object by making it live longer than it was supposed to.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Actually, you wouldn’t get a NPE. Everything in Java (but native data types) are pointers in memory. As long as there is at least one strong reference to it, the garbage collector won’t remove it. In this instance, the “bad” behavior would be that all users will “share” or point to the same “session” object. That object may also end up in an invalid state.

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com